소스 검색

Skeleton Animation: Clean up

Mugen87 8 년 전
부모
커밋
7e4a4ab0d2
3개의 변경된 파일77개의 추가작업 그리고 55개의 파일을 삭제
  1. 4 1
      docs/api/objects/SkinnedMesh.html
  2. 15 16
      src/objects/Skeleton.js
  3. 58 38
      src/objects/SkinnedMesh.js

+ 4 - 1
docs/api/objects/SkinnedMesh.html

@@ -152,7 +152,10 @@
 		Updates the [page:Matrix4 MatrixWorld].
 		</div>
 
-
+		<h3>[method:null initBones]()</h3>
+		<div>
+		Creates an array of hierarchical [page:Bone bones] objects from the internal geometry.
+		</div>
 
 		<h2>Source</h2>
 

+ 15 - 16
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 );
 
 			}
 

+ 58 - 38
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,9 +179,9 @@ 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" ) {