层级模型

使用层级模型

创建两个网格模型mesh1、mesh2,通过THREE.Group类创建一个组对象group,然后通过add方法把网格模型mesh1、mesh2作为设置为组对象group的子对象,然后在通过执行scene.add(group)把组对象group作为场景对象的scene的子对象。也就是说场景对象是scene是group的父对象,group是mesh1、mesh2的父对象,这样就构成了一个三层的层级结构。

1
2
3
4
5
const group = new THREE.Group();
group.add(mesh1);
group.add(mesh2);
scene.add(group);//.add()方法都是继承自它们共同的基类(父类)Object3D
//等价于group.add(mesh1,mesh2);

Three.js场景对象Scene、组对象Group都有一个子对象属性.children,通过该属性可以访问父对象的子对象,子对象属性.children的值是数组,所有子对象是数组的值。场景对象Scene的子对象,除了组对象Group之外,还可以看到环境光AmbientLight、平行光DirectionalLight、辅助坐标对象AxesHelper等。场景对象Scene构成的层级模型本身是一个树结构,场景对象层级模型的第一层,也就是树结构的根节点,一般来说网格模型Mesh、点模型Points、线模型Line是树结构的最外层叶子结点。构建层级模型的中间层一般都是通过Three.js的Group类来完成,Group类实例化的对象可以称为组对象。

1
2
console.log('查看group的子对象',group.children);
console.log('查看Scene的子对象',scene.children);

网格模型mesh1、mesh2作为设置为父对象group的子对象,如果父对象group进行旋转、缩放、平移变换,子对象同样跟着变换。使用层级模型可以操作一组对象。

1
2
3
4
5
6
//沿着Y轴平移mesh1和mesh2的父对象,mesh1和mesh2跟着平移
group.translateY(100);
//父对象缩放,子对象跟着缩放
group.scale.set(4,4,4);
//父对象旋转,子对象跟着旋转
group.rotateY(Math.PI/6)

如下代码等效

1
2
3
4
const mesh1 = new THREE.Mesh(geometry, material);
const mesh2 = new THREE.Mesh(geometry, material);
const obj = new THREE.Object3D();//作为mesh1和mesh2的父对象
obj.add(mesh1,mesh2);

Three.js默认mesh也可以添加子对象,mesh基类也是Object3D。如下代码与group.add(mesh1,mesh2);等效。

1
2
group.add(mesh1);
mesh1.add(mesh2);

遍历模型树结构、查询模型节点

在层级模型中可以给组或者模型对象通过.name属性命名进行标记。

1
2
group.name='小区房子';
mesh.name='一号楼';

如下代码将5个mesh作为group1(高层)的子对象,将5个mesh作为group2(洋房)的子对象,将group1和group2作为group3(小区房子)的子对象,一共是4层模型。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
const group1 = new THREE.Group();
group1.name = "高层";
for (let i = 0; i < 5; i++) {
/*...*/
group1.add(mesh);
mesh.name = i + 1 + '号楼';
}
group1.position.y = 30;

const group2 = new THREE.Group();
group2.name = "洋房";
for (let i = 0; i < 5; i++) {
/*...*/
group2.add(mesh);
mesh.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);

Three.js层级模型就是一个树结构,可以通过递归遍历的算法去遍历Three.js一个模型对象包含的所有后代。obj.name包括mesh的name和group的name。

1
2
3
4
5
6
7
8
// 递归遍历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);
}
});。

通过一些方法查找一个模型树中的某个节点,并对其进行设置。

1
2
3
// 返回名.name为"4号楼"对应的对象
const nameNode = scene.getObjectByName ("4号楼");
nameNode.material.color.set(0xff0000);

本地坐标和世界坐标

改变子对象的.position,子对象在世界坐标系中的坐标会发生改变。改变父对象的.position,子对象在世界坐标系中的位置也会跟着变化,也就是说父对象.position和子对象.position叠加才是才是子对象的.position。任何一个模型的本地坐标就是模型的.position属性。一个模型的世界坐标,是模型自身.position和所有父对象.position累加的坐标。

1
2
3
4
mesh.position.set(50, 0, 0);
const group = new THREE.Group();
group.add(mesh);
group.position.set(50, 0, 0);

mesh.getWorldPosition(Vector3)读取一个模型的世界坐标,并把读取结果存储到参数Vector3中。

1
2
3
4
5
6
// 声明一个三维向量用来表示某个坐标
const worldPosition = new THREE.Vector3();
// 获取mesh的世界坐标,mesh的世界坐标受到父对象group的.position影响
mesh.getWorldPosition(worldPosition);
console.log('世界坐标',worldPosition);
console.log('本地坐标',mesh.position);

mesh.add(坐标系)给mesh添加一个可视化的局部坐标系。

1
2
3
//可视化mesh的局部坐标系
const meshAxesHelper = new THREE.AxesHelper(50);
mesh.add(meshAxesHelper);

移除对象.remove()

.add()方法是给父对象添加一个子对象,.remove()方法是删除父对象中的一个子对象,这将改变.children()属性。

1
2
3
4
// 删除父对象group的子对象网格模型mesh1
group.remove(mesh1);
scene.remove(ambient);//移除场景中环境光
scene.remove(model);//移除场景中模型对象

也可以一次性移除多个子对象。

1
group.remove(mesh1,mesh2);

模型属性.visible

模型对象的父类Object3D封装了一个属性.visible,通过该属性可以隐藏或显示一个模型。

1
2
3
mesh.visible =false;// 隐藏一个网格模型,visible的默认值是true
group.visible =false;// 隐藏一个包含多个模型的组对象group
mesh.visible =true;// 使网格模型mesh处于显示状态

材质对象的父类Material封装了一个.visible属性,通过该属性可以控制是否隐藏该材质对应的模型对象。

1
2
3
// 隐藏网格模型mesh,visible的默认值是true
mesh.material.visible =false;
// 注意如果mesh2和mesh的.material属性指向同一个材质,mesh2也会跟着mesh隐藏

注意:如果多个模型引用了同一个材质,如果该材质.visible设置为false,意味着隐藏绑定该材质的所有模型。

Donate
  • Copyright: Copyright is owned by the author. For commercial reprints, please contact the author for authorization. For non-commercial reprints, please indicate the source.

扫一扫,分享到微信

微信分享二维码

请我喝杯咖啡吧~

支付宝
微信