我尝试使用THREE.Bone
,THREE.Skeleton
和THREE.SkinnedMesh
类在THREE.js
中定义人体模型。
我定义了一个由12个正文部分组成的自定义骨架结构,每个部分都是THREE.Bone
个实例,并使用.add()
方法定义它们之间的父/子关系。最后,我创建了一个标准THREE.Object3D
作为完整骨架父体的体根。
仅发布结构的一部分以简洁:
// create person object
var body_root = new THREE.Object3D()
// create torso
var torso = new THREE.Bone();
torso.id = 1;
torso.name = "torso";
x_t = 0;
y_t = 0;
z_t = 0;
torso.position.set(x_t,y_t,z_t);
x_alpha = 0 * Math.PI;
y_alpha = 0 * Math.PI;
z_alpha = 0 * Math.PI;
torso.rotation.set(x_alpha,y_alpha,z_alpha);
// create right arm
var right_arm = new THREE.Bone();
right_arm.id = 2;
right_arm.name = "right_arm";
x_t = -TORSO_WIDTH / 2;
y_t = TORSO_HEIGHT;
z_t = 0;
right_arm.position.set(x_t,y_t,z_t);
x_alpha = 0 * Math.PI;
y_alpha = 0 * Math.PI;
z_alpha = 0 * Math.PI;
right_arm.rotation.set(x_alpha,y_alpha,z_alpha);
// add right_arm as child of torso
torso.add( right_arm );
这很好用,加载页面后我可以访问模型并通过控制台正确遍历它。
然而,当我尝试在场景中渲染骨架时,事情变得棘手。
1。如何为自定义骨架结构添加THREE.SkinnedMesh
?
在documentation(查看源代码)中,为所有骨骼共同创建CylinderGeometry
和SkinnedMesh
var geometry = new THREE.CylinderGeometry( 5, 5, 5, 5, 15, 5, 30 );
var mesh = THREE.SkinnedMesh( geometry, material );
然后骨骼结构绑定:
// See example from THREE.Skeleton for the armSkeleton
var rootBone = armSkeleton.bones[ 0 ];
mesh.add( rootBone );
// Bind the skeleton to the mesh
mesh.bind( armSkeleton );
这非常适用于文档中的简单示例(下一个的每个父节点共有5个骨骼),但是如何将此示例调整为更复杂的结构,其中一些骨骼有多个子节点?我如何实现具有不同几何形状的骨骼?例如,我想实现像肩膀和肘关节这样的关节,我只能用不同基底半径的圆柱来改变旋转和身体部位,如手臂和前臂。
是否可以单独为每个关节定义SkinnedMesh,并且结构比示例中的更复杂?如果是这样,你怎么把它们连在一起呢?
2。我是否可以在不定义蒙皮网格的情况下向场景添加THREE.SkeletonHelper
但仅使用骨骼?
由于我不知道问题1的答案,所以我决定简单地尝试渲染骨架结构。通过创建THREE.SkeletonHelper
实例并将其添加到场景中,可以在其他示例(例如this one)中完成此操作。
我尝试将body_root
变量(而不是SkinnedMesh
)传递给构造函数,并创建了帮助程序,但未呈现。
helper = new THREE.SkeletonHelper( body_root );
helper.material.linewidth = 3;
scene.add( helper );
为了可视化帮助器,它需要绑定到网格物体,即使网格没有直接添加到场景中,即添加线mesh.bind(armSkeleton)
也可以看到骨架帮助器。
这是否可以在不定义网格的情况下可视化骨架帮助器?如果是这样的话?
关于问题2的注释:
我相信这应该是可能的,因为THREE.SkeletonHelper
类在内部定义了自己的几何和材质,所以应该可以渲染它而不需要骨架的网格:
THREE.SkeletonHelper = function ( object ) {
this.bones = this.getBoneList( object );
var geometry = new THREE.Geometry();
for ( var i = 0; i < this.bones.length; i ++ ) {
var bone = this.bones[ i ];
if ( bone.parent instanceof THREE.Bone ) {
geometry.vertices.push( new THREE.Vector3() );
geometry.vertices.push( new THREE.Vector3() );
geometry.colors.push( new THREE.Color( 0, 0, 1 ) );
geometry.colors.push( new THREE.Color( 0, 1, 0 ) );
}
}
geometry.dynamic = true;
var material = new THREE.LineBasicMaterial( { vertexColors: THREE.VertexColors, depthTest: false, depthWrite: false, transparent: true } );
THREE.LineSegments.call( this, geometry, material );
this.root = object;
this.matrix = object.matrixWorld;
this.matrixAutoUpdate = false;
this.update();
};