参考学习
http://www.yanhuangxueyuan.com/doc/Three.js/Group.html
https://blog.csdn.net/ithanmang/article/details/80965712
http://www.yanhuangxueyuan.com/Three.js/
https://www.cnblogs.com/guxingy/p/11956390.html
https://www.cnblogs.com/richardwlee/p/10573663.html
一.概念
以机器人模型说明层级概念,一个整体机器人通过一个组对象Group1
,然后一条腿用一个组对象Group2
表示,一条腿假设包含大腿和小腿两个网格模型Mesh
,则大腿和小腿的两个网格对象可以作为父对象腿Group2
的两个子对象,Group2
表示的两条腿又可以作为机器人Group1
的两个子对象,层级如下
机器人-腿-大腿,小腿 三个层级。
如果跟对象机器人位置变化,腿也会变化。Mesh
如果是Group
的子对象,则,Mesh
会随着Group
变化。
Group
的基类是Object3D
,可以通过Object3D
创建一个父对象。建议使用Group
作为点,线,网络等模型的父对象。
二.add()和.remove()方法
1.add()
var mesh = new THREE.Mesh();
var group = new THREE.Group();
//将网格模型添加到组中,是group的子对象
group.add(mesh);
//group添加到场景中, group作为场景的子对象
scene.add(group);
//如果有多个可以同时插入多个
group.add(mesh1,mesh2);
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 THREE.Group();
headGroup.name = "头部"
headGroup.add(headMesh, leftEyeMesh, rightEyeMesh);
2.remove()
场景Scene或组对象Group的.remove()方法使用规则可以查看它们的基类Object3D。
scene.remove(light, group);
只去掉灯光就黑黑的
三.递归遍历方法.traverse()
可以通过递归遍历的算法去遍历Threejs一个模型对象的所有后代,可以通过下面代码递归遍历上面创建一个机器人模型或者一个外部加载的三维模型。
scene.traverse(function(obj){
if(obj.type === "Group"){
console.log(obj.name);
}
console.log(obj.id);
console.log(obj.parent);
console.log(obj.childeren);
})
四.查找某个模型
// 遍历查找对象的子对象,返回name对应的对象(name是可以重名的,返回第一个)
var nameNode = scene.getObjectByName("leftLeg");
nameNode.material.color.set(0xff0000);
// 遍历查找对象的子对象,并返回id对应的对象
var idNode = scene.getObjectById(4);
console.log(idNode);
例子
设置mesh的名字为“hello”,让名为hello的mesh变绿色
var mesh = new THREE.Mesh(new THREE.CubeGeometry(5, 10, 20),
new THREE.MeshLambertMaterial({
color: 0xffff00
})
);
scene.add(mesh);
mesh.material = new THREE.MeshLambertMaterial({
color:0xff0000
});
mesh.position.set(10,10,10);
mesh.scale.set(0.1,0.1,0.1);
mesh.rotation.x = 90;
mesh.name = "hello";
var group = new THREE.Group();
group.name = "test";
group.add(mesh);
scene.add(group);
}
var nameNode = scene.getObjectByName("hello");
nameNode.material.color.set(0x00ff00);
五.外部模型拾取时的Group问题
参考:
https://blog.csdn.net/ithanmang/article/details/80965712
在解析外部模型例如 obj
模型的时候我们经常会发现、匿名函数中的加载解析后的参数object是一个Group
,或者当前我们加载外部模型obj
为例,然后通过Raycaster射线拾取数组的时候对象,当传递进去是scene.children
发现并不会选中模型,但我们自己创建一些简单的模型会被选中。
这是因为,加载的外部模型会是在一个Group
组对象中,如果直接scene.children
是无法获取的,我们自己创建的模型并没有放进Group
中,是属于scene.children
的,所以可以获取到。 例如我们加载一个obj
模型,看下他的children
属性。
页面加载后的Scene
对象
children
是一个数组类型,有三个元素,两个灯光,一个Group
对象,其中Group
对象中的数据就是obj
模型。
例子
var geometry = new THREE.BoxBufferGeometry( 1, 1, 1 );
var material = new THREE.MeshBasicMaterial( {color: 0x00ff00} );
var cubeA = new THREE.Mesh( geometry, material );
cubeA.position.set( 100, 100, 0 );
var cubeB = new THREE.Mesh( geometry, material );
cubeB.position.set( -100, -100, 0 );
//创建一个组对象,添加两个立方体
//作为一个组对象这些立方体对象可以被旋转、缩放、等等...
var group = new THREE.Group();
group.add( cubeA );
group.add( cubeB );
scene.add( group );
构造函数
这里没看明白
function Group() {
Object3D.call( this );
this.type = 'Group';
}
Group.prototype = Object.assign( Object.create( Object3D.prototype ), {
constructor: Group,
isGroup: true
} );
参考Object3D对象中的,公共方法。
.type string返回对象的类型。
问题待解决
如何使用Raycaster拾取到Group对象