Files
three.js/src/objects/SkinnedMesh.js
T
alteredq f4fe695d9a First somehow working version ;).
Just one hardcoded shader for the moment. Everything needs to get cleaned / bugfixed / optimized.
2011-02-17 00:27:42 +01:00

216 lines
4.9 KiB
JavaScript

/**
* @author mikael emtinger / http://gomo.se/
*/
// do not crash if somebody includes the file in oldie browser
if ( !window.Float32Array ) {
window.Float32Array = Array;
}
THREE.SkinnedMesh = function( geometry, materials ) {
THREE.Mesh.call( this, geometry, materials );
// init bones
this.identityMatrix = new THREE.Matrix4();
this.bones = [];
this.boneMatrices = [];
if( this.geometry.bones !== undefined ) {
for( var b = 0; b < this.geometry.bones.length; b++ ) {
var bone = this.addBone();
bone.name = this.geometry.bones[ b ].name;
bone.position.x = this.geometry.bones[ b ].pos [ 0 ];
bone.position.y = this.geometry.bones[ b ].pos [ 1 ];
bone.position.z = this.geometry.bones[ b ].pos [ 2 ];
bone.quaternion.x = this.geometry.bones[ b ].rotq[ 0 ];
bone.quaternion.y = this.geometry.bones[ b ].rotq[ 1 ];
bone.quaternion.z = this.geometry.bones[ b ].rotq[ 2 ];
bone.quaternion.w = this.geometry.bones[ b ].rotq[ 3 ];
bone.scale.x = this.geometry.bones[ b ].scl !== undefined ? this.geometry.bones[ b ].scl[ 0 ] : 1;
bone.scale.y = this.geometry.bones[ b ].scl !== undefined ? this.geometry.bones[ b ].scl[ 1 ] : 1;
bone.scale.z = this.geometry.bones[ b ].scl !== undefined ? this.geometry.bones[ b ].scl[ 2 ] : 1;
}
for( var b = 0; b < this.bones.length; b++ ) {
if( this.geometry.bones[ b ].parent === -1 )
this.addChild( this.bones[ b ] );
else
this.bones[ this.geometry.bones[ b ].parent ].addChild( this.bones[ b ] );
}
//this.boneMatrices = new Float32Array( 16 * this.bones.length );
this.pose();
}
};
THREE.SkinnedMesh.prototype = new THREE.Mesh();
THREE.SkinnedMesh.prototype.constructor = THREE.SkinnedMesh;
/*
* Update
*/
THREE.SkinnedMesh.prototype.update = function( parentGlobalMatrix, forceUpdate, camera, renderer ) {
// visible?
if( this.visible ) {
// update local
if( this.autoUpdateMatrix )
forceUpdate |= this.updateMatrix();
// update global
if( forceUpdate || this.matrixNeedsToUpdate ) {
if( parentGlobalMatrix )
this.globalMatrix.multiply( parentGlobalMatrix, this.localMatrix );
else
this.globalMatrix.copy( this.localMatrix );
this.matrixNeedsToUpdate = false;
forceUpdate = true;
// update normal
this.normalMatrix = THREE.Matrix4.makeInvert3x3( this.globalMatrix ).transpose();
}
// update children
for( var i = 0; i < this.children.length; i++ )
if( this.children[ i ] instanceof THREE.Bone )
this.children[ i ].update( this.identityMatrix, false, camera, renderer );
else
this.children[ i ].update( this.globalMatrix, forceUpdate, camera, renderer );
// check camera frustum and add to render list
if( renderer && camera ) {
if( camera.frustumContains( this ) )
renderer.addToRenderList( this );
else
renderer.removeFromRenderList( this );
}
} else {
renderer.removeFromRenderList( this );
}
};
/*
* Add
*/
THREE.SkinnedMesh.prototype.addBone = function( bone ) {
if( bone === undefined )
bone = new THREE.Bone( this );
this.bones.push( bone );
return bone;
};
/*
* Pose
*/
THREE.SkinnedMesh.prototype.pose = function() {
this.update( undefined, true );
var bim, bone,
boneInverses = [];
for( var b = 0; b < this.bones.length; b++ ) {
boneInverses.push( THREE.Matrix4.makeInvert( this.bones[ b ].skinMatrix, new THREE.Matrix4() ) );
this.boneMatrices.push( this.bones[ b ].skinMatrix.flatten32 );
/*
bone = this.bones[ b ];
boneInverses.push( THREE.Matrix4.makeInvert( bone.skinMatrix ) );
bim = new Float32Array( 16 );
bone.skinMatrix.flattenToArray( bim );
this.boneMatrices.push( bim );
//bone.skinMatrix.flattenToArrayOffset( this.boneMatrices, b * 16 );
*/
}
// project vertices to local
if( this.geometry.skinVerticesA === undefined ) {
this.geometry.skinVerticesA = [];
this.geometry.skinVerticesB = [];
var orgVertex;
var vertex;
for( var i = 0; i < this.geometry.skinIndices.length; i++ ) {
orgVertex = this.geometry.vertices[ i ].position;
var indexA = this.geometry.skinIndices[ i ].x;
var indexB = this.geometry.skinIndices[ i ].y;
vertex = new THREE.Vector3( orgVertex.x, orgVertex.y, orgVertex.z );
this.geometry.skinVerticesA.push( boneInverses[ indexA ].multiplyVector3( vertex ) );
vertex = new THREE.Vector3( orgVertex.x, orgVertex.y, orgVertex.z );
this.geometry.skinVerticesB.push( boneInverses[ indexB ].multiplyVector3( vertex ) );
// todo: add more influences
// normalize weights
if( this.geometry.skinWeights[ i ].x + this.geometry.skinWeights[ i ].y !== 1 ) {
var len = ( 1.0 - ( this.geometry.skinWeights[ i ].x + this.geometry.skinWeights[ i ].y )) * 0.5;
this.geometry.skinWeights[ i ].x += len;
this.geometry.skinWeights[ i ].y += len;
}
}
}
};