THREE.js - add THREE.SkinnedMesh to the custom skeleton structure

I am trying to define a human body model in THREE.js using the classes THREE.Bone , THREE.Skeleton and THREE.SkinnedMesh .

I defined a custom skeleton structure consisting of 12 body parts, each of which is an instance of THREE.Bone , and used the .add() method to determine the relationship between parents and children among them. Finally, I created the standard THREE.Object3D as the root of the body, which is the parent of the complete skeleton.

Posting only parts of the structure for short:

 // 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 very well, and after loading the page, I can access the model and test it correctly through the console.

However, when I try to display the skeleton in the scene, everything becomes complicated.

1. How to add THREE.SkinnedMesh for custom skeleton structure?

In the documentation (check the source code) CylinderGeometry and a SkinnedMesh are created for all bones together

 var geometry = new THREE.CylinderGeometry( 5, 5, 5, 5, 15, 5, 30 ); var mesh = THREE.SkinnedMesh( geometry, material ); 

and then the bone structure binds:

 // 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 fine for a simple example in the documentation (5 bones of each parent of the next), but how can I adapt this example to a more complex structure in which some bones have several children? And how can I implement bones with different geometry? For example, I would like to use joints such as the shoulder and elbow, with a sphere for which I can only change the rotation and parts of the body, such as the arm and forearm, with cylinders having different radii of the base.

Is it possible to define SkinnedMesh for each joint independently and for a more complex structure than that shown in the example? If so, how do you tie them all together?

2. Can I add THREE.SkeletonHelper to the scene without defining a skin mesh, but using only bones?

Since I do not know the answer to question 1, I decided to just try to display the structure of the skeleton. This is done in other examples (like this one ) by creating an instance of THREE.SkeletonHelper and adding it to the scene.

I tried passing the body_root variable (instead of SkinnedMesh ) to the constructor, and the helper was created but not displayed.

 helper = new THREE.SkeletonHelper( body_root ); helper.material.linewidth = 3; scene.add( helper ); 

To visualize the assistant, it must be attached to the grid, even if the grid is not added directly to the scene, i.e. adding a mesh.bind(armSkeleton) line mesh.bind(armSkeleton) renders the helper skeleton.

Is it possible to render the helper skeleton at all without defining a grid? If so, how?

NOTE on Question 2:

I believe that this should be possible, since the THREE.SkeletonHelper class defines its own geometry and material internally, so it can be done without the need for a skeleton grid:

 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(); }; 
+6
source share

All Articles