Appearance
三维软件模型命名
其实模型节点命名可以类比前后端API接口命名,web3d前端和后端对接需要命名接口,和3D美术对接,同样需要给一些模型节点命名。
- 模型命名可以使用汉字、英文、拼音其他语言形式。
- 如果使用汉字注意,有些三维建模软件可能存在导出乱码问题。
一般三维建模软件的目录树,都有模型的名称,three.js加载外部模型,外部模型的名称体现为three.js对象的.name属性,three.js可以通过.getObjectByName()方法,把模型节点的名字.name作为改函数参数,快速查找某个模型对象。
js
// 返回名.name为"1号楼"对应的对象
const nameNode = gltf.scene.getObjectByName("1号楼");
nameNode.material.color.set(0xff0000);//改变1号楼Mesh材质颜色对于大类,可以进行分组,这样更好管理,比如高层分为一组,洋房分为一组。如果这样做的好处是,程序员可以通过分类名称,快速获取所有模型,然后进行同样的渲染操作,比如洋房批量改变颜色。
js
//获得所有'洋房'房子的父对象
const obj = gltf.scene.getObjectByName('洋房');
console.log('obj', obj); //控制台查看返回结果
console.log('obj.children', obj.children);
// obj.children的所有子对象都是Mesh,改变Mesh对应颜色
obj.children.forEach(function (mesh) {
mesh.material.color.set(0xffff00);
})递归遍历层级模型修改材质
加载一个外部模型,比如gltf模型,如果你想批量修改每个Mesh的材质,一个一个设置比较麻烦,可以通过递归遍历方法.traverse()批量操作更加方便。
递归遍历方法.traverse()
js
// 递归遍历所有模型节点批量修改材质
gltf.scene.traverse(function(obj) {
if (obj.isMesh) {//判断是否是网格模型
console.log('模型节点',obj);
console.log('模型节点名字',obj.name);
}
});threejs解析gltf模型默认材质一般是MeshStandardMaterial或MeshPhysicalMaterial,相比较其它网格材质,这两个材质属于PBR物理材质,可以提供更加真实的材质效果
js
// 递归遍历所有模型节点批量修改材质
gltf.scene.traverse(function(obj) {
if (obj.isMesh) {
console.log('gltf默认材质',obj.material);
}
});批量修改gltf所有Mesh的材质
js
gltf.scene.traverse(function(obj) {
if (obj.isMesh) {
// 重新设置材质
obj.material = new THREE.MeshLambertMaterial({
color:0xffffff,
});
}
});外部模型材质是否共享的问题
美术通过三维建模软件,比如Blender绘制好一个三维场景以后,一些外观一样的Mesh,可能会共享一个材质对象。
通过.name标记材质,测试mesh1和mesh2是否共享了材质
js
const mesh1 = gltf.scene.getObjectByName("1号楼");
mesh1.material.name = '楼房材质';//通过name标记mesh1对应材质
const mesh2 = gltf.scene.getObjectByName("2号楼");
//通过name相同,可以判断mesh1.material和mesh2.material共享了同一个材质对象
console.log('mesh2.material.name', mesh2.material.name);如何解决呢
- 三维建模软件中设置,需要代码改变材质的Mesh不要共享材质,要独享材质。
- 代码批量更改:克隆材质对象,重新赋值给mesh的材质属性
js
//用代码方式解决mesh共享材质问题
gltf.scene.getObjectByName("小区房子").traverse(function (obj) {
if (obj.isMesh) {
// .material.clone()返回一个新材质对象,和原来一样,重新赋值给.material属性
obj.material = obj.material.clone();
}
});
mesh1.material.color.set(0xffff00);
mesh2.material.color.set(0x00ff00);