如何在 Three.js 中覆盖 GLTF 材质

问题描述 投票:0回答:2

我正在尝试创建一种动态方式来在 Three.js 中的 gltf 导入模型上显示太阳能数据。目的是将不同的纯色与模型的不同部分相关联,并能够关闭和打开它们。我当前的障碍是改变 gltf 中材质的颜色。

我尝试使用

ObjLoader
来代替,以便我可以输入自己的材料,但这不起作用:/

这是我目前拥有的js:

const gltfLoader = new THREE.GLTFLoader();
gltfLoader.load('Building.glb', (gltf) => {
  const root = gltf.scene;
  scene.add(root);

  const box = new THREE.Box3().setFromObject(root);
  const boxSize = box.getSize(new THREE.Vector3()).length();
  const boxCenter = box.getCenter(new THREE.Vector3());

  frameArea(boxSize * 0.5, boxSize, boxCenter, camera);

  controls.maxDistance = boxSize * 10;
  controls.target.copy(boxCenter);
  controls.update();
});


function frameArea(sizeToFitOnScreen, boxSize, boxCenter, camera) {
  const halfSizeToFitOnScreen = sizeToFitOnScreen * 0.5;
  const halfFovY = THREE.Math.degToRad(camera.fov * .5);
  const distance = halfSizeToFitOnScreen / Math.tan(halfFovY);
  const direction = (new THREE.Vector3())
    .subVectors(camera.position, boxCenter)
    .multiply(new THREE.Vector3(1, 0, 1))
    .normalize();

  camera.position.copy(direction.multiplyScalar(distance).add(boxCenter));

  camera.near = boxSize / 100;
  camera.far = boxSize * 100;

  camera.updateProjectionMatrix();

  // point the camera to look at the center of the box
  camera.lookAt(boxCenter.x, boxCenter.y, boxCenter.z);
}

renderer = new THREE.WebGLRenderer({ canvas: myCanvas, antialias: true });
renderer.setClearColor(0x000000);
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);



function resizeRendererToDisplaySize(renderer) {
  const canvas = renderer.domElement;
  const width = canvas.clientWidth;
  const height = canvas.clientHeight;
  const needResize = canvas.width !== width || canvas.height !== height;
  if (needResize) {
    renderer.setSize(width, height, false);
  }
  return needResize;
}

function render() {
  if (resizeRendererToDisplaySize(renderer)) {
    const canvas = renderer.domElement;
    camera.aspect = canvas.clientWidth / canvas.clientHeight;
    camera.updateProjectionMatrix();
  }
  renderer.render(scene, camera);
  requestAnimationFrame(render);
}
requestAnimationFrame(render);
three.js rhino gltf grasshopper
2个回答
26
投票

加载器返回的

gltf.scene
结果是一个
THREE.Scene
实例 - 一旦拥有它,使用什么文件格式加载模型就不再重要了。在这种情况下,您需要遍历该场景并更改其中任何网格的材质。
MeshStandardMaterial
Mesh
文档可能会有所帮助。

var model = gltf.scene;
var newMaterial = new THREE.MeshStandardMaterial({color: 0xff0000});
model.traverse((o) => {
  if (o.isMesh) o.material = newMaterial;
});

如果您需要更改纹理,请注意

GLTFLoader
文档中的说明


4
投票

作为上述答案的附录,

gltf.scene
THREE.Scene
不对应。
gltf.scene
是一个
THREE.Group
实例,但您应该能够如上所述进行遍历。 https://github.com/mrdoob/ Three.js/blob/94f043c4e105eb73236529231388402da2b07cba/examples/jsm/loaders/GLTFLoader.js#L3890

对于 Three.js,最好使用

GLTFLoader
加载模型,因为 Wavefront (.obj) 格式仅支持几何数据。它无法存储其他内容,例如材质、动画等,这很可能是它不适合您的原因。

正如 Don 所说,最好的方法是遍历

gltf.scene
并单独访问网格(根据 GLTFLoader 代码,网格应根据 gltf 文件中导出的名称命名,因此您应该能够使用以下命令来识别网格)
mesh.name
属性(如果您使用 Blender 或 Maya 等 DCC 应用程序来命名它们)。

© www.soinside.com 2019 - 2024. All rights reserved.