threejs(四)层级模型
Group层级模型
可以用group
给多个mesh创建一个组对象,这样就可以对group组对象做统一操作,不用每个单对象一一处理。
1、THREE.Group
.add
:添加 mesh
.children
:查看子对象
.name
:给group命名
.traverse()
:遍历网格模型
.getObjectByName()
:查找某个具体的模型
示例1 — group 简单示例
//创建两个网格模型mesh1、mesh2
const geometry = new THREE.BoxGeometry(20, 20, 20);
const material = new THREE.MeshLambertMaterial({color: 0x00ffff});
const group = new THREE.Group();
const mesh1 = new THREE.Mesh(geometry, material);
const mesh2 = new THREE.Mesh(geometry, material);group.add(mesh1); //把mesh1型插入到组group中,mesh1作为group的子对象
group.add(mesh2); //把mesh2型插入到组group中,mesh2作为group的子对象// group.translateY(100); // 沿着Y轴平移mesh1和mesh2的父对象,mesh1和mesh2跟着平移//把group插入到场景中作为场景子对象
scene.add(group);console.log('查看Scene的子对象', scene.children);
示例2 — 高层楼房及洋房简单示例
// 批量创建多个长方体表示高层楼
const group1 = new THREE.Group(); //所有高层楼的父对象
group1.name = "高层";
for (let i = 0; i < 5; i++) {const geometry = new THREE.BoxGeometry(20, 60, 10);const material = new THREE.MeshLambertMaterial({color: 0x00ffff});const mesh = new THREE.Mesh(geometry, material);mesh.position.x = i * 30; // 网格模型mesh沿着x轴方向阵列group1.add(mesh); //添加到组对象group1mesh.name = i + 1 + '号楼';// console.log('mesh.name',mesh.name);
}
group1.position.y = 30;const group2 = new THREE.Group();
group2.name = "洋房";
// 批量创建多个长方体表示洋房
for (let i = 0; i < 5; i++) {const geometry = new THREE.BoxGeometry(20, 30, 10);const material = new THREE.MeshLambertMaterial({color: 0x00ffff});const mesh = new THREE.Mesh(geometry, material);mesh.position.x = i * 30;group2.add(mesh); //添加到组对象group2mesh.name = i + 6 + '号楼';
}
group2.position.z = 50;
group2.position.y = 15;const model = new THREE.Group();
model.name='小区房子';
model.add(group1, group2);
model.position.set(-50,0,-25);
示例3:遍历模型树结构,并改变所有mesh颜色
traverse
// 递归遍历model包含所有的模型节点
model.traverse(function(obj) {console.log('所有模型节点的名称',obj.name);// obj.isMesh:if判断模型对象obj是不是网格模型'Mesh'if (obj.isMesh) {//判断条件也可以是obj.type === 'Mesh'obj.material.color.set(0xffff00);}
});
示例4:查找某个具体的模型.getObjectByName()
.getObjectByName()
类似JS中 getElementById 的方法,这里是根据对象名称查找元素,找到元素后给他设置属性
// 返回名.name为"1号楼"对应的对象
const nameNode = scene.getObjectByName ("1号楼");
nameNode?.material.color.set(0xff0000);
2、本地坐标和世界坐标
改变子对象的.position,子对象在3D空间中的坐标会发生改变。
改变父对象的.position,子对象在3D空间中的位置也会跟着变化,也就是说父对象.position和子对象.position叠加才是才是子对象的.position。
任何一个模型的本地坐标
(局部坐标)就是模型的.position属性。(有点像前端的reletive position属性,相对于直接父级的位置)
一个模型的世界坐标
,说的是,模型自身.position和所有父对象.position累加的坐标。(有点像前端的absolute position属性,相对于视窗的位置)
.getWorldPosition() 获取世界坐标
mesh.getWorldPosition(Vector3)
读取一个模型的世界坐标,并把读取结果存储到参数Vector3中。
所以要定义一个 verctor3 向量来存
// 声明一个三维向量用来表示某个坐标
const worldPosition = new THREE.Vector3();
// 获取mesh的世界坐标,你会发现mesh的世界坐标受到父对象group的.position影响
mesh.getWorldPosition(worldPosition);
console.log('世界坐标',worldPosition);
console.log('本地坐标',mesh.position);
3、.remove 模型移除对象
可以移除 group 中的 children对象,也可以删除场景的光源等等
// 删除父对象group的子对象网格模型mesh1
group.remove(mesh1);
scene.remove(ambient);//移除场景中环境光
scene.remove(model);//移除场景中模型对象
一次移除多个子对象
group.remove(mesh1,mesh2);
4、.visible模型隐藏对象
模型属性.visible
可以给 group、mesh 等的 visible 属性赋值为 false,就可以实现对象隐藏
mesh.visible =false;// 隐藏一个网格模型,visible的默认值是true
group.visible =false;// 隐藏一个包含多个模型的组对象group
材质属性.visible
给 material 设置 visible 为 false,就是使用这个 material 的 mesh 对象都不可见了。
// 隐藏网格模型mesh,visible的默认值是true
mesh.material.visible =false;
// 注意如果mesh2和mesh的.material属性指向同一个材质,mesh2也会跟着mesh隐藏