Three层级模型以及组对象

前言:在场景中层级模型、网格模型等,就像是多个零件就需要多个网格模型。其实一个层级模型就像一本书的目录一样。层级模型结构如下:

层级模型与在生活中物体当然有关系,比如说一个人身体,头、眼睛、手、腿都是人类的一部分;牛肉、西红柿、生菜都是汉堡包制作好的一部分。

1.组对象(group)

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

javascript 复制代码
/ 网格模型Mesh 
var geometry = new BoxGeometry(100, 100, 100); 
// 三角形面渲染模式 
var meterial = new MeshLambertMaterial({    
    color: 0xff0000, //三角面颜色
}); 
//材质对象 
var group = new Group(); 
//创建组 
var mesh1 = new Mesh(geometry, meterial);
var mesh2 = new Mesh(geometry, meterial); 
// 第二个网格模型沿着X轴平移 mesh2.translateX(200); 
// 把mesh1型插入到组group中,mesh1作为group的子对象 
group.add(mesh1);
//把mesh2型插入到组group中,mesh2作为group的子对象 
group.add(mesh2); 
//把group插入到场景中作为场景子对象 
scene.add(group);

效果图:

剩下,需要mesh1和mesh2的父对象调整位置。

通过沿着平移mesh1和mesh2的父对象,mesh1和mesh2跟着平移。

javascript 复制代码
group.translateY(100);

父对象缩放,子对象跟着缩放。

javascript 复制代码
group.scale.set(4,4,4);

父对象旋转,子对象跟着旋转。

javascript 复制代码
group.rotateY(Math.PI/6);

2.查看子对象.children

Threejs场景对象scene、组对象group都是有一个子对象属性.children。其实.children的类型返回是数组。

javascript 复制代码
console.log('查看group的子对象',group.children)

3.处理场景对象结构

一般来说网格模型mesh、点模型points、线模型line是树结构的最外层叶子结点。构建层级模型的中间层一般都是通过Threejs的group类来完成,group类实例化的对象可以称为组对象。

3.1 add()方法

.add()方法是给父对象添加一个子对象。

还包括场景对象scene、组对象group、网格模型对象mesh、光源对象light等都是继承它们的基类。

可以单独插入一个对象,也可以插入多个对象。

javascript 复制代码
group.add(mesh1); group.add(mesh2); 
//或者 
group.add(mesh1,mesh2);

3.2 remove()方法

.remove()方法是删除父对象中的一个子对象。

javascript 复制代码
// 删除父对象group的子对象网格模型mesh1 
group.add(mesh1) 
// 一次删除场景中多个对象 
scene.remove(light,group)

4.设置模型命名(.name属性)

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

javascript 复制代码
group.add(Mesh) 
// 网格模型命名
mesh.name = "眼睛" 
// mesh父对象对象命名 
group.name = "头"

5.树结构层级模型

例题:

可以直接通过代码创建一个非常简易的机器人模型。

javascript 复制代码
// 头部网格模型和组 
var headMesh = sphereMesh(10, 0, 0, 0); 
headMesh.name = "脑壳" 
var leftEyeMesh = sphereMesh(1, 8, 5, 4); 
leftEyeMesh.name = "左眼"
var rightEyeMesh = sphereMesh(1, 8, 5, -4);
rightEyeMesh.name = "右眼" 
var headGroup = new Group();
headGroup.name = "头部"
headGroup.add(headMesh, leftEyeMesh, rightEyeMesh); 

// 身体网格模型和组 
var neckMesh = cylinderMesh(3, 10, 0, -15, 0); 
neckMesh.name = "脖子" 
var bodyMesh = cylinderMesh(14, 30, 0, -35, 0);
bodyMesh.name = "腹部" 
var leftLegMesh = cylinderMesh(4, 60, 0, -80, -7); 
leftLegMesh.name = "左腿" 
var rightLegMesh = cylinderMesh(4, 60, 0, -80, 7); 
rightLegMesh.name = "右腿" 
var legGroup = new Group(); 
legGroup.name = "腿" 
legGroup.add(leftLegMesh, rightEyeMesh); 
var bodyGroup = new Group(); 
bodyGroup.name = "身体" 
bodyGroup.add(neckMesh, bodyMesh, legGroup); 

