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 ); }