170 lines
3.2 KiB
JavaScript
170 lines
3.2 KiB
JavaScript
/**
|
|
* @author mikael emtinger / http://gomo.se/
|
|
* @author alteredq / http://alteredqualia.com/
|
|
* @author ikerr / http://verold.com
|
|
*/
|
|
|
|
THREE.SkinnedMesh = function ( geometry, material, useVertexTexture ) {
|
|
|
|
THREE.Mesh.call( this, geometry, material );
|
|
|
|
this.type = 'SkinnedMesh';
|
|
|
|
this.bindMode = "attached";
|
|
this.bindMatrix = new THREE.Matrix4();
|
|
this.bindMatrixInverse = new THREE.Matrix4();
|
|
|
|
// init bones
|
|
|
|
// TODO: remove bone creation as there is no reason (other than
|
|
// convenience) for THREE.SkinnedMesh to do this.
|
|
|
|
var bones = [];
|
|
|
|
if ( this.geometry && this.geometry.bones !== undefined ) {
|
|
|
|
var bone, gbone, p, q, s;
|
|
|
|
for ( var b = 0, bl = this.geometry.bones.length; b < bl; ++ b ) {
|
|
|
|
gbone = this.geometry.bones[ b ];
|
|
|
|
p = gbone.pos;
|
|
q = gbone.rotq;
|
|
s = gbone.scl;
|
|
|
|
bone = new THREE.Bone( this );
|
|
bones.push( bone );
|
|
|
|
bone.name = gbone.name;
|
|
bone.position.set( p[ 0 ], p[ 1 ], p[ 2 ] );
|
|
bone.quaternion.set( q[ 0 ], q[ 1 ], q[ 2 ], q[ 3 ] );
|
|
|
|
if ( s !== undefined ) {
|
|
|
|
bone.scale.set( s[ 0 ], s[ 1 ], s[ 2 ] );
|
|
|
|
} else {
|
|
|
|
bone.scale.set( 1, 1, 1 );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for ( var b = 0, bl = this.geometry.bones.length; b < bl; ++ b ) {
|
|
|
|
gbone = this.geometry.bones[ b ];
|
|
|
|
if ( gbone.parent !== - 1 ) {
|
|
|
|
bones[ gbone.parent ].add( bones[ b ] );
|
|
|
|
} else {
|
|
|
|
this.add( bones[ b ] );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
this.normalizeSkinWeights();
|
|
|
|
this.updateMatrixWorld( true );
|
|
this.bind( new THREE.Skeleton( bones, undefined, useVertexTexture ) );
|
|
|
|
};
|
|
|
|
|
|
THREE.SkinnedMesh.prototype = Object.create( THREE.Mesh.prototype );
|
|
THREE.SkinnedMesh.prototype.constructor = THREE.SkinnedMesh;
|
|
|
|
THREE.SkinnedMesh.prototype.bind = function( skeleton, bindMatrix ) {
|
|
|
|
this.skeleton = skeleton;
|
|
|
|
if ( bindMatrix === undefined ) {
|
|
|
|
this.updateMatrixWorld( true );
|
|
|
|
bindMatrix = this.matrixWorld;
|
|
|
|
}
|
|
|
|
this.bindMatrix.copy( bindMatrix );
|
|
this.bindMatrixInverse.getInverse( bindMatrix );
|
|
|
|
};
|
|
|
|
THREE.SkinnedMesh.prototype.pose = function () {
|
|
|
|
this.skeleton.pose();
|
|
|
|
};
|
|
|
|
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.updateMatrixWorld = function( force ) {
|
|
|
|
THREE.Mesh.prototype.updateMatrixWorld.call( this, true );
|
|
|
|
if ( this.bindMode === "attached" ) {
|
|
|
|
this.bindMatrixInverse.getInverse( this.matrixWorld );
|
|
|
|
} else if ( this.bindMode === "detached" ) {
|
|
|
|
this.bindMatrixInverse.getInverse( this.bindMatrix );
|
|
|
|
} else {
|
|
|
|
THREE.warn( 'THREE.SkinnedMesh unreckognized bindMode: ' + this.bindMode );
|
|
|
|
}
|
|
|
|
};
|
|
|
|
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;
|
|
|
|
};
|
|
|