|
@@ -14953,6 +14953,7 @@ THREE.Mesh.prototype.clone = function ( object, recursive ) {
|
|
|
/**
|
|
|
* @author mikael emtinger / http://gomo.se/
|
|
|
* @author alteredq / http://alteredqualia.com/
|
|
|
+ * @author ikerr / http://verold.com
|
|
|
*/
|
|
|
|
|
|
THREE.Bone = function ( belongsToSkin ) {
|
|
@@ -14960,7 +14961,6 @@ THREE.Bone = function ( belongsToSkin ) {
|
|
|
THREE.Object3D.call( this );
|
|
|
|
|
|
this.skin = belongsToSkin;
|
|
|
- this.skinMatrix = new THREE.Matrix4();
|
|
|
|
|
|
this.accumulatedRotWeight = 0;
|
|
|
this.accumulatedPosWeight = 0;
|
|
@@ -14970,310 +14970,302 @@ THREE.Bone = function ( belongsToSkin ) {
|
|
|
|
|
|
THREE.Bone.prototype = Object.create( THREE.Object3D.prototype );
|
|
|
|
|
|
-THREE.Bone.prototype.update = function ( parentSkinMatrix, forceUpdate ) {
|
|
|
+THREE.Bone.prototype.updateMatrixWorld = function ( force ) {
|
|
|
|
|
|
- // update local
|
|
|
+ THREE.Object3D.prototype.updateMatrixWorld.call( this, force );
|
|
|
|
|
|
- if ( this.matrixAutoUpdate ) {
|
|
|
+ // Reset weights to be re-accumulated in the next frame
|
|
|
|
|
|
- forceUpdate |= this.updateMatrix();
|
|
|
+ this.accumulatedRotWeight = 0;
|
|
|
+ this.accumulatedPosWeight = 0;
|
|
|
+ this.accumulatedSclWeight = 0;
|
|
|
|
|
|
- }
|
|
|
+};
|
|
|
|
|
|
- // update skin matrix
|
|
|
|
|
|
- if ( forceUpdate || this.matrixWorldNeedsUpdate ) {
|
|
|
+// File:src/objects/Skeleton.js
|
|
|
|
|
|
- if ( parentSkinMatrix ) {
|
|
|
+/**
|
|
|
+ * @author mikael emtinger / http://gomo.se/
|
|
|
+ * @author alteredq / http://alteredqualia.com/
|
|
|
+ * @author michael guerrero / http://realitymeltdown.com
|
|
|
+ * @author ikerr / http://verold.com
|
|
|
+ */
|
|
|
|
|
|
- this.skinMatrix.multiplyMatrices( parentSkinMatrix, this.matrix );
|
|
|
+THREE.Skeleton = function ( bones, boneInverses, useVertexTexture ) {
|
|
|
|
|
|
- } else {
|
|
|
+ this.useVertexTexture = useVertexTexture !== undefined ? useVertexTexture : true;
|
|
|
|
|
|
- this.skinMatrix.copy( this.matrix );
|
|
|
+ this.identityMatrix = new THREE.Matrix4();
|
|
|
|
|
|
- }
|
|
|
+ // copy the bone array
|
|
|
|
|
|
- this.matrixWorldNeedsUpdate = false;
|
|
|
- forceUpdate = true;
|
|
|
+ bones = bones || [];
|
|
|
|
|
|
- // Reset weights to be re-accumulated in the next frame
|
|
|
+ this.bones = bones.slice( 0 );
|
|
|
|
|
|
- this.accumulatedRotWeight = 0;
|
|
|
- this.accumulatedPosWeight = 0;
|
|
|
- this.accumulatedSclWeight = 0;
|
|
|
+ // create a bone texture or an array of floats
|
|
|
|
|
|
- }
|
|
|
+ if ( this.useVertexTexture ) {
|
|
|
|
|
|
- // update children
|
|
|
+ // layout (1 matrix = 4 pixels)
|
|
|
+ // RGBA RGBA RGBA RGBA (=> column1, column2, column3, column4)
|
|
|
+ // with 8x8 pixel texture max 16 bones (8 * 8 / 4)
|
|
|
+ // 16x16 pixel texture max 64 bones (16 * 16 / 4)
|
|
|
+ // 32x32 pixel texture max 256 bones (32 * 32 / 4)
|
|
|
+ // 64x64 pixel texture max 1024 bones (64 * 64 / 4)
|
|
|
|
|
|
- for ( var i = 0, l = this.children.length; i < l; i ++ ) {
|
|
|
+ var size;
|
|
|
|
|
|
- this.children[ i ].update( this.skinMatrix, forceUpdate );
|
|
|
+ if ( this.bones.length > 256 )
|
|
|
+ size = 64;
|
|
|
+ else if ( this.bones.length > 64 )
|
|
|
+ size = 32;
|
|
|
+ else if ( this.bones.length > 16 )
|
|
|
+ size = 16;
|
|
|
+ else
|
|
|
+ size = 8;
|
|
|
|
|
|
- }
|
|
|
+ this.boneTextureWidth = size;
|
|
|
+ this.boneTextureHeight = size;
|
|
|
|
|
|
-};
|
|
|
+ this.boneMatrices = new Float32Array( this.boneTextureWidth * this.boneTextureHeight * 4 ); // 4 floats per RGBA pixel
|
|
|
+ this.boneTexture = new THREE.DataTexture( this.boneMatrices, this.boneTextureWidth, this.boneTextureHeight, THREE.RGBAFormat, THREE.FloatType );
|
|
|
+ this.boneTexture.minFilter = THREE.NearestFilter;
|
|
|
+ this.boneTexture.magFilter = THREE.NearestFilter;
|
|
|
+ this.boneTexture.generateMipmaps = false;
|
|
|
+ this.boneTexture.flipY = false;
|
|
|
|
|
|
+ } else {
|
|
|
|
|
|
-// File:src/objects/Skeleton.js
|
|
|
+ this.boneMatrices = new Float32Array( 16 * this.bones.length );
|
|
|
|
|
|
-/**
|
|
|
- * @author mikael emtinger / http://gomo.se/
|
|
|
- * @author alteredq / http://alteredqualia.com/
|
|
|
- * @author michael guerrero / http://realitymeltdown.com
|
|
|
- */
|
|
|
+ }
|
|
|
|
|
|
-THREE.Skeleton = function ( boneList, useVertexTexture ) {
|
|
|
+ // use the supplied bone inverses or calculate the inverses
|
|
|
|
|
|
- this.useVertexTexture = useVertexTexture !== undefined ? useVertexTexture : true;
|
|
|
+ if ( boneInverses === undefined ) {
|
|
|
|
|
|
- // init bones
|
|
|
+ this.calculateInverses();
|
|
|
|
|
|
- this.bones = [];
|
|
|
- this.boneMatrices = [];
|
|
|
+ } else {
|
|
|
|
|
|
- var bone, gbone, p, q, s;
|
|
|
+ if ( this.bones.length === boneInverses.length ) {
|
|
|
|
|
|
- if ( boneList !== undefined ) {
|
|
|
+ this.boneInverses = boneInverses.slice( 0 );
|
|
|
|
|
|
- for ( var b = 0; b < boneList.length; ++b ) {
|
|
|
+ } else {
|
|
|
|
|
|
- gbone = boneList[ b ];
|
|
|
+ console.warn( 'THREE.Skeleton bonInverses is the wrong length.' );
|
|
|
|
|
|
- p = gbone.pos;
|
|
|
- q = gbone.rotq;
|
|
|
- s = gbone.scl;
|
|
|
+ this.boneInverses = [];
|
|
|
|
|
|
- bone = this.addBone();
|
|
|
+ for ( var b = 0, bl = this.bones.length; b < bl; b ++ ) {
|
|
|
|
|
|
- bone.name = gbone.name;
|
|
|
- bone.position.set( p[ 0 ], p[ 1 ], p[ 2 ] );
|
|
|
- bone.quaternion.set( q[ 0 ], q[ 1 ], q[ 2 ], q[ 3 ] );
|
|
|
+ this.boneInverses.push( new THREE.Matrix4() );
|
|
|
|
|
|
- if ( s !== undefined ) {
|
|
|
-
|
|
|
- bone.scale.set( s[ 0 ], s[ 1 ], s[ 2 ] );
|
|
|
+ }
|
|
|
|
|
|
- } else {
|
|
|
+ }
|
|
|
|
|
|
- bone.scale.set( 1, 1, 1 );
|
|
|
+ }
|
|
|
|
|
|
- }
|
|
|
+};
|
|
|
|
|
|
- }
|
|
|
+THREE.Skeleton.prototype.calculateInverses = function () {
|
|
|
|
|
|
- for ( var b = 0; b < boneList.length; ++b ) {
|
|
|
+ this.boneInverses = [];
|
|
|
|
|
|
- gbone = boneList[ b ];
|
|
|
+ for ( var b = 0, bl = this.bones.length; b < bl; b ++ ) {
|
|
|
|
|
|
- if ( gbone.parent !== - 1 ) {
|
|
|
+ var inverse = new THREE.Matrix4();
|
|
|
|
|
|
- this.bones[ gbone.parent ].add( this.bones[ b ] );
|
|
|
+ if ( this.bones[ b ] ) {
|
|
|
|
|
|
- }
|
|
|
+ inverse.getInverse( this.bones[ b ].matrixWorld );
|
|
|
|
|
|
}
|
|
|
|
|
|
- //
|
|
|
+ this.boneInverses.push( inverse );
|
|
|
|
|
|
- var nBones = this.bones.length;
|
|
|
+ }
|
|
|
|
|
|
- if ( this.useVertexTexture ) {
|
|
|
+};
|
|
|
|
|
|
- // layout (1 matrix = 4 pixels)
|
|
|
- // RGBA RGBA RGBA RGBA (=> column1, column2, column3, column4)
|
|
|
- // with 8x8 pixel texture max 16 bones (8 * 8 / 4)
|
|
|
- // 16x16 pixel texture max 64 bones (16 * 16 / 4)
|
|
|
- // 32x32 pixel texture max 256 bones (32 * 32 / 4)
|
|
|
- // 64x64 pixel texture max 1024 bones (64 * 64 / 4)
|
|
|
+THREE.Skeleton.prototype.pose = function () {
|
|
|
|
|
|
- var size;
|
|
|
+ var bone;
|
|
|
|
|
|
- if ( nBones > 256 )
|
|
|
- size = 64;
|
|
|
- else if ( nBones > 64 )
|
|
|
- size = 32;
|
|
|
- else if ( nBones > 16 )
|
|
|
- size = 16;
|
|
|
- else
|
|
|
- size = 8;
|
|
|
+ // recover the bind-time world matrices
|
|
|
|
|
|
- this.boneTextureWidth = size;
|
|
|
- this.boneTextureHeight = size;
|
|
|
+ for ( var b = 0, bl = this.bones.length; b < bl; b ++ ) {
|
|
|
|
|
|
- this.boneMatrices = new Float32Array( this.boneTextureWidth * this.boneTextureHeight * 4 ); // 4 floats per RGBA pixel
|
|
|
- this.boneTexture = new THREE.DataTexture( this.boneMatrices, this.boneTextureWidth, this.boneTextureHeight, THREE.RGBAFormat, THREE.FloatType );
|
|
|
- this.boneTexture.minFilter = THREE.NearestFilter;
|
|
|
- this.boneTexture.magFilter = THREE.NearestFilter;
|
|
|
- this.boneTexture.generateMipmaps = false;
|
|
|
- this.boneTexture.flipY = false;
|
|
|
+ bone = this.bones[ b ];
|
|
|
|
|
|
- } else {
|
|
|
+ if ( bone ) {
|
|
|
|
|
|
- this.boneMatrices = new Float32Array( 16 * nBones );
|
|
|
+ bone.matrixWorld.getInverse( this.boneInverses[ b ] );
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
-};
|
|
|
+ // compute the local matrices, positions, rotations and scales
|
|
|
|
|
|
+ for ( var b = 0, bl = this.bones.length; b < bl; b ++ ) {
|
|
|
|
|
|
-THREE.Skeleton.prototype = Object.create( THREE.Mesh.prototype );
|
|
|
+ bone = this.bones[ b ];
|
|
|
|
|
|
+ if ( bone ) {
|
|
|
|
|
|
-THREE.Skeleton.prototype.addBone = function ( bone ) {
|
|
|
+ if ( bone.parent ) {
|
|
|
|
|
|
- if ( bone === undefined ) {
|
|
|
+ bone.matrix.getInverse( bone.parent.matrixWorld );
|
|
|
+ bone.matrix.multiply( bone.matrixWorld );
|
|
|
|
|
|
- bone = new THREE.Bone( this );
|
|
|
+ }
|
|
|
+ else {
|
|
|
|
|
|
- }
|
|
|
+ bone.matrix.copy( bone.matrixWorld );
|
|
|
+
|
|
|
+ }
|
|
|
|
|
|
- this.bones.push( bone );
|
|
|
+ bone.matrix.decompose( bone.position, bone.quaternion, bone.scale );
|
|
|
|
|
|
- return bone;
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
|
|
|
};
|
|
|
|
|
|
+THREE.Skeleton.prototype.update = function () {
|
|
|
|
|
|
-THREE.Skeleton.prototype.calculateInverses = function () {
|
|
|
+ var offsetMatrix = new THREE.Matrix4();
|
|
|
|
|
|
- this.boneInverses = [];
|
|
|
+ // flatten bone matrices to array
|
|
|
|
|
|
- for ( var b = 0, bl = this.bones.length; b < bl; ++b ) {
|
|
|
+ for ( var b = 0, bl = this.bones.length; b < bl; b ++ ) {
|
|
|
|
|
|
- var inverse = new THREE.Matrix4();
|
|
|
+ // compute the offset between the current and the original transform
|
|
|
|
|
|
- inverse.getInverse( this.bones[ b ].skinMatrix );
|
|
|
+ var matrix = this.bones[ b ] ? this.bones[ b ].matrixWorld : this.identityMatrix;
|
|
|
|
|
|
- this.boneInverses.push( inverse );
|
|
|
+ offsetMatrix.multiplyMatrices( matrix, this.boneInverses[ b ] );
|
|
|
+ offsetMatrix.flattenToArrayOffset( this.boneMatrices, b * 16 );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ if ( this.useVertexTexture ) {
|
|
|
+
|
|
|
+ this.boneTexture.needsUpdate = true;
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
+
|
|
|
// File:src/objects/SkinnedMesh.js
|
|
|
|
|
|
/**
|
|
|
* @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.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.bindMode = "attached";
|
|
|
+ this.bindMatrix = new THREE.Matrix4();
|
|
|
+ this.bindMatrixInverse = new THREE.Matrix4();
|
|
|
|
|
|
- }
|
|
|
+ // init bones
|
|
|
|
|
|
- this.identityMatrix = new THREE.Matrix4();
|
|
|
+ // TODO: remove bone creation as there is no reason (other than
|
|
|
+ // convenience) for THREE.SkinnedMesh to do this.
|
|
|
|
|
|
- this.pose();
|
|
|
+ var bones = [];
|
|
|
|
|
|
-};
|
|
|
+ if ( this.geometry && this.geometry.bones !== undefined ) {
|
|
|
|
|
|
+ var bone, gbone, p, q, s;
|
|
|
|
|
|
-THREE.SkinnedMesh.prototype = Object.create( THREE.Mesh.prototype );
|
|
|
+ for ( var b = 0, bl = this.geometry.bones.length; b < bl; ++b ) {
|
|
|
|
|
|
-THREE.SkinnedMesh.prototype.updateMatrixWorld = function () {
|
|
|
+ gbone = this.geometry.bones[ b ];
|
|
|
|
|
|
- var offsetMatrix = new THREE.Matrix4();
|
|
|
-
|
|
|
- return function ( force ) {
|
|
|
-
|
|
|
- this.matrixAutoUpdate && this.updateMatrix();
|
|
|
+ p = gbone.pos;
|
|
|
+ q = gbone.rotq;
|
|
|
+ s = gbone.scl;
|
|
|
|
|
|
- // update matrixWorld
|
|
|
+ bone = new THREE.Bone( this );
|
|
|
+ bones.push( bone );
|
|
|
|
|
|
- if ( this.matrixWorldNeedsUpdate || force ) {
|
|
|
+ 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 ( this.parent ) {
|
|
|
+ if ( s !== undefined ) {
|
|
|
|
|
|
- this.matrixWorld.multiplyMatrices( this.parent.matrixWorld, this.matrix );
|
|
|
+ bone.scale.set( s[ 0 ], s[ 1 ], s[ 2 ] );
|
|
|
|
|
|
} else {
|
|
|
|
|
|
- this.matrixWorld.copy( this.matrix );
|
|
|
+ bone.scale.set( 1, 1, 1 );
|
|
|
|
|
|
}
|
|
|
|
|
|
- this.matrixWorldNeedsUpdate = false;
|
|
|
-
|
|
|
- force = true;
|
|
|
-
|
|
|
}
|
|
|
|
|
|
- // update children
|
|
|
-
|
|
|
- for ( var i = 0, l = this.children.length; i < l; i ++ ) {
|
|
|
+ for ( var b = 0, bl = this.geometry.bones.length; b < bl; ++b ) {
|
|
|
|
|
|
- var child = this.children[ i ];
|
|
|
+ gbone = this.geometry.bones[ b ];
|
|
|
|
|
|
- if ( child instanceof THREE.Bone ) {
|
|
|
+ if ( gbone.parent !== - 1 ) {
|
|
|
|
|
|
- child.update( this.identityMatrix, false );
|
|
|
+ bones[ gbone.parent ].add( bones[ b ] );
|
|
|
|
|
|
} else {
|
|
|
|
|
|
- child.updateMatrixWorld( true );
|
|
|
+ this.add( bones[ b ] );
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
- // make a snapshot of the bones' rest position
|
|
|
-
|
|
|
- if ( this.skeleton.boneInverses === undefined ) {
|
|
|
+ }
|
|
|
|
|
|
- this.skeleton.calculateInverses();
|
|
|
+ this.normalizeSkinWeights();
|
|
|
|
|
|
- }
|
|
|
+ this.updateMatrixWorld( true );
|
|
|
+ this.bind( new THREE.Skeleton( bones, undefined, useVertexTexture ) );
|
|
|
|
|
|
- // 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;
|
|
|
+THREE.SkinnedMesh.prototype = Object.create( THREE.Mesh.prototype );
|
|
|
|
|
|
- // 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
|
|
|
+THREE.SkinnedMesh.prototype.bind = function( skeleton, bindMatrix ) {
|
|
|
|
|
|
- offsetMatrix.multiplyMatrices( this.skeleton.bones[ b ].skinMatrix, this.skeleton.boneInverses[ b ] );
|
|
|
- offsetMatrix.flattenToArrayOffset( this.skeleton.boneMatrices, b * 16 );
|
|
|
+ this.skeleton = skeleton;
|
|
|
|
|
|
- }
|
|
|
+ if ( bindMatrix === undefined ) {
|
|
|
|
|
|
- if ( this.skeleton.useVertexTexture ) {
|
|
|
+ this.updateMatrixWorld( true );
|
|
|
|
|
|
- this.skeleton.boneTexture.needsUpdate = true;
|
|
|
+ bindMatrix = this.matrixWorld;
|
|
|
|
|
|
- }
|
|
|
+ }
|
|
|
|
|
|
- };
|
|
|
+ this.bindMatrix.copy( bindMatrix );
|
|
|
+ this.bindMatrixInverse.getInverse( bindMatrix );
|
|
|
|
|
|
-}();
|
|
|
+};
|
|
|
|
|
|
THREE.SkinnedMesh.prototype.pose = function () {
|
|
|
|
|
|
- this.updateMatrixWorld( true );
|
|
|
-
|
|
|
- this.normalizeSkinWeights();
|
|
|
+ this.skeleton.pose();
|
|
|
|
|
|
};
|
|
|
|
|
@@ -15307,7 +15299,27 @@ THREE.SkinnedMesh.prototype.normalizeSkinWeights = function () {
|
|
|
|
|
|
};
|
|
|
|
|
|
-THREE.SkinnedMesh.prototype.clone = function ( object ) {
|
|
|
+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 {
|
|
|
+
|
|
|
+ console.warn( 'THREE.SkinnedMesh unreckognized bindMode: ' + this.bindMode );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+};
|
|
|
+
|
|
|
+THREE.SkinnedMesh.prototype.clone = function( object ) {
|
|
|
|
|
|
if ( object === undefined ) {
|
|
|
|
|
@@ -15321,6 +15333,7 @@ THREE.SkinnedMesh.prototype.clone = function ( object ) {
|
|
|
|
|
|
};
|
|
|
|
|
|
+
|
|
|
// File:src/objects/MorphAnimMesh.js
|
|
|
|
|
|
/**
|
|
@@ -17002,7 +17015,7 @@ THREE.ShaderChunk[ 'map_pars_fragment'] = "#if defined( USE_MAP ) || defined( US
|
|
|
|
|
|
// File:src/renderers/shaders/ShaderChunk/skinnormal_vertex.glsl
|
|
|
|
|
|
-THREE.ShaderChunk[ 'skinnormal_vertex'] = "#ifdef USE_SKINNING\n\n mat4 skinMatrix = mat4( 0.0 );\n skinMatrix += skinWeight.x * boneMatX;\n skinMatrix += skinWeight.y * boneMatY;\n skinMatrix += skinWeight.z * boneMatZ;\n skinMatrix += skinWeight.w * boneMatW;\n\n #ifdef USE_MORPHNORMALS\n\n vec4 skinnedNormal = skinMatrix * vec4( morphedNormal, 0.0 );\n\n #else\n\n vec4 skinnedNormal = skinMatrix * vec4( normal, 0.0 );\n\n #endif\n\n#endif";
|
|
|
+THREE.ShaderChunk[ 'skinnormal_vertex'] = "#ifdef USE_SKINNING\n\n mat4 skinMatrix = mat4( 0.0 );\n skinMatrix += skinWeight.x * boneMatX;\n skinMatrix += skinWeight.y * boneMatY;\n skinMatrix += skinWeight.z * boneMatZ;\n skinMatrix += skinWeight.w * boneMatW;\n skinMatrix = bindMatrixInverse * skinMatrix * bindMatrix;\n\n #ifdef USE_MORPHNORMALS\n\n vec4 skinnedNormal = skinMatrix * vec4( morphedNormal, 0.0 );\n\n #else\n\n vec4 skinnedNormal = skinMatrix * vec4( normal, 0.0 );\n\n #endif\n\n#endif\n";
|
|
|
|
|
|
// File:src/renderers/shaders/ShaderChunk/logdepthbuf_pars_vertex.glsl
|
|
|
|
|
@@ -17074,7 +17087,7 @@ THREE.ShaderChunk[ 'color_vertex'] = "#ifdef USE_COLOR\n\n #ifdef GAMMA_INPUT\n\
|
|
|
|
|
|
// File:src/renderers/shaders/ShaderChunk/skinning_vertex.glsl
|
|
|
|
|
|
-THREE.ShaderChunk[ 'skinning_vertex'] = "#ifdef USE_SKINNING\n\n #ifdef USE_MORPHTARGETS\n\n vec4 skinVertex = vec4( morphed, 1.0 );\n\n #else\n\n vec4 skinVertex = vec4( position, 1.0 );\n\n #endif\n\n vec4 skinned = vec4( 0.0 );\n skinned += boneMatX * skinVertex * skinWeight.x;\n skinned += boneMatY * skinVertex * skinWeight.y;\n skinned += boneMatZ * skinVertex * skinWeight.z;\n skinned += boneMatW * skinVertex * skinWeight.w;\n\n#endif";
|
|
|
+THREE.ShaderChunk[ 'skinning_vertex'] = "#ifdef USE_SKINNING\n\n #ifdef USE_MORPHTARGETS\n\n vec4 skinVertex = bindMatrix * vec4( morphed, 1.0 );\n\n #else\n\n vec4 skinVertex = bindMatrix * vec4( position, 1.0 );\n\n #endif\n\n vec4 skinned = vec4( 0.0 );\n skinned += boneMatX * skinVertex * skinWeight.x;\n skinned += boneMatY * skinVertex * skinWeight.y;\n skinned += boneMatZ * skinVertex * skinWeight.z;\n skinned += boneMatW * skinVertex * skinWeight.w;\n skinned = bindMatrixInverse * skinned;\n\n#endif\n";
|
|
|
|
|
|
// File:src/renderers/shaders/ShaderChunk/envmap_pars_vertex.glsl
|
|
|
|
|
@@ -17174,7 +17187,7 @@ THREE.ShaderChunk[ 'shadowmap_pars_fragment'] = "#ifdef USE_SHADOWMAP\n\n unifor
|
|
|
|
|
|
// File:src/renderers/shaders/ShaderChunk/skinning_pars_vertex.glsl
|
|
|
|
|
|
-THREE.ShaderChunk[ 'skinning_pars_vertex'] = "#ifdef USE_SKINNING\n\n #ifdef BONE_TEXTURE\n\n uniform sampler2D boneTexture;\n uniform int boneTextureWidth;\n uniform int boneTextureHeight;\n\n mat4 getBoneMatrix( const in float i ) {\n\n float j = i * 4.0;\n float x = mod( j, float( boneTextureWidth ) );\n float y = floor( j / float( boneTextureWidth ) );\n\n float dx = 1.0 / float( boneTextureWidth );\n float dy = 1.0 / float( boneTextureHeight );\n\n y = dy * ( y + 0.5 );\n\n vec4 v1 = texture2D( boneTexture, vec2( dx * ( x + 0.5 ), y ) );\n vec4 v2 = texture2D( boneTexture, vec2( dx * ( x + 1.5 ), y ) );\n vec4 v3 = texture2D( boneTexture, vec2( dx * ( x + 2.5 ), y ) );\n vec4 v4 = texture2D( boneTexture, vec2( dx * ( x + 3.5 ), y ) );\n\n mat4 bone = mat4( v1, v2, v3, v4 );\n\n return bone;\n\n }\n\n #else\n\n uniform mat4 boneGlobalMatrices[ MAX_BONES ];\n\n mat4 getBoneMatrix( const in float i ) {\n\n mat4 bone = boneGlobalMatrices[ int(i) ];\n return bone;\n\n }\n\n #endif\n\n#endif";
|
|
|
+THREE.ShaderChunk[ 'skinning_pars_vertex'] = "#ifdef USE_SKINNING\n\n uniform mat4 bindMatrix;\n uniform mat4 bindMatrixInverse;\n\n #ifdef BONE_TEXTURE\n\n uniform sampler2D boneTexture;\n uniform int boneTextureWidth;\n uniform int boneTextureHeight;\n\n mat4 getBoneMatrix( const in float i ) {\n\n float j = i * 4.0;\n float x = mod( j, float( boneTextureWidth ) );\n float y = floor( j / float( boneTextureWidth ) );\n\n float dx = 1.0 / float( boneTextureWidth );\n float dy = 1.0 / float( boneTextureHeight );\n\n y = dy * ( y + 0.5 );\n\n vec4 v1 = texture2D( boneTexture, vec2( dx * ( x + 0.5 ), y ) );\n vec4 v2 = texture2D( boneTexture, vec2( dx * ( x + 1.5 ), y ) );\n vec4 v3 = texture2D( boneTexture, vec2( dx * ( x + 2.5 ), y ) );\n vec4 v4 = texture2D( boneTexture, vec2( dx * ( x + 3.5 ), y ) );\n\n mat4 bone = mat4( v1, v2, v3, v4 );\n\n return bone;\n\n }\n\n #else\n\n uniform mat4 boneGlobalMatrices[ MAX_BONES ];\n\n mat4 getBoneMatrix( const in float i ) {\n\n mat4 bone = boneGlobalMatrices[ int(i) ];\n return bone;\n\n }\n\n #endif\n\n#endif\n";
|
|
|
|
|
|
// File:src/renderers/shaders/ShaderChunk/logdepthbuf_pars_fragment.glsl
|
|
|
|
|
@@ -18496,13 +18509,14 @@ THREE.ShaderLib = {
|
|
|
|
|
|
" #ifdef USE_SKINNING",
|
|
|
|
|
|
- " vec4 skinVertex = vec4( position, 1.0 );",
|
|
|
+ " vec4 skinVertex = bindMatrix * vec4( position, 1.0 );",
|
|
|
|
|
|
" vec4 skinned = vec4( 0.0 );",
|
|
|
" skinned += boneMatX * skinVertex * skinWeight.x;",
|
|
|
" skinned += boneMatY * skinVertex * skinWeight.y;",
|
|
|
" skinned += boneMatZ * skinVertex * skinWeight.z;",
|
|
|
" skinned += boneMatW * skinVertex * skinWeight.w;",
|
|
|
+ " skinned = bindMatrixInverse * skinned;",
|
|
|
|
|
|
" displacedPosition = skinned.xyz;",
|
|
|
|
|
@@ -18518,13 +18532,14 @@ THREE.ShaderLib = {
|
|
|
|
|
|
" #ifdef USE_SKINNING",
|
|
|
|
|
|
- " vec4 skinVertex = vec4( position, 1.0 );",
|
|
|
+ " vec4 skinVertex = bindMatrix * vec4( position, 1.0 );",
|
|
|
|
|
|
" vec4 skinned = vec4( 0.0 );",
|
|
|
" skinned += boneMatX * skinVertex * skinWeight.x;",
|
|
|
" skinned += boneMatY * skinVertex * skinWeight.y;",
|
|
|
" skinned += boneMatZ * skinVertex * skinWeight.z;",
|
|
|
" skinned += boneMatW * skinVertex * skinWeight.w;",
|
|
|
+ " skinned = bindMatrixInverse * skinned;",
|
|
|
|
|
|
" displacedPosition = skinned.xyz;",
|
|
|
|
|
@@ -21962,6 +21977,25 @@ THREE.WebGLRenderer = function ( parameters ) {
|
|
|
|
|
|
if ( camera.parent === undefined ) camera.updateMatrixWorld();
|
|
|
|
|
|
+ // update Skeleton objects
|
|
|
+ function updateSkeletons( object ) {
|
|
|
+
|
|
|
+ if ( object instanceof THREE.SkinnedMesh ) {
|
|
|
+
|
|
|
+ object.skeleton.update();
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ for ( var i = 0, l = object.children.length; i < l; i ++ ) {
|
|
|
+
|
|
|
+ updateSkeletons( object.children[ i ] );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ updateSkeletons( scene );
|
|
|
+
|
|
|
camera.matrixWorldInverse.getInverse( camera.matrixWorld );
|
|
|
|
|
|
_projScreenMatrix.multiplyMatrices( camera.projectionMatrix, camera.matrixWorldInverse );
|
|
@@ -23063,7 +23097,19 @@ THREE.WebGLRenderer = function ( parameters ) {
|
|
|
|
|
|
if ( material.skinning ) {
|
|
|
|
|
|
- if ( _supportsBoneTextures && object.skeleton.useVertexTexture ) {
|
|
|
+ if ( object.bindMatrix && p_uniforms.bindMatrix !== null ) {
|
|
|
+
|
|
|
+ _gl.uniformMatrix4fv( p_uniforms.bindMatrix, false, object.bindMatrix.elements );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ if ( object.bindMatrixInverse && p_uniforms.bindMatrixInverse !== null ) {
|
|
|
+
|
|
|
+ _gl.uniformMatrix4fv( p_uniforms.bindMatrixInverse, false, object.bindMatrixInverse.elements );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ if ( _supportsBoneTextures && object.skeleton && object.skeleton.useVertexTexture ) {
|
|
|
|
|
|
if ( p_uniforms.boneTexture !== null ) {
|
|
|
|
|
@@ -23086,7 +23132,7 @@ THREE.WebGLRenderer = function ( parameters ) {
|
|
|
|
|
|
}
|
|
|
|
|
|
- } else {
|
|
|
+ } else if ( object.skeleton && object.skeleton.boneMatrices ) {
|
|
|
|
|
|
if ( p_uniforms.boneGlobalMatrices !== null ) {
|
|
|
|
|
@@ -25353,8 +25399,7 @@ THREE.WebGLProgram = ( function () {
|
|
|
|
|
|
var identifiers = [
|
|
|
|
|
|
- 'viewMatrix', 'modelViewMatrix', 'projectionMatrix', 'normalMatrix', 'modelMatrix', 'cameraPosition',
|
|
|
- 'morphTargetInfluences'
|
|
|
+ 'viewMatrix', 'modelViewMatrix', 'projectionMatrix', 'normalMatrix', 'modelMatrix', 'cameraPosition', 'morphTargetInfluences', 'bindMatrix', 'bindMatrixInverse'
|
|
|
|
|
|
];
|
|
|
|
|
@@ -29053,7 +29098,7 @@ THREE.Animation.prototype.reset = function () {
|
|
|
object.animationCache[this.data.name] = {};
|
|
|
object.animationCache[this.data.name].prevKey = { pos: 0, rot: 0, scl: 0 };
|
|
|
object.animationCache[this.data.name].nextKey = { pos: 0, rot: 0, scl: 0 };
|
|
|
- object.animationCache[this.data.name].originalMatrix = object instanceof THREE.Bone ? object.skinMatrix : object.matrix;
|
|
|
+ object.animationCache[this.data.name].originalMatrix = object.matrix;
|
|
|
|
|
|
}
|
|
|
|
|
@@ -29225,7 +29270,6 @@ THREE.Animation.prototype.update = (function(){
|
|
|
|
|
|
}
|
|
|
|
|
|
-
|
|
|
} else if ( this.interpolationType === THREE.AnimationHandler.CATMULLROM ||
|
|
|
this.interpolationType === THREE.AnimationHandler.CATMULLROM_FORWARD ) {
|
|
|
|
|
@@ -29468,7 +29512,7 @@ THREE.KeyFrameAnimation.prototype.play = function ( startTime ) {
|
|
|
node.animationCache = {};
|
|
|
node.animationCache.prevKey = null;
|
|
|
node.animationCache.nextKey = null;
|
|
|
- node.animationCache.originalMatrix = object instanceof THREE.Bone ? object.skinMatrix : object.matrix;
|
|
|
+ node.animationCache.originalMatrix = object.matrix;
|
|
|
|
|
|
}
|
|
|
|
|
@@ -29515,17 +29559,8 @@ THREE.KeyFrameAnimation.prototype.stop = function() {
|
|
|
|
|
|
var original = node.animationCache.originalMatrix;
|
|
|
|
|
|
- if( obj instanceof THREE.Bone ) {
|
|
|
-
|
|
|
- original.copy( obj.skinMatrix );
|
|
|
- obj.skinMatrix = original;
|
|
|
-
|
|
|
- } else {
|
|
|
-
|
|
|
- original.copy( obj.matrix );
|
|
|
- obj.matrix = original;
|
|
|
-
|
|
|
- }
|
|
|
+ original.copy( obj.matrix );
|
|
|
+ obj.matrix = original;
|
|
|
|
|
|
delete node.animationCache;
|
|
|
|
|
@@ -33117,17 +33152,18 @@ THREE.PointLightHelper.prototype.update = function () {
|
|
|
* @author Sean Griffin / http://twitter.com/sgrif
|
|
|
* @author Michael Guerrero / http://realitymeltdown.com
|
|
|
* @author mrdoob / http://mrdoob.com/
|
|
|
+ * @author ikerr / http://verold.com
|
|
|
*/
|
|
|
|
|
|
THREE.SkeletonHelper = function ( object ) {
|
|
|
|
|
|
- var skeleton = object.skeleton;
|
|
|
+ this.bones = this.getBoneList( object );
|
|
|
|
|
|
var geometry = new THREE.Geometry();
|
|
|
|
|
|
- for ( var i = 0; i < skeleton.bones.length; i ++ ) {
|
|
|
+ for ( var i = 0; i < this.bones.length; i ++ ) {
|
|
|
|
|
|
- var bone = skeleton.bones[ i ];
|
|
|
+ var bone = this.bones[ i ];
|
|
|
|
|
|
if ( bone.parent instanceof THREE.Bone ) {
|
|
|
|
|
@@ -33144,7 +33180,7 @@ THREE.SkeletonHelper = function ( object ) {
|
|
|
|
|
|
THREE.Line.call( this, geometry, material, THREE.LinePieces );
|
|
|
|
|
|
- this.skeleton = skeleton;
|
|
|
+ this.root = object;
|
|
|
|
|
|
this.matrixWorld = object.matrixWorld;
|
|
|
this.matrixAutoUpdate = false;
|
|
@@ -33156,20 +33192,47 @@ THREE.SkeletonHelper = function ( object ) {
|
|
|
|
|
|
THREE.SkeletonHelper.prototype = Object.create( THREE.Line.prototype );
|
|
|
|
|
|
+THREE.SkeletonHelper.prototype.getBoneList = function( object ) {
|
|
|
+
|
|
|
+ var boneList = [];
|
|
|
+
|
|
|
+ if ( object instanceof THREE.Bone ) {
|
|
|
+
|
|
|
+ boneList.push( object );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ for ( var i = 0; i < object.children.length; i ++ ) {
|
|
|
+
|
|
|
+ boneList.push.apply( boneList, this.getBoneList( object.children[ i ] ) );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ return boneList;
|
|
|
+
|
|
|
+};
|
|
|
+
|
|
|
THREE.SkeletonHelper.prototype.update = function () {
|
|
|
|
|
|
var geometry = this.geometry;
|
|
|
|
|
|
+ var matrixWorldInv = new THREE.Matrix4().getInverse( this.root.matrixWorld );
|
|
|
+
|
|
|
+ var boneMatrix = new THREE.Matrix4();
|
|
|
+
|
|
|
var j = 0;
|
|
|
|
|
|
- for ( var i = 0; i < this.skeleton.bones.length; i ++ ) {
|
|
|
+ for ( var i = 0; i < this.bones.length; i ++ ) {
|
|
|
|
|
|
- var bone = this.skeleton.bones[ i ];
|
|
|
+ var bone = this.bones[ i ];
|
|
|
|
|
|
if ( bone.parent instanceof THREE.Bone ) {
|
|
|
|
|
|
- geometry.vertices[ j ].setFromMatrixPosition( bone.skinMatrix );
|
|
|
- geometry.vertices[ j + 1 ].setFromMatrixPosition( bone.parent.skinMatrix );
|
|
|
+ boneMatrix.multiplyMatrices( matrixWorldInv, bone.matrixWorld );
|
|
|
+ geometry.vertices[ j ].setFromMatrixPosition( boneMatrix );
|
|
|
+
|
|
|
+ boneMatrix.multiplyMatrices( matrixWorldInv, bone.parent.matrixWorld );
|
|
|
+ geometry.vertices[ j + 1 ].setFromMatrixPosition( boneMatrix );
|
|
|
|
|
|
j += 2;
|
|
|
|