1、组对象Group、层级模型-形成树状结构

threejs 仓库 threejs 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);
mesh2.translateX(25);
//把mesh1型插入到组group中,mesh1作为group的子对象
group.add(mesh1);
//把mesh2型插入到组group中,mesh2作为group的子对象
group.add(mesh2);
//把group插入到场景中作为场景子对象
scene.add(group);

分组group对象作用:方便将大量模型按业务逻辑进行分组和结构化,方便统一对模型进行修改和操作。

(1) 添加对象-add()方法

通过add方法把多个模型设置为组对象group的子对象children中。

threejs 仓库 threejs group_Group_02

 

物体对象Object3D和组对象Group,通常都用来当父节点使用,可把两者画等号。

场景对象Scene、组对象Group的.add()方法都是继承自它们共同的基类Object3D。

父对象旋转缩放平移变换,子对象跟着变化。mesh也能添加mesh子对象。

(2)访问子对象-children属性

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

(3)移除对象.remove()

// 删除父对象group的子对象网格模型mesh1
group.remove(mesh1,mesh2);

scene.remove(ambient);//移除场景中环境光
scene.remove(model);//移除场景中模型对象

 (4) 隐藏或显示-visible属性

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

注意,这4个属性或方法,都是从object3D继承过来的。

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

(1)name属性

层级模型中可以给一些模型对象通过.name属性命名进行标记。

下面是通过代码创建了一个层级模型,一般实际开发的时候,会加载外部的模型,然后从模型对象通过节点的名称.name查找某个子对象。

threejs 仓库 threejs group_递归遍历_03

(2)递归遍历方法.traverse()

Threejs层级模型就是一个树结构,可以通过递归遍历的算法去遍历Threejs一个模型对象包含的所有后代。

// 递归遍历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);
    }
});

(3)查找某个模型.getObjectByName()

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

3、本地(局部)坐标和世界坐标

模型的本地坐标(局部坐标),就是模型的.position属性。

模型的世界坐标,是模型自身.position和所有父对象.position累加的坐标。

 (1)获取世界坐标.getWorldPosition()

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

(2)给子对象添加一个局部坐标系

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