// 人,组合成为人类 
var personGroup = new Group(); 
personGroup.name = "人" 
personGroup.add(headGroup, bodyGroup);
personGroup.translateY(50) 
scene.add(personGroup); 

// 球体网格模型创建函数
function sphereMesh(R, x, y, z) {     
    var geometry = new SphereGeometry(R, 25, 25); //球体几何体 
    var material = new MeshPhongMaterial({       
        color: 0x0000ff    
    }); //材质对象Material     
    var mesh = new Mesh(geometry, material); // 创建网格模型对象  
    mesh.position.set(x, y, z);     
    return mesh; 
} 
// 圆柱体网格模型创建函数 
function cylinderMesh(R, h, x, y, z) {     var geometry = new CylinderGeometry(R, R, h, 25, 25); //球体几何体     var material = new MeshPhongMaterial({     
        color: 0x0000ff     
         }); //材质对象Material    
    var mesh = new Mesh(geometry, material); // 创建网格模型对象     mesh.position.set(x, y, z);     
    return mesh; 
}

人体里有多个结构,头部作为网格模型,脑壳、眼睛和耳朵等作为组对象;身体作为网格模型,脖子、左腿和右腿作为组对象等。最后把多个结构称为人类。

效果图:

5.处理递归遍历方法.traverse()

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

javascript 复制代码
scene.traverse(function(obj) { 
    if (obj.type === "Group") { 
        console.log(obj.name); 
    }
    if (obj.type === "Mesh")
    { 
        console.log(' ' + obj.name);
        obj.material.color.set(0xffff00);
    } 
    if (obj.name === "左眼" | obj.name === "右眼")
    {
        obj.material.color.set(0x000000) 
    } 
    // 打印id属性
    console.log(obj.id);
    // 打印该对象的父对象 
    console.log(obj.parent); 
    // 打印该对象的子对象
    console.log(obj.children); 
})

6.查找某个具体的模型

看到Threejs的.getObjectById()、.getObjectByName()等方法。Threejs和前端DOM一样,可以通过一个方法查找树结构父元素的某个后代对象,对于普通前端而言可以通过name或id等方式查找一个或多个DOM元素,Threejs同样可以通过一些方法查找一个模型树中的某个节点。

javascript 复制代码
// 遍历查找scene中复合条件的子对象,并返回id对应的对象 
var idNode = scene.getObjectById ( 4 ); 
console.log(idNode);

遍历查找对象的子对象,返回name对应的对象(name是可以重名的,返回第一个)。

javascript 复制代码
var nameNode = scene.getObjectByName ( "左腿" ); 
nameNode.material.color.set(0xff0000);
相关推荐
也无晴也无风雨1 小时前
深入剖析输入URL按下回车,浏览器做了什么
前端·后端·计算机网络
Martin -Tang2 小时前
Vue 3 中,ref 和 reactive的区别
前端·javascript·vue.js
FakeOccupational3 小时前
nodejs 020: React语法规则 props和state
前端·javascript·react.js
放逐者-保持本心,方可放逐3 小时前
react 组件应用
开发语言·前端·javascript·react.js·前端框架
曹天骄4 小时前
next中服务端组件共享接口数据
前端·javascript·react.js
阮少年、5 小时前
java后台生成模拟聊天截图并返回给前端
java·开发语言·前端
郝晨妤6 小时前
鸿蒙ArkTS和TS有什么区别?
前端·javascript·typescript·鸿蒙
AvatarGiser6 小时前
《ElementPlus 与 ElementUI 差异集合》Icon 图标 More 差异说明
前端·vue.js·elementui
喝旺仔la6 小时前
vue的样式知识点
前端·javascript·vue.js
别忘了微笑_cuicui6 小时前
elementUI中2个日期组件实现开始时间、结束时间(禁用日期面板、控制开始时间不能超过结束时间的时分秒)实现方案
前端·javascript·elementui