diff --git a/docs/api/objects/SkinnedMesh.html b/docs/api/objects/SkinnedMesh.html
index 7a55ea7e481604d27c81a126361527e39451018c..c5aaeaafa35c47aad075eba4cfca2d7047246cea 100644
--- a/docs/api/objects/SkinnedMesh.html
+++ b/docs/api/objects/SkinnedMesh.html
@@ -152,7 +152,10 @@
Updates the [page:Matrix4 MatrixWorld].
-
+
[method:null initBones]()
+
+ Creates an array of hierarchical [page:Bone bones] objects from the internal geometry.
+
Source
diff --git a/src/objects/Skeleton.js b/src/objects/Skeleton.js
index 085a1e4c671ad5b2a41113ad04187c7dbb745b10..31daeaaf29b5ef79057b4a9506b706a34bcc3cca 100644
--- a/src/objects/Skeleton.js
+++ b/src/objects/Skeleton.js
@@ -9,8 +9,6 @@ import { Matrix4 } from '../math/Matrix4';
function Skeleton( bones, boneInverses ) {
- this.identityMatrix = new Matrix4();
-
// copy the bone array
bones = bones || [];
@@ -36,7 +34,7 @@ function Skeleton( bones, boneInverses ) {
this.boneInverses = [];
- for ( var b = 0, bl = this.bones.length; b < bl; b ++ ) {
+ for ( var i = 0, il = this.bones.length; i < il; i ++ ) {
this.boneInverses.push( new Matrix4() );
@@ -54,13 +52,13 @@ Object.assign( Skeleton.prototype, {
this.boneInverses = [];
- for ( var b = 0, bl = this.bones.length; b < bl; b ++ ) {
+ for ( var i = 0, il = this.bones.length; i < il; i ++ ) {
var inverse = new Matrix4();
- if ( this.bones[ b ] ) {
+ if ( this.bones[ i ] ) {
- inverse.getInverse( this.bones[ b ].matrixWorld );
+ inverse.getInverse( this.bones[ i ].matrixWorld );
}
@@ -72,17 +70,17 @@ Object.assign( Skeleton.prototype, {
pose: function () {
- var bone;
+ var bone, i, il;
// recover the bind-time world matrices
- for ( var b = 0, bl = this.bones.length; b < bl; b ++ ) {
+ for ( i = 0, il = this.bones.length; i < il; i ++ ) {
- bone = this.bones[ b ];
+ bone = this.bones[ i ];
if ( bone ) {
- bone.matrixWorld.getInverse( this.boneInverses[ b ] );
+ bone.matrixWorld.getInverse( this.boneInverses[ i ] );
}
@@ -90,9 +88,9 @@ Object.assign( Skeleton.prototype, {
// compute the local matrices, positions, rotations and scales
- for ( var b = 0, bl = this.bones.length; b < bl; b ++ ) {
+ for ( i = 0, il = this.bones.length; i < il; i ++ ) {
- bone = this.bones[ b ];
+ bone = this.bones[ i ];
if ( bone ) {
@@ -118,6 +116,7 @@ Object.assign( Skeleton.prototype, {
update: ( function () {
var offsetMatrix = new Matrix4();
+ var identityMatrix = new Matrix4();
return function update() {
@@ -128,14 +127,14 @@ Object.assign( Skeleton.prototype, {
// flatten bone matrices to array
- for ( var b = 0, bl = bones.length; b < bl; b ++ ) {
+ for ( var i = 0, il = bones.length; i < il; i ++ ) {
// compute the offset between the current and the original transform
- var matrix = bones[ b ] ? bones[ b ].matrixWorld : this.identityMatrix;
+ var matrix = bones[ i ] ? bones[ i ].matrixWorld : identityMatrix;
- offsetMatrix.multiplyMatrices( matrix, boneInverses[ b ] );
- offsetMatrix.toArray( boneMatrices, b * 16 );
+ offsetMatrix.multiplyMatrices( matrix, boneInverses[ i ] );
+ offsetMatrix.toArray( boneMatrices, i * 16 );
}
diff --git a/src/objects/SkinnedMesh.js b/src/objects/SkinnedMesh.js
index f10e6faf1a4393fb49c162f18c5fb145997707e9..6fd06b4dd09ac05038024b5aaa51c68fe339851d 100644
--- a/src/objects/SkinnedMesh.js
+++ b/src/objects/SkinnedMesh.js
@@ -18,66 +18,84 @@ function SkinnedMesh( geometry, material ) {
this.type = 'SkinnedMesh';
- this.bindMode = "attached";
+ this.bindMode = 'attached';
this.bindMatrix = new Matrix4();
this.bindMatrixInverse = new Matrix4();
- // init bones
+ var bones = this.initBones();
+ var skeleton = new Skeleton( bones );
- // TODO: remove bone creation as there is no reason (other than
- // convenience) for THREE.SkinnedMesh to do this.
+ this.bind( skeleton, this.matrixWorld );
- var bones = [];
+ this.normalizeSkinWeights();
- if ( this.geometry && this.geometry.bones !== undefined ) {
+}
- var bone, gbone;
+SkinnedMesh.prototype = Object.assign( Object.create( Mesh.prototype ), {
- for ( var b = 0, bl = this.geometry.bones.length; b < bl; ++ b ) {
+ constructor: SkinnedMesh,
- gbone = this.geometry.bones[ b ];
+ isSkinnedMesh: true,
- bone = new Bone();
- bones.push( bone );
+ initBones: function () {
- bone.name = gbone.name;
- bone.position.fromArray( gbone.pos );
- bone.quaternion.fromArray( gbone.rotq );
- if ( gbone.scl !== undefined ) bone.scale.fromArray( gbone.scl );
+ var bones = [], bone, gbone;
+ var i, il;
- }
+ if ( this.geometry && this.geometry.bones !== undefined ) {
+
+ // first, create array of 'Bone' objects from geometry data
- for ( var b = 0, bl = this.geometry.bones.length; b < bl; ++ b ) {
+ for ( i = 0, il = this.geometry.bones.length; i < il; i ++ ) {
- gbone = this.geometry.bones[ b ];
+ gbone = this.geometry.bones[ i ];
- if ( gbone.parent !== - 1 && gbone.parent !== null &&
- bones[ gbone.parent ] !== undefined ) {
+ // create new 'Bone' object
- bones[ gbone.parent ].add( bones[ b ] );
+ bone = new Bone();
+ bones.push( bone );
- } else {
+ // apply values
- this.add( bones[ b ] );
+ bone.name = gbone.name;
+ bone.position.fromArray( gbone.pos );
+ bone.quaternion.fromArray( gbone.rotq );
+ if ( gbone.scl !== undefined ) bone.scale.fromArray( gbone.scl );
}
- }
+ // second, create bone hierarchy
- }
+ for ( i = 0, il = this.geometry.bones.length; i < il; i ++ ) {
- this.normalizeSkinWeights();
+ gbone = this.geometry.bones[ i ];
- this.updateMatrixWorld( true );
- this.bind( new Skeleton( bones ), this.matrixWorld );
+ if ( ( gbone.parent !== - 1 ) && ( gbone.parent !== null ) && ( bones[ gbone.parent ] !== undefined ) ) {
-}
+ // subsequent bones in the hierarchy
-SkinnedMesh.prototype = Object.assign( Object.create( Mesh.prototype ), {
+ bones[ gbone.parent ].add( bones[ i ] );
- constructor: SkinnedMesh,
+ } else {
- isSkinnedMesh: true,
+ // topmost bone, immediate child of the skinned mesh
+
+ this.add( bones[ i ] );
+
+ }
+
+ }
+
+ }
+
+ // now the bones are part of the scene graph and children of the skinned mesh.
+ // let's update the corresponding matrices
+
+ this.updateMatrixWorld( true );
+
+ return bones;
+
+ },
bind: function ( skeleton, bindMatrix ) {
@@ -106,13 +124,15 @@ SkinnedMesh.prototype = Object.assign( Object.create( Mesh.prototype ), {
normalizeSkinWeights: function () {
+ var scale, i;
+
if ( this.geometry && this.geometry.isGeometry ) {
- for ( var i = 0; i < this.geometry.skinWeights.length; i ++ ) {
+ for ( i = 0; i < this.geometry.skinWeights.length; i ++ ) {
var sw = this.geometry.skinWeights[ i ];
- var scale = 1.0 / sw.lengthManhattan();
+ scale = 1.0 / sw.lengthManhattan();
if ( scale !== Infinity ) {
@@ -132,14 +152,14 @@ SkinnedMesh.prototype = Object.assign( Object.create( Mesh.prototype ), {
var skinWeight = this.geometry.attributes.skinWeight;
- for ( var i = 0; i < skinWeight.count; i ++ ) {
+ for ( i = 0; i < skinWeight.count; i ++ ) {
vec.x = skinWeight.getX( i );
vec.y = skinWeight.getY( i );
vec.z = skinWeight.getZ( i );
vec.w = skinWeight.getW( i );
- var scale = 1.0 / vec.lengthManhattan();
+ scale = 1.0 / vec.lengthManhattan();
if ( scale !== Infinity ) {
@@ -159,21 +179,21 @@ SkinnedMesh.prototype = Object.assign( Object.create( Mesh.prototype ), {
},
- updateMatrixWorld: function () {
+ updateMatrixWorld: function ( force ) {
- Mesh.prototype.updateMatrixWorld.call( this, true );
+ Mesh.prototype.updateMatrixWorld.call( this, force );
- if ( this.bindMode === "attached" ) {
+ if ( this.bindMode === 'attached' ) {
this.bindMatrixInverse.getInverse( this.matrixWorld );
- } else if ( this.bindMode === "detached" ) {
+ } else if ( this.bindMode === 'detached' ) {
this.bindMatrixInverse.getInverse( this.bindMatrix );
} else {
- console.warn( 'THREE.SkinnedMesh unrecognized bindMode: ' + this.bindMode );
+ console.warn( 'THREE.SkinnedMesh: Unrecognized bindMode: ' + this.bindMode );
}