| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164 |
- /**
- * @author mikael emtinger / http://gomo.se/
- * @author alteredq / http://alteredqualia.com/
- */
- THREE.SkinnedMesh = function ( geometry, material, useVertexTexture ) {
- THREE.Mesh.call( this, geometry, material );
- this.skeleton = new THREE.Skeleton( this.geometry && this.geometry.bones, useVertexTexture );
- // Add root level bones as children of the mesh
- for ( var b = 0; b < this.skeleton.bones.length; ++b ) {
- var bone = this.skeleton.bones[ b ];
- if ( bone.parent === undefined ) {
- this.add( bone );
- }
- }
- this.identityMatrix = new THREE.Matrix4();
- this.pose();
- };
- THREE.SkinnedMesh.prototype = Object.create( THREE.Mesh.prototype );
- THREE.SkinnedMesh.prototype.updateMatrixWorld = function () {
- var offsetMatrix = new THREE.Matrix4();
- return function ( force ) {
- this.matrixAutoUpdate && this.updateMatrix();
- // update matrixWorld
- if ( this.matrixWorldNeedsUpdate || force ) {
- if ( this.parent ) {
- this.matrixWorld.multiplyMatrices( this.parent.matrixWorld, this.matrix );
- } else {
- this.matrixWorld.copy( this.matrix );
- }
- this.matrixWorldNeedsUpdate = false;
- force = true;
- }
- // update children
- for ( var i = 0, l = this.children.length; i < l; i ++ ) {
- var child = this.children[ i ];
- if ( child instanceof THREE.Bone ) {
- child.update( this.identityMatrix, false );
- } else {
- child.updateMatrixWorld( true );
- }
- }
- // make a snapshot of the bones' rest position
- if ( this.skeleton.boneInverses === undefined ) {
- this.skeleton.calculateInverses();
- }
- // flatten bone matrices to array
- for ( var b = 0, bl = this.skeleton.bones.length; b < bl; b ++ ) {
- // compute the offset between the current and the original transform;
- // TODO: we could get rid of this multiplication step if the skinMatrix
- // was already representing the offset; however, this requires some
- // major changes to the animation system
- offsetMatrix.multiplyMatrices( this.skeleton.bones[ b ].skinMatrix, this.skeleton.boneInverses[ b ] );
- offsetMatrix.flattenToArrayOffset( this.skeleton.boneMatrices, b * 16 );
- }
- if ( this.skeleton.useVertexTexture ) {
- this.skeleton.boneTexture.needsUpdate = true;
- }
- };
- }();
- THREE.SkinnedMesh.prototype.pose = function () {
- this.updateMatrixWorld( true );
- this.normalizeSkinWeights();
- };
- THREE.SkinnedMesh.prototype.normalizeSkinWeights = function () {
- if ( this.geometry instanceof THREE.Geometry ) {
- for ( var i = 0; i < this.geometry.skinIndices.length; i ++ ) {
- var sw = this.geometry.skinWeights[ i ];
- var scale = 1.0 / sw.lengthManhattan();
- if ( scale !== Infinity ) {
- sw.multiplyScalar( scale );
- } else {
- sw.set( 1 ); // this will be normalized by the shader anyway
- }
- }
- } else {
- // skinning weights assumed to be normalized for THREE.BufferGeometry
- }
- };
- THREE.SkinnedMesh.prototype.clone = function ( object ) {
- if ( object === undefined ) {
- object = new THREE.SkinnedMesh( this.geometry, this.material, this.useVertexTexture );
- }
- THREE.Mesh.prototype.clone.call( this, object );
- return object;
- };
|