【问题标题】:Three.js - Trying to load multiple material objectsThree.js - 尝试加载多个材质对象
【发布时间】:2020-07-28 19:35:52
【问题描述】:

我正在使用three.js,我正在尝试加载多个材质对象。当我运行代码时,第一个材质对象正确映射到数据。一旦它旋转,第二个材质对象就会意外填充。理想情况下,我希望第一个材质对象 [cubeMaterial] 读取数据 [0],即 49,第二个材质对象 [cubeMaterialTwo] 读取数据 [1],即 7。

这是我的代码:

<script src="https://cdn.jsdelivr.net/npm/three@0.118.3/build/three.js"></script>

let scene, camera, renderer;

let cubeGroup;

init();
animate();

function init() {

const data = [
[49, 7]
]

var i = 1;

width = 500
height = 500
fov = 9
aspect = 1/5
near = .1
far = 1000

loader = new THREE.TextureLoader()

scene = new THREE.Scene(); // ADDED

camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
camera.position.set(50, 30, 50);
camera.lookAt( scene.position );


cubeGeometries = data.map(row => {
 return row.map(c => {
  return new THREE.BoxBufferGeometry(0.2, c / 8, 0.2);
 })
})

var materialArray = [];

const cubeMaterial = new THREE.MeshBasicMaterial({
 map: loader.load('../path/to/.jpgOne')
});
cubeMaterial.color.convertSRGBToLinear();

const cubeMaterialTwo = new THREE.MeshBasicMaterial({
map: loader.load('../path/to/.jpgTwo')
});
cubeMaterialTwo.color.convertSRGBToLinear();

materialArray.push(cubeMaterial, cubeMaterialTwo);

const cubeMeshes = cubeGeometries.map(row => {
  return row.map(cubeGeometry => new THREE.Mesh(cubeGeometry, materialArray))
})

cubeGroup = new THREE.Group();
 data.forEach((row, i, iarr) => {
  row.forEach((d, j, jarr) => {
   cubeMeshes[i][j].position.set(
    i / iarr.length - 0.5,
    d / 8 * 0.5 - 0.6,
    j / jarr.length - 0.5);

   //cubeMeshes[i][j].scale.set(1,4,1);
   cubeGroup.add(cubeMeshes[i][j]);
  })
 })

const mainLight = new THREE.DirectionalLight(0xffffff, 5.0);
 mainLight.position.set(10, 10, 10);

const ambientLight = new THREE.HemisphereLight(0xddeeff, 0x202020, 3);

var material = new THREE.LineBasicMaterial({
 color: 0x0000ff
});

scene.add(cubeGroup);
scene.add(mainLight);
scene.add(ambientLight);


renderer = new THREE.WebGLRenderer({
  antialias: true
});

renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(window.devicePixelRatio);
renderer.outputEncoding = THREE.sRGBEncoding;
renderer.physicallyCorrectLights = true;

document.body.appendChild(renderer.domElement); 

}

function animate() {
 requestAnimationFrame( animate );
 cubeGroup.rotation.y += 0.005;
 renderer.render( scene, camera );

}

【问题讨论】:

  • 只是快速阅读您的代码,您正在以同步模式为加载器(异步)使用单个变量。我建议创建一个 TextureLoader 的新实例以检查问题所在
  • @jscastro 感谢您的评论。不幸的是还是同样的问题。

标签: javascript canvas three.js data-visualization


【解决方案1】:

我已经对您的代码进行了最低限度的调整,它正在加载两个纹理,但是当您将完整的 materialArray 传递给 Mesh 构造函数时,您在网格的相对侧使用它们。 我已经用你的代码创建了一个fiddle loading two textures 来重现这个问题,但它同时加载了这两个问题。

  const cubeMaterial = new THREE.MeshBasicMaterial({
    map: new THREE.TextureLoader().load('https://i.postimg.cc/25m7H09s/metal1.jpg')
  });
  cubeMaterial.color.convertSRGBToLinear();

  const cubeMaterialTwo = new THREE.MeshBasicMaterial({
    map: new THREE.TextureLoader().load('https://i.postimg.cc/pXs9NqTN/OIP.jpg')
  });
  cubeMaterialTwo.color.convertSRGBToLinear();

不确定这是否是您尝试实现的目标,或者加载两个网格,每个网格都带有一个纹理,但肯定是 TextureLoader 正在加载两个纹理。

如果此答案解决了您最初的问题,请将其标记为“已接受答案”,这样也有助于其他用户知道这是问题的正确解决方案。

编辑:我现在修改了fiddle loading two textures,为每个对象随机设置了一个...您可以尝试多次,您会发现它有效。

  return row.map(cubeGeometry => new THREE.Mesh(cubeGeometry, materialArray[Math.round(Math.random())]))
  })

编辑 2:我找到了您上一个问题的解决方案,正如您所说的,您需要一个迭代器,并且每个块都有不同的纹理。这里有new fiddle,相关代码就是这几行替换原来的。

  let index = 0;
  const cubeMeshes = cubeGeometries.map((row) => {
    index++;
    return row.map((cubeGeometry, index) => new THREE.Mesh(cubeGeometry, materialArray[index]))
  })

【讨论】:

  • 感谢您抽出时间来帮助我解决这个问题。不幸的是,这并不能解决我遇到的问题。我想要做的不是翻转对象,例如,较高的块在一侧有一个纹理,然后当它旋转时,它会翻转到另一个纹理。我想要实现的是,较高的块是整个功能(两侧)的一种纹理(材料),而另一个块(较小的块)也是整个功能的另一种纹理。如果我没有说得更清楚,我深表歉意。
  • 这个问题是因为你将完整的materialArray 传递给网格构造函数,如果你想你必须在materialArray 位置上使用随机...
  • 编辑了我的答案和小提琴......只需在答案链接中尝试。你必须运行它几次,因为它是一个随机的 0-1 并且很多次可能是相同的索引返回..
  • 我已将答案标记为已接受,因为它回答了我的原始问题。话虽如此,我真正想做的(我本来应该更清楚的)是将数据对象附加到每种材料上,这样它就不是随机的。高条总是一种纹理,小条总是另一种。这可能吗?
  • 然后你需要一个通过 materialArray 项目的迭代器变量,正如你在下面的代码中使用 data.forEach 时使用的那样。
猜你喜欢
  • 2023-03-20
  • 2013-05-22
  • 1970-01-01
  • 2012-09-08
  • 1970-01-01
  • 1970-01-01
  • 2013-07-30
  • 2020-02-15
  • 2017-06-14
相关资源
最近更新 更多