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);
相关推荐
mldong1 小时前
你的 Vue3 项目也能有钉钉同款审批流设计器:npm 装包,10 分钟画出第一条审批流
前端·vue.js
2分钟速写快排2 小时前
什么是 RAG?如何用 RAG 实现一个用户记忆?
前端·后端·ai编程
passerby60612 小时前
如何自己造一个时间处理库
前端·javascript·github
走到天涯海角3 小时前
react里面的长列表渲染优化
前端·react.js·前端框架
小羊没烦恼!3 小时前
Hello Web API系列教程——Web API与国际化
java·服务器·前端·javascript·php
北岛贰4 小时前
迷茫焦虑期,我做了一个带支付带官网的 AI 聊天虚拟恋人 App
前端·人工智能·后端
mayaairi5 小时前
Vue2 组件通讯(三):全局事件总线、PubSub、插槽与组件实例属性
前端·javascript·vue.js
kyriewen6 小时前
面试官问我:AI 都能写代码了,前端凭什么还值 25K
前端·javascript·人工智能
风骏时光牛马6 小时前
AI源码分析:拆解模型底层实现逻辑
前端
IT_陈寒7 小时前
React子组件莫名其妙重渲染?你可能漏了这个Hook
前端·人工智能·后端