2
0
Эх сурвалжийг харах

begin conversion of BlendCharacter to new animation system.

Ben Houston 10 жил өмнө
parent
commit
002c3135bc

+ 22 - 146
examples/js/BlendCharacter.js

@@ -20,12 +20,14 @@ THREE.BlendCharacter = function () {
 
 			THREE.SkinnedMesh.call( scope, geometry, originalMaterial );
 
+			scope.mixer = new THREE.AnimationMixer( scope );
+
 			// Create the animations
 
 			for ( var i = 0; i < geometry.animations.length; ++ i ) {
 
 				var animName = geometry.animations[ i ].name;
-				scope.animations[ animName ] = new THREE.Animation( scope, geometry.animations[ i ] );
+				scope.animations[ animName ] = THREE.AnimationClip.FromJSONLoaderAnimation( geometry.animations[ i ], geometry.bones );
 
 			}
 
@@ -38,191 +40,65 @@ THREE.BlendCharacter = function () {
 
 	this.update = function( dt ) {
 
-		for ( var i = this.weightSchedule.length - 1; i >= 0; -- i ) {
-
-			var data = this.weightSchedule[ i ];
-			data.timeElapsed += dt;
-
-			// If the transition is complete, remove it from the schedule
-
-			if ( data.timeElapsed > data.duration ) {
-
-				data.anim.weight = data.endWeight;
-				this.weightSchedule.splice( i, 1 );
-
-				// If we've faded out completely, stop the animation
-
-				if ( data.anim.weight == 0 ) {
-
-					data.anim.stop( 0 );
-
-				}
-
-			} else {
-
-				// interpolate the weight for the current time
-
-				data.anim.weight = data.startWeight + ( data.endWeight - data.startWeight ) * data.timeElapsed / data.duration;
-
-			}
-
-		}
-
-		this.updateWarps( dt );
-
-	};
-
-	this.updateWarps = function( dt ) {
-
-		// Warping modifies the time scale over time to make 2 animations of different
-		// lengths match. This is useful for smoothing out transitions that get out of
-		// phase such as between a walk and run cycle
-
-		for ( var i = this.warpSchedule.length - 1; i >= 0; -- i ) {
-
-			var data = this.warpSchedule[ i ];
-			data.timeElapsed += dt;
-
-			if ( data.timeElapsed > data.duration ) {
-
-				data.to.weight = 1;
-				data.to.timeScale = 1;
-				data.from.weight = 0;
-				data.from.timeScale = 1;
-				data.from.stop( 0 );
-
-				this.warpSchedule.splice( i, 1 );
-
-			} else {
-
-				var alpha = data.timeElapsed / data.duration;
-
-				var fromLength = data.from.data.length;
-				var toLength = data.to.data.length;
-
-				var fromToRatio = fromLength / toLength;
-				var toFromRatio = toLength / fromLength;
-
-				// scale from each time proportionally to the other animation
-
-				data.from.timeScale = ( 1 - alpha ) + fromToRatio * alpha;
-				data.to.timeScale = alpha + toFromRatio * ( 1 - alpha );
-
-				data.from.weight = 1 - alpha;
-				data.to.weight = alpha;
-
-			}
-
-		}
+		scope.mixer.update( dt );
 
 	};
 
 	this.play = function( animName, weight ) {
 
-		this.animations[ animName ].play( 0, weight );
+		this.removeAllActions();
+		this.mixer.play( new THREE.AnimationAction( this.animations[ animName ], 0, 1, 1, true ) );
 
 	};
 
 	this.crossfade = function( fromAnimName, toAnimName, duration ) {
 
-		var fromAnim = this.animations[ fromAnimName ];
-		var toAnim = this.animations[ toAnimName ];
+		var fromAction = new THREE.AnimationAction( this.animations[ fromAnimName ], 0, 1, 1, true );
+		var toAction = new THREE.AnimationAction( this.animations[ toAnimName ], 0, 1, 1, true );
 
-		fromAnim.play( 0, 1 );
-		toAnim.play( 0, 0 );
+		this.mixer.play( fromAction );
+		this.mixer.play( toAction );
 
-		this.weightSchedule.push( {
-
-			anim: fromAnim,
-			startWeight: 1,
-			endWeight: 0,
-			timeElapsed: 0,
-			duration: duration
-
-		} );
-
-		this.weightSchedule.push( {
-
-			anim: toAnim,
-			startWeight: 0,
-			endWeight: 1,
-			timeElapsed: 0,
-			duration: duration
-
-		} );
+		this.mixer.crossFade( fromAction, toAction, duration, false );
 
 	};
 
 	this.warp = function( fromAnimName, toAnimName, duration ) {
 
-		var fromAnim = this.animations[ fromAnimName ];
-		var toAnim = this.animations[ toAnimName ];
-
-		fromAnim.play( 0, 1 );
-		toAnim.play( 0, 0 );
+		var fromAction = new THREE.AnimationAction( this.animations[ fromAnimName ], 0, 1, 1, true );
+		var toAction = new THREE.AnimationAction( this.animations[ toAnimName ], 0, 1, 1, true );
 
-		this.warpSchedule.push( {
+		this.mixer.play( fromAction );
+		this.mixer.play( toAction );
 
-			from: fromAnim,
-			to: toAnim,
-			timeElapsed: 0,
-			duration: duration
-
-		} );
+		this.mixer.crossFade( fromAction, toAction, duration, true );
 
 	};
 
 	this.applyWeight = function( animName, weight ) {
 
-		this.animations[ animName ].weight = weight;
+		if( this.mixer[ animName ] ) {
+			this.mixer[ animName ].weight = weight;
+		}
 
 	};
 
 	this.pauseAll = function() {
 
-		for ( var a in this.animations ) {
-
-			if ( this.animations[ a ].isPlaying ) {
-
-				this.animations[ a ].stop();
-
-			}
-
-		}
+		this.mixer.timeScale = 0;
 
 	};
 
 	this.unPauseAll = function() {
 
-		for ( var a in this.animations ) {
-
-			if ( this.animations[ a ].isPlaying && this.animations[ a ].isPaused ) {
-
-				this.animations[ a ].pause();
-
-			}
-
-		}
+		this.mixer.timeScale = 1;
 
 	};
 
 
 	this.stopAll = function() {
 
-		for ( a in this.animations ) {
-
-			if ( this.animations[ a ].isPlaying ) {
-
-				this.animations[ a ].stop( 0 );
-
-			}
-
-			this.animations[ a ].weight = 0;
-
-		}
-
-		this.weightSchedule.length = 0;
-		this.warpSchedule.length = 0;
+		this.removeAllActions();
 
 	};
 

+ 1 - 1
examples/webgl_animation_skinning_morph.html

@@ -237,7 +237,7 @@
 				var clipMorpher = THREE.AnimationClip.CreateMorphAnimation( mesh.geometry.morphTargets, 3 );
 				mixer.addAction( new THREE.AnimationAction( clipMorpher, 0, 1, 1, true ) );
 
-				var clipBones = THREE.AnimationClip.FromJSONLoaderAnimation( geometry );
+				var clipBones = THREE.AnimationClip.FromJSONLoaderAnimation( geometry.animation, geometry.bones );
 				mixer.addAction( new THREE.AnimationAction( clipBones, 0, 1, 1, true ) );
 			}
 

+ 4 - 4
src/animation/AnimationClip.js

@@ -188,9 +188,9 @@ THREE.AnimationClip.FromImplicitMorphTargetAnimations = function( morphTargets,
 
 };
 
-THREE.AnimationClip.FromJSONLoaderAnimation = function( jsonLoader, nodeName ) {
+THREE.AnimationClip.FromJSONLoaderAnimation = function( animation, bones, nodeName ) {
 
-	var animation = jsonLoader.animation;
+	//var animation = jsonLoader.animation;
 	if( ! animation ) {
 		console.error( "  no animation in JSONLoader data" );
 		return null;
@@ -228,7 +228,7 @@ THREE.AnimationClip.FromJSONLoaderAnimation = function( jsonLoader, nodeName ) {
 
 	var tracks = [];
 
-	var boneList = jsonLoader.bones;
+	//var boneList = jsonLoader.bones;
 	var animationTracks = animation.hierarchy;
 
 	for ( var h = 0; h < animationTracks.length; h ++ ) {
@@ -279,7 +279,7 @@ THREE.AnimationClip.FromJSONLoaderAnimation = function( jsonLoader, nodeName ) {
 		}
 		else {
 
-			var boneName = nodeName + '.bones[' + boneList[ h ].name + ']';
+			var boneName = nodeName + '.bones[' + bones[ h ].name + ']';
 			//console.log( 'boneName', boneName );
 		
 			// track contains positions...

+ 7 - 0
src/animation/AnimationMixer.js

@@ -99,6 +99,13 @@ THREE.AnimationMixer.prototype = {
 
 	},
 
+	play: function( action, optionalFadeInDuration ) {
+
+		action.startTime = this.time;
+		this.addAction( action );
+
+	},
+
 	fadeOut: function( action, duration ) {
 
 		var keys = [];

+ 1 - 0
src/animation/AnimationUtils.js

@@ -41,6 +41,7 @@
 
 	},
 
+	// NOTE: this is an accumulator function that modifies the first argument (e.g. a).  This is to minimize memory alocations.
 	getLerpFunc: function( exemplarValue, interTrack ) {
 
 		if( exemplarValue === undefined || exemplarValue === null ) throw new Error( "examplarValue is null" );