I'm trying to define a model of the human body in THREE.js
using the classes THREE.Bone
, THREE.Skeleton
and THREE.SkinnedMesh
.
I defined a custom skeleton structure made of 12 body parts, each of which is a THREE.Bone
instance, and used the .add()
method to define parent / child relationships among them. Finally, I created a standard THREE.Object3D
as the body root that is parent of the full skeleton.
Posting only part of the structure for conciseness:
// 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 );
This works just fine, and after loading the page I can access the model and traverse it correctly through the console.
However, when I try to render the skeleton in the scene things get tricky.
1. How can I add a THREE.SkinnedMesh
for a custom skeleton structure?
In the documentation (check source code) a CylinderGeometry
and a SkinnedMesh
are created for all the bones jointly
var geometry = new THREE.CylinderGeometry( 5, 5, 5, 5, 15, 5, 30 ); var mesh = THREE.SkinnedMesh( geometry, material );
and then the bone structure is binded:
// 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 );
This works perfectly for the simple example in the documentation (5 bones each one parent of the next one), but how can I adapt this example to a more complex structure in which some bones have multiple children? And how can I implement bones with different geometry? For instance I would like to implement joints like shoulder and elbow with a sphere for which I can only change rotation and body parts like arm and forearm with cylinders having different base radius.
Is it possible to define a SkinnedMesh for each joint independently and for a more complex structure than the one in the example? If so how do you link them all together?
2. Can I add a THREE.SkeletonHelper
to the scene without defining a skinned mesh but using only the bones?
Since I don't know the answer to question 1 I decided to simply try to render the skeleton structure. This is done in other examples (such as this one) by creating a THREE.SkeletonHelper
instance and adding that to the scene.
I tried passing the body_root
variable (instead of the SkinnedMesh
) to the constructor and the helper is created, but not rendered.
helper = new THREE.SkeletonHelper( body_root ); helper.material.linewidth = 3; scene.add( helper );
In order to visualize the helper it needs to be binded to a mesh, even if the mesh is not added directly to the scene, i.e. adding the line mesh.bind(armSkeleton)
visualizes the skeleton helper.
Is this possible at all to visualize the skeleton helper without defining a mesh? If so how?
NOTE on question 2:
I believe this should be possible, since the THREE.SkeletonHelper
class defines internally its own geometry and material, so it should be possible to render it without needing the mesh of the skeleton:
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(); };
0 comments:
Post a Comment