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

simplifying code in the clip-based animation system.

Ben Houston 10 жил өмнө
parent
commit
801124dceb

+ 30 - 101
src/animation/AnimationClip.js

@@ -75,70 +75,44 @@ THREE.AnimationClip.prototype = {
 };
 
 
-THREE.AnimationClip.CreateMorphAnimationFromNames = function( morphTargetNames, duration ) {
+THREE.AnimationClip.CreateFromMorphTargetSequence = function( name, morphTargetSequence, fps ) {
 
+
+	var numMorphTargets = morphTargetSequence.length;
 	var tracks = [];
-	var frameStep = duration / morphTargetNames.length;
 
-	for( var i = 0; i < morphTargetNames.length; i ++ ) {
+	for( var i = 0; i < numMorphTargets; 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 + numMorphTargets - 1 ) % numMorphTargets, value: 0 } );
+		keys.push( { time: i, value: 1 } );
+		keys.push( { time: ( i + 1 ) % numMorphTargets, value: 0 } );
 
-			keys.push( { time: ( i + 1 ) * frameStep, value: 0 } );
+		keys.sort( THREE.KeyframeTrack.keyComparer );
 
+		// if there is a key at the first frame, duplicate it as the last frame as well for perfect loop.
+		if( keys[0].time === 0 ) {
+			keys.push( {
+				time: numMorphTargets,
+				value: keys[0].value
+			});
 		}
 
-		if( ( i - 1 ) < 0 ) {
-			
-			keys.push( { time: ( morphTargetNames.length - 1 ) * frameStep, value: 0 } );
-			keys.push( { time: morphTargetNames.length * frameStep, value: 1 } );
-
-		}
-
-		var morphName = morphTargetNames[i];
-		var trackName = '.morphTargetInfluences[' + morphName + ']';
-		var track = new THREE.NumberKeyframeTrack( trackName, keys );
-
-		tracks.push( track );
+		tracks.push( new THREE.NumberKeyframeTrack( '.morphTargetInfluences[' + morphTargetSequence[i].name + ']', keys ) );
 	}
 
-	var clip = new THREE.AnimationClip( 'morphAnimation', duration, tracks );
+	return new THREE.AnimationClip( name, -1, tracks ).scale( 1.0 / fps );
 
-	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 ) {
+THREE.AnimationClip.CreateClipsFromMorphTargetSequences = function( morphTargets, fps ) {
 	
-	var animations = {};
-	var animationsArray = [];
+	var animationToMorphTargets = {};
 
 	var pattern = /([a-z]+)_?(\d+)/;
 
+	// sort morph target names into animation groups based patterns like Walk_001, Walk_002, Run_001, Run_002
 	for ( var i = 0, il = morphTargets.length; i < il; i ++ ) {
 
 		var morphTarget = morphTargets[ i ];
@@ -146,29 +120,24 @@ THREE.AnimationClip.FromImplicitMorphTargetAnimations = function( morphTargets,
 
 		if ( parts && parts.length > 1 ) {
 
-			var animationName = parts[ 1 ];
+			var name = parts[ 1 ];
 
-			var animation = animations[ animationName ];
-			if ( ! animation ) {
-				animations[ animationName ] = animation = { name: animationName, morphTargetNames: [] };
-				animationsArray.push( animation );
+			var animationToMorphTargets = animationToMorphTargets[ name ] || [];
+			if( ! animationToMorphTargets ) {
+				animationToMorphTargets = [];
 			}
 
-			animation.morphTargetNames.push( morphTarget.name );
+			animationToMorphTargets.push( morphTarget );
+
 		}
 
 	}
 
 	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;
+	for( var name in animationToMorphTargets ) {
 
-		clips.push( clip );
+		clips.push( THREE.AnimationClip.CreateFromMorphTargetSequence( name, animationToMorphTargets[ name ], fps ) );
 	}
 
 	return clips;
@@ -178,57 +147,17 @@ THREE.AnimationClip.FromImplicitMorphTargetAnimations = function( morphTargets,
 // parse the standard JSON format for clips
 THREE.AnimationClip.parse = function( json ) {
 
-	optionalPrefix = optionalPrefix || "";
-	var name = json.name || "default";
-	var duration = json.duration || -1;
-	var fps = json.fps || 30;
-	var animationTracks = json.tracks || [];
-
-	var tracks = [];
-
-	for( var i = 0; i < animationTracks.length; i ++ ) {
+	for( var i = 0; i < json.tracks.length; i ++ ) {
 
-		var track = THREE.KeyframeTrack.parse( animationTracks[i] ).scale( 1 / fps );
-		tracks.push( track );
+		tracks.push( THREE.KeyframeTrack.parse( json.tracks[i] ).scale( 1.0 / json.fps ) );
 
 	}
 
-	if( tracks.length === 0 ) return null;
-
-	return new THREE.AnimationClip( name, duration, tracks );
+	return new THREE.AnimationClip( json.name, json.duration, tracks );
 
 };
 
 
-// parse the JSON format for THREE.Geometry clips
-THREE.AnimationClip.parseGeometryClip = function( json ) {
-
-	var name = json.name || "default";
-	var duration = json.duration || -1;
-	var fps = json.fps || 30;
-	var animationTracks = json.tracks || [];
-
-	var tracks = [];
-
-	for( var i = 0; i < animationTracks.length; i ++ ) {
-
-		var track = THREE.KeyframeTrack.parse( animationTracks[i] ).scale( 1 / fps );
-		if( track.name.indexOf('morphTargets') >= 0 ) {
-			track.name = track.name.replace('morphTargets', 'morphTargetInfluences' );
-		}
-		if( track.name.indexOf('.') !== 0 ) {
-			track.name = '.' + track.name;			
-		}
-		tracks.push( track );
-
-	}
-
-	if( tracks.length === 0 ) return null;
-
-	return new THREE.AnimationClip( name, duration, tracks );
-
-};
-
 // parse the old animation.hierarchy format
 THREE.AnimationClip.parseAnimationHierarchy = function( animation, bones, nodeName ) {
 

+ 7 - 11
src/animation/KeyframeTrack.js

@@ -137,19 +137,11 @@ THREE.KeyframeTrack.prototype = {
 	         Tracks with out of order keys should be considered to be invalid.  - bhouston
 	sort: function() {
 
-		function keyComparator(key0, key1) {
-			return key0.time - key1.time;
-		};
-
-		return function() {
-
-			this.keys.sort( keyComparator );
-
-			return this;
+		this.keys.sort( THREE.KeyframeTrack.keyComparer );
 
-		}
+		return this;
 
-	}(),*/
+	},*/
 
 	// ensure we do not get a GarbageInGarbageOut situation, make sure tracks are at least minimally viable
 	// One could eventually ensure that all key.values in a track are all of the same type (otherwise interpolation makes no sense.)
@@ -238,6 +230,10 @@ THREE.KeyframeTrack.prototype = {
 
 };
 
+THREE.KeyframeTrack.keyComparer = function keyComparator(key0, key1) {
+	return key0.time - key1.time;
+};
+
 THREE.KeyframeTrack.parse = function( json ) {
 
 	if( json.type === undefined ) throw new Error( "track type undefined, can not parse" );

+ 1 - 1
src/loaders/JSONLoader.js

@@ -439,7 +439,7 @@ THREE.JSONLoader.prototype = {
 
 			for( var i = 0; i < clips.length; i ++ ) {
 
-				var clip = THREE.AnimationClip.parseGeometryClip( clips[i] );
+				var clip = THREE.AnimationClip.parse( clips[i] );
 				if( clip ) geometry.clips.push( clip );
 
 			}

+ 3 - 3
src/loaders/ObjectLoader.js

@@ -633,9 +633,9 @@ THREE.ObjectLoader.prototype = {
 				//  One will end up with a few named clips for the scene composed of merged tracks from individual nodes.
 				for( var i = 0; i < Math.min( 1, data.clips.length ); i ++ ) {
 
-					var dataTracks = data.clips[i].tracks;
-
-					var fpsToSeconds = ( data.clips[i].fps !== undefined ) ? ( 1.0 / data.clips[i].fps ) : 1.0;
+					var dataClips = data.clips[i];
+					var dataTracks = dataClips.tracks || [];
+					var fpsToSeconds = 1.0 / ( dataClips.fps || 30 );
 
 					for( var i = 0; i < dataTracks.length; i ++ ) {
 

+ 1 - 1
utils/exporters/blender/addons/io_three/exporter/api/mesh.py

@@ -473,7 +473,7 @@ def animated_blend_shapes(mesh, options):
         animCurves = animCurves.action.fcurves
 
     for key in shp.key_blocks.keys()[1:]:    # skip "Basis"
-        key_name = constants.MORPH_TARGETS+"["+key+"]"
+        key_name = ".morphTargetInfluences["+key+"]"
         found_animation = False
         data_path = 'key_blocks["'+key+'"].value'
         values = []

+ 4 - 4
utils/exporters/blender/addons/io_three/exporter/api/object.py

@@ -172,10 +172,10 @@ def __parse_tracked_vector(fcurves, start_index, nb_curves):
 
 # trackable transform fields ( <output field>, <nb fcurve>, <type> )
 TRACKABLE_FIELDS = {
-    "location": ( "position", 3, "vector3" ),
-    "scale": ( "scale", 3, "vector3" ),
-    "rotation_euler": ( "rotation", 3, "vector3" ),
-    "rotation_quaternion": ( "quaternion", 4, "quaternion" )
+    "location": ( ".position", 3, "vector3" ),
+    "scale": ( ".scale", 3, "vector3" ),
+    "rotation_euler": ( ".rotation", 3, "vector3" ),
+    "rotation_quaternion": ( ".quaternion", 4, "quaternion" )
 }
 
 @_object