Răsfoiți Sursa

start to replace the internals of MorphAnimMesh.

Ben Houston 10 ani în urmă
părinte
comite
2bd48d573e

+ 1 - 1
examples/js/MD2Character.js

@@ -223,7 +223,7 @@ THREE.MD2Character = function () {
 
 		mesh.parseAnimations();
 
-		mesh.playAnimation( geometry.firstAnimation, scope.animationFPS );
+		mesh.playAnimation( mesh.firstAnimationClip.name, scope.animationFPS );
 		mesh.baseDuration = mesh.duration;
 
 		return mesh;

+ 1 - 1
examples/webgl_animation_skinning_morph_mixer.html

@@ -235,7 +235,7 @@
 
 				mixer = new THREE.AnimationMixer( mesh );
 		
-				var clipMorpher = THREE.AnimationClipCreator.CreateMorphAnimation( mesh.geometry.morphTargets, 3 );
+				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 );

+ 8 - 6
examples/webgl_morphtargets_md2.html

@@ -305,19 +305,21 @@
 
 				var folder = gui.addFolder( "Animations" );
 
-				var generateCallback = function( animationName ) {
+				var generateCallback = function( animationClip ) {
 
-					return function () { character.setAnimation( animationName ); };
+					return function () { character.setAnimation( animationClip.name ); };
 
 				};
 
 				var i = 0, guiItems = [];
-				var animations = character.meshBody.geometry.animations;
+				var animationClips = character.meshBody.animationClips;
 
-				for ( var a in animations ) {
+				for ( var i = 0; i < animationClips.length; i ++ ) {
 
-					playbackConfig[ a ] = generateCallback( a );
-					guiItems[ i ] = folder.add( playbackConfig, a, a );
+					var animationClip = animationClips[i];
+
+					playbackConfig[ animationClip.name ] = generateCallback( animationClip );
+					guiItems[ i ] = folder.add( playbackConfig, animationClip.name, animationClip.name );
 
 					i ++;
 

+ 107 - 0
src/animation/AnimationClip.js

@@ -81,6 +81,113 @@ THREE.AnimationClip.prototype = {
                     },
 */
 
+THREE.AnimationClip.CreateMorphAnimationFromNames = function( morphTargetNames, duration ) {
+	//console.log( morphTargetNames, duration );
+
+	var tracks = [];
+	var frameStep = duration / morphTargetNames.length;
+	//console.log( 'frameStep', frameStep );
+
+	for( var i = 0; i < morphTargetNames.length; i ++ ) {
+
+		var keys = [];
+
+		if( ( i - 1 ) >= 0 ) {
+
+			keys.push( { time: ( i - 1 ) * frameStep, value: 0 } );
+
+		}
+
+		keys.push( { time: i * frameStep, value: 1 } );
+
+		if( ( i + 1 ) <= morphTargetNames.length ) {
+
+			keys.push( { time: ( i + 1 ) * frameStep, value: 0 } );
+
+		}
+
+		if( ( i - 1 ) < 0 ) {
+			
+			keys.push( { time: ( morphTargetNames.length - 1 ) * frameStep, value: 0 } );
+			keys.push( { time: morphTargetNames.length * frameStep, value: 1 } );
+
+		}
+
+		//console.log( 'keys', keys );
+
+		var morphName = morphTargetNames[i];
+		var trackName = '.morphTargetInfluences[' + morphName + ']';
+		var track = new THREE.KeyframeTrack( trackName, keys );
+
+		tracks.push( track );
+	}
+
+	var clip = new THREE.AnimationClip( 'morphAnimation', duration, tracks );
+	//console.log( 'morphAnimationClip', clip );
+
+	return clip;
+};
+
+THREE.AnimationClip.CreateMorphAnimation = function( morphTargets, duration ) {
+
+	var morphTargetNames = [];
+
+	for( var i = 0; i < morphTargets.length; i ++ ) {
+
+		morphTargetNames.push( morphTargets[i].name );
+
+	}
+
+	return THREE.AnimationClip.CreateMorphAnimationFromNames( morphTargetNames, duration );
+
+};
+
+
+THREE.AnimationClip.FromImplicitMorphTargetAnimations = function( morphTargets, fps ) {
+	
+	var animations = {};
+	var animationsArray = [];
+
+	var pattern = /([a-z]+)_?(\d+)/;
+
+	for ( var i = 0, il = morphTargets.length; i < il; i ++ ) {
+
+		var morphTarget = morphTargets[ i ];
+		var parts = morphTarget.name.match( pattern );
+
+		if ( parts && parts.length > 1 ) {
+
+			var animationName = parts[ 1 ];
+
+			var animation = animations[ animationName ];
+			if ( ! animation ) {
+				animations[ animationName ] = animation = { name: animationName, morphTargetNames: [] };
+				animationsArray.push( animation );
+			}
+
+			animation.morphTargetNames.push( morphTarget.name );
+		}
+
+	}
+
+	//console.log( animations );
+
+	var clips = [];
+
+	for( var i = 0; i < animationsArray.length; i ++ ) {
+
+		var animation = animationsArray[i];
+
+		var clip = new THREE.AnimationClip.CreateMorphAnimationFromNames( animation.morphTargetNames, animation.morphTargetNames.length * fps );
+		clip.name = animation.name;
+
+		clips.push( clip );
+	}
+
+	return clips;
+
+};
+
 THREE.AnimationClip.FromJSONLoaderAnimation = function( jsonLoader, nodeName ) {
 
 	var animation = jsonLoader.animation;

+ 6 - 0
src/animation/AnimationMixer.js

@@ -46,6 +46,12 @@ THREE.AnimationMixer.prototype = {
 
 	},
 
+	removeAllActions: function() {
+
+		this.actions = [];
+
+	},
+
 	removeAction: function( action ) {
 		//console.log( this.root.name + ".AnimationMixer.addRemove( " + action.name + " )" );
 

+ 4 - 4
src/animation/PropertyBinding.js

@@ -224,11 +224,11 @@ THREE.PropertyBinding.prototype = {
 				this.triggerDirty();
 			}
 
-		}
+			// reset accumulator
+			this.cumulativeValue = null;
+			this.cumulativeWeight = 0;
 
-		// reset accumulator
-		this.cumulativeValue = null;
-		this.cumulativeWeight = 0;
+		}
 	},
 
 	get: function() {

+ 21 - 139
src/objects/MorphAnimMesh.js

@@ -10,105 +10,51 @@ THREE.MorphAnimMesh = function ( geometry, material ) {
 
 	// API
 
-	this.duration = 1000; // milliseconds
-	this.mirroredLoop = false;
-	this.time = 0;
-
-	// internals
-
-	this.lastKeyframe = 0;
-	this.currentKeyframe = 0;
-
-	this.direction = 1;
-	this.directionBackwards = false;
-
-	this.setFrameRange( 0, geometry.morphTargets.length - 1 );
+	this.mixer = new THREE.AnimationMixer( this );
 
 };
 
 THREE.MorphAnimMesh.prototype = Object.create( THREE.Mesh.prototype );
 THREE.MorphAnimMesh.prototype.constructor = THREE.MorphAnimMesh;
 
-THREE.MorphAnimMesh.prototype.setFrameRange = function ( start, end ) {
-
-	this.startKeyframe = start;
-	this.endKeyframe = end;
-
-	this.length = this.endKeyframe - this.startKeyframe + 1;
-
-};
-
 THREE.MorphAnimMesh.prototype.setDirectionForward = function () {
 
-	this.direction = 1;
-	this.directionBackwards = false;
+	this.mixer.timeScale = 1.0;
 
 };
 
 THREE.MorphAnimMesh.prototype.setDirectionBackward = function () {
 
-	this.direction = - 1;
-	this.directionBackwards = true;
+	this.mixer.timeScale = -1.0;
 
 };
 
 THREE.MorphAnimMesh.prototype.parseAnimations = function () {
 
-	var geometry = this.geometry;
-
-	if ( ! geometry.animations ) geometry.animations = {};
-
-	var firstAnimation, animations = geometry.animations;
-
-	var pattern = /([a-z]+)_?(\d+)/;
-
-	for ( var i = 0, il = geometry.morphTargets.length; i < il; i ++ ) {
-
-		var morph = geometry.morphTargets[ i ];
-		var parts = morph.name.match( pattern );
-
-		if ( parts && parts.length > 1 ) {
-
-			var label = parts[ 1 ];
+	this.animationClips = THREE.AnimationClip.FromImplicitMorphTargetAnimations( this.geometry.morphTargets, 20 );
+	this.firstAnimationClip = this.animationClips[0];
 
-			if ( ! animations[ label ] ) animations[ label ] = { start: Infinity, end: - Infinity };
-
-			var animation = animations[ label ];
+};
 
-			if ( i < animation.start ) animation.start = i;
-			if ( i > animation.end ) animation.end = i;
+THREE.MorphAnimMesh.prototype.playAnimation = function ( label ) {
 
-			if ( ! firstAnimation ) firstAnimation = label;
+	this.mixer.removeAllActions();
 
+	var clip = null;
+	for( var i = 0; i < this.animationClips.length; i ++ ) {
+		if( this.animationClips[ i ].name === label ) {
+			clip = this.animationClips[ i ];
+			break;
 		}
-
 	}
+	
+	if ( clip ) {
 
-	geometry.firstAnimation = firstAnimation;
-
-};
-
-THREE.MorphAnimMesh.prototype.setAnimationLabel = function ( label, start, end ) {
-
-	if ( ! this.geometry.animations ) this.geometry.animations = {};
-
-	this.geometry.animations[ label ] = { start: start, end: end };
-
-};
-
-THREE.MorphAnimMesh.prototype.playAnimation = function ( label, fps ) {
-
-	var animation = this.geometry.animations[ label ];
-
-	if ( animation ) {
-
-		this.setFrameRange( animation.start, animation.end );
-		this.duration = 1000 * ( ( animation.end - animation.start ) / fps );
-		this.time = 0;
+		this.mixer.addAction( new THREE.AnimationAction( clip, 0, 1, 1, true ) );
 
 	} else {
 
-		console.warn( 'THREE.MorphAnimMesh: animation[' + label + '] undefined in .playAnimation()' );
+		throw new Error( 'THREE.MorphAnimMesh: animationClips[' + label + '] undefined in .playAnimation()' );
 
 	}
 
@@ -116,65 +62,7 @@ THREE.MorphAnimMesh.prototype.playAnimation = function ( label, fps ) {
 
 THREE.MorphAnimMesh.prototype.updateAnimation = function ( delta ) {
 
-	var frameTime = this.duration / this.length;
-
-	this.time += this.direction * delta;
-
-	if ( this.mirroredLoop ) {
-
-		if ( this.time > this.duration || this.time < 0 ) {
-
-			this.direction *= - 1;
-
-			if ( this.time > this.duration ) {
-
-				this.time = this.duration;
-				this.directionBackwards = true;
-
-			}
-
-			if ( this.time < 0 ) {
-
-				this.time = 0;
-				this.directionBackwards = false;
-
-			}
-
-		}
-
-	} else {
-
-		this.time = this.time % this.duration;
-
-		if ( this.time < 0 ) this.time += this.duration;
-
-	}
-
-	var keyframe = this.startKeyframe + THREE.Math.clamp( Math.floor( this.time / frameTime ), 0, this.length - 1 );
-
-	var influences = this.morphTargetInfluences;
-
-	if ( keyframe !== this.currentKeyframe ) {
-
-		influences[ this.lastKeyframe ] = 0;
-		influences[ this.currentKeyframe ] = 1;
-		influences[ keyframe ] = 0;
-
-		this.lastKeyframe = this.currentKeyframe;
-		this.currentKeyframe = keyframe;
-
-	}
-
-	var mix = ( this.time % frameTime ) / frameTime;
-
-	if ( this.directionBackwards ) {
-
-		mix = 1 - mix;
-
-	}
-
-	influences[ this.currentKeyframe ] = mix;
-	influences[ this.lastKeyframe ] = 1 - mix;
+	this.mixer.update( delta );
 
 };
 
@@ -202,15 +90,9 @@ THREE.MorphAnimMesh.prototype.clone = function () {
 
 THREE.MorphAnimMesh.prototype.copy = function ( source ) {
 
-	this.duration = source.duration;
-	this.mirroredLoop = source.mirroredLoop;
-	this.time = source.time;
-
-	this.lastKeyframe = source.lastKeyframe;
-	this.currentKeyframe = source.currentKeyframe;
-
-	this.direction = source.direction;
-	this.directionBackwards = source.directionBackwards;
+	this.mixer.copy( source.mixer );
+	this.animationClips = source.animationClips;
+	this.firstAnimationClips = source.firstAnimationClips;
 
 	THREE.Mesh.prototype.copy.call( this, source );