我正在尝试创建一种动态方式来在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);
答案 0 :(得分:1)
作为上述答案的补充,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 文件中的导出名称命名,因此您应该能够如果您使用 Blender 或 Maya 等 DCC 应用程序命名网格,则可以使用 mesh.name
属性识别网格。
答案 1 :(得分:0)
加载器返回的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
documentation中的说明。