Browse Source

create the files for the individual animation components.

Ben Houston 10 years ago
parent
commit
9ad046d757

+ 66 - 0
src/animation/Action.js

@@ -0,0 +1,66 @@
+/**
+ * @author Ben Houston / http://clara.io/
+ * @author David Sarno / http://lighthaus.us/
+ */
+
+THREE.Action = function ( clip, startTime, timeScale, weight, loop ) {
+
+	this.clip = clip;
+	this.startTime = startTime || 0;
+	this.timeScale = timeScale || 1;
+	this.weight = weight || 1;
+	this.loop = loop || false;
+
+	this.cache = {}; // track name, track, last evaluated time, last evaluated value (with weight included), keyIndex.
+};
+
+THREE.Action.prototype = {
+
+	constructor: THREE.Action,
+
+	toClipTime: function( time ) {
+
+		var clipTime = time - this.startTime;
+
+		clipTime *= this.timeScale;
+
+		if( this.loop ) {
+
+			if( clipTime < 0 ) {
+
+				clipTime = clipTime - Math.floor( clipTime / this.clip.duration ) * this.clip.duration;
+
+			}
+
+	   		clipTime = clipTime % this.clip.duration;
+
+	   	}
+	   	else {
+
+	   		clipTime = Math.min( clipTime, this.clip.duration );
+	   		clipTime = Math.max( clipTime, 0 );
+
+	   	}
+
+   		return clipTime;
+	}
+
+	getAt: function( time ) {
+
+		var clipTime = this.toClipTime( time );
+
+		var results = {};
+
+		foreach( var name in clip.tracks ) {
+
+			var track = clip.tracks[name];
+
+			var value = track.getAt( time );
+
+			results[name] = value;
+		}
+
+		return results;
+	}
+
+};

+ 98 - 0
src/animation/AnimationMath.js

@@ -0,0 +1,98 @@
+/**
+ * @author Ben Houston / http://clara.io/
+ * @author David Sarno / http://lighthaus.us/
+ */
+
+ THREE.AnimationUtils = {
+
+ 	lerp: function( a, b, alpha ) {
+
+		if( a.lerp ) {
+
+			return a.clone().lerp( b, alpha );
+
+		}
+		else if( a.slerp ) {
+
+			return a.clone().lerp( b, alpha );
+
+		}
+		else {
+
+			return a * ( 1 - alpha ) + b * alpha;
+			
+		}
+	},
+
+
+
+	// TODO: Cache this at some point
+	findNode: function( root, nodeName ) {
+
+		if( ! nodeName || nodeName === "" || nodeName === "root" || nodeName === "." || nodeName === -1 ) {
+
+			return root;
+
+		}
+
+		// (2) search into skeleton bones.
+		if( root.skeleton ) {
+
+			var searchSkeleton = function( skeleton ) {
+
+				for( var i = 0; i < skeleton.bones.length; i ++ ) {
+
+					var bone = skeleton.bones[i];
+
+					if( bone.name === nodeName ) {
+
+						return childNode;
+
+					}
+				}
+
+				return null;
+
+			};
+
+			var boneNode = searchSkeleton( root.skeleton );
+
+			if( boneNode ) return boneNode;
+		}
+
+		// (3) search into node subtree.
+		if( root.children ) {
+
+			var searchNodeSubtree = function( children ) {
+
+				for( var i = 0; i < children.length; i ++ ) {
+
+					var childNode = children[i];
+
+					if( childNode.name === nodeName ) {
+
+						return childNode;
+
+					}
+
+					var result = searchNodeSubtree( childNode.children );
+
+					if( result ) return result;
+
+				}
+
+				return null;	
+
+			};
+
+			var subTreeNode = searchNodeSubtree( root.children );
+
+			if( subTreeNode ) return subTreeNode;
+
+		}
+
+		console.log( "no node found for name: " + name );
+
+		return null;
+	}
+};

+ 137 - 0
src/animation/Clip.js

@@ -0,0 +1,137 @@
+/**
+ * @author Ben Houston / http://clara.io/
+ * @author David Sarno / http://lighthaus.us/
+ */
+
+THREE.Clip = function ( name, duration, tracks ) {
+
+	this.name = name || "";
+	this.duration = duration || 0;
+	this.tracks = tracks || [];
+
+};
+
+THREE.Clip.prototype = {
+
+	constructor: THREE.Clip,
+
+	importFromData: function( data ) {
+
+		init: function ( data ) {
+
+		if ( data.initialized === true ) return data;
+
+		// loop through all keys
+
+		for ( var h = 0; h < data.hierarchy.length; h ++ ) {
+
+			for ( var k = 0; k < data.hierarchy[ h ].keys.length; k ++ ) {
+
+				// remove minus times
+
+				if ( data.hierarchy[ h ].keys[ k ].time < 0 ) {
+
+					 data.hierarchy[ h ].keys[ k ].time = 0;
+
+				}
+
+				// create quaternions
+
+				if ( data.hierarchy[ h ].keys[ k ].rot !== undefined &&
+				  ! ( data.hierarchy[ h ].keys[ k ].rot instanceof THREE.Quaternion ) ) {
+
+					var quat = data.hierarchy[ h ].keys[ k ].rot;
+					data.hierarchy[ h ].keys[ k ].rot = new THREE.Quaternion().fromArray( quat );
+
+				}
+
+			}
+
+			// prepare morph target keys
+
+			if ( data.hierarchy[ h ].keys.length && data.hierarchy[ h ].keys[ 0 ].morphTargets !== undefined ) {
+
+				// get all used
+
+				var usedMorphTargets = {};
+
+				for ( var k = 0; k < data.hierarchy[ h ].keys.length; k ++ ) {
+
+					for ( var m = 0; m < data.hierarchy[ h ].keys[ k ].morphTargets.length; m ++ ) {
+
+						var morphTargetName = data.hierarchy[ h ].keys[ k ].morphTargets[ m ];
+						usedMorphTargets[ morphTargetName ] = - 1;
+
+					}
+
+				}
+
+				data.hierarchy[ h ].usedMorphTargets = usedMorphTargets;
+
+
+				// set all used on all frames
+
+				for ( var k = 0; k < data.hierarchy[ h ].keys.length; k ++ ) {
+
+					var influences = {};
+
+					for ( var morphTargetName in usedMorphTargets ) {
+
+						for ( var m = 0; m < data.hierarchy[ h ].keys[ k ].morphTargets.length; m ++ ) {
+
+							if ( data.hierarchy[ h ].keys[ k ].morphTargets[ m ] === morphTargetName ) {
+
+								influences[ morphTargetName ] = data.hierarchy[ h ].keys[ k ].morphTargetsInfluences[ m ];
+								break;
+
+							}
+
+						}
+
+						if ( m === data.hierarchy[ h ].keys[ k ].morphTargets.length ) {
+
+							influences[ morphTargetName ] = 0;
+
+						}
+
+					}
+
+					data.hierarchy[ h ].keys[ k ].morphTargetsInfluences = influences;
+
+				}
+
+			}
+
+
+			// remove all keys that are on the same time
+
+			for ( var k = 1; k < data.hierarchy[ h ].keys.length; k ++ ) {
+
+				if ( data.hierarchy[ h ].keys[ k ].time === data.hierarchy[ h ].keys[ k - 1 ].time ) {
+
+					data.hierarchy[ h ].keys.splice( k, 1 );
+					k --;
+
+				}
+
+			}
+
+
+			// set index
+
+			for ( var k = 0; k < data.hierarchy[ h ].keys.length; k ++ ) {
+
+				data.hierarchy[ h ].keys[ k ].index = k;
+
+			}
+
+		}
+
+		data.initialized = true;
+
+		return data;
+
+	}
+};
+
+

+ 21 - 0
src/animation/ConstantTrack.js

@@ -0,0 +1,21 @@
+
+
+THREE.ConstantTrack = function ( name, value ) {
+
+	this.value = value || null;
+
+	THREE.Track.call( this, name );
+
+};
+
+THREE.ConstantTrack.prototype = {
+
+	constructor: THREE.ConstantTrack,
+
+	getAt: function( time ) {
+
+		return this.value;
+
+	}
+
+};

+ 53 - 0
src/animation/KeyframeTrack.js

@@ -0,0 +1,53 @@
+
+
+THREE.KeyframeTrack = function ( name, keys ) {
+
+	this.keys = keys || [];	// time in seconds, value as value
+
+	// TODO: sort keys via their times
+	this.keys.sort( function( a, b ) { return a.time < b.time; } );
+
+	THREE.Track.call( this, name );
+
+};
+
+THREE.KeyframeTrack.prototype = {
+
+	constructor: THREE.Track,
+
+	getAt: function( time ) {
+
+		if( this.keys.length == 0 ) throw new Error( "no keys in track named " + this.name );
+		
+		// before the start of the track, return the first key value
+		if( this.keys[0].time >= time ) {
+
+			return this.keys[0].value;
+
+		}
+
+		// past the end of the track, return the last key value
+		if( this.keys[ this.keys.length - 1 ].time <= time ) {
+
+			return this.keys[ this.keys.length - 1 ].value;
+
+		}
+
+		// interpolate to the required time
+		for( var i = 1; i < this.keys.length; i ++ ) {
+
+			if( time <= this.keys[ i ].time ) {
+
+				// linear interpolation to start with
+				var alpha = ( time - this.keys[ i - 1 ].time ) / ( this.keys[ i ].time - this.keys[ i - 1 ].time );
+
+				return THREE.AnimationUtils.lerp( this.keys[ i - 1 ].value, this.keys[ i ].value, alpha );
+
+			}
+		}
+
+		throw new Error( "should never get here." );
+
+	};
+
+};

+ 78 - 0
src/animation/Mixer.js

@@ -0,0 +1,78 @@
+/**
+ * @author Ben Houston / http://clara.io/
+ * @author David Sarno / http://lighthaus.us/
+ */
+
+THREE.Mixer = function( root ) {
+
+	this.root = root;
+	this.actions = [];
+	this.trackInfos = {};
+
+};
+
+THREE.Mixer.prototype = {
+
+	constructor: THREE.Mixer,
+
+	addAction: function( action ) {
+
+		this.actions.push( action );
+
+		foreach( var track in action.tracks ) {
+			if( ! this.trackInfos[track.name] ) {
+				this.trackInfos[track.name] = {
+					node: THREE.AnimationUtils.findNode( this.root, track.nodeName ),
+					propertyName: track.propertyName
+				} 
+			}
+		}
+
+	},
+
+	update: function( time ) {
+
+		var mixerResults = {};
+
+		for( var i = 0; i < this.actions.length; i ++ ) {
+
+			var action = this.actions[i];
+
+			var actionResults = action.update( time );
+
+			foreach( var result in actionResults ) {
+
+				// TODO: do iterative linear interpolator based on cumulative weight ratios
+				mixerResults[result.name].value = result.value;
+
+			}
+
+		}
+
+		// apply to nodes
+		foreach( var mixerResult in mixerResults ) {
+
+			var trackInfo = this.trackInfos[mixerResult.name];
+
+			// must use copy for Object3D.Euler/Quaternion
+			if( trackInfo.node[trackInfo.propertyName].copy ) {
+				trackInfo.node[trackInfo.propertyName].copy( mixerResult.value );
+			}
+			// otherwise just copy across value
+			else {
+				trackInfo.node[trackInfo.propertyName] = mixerResult.value;	
+			}
+
+
+			// trigger node dirty			
+			if( trackInfo.node.needsUpdate ) { // material
+				trackInfo.node.needsUpdate = true;
+			}			
+			if( trackInfo.node.matrixWorldNeedsUpdate && ! this.matrixAutoUpdate ) { // node transform
+				trackInfo.node.matrixWorldNeedsUpdate = true;
+			}
+			
+		}
+	}
+
+};

+ 41 - 0
src/animation/Track.js

@@ -0,0 +1,41 @@
+
+THREE.Track = function ( name ) {
+
+	this.name = name;
+
+	var nodeName = "";
+	var propertyName = "";
+
+	if( name.indexOf( '.') >= 0 ) {
+		var nameTokens = name.split( '.' );
+		if( nameTokens.length > 1 ) {
+			nodeName = nameTokens[0];
+		}
+		if( nameTokens.length > 2 ) {
+			propertyName = nameTokens[1];
+		}
+	}
+
+	if( nodeName.indexOf( '/' ) >= 0 ) {
+		var nodeNameTokens = nodeName.split( '/' );
+		if( nameTokens.length > 1 ) {
+			nodeName = nameTokens[nameTokens.length - 1];
+		}		
+	}
+
+	this.nodeName = nodeName;
+	this.propertyName = propertyName;
+
+};
+
+THREE.Track.prototype = {
+
+	constructor: THREE.Track,
+
+	getAt: function( time ) {
+
+		return null;
+
+	}
+
+};

+ 0 - 488
src/objects/Clip.js

@@ -1,488 +0,0 @@
-	/**
- * @author Ben Houston / http://clara.io/
- * @author David Sarno / http://lighthaus.us/
- */
-
- THREE.AnimationMath = {
-
- 	lerp: function( a, b, alpha ) {
-
-		if( a.lerp ) {
-
-			return a.clone().lerp( b, alpha );
-
-		}
-		else if( a.slerp ) {
-
-			return a.clone().lerp( b, alpha );
-
-		}
-		else {
-
-			return a * ( 1 - alpha ) + b * alpha;
-			
-		}
-	}
-
-};
-
-THREE.Mixer = function( root ) {
-
-	this.root = root;
-	this.actions = [];
-	this.trackInfos = {};
-
-};
-
-THREE.Mixer.prototype = {
-
-	constructor: THREE.Mixer,
-
-	addAction: function( action ) {
-
-		this.actions.push( action );
-
-		foreach( var track in action.tracks ) {
-			if( ! this.trackInfos[track.name] ) {
-				this.trackInfos[track.name] = {
-					node: this.findNode( track.nodeName ),
-					propertyName: track.propertyName
-				} 
-			}
-		}
-
-	},
-
-	update: function( time ) {
-
-		var mixerResults = {};
-
-		for( var i = 0; i < this.actions.length; i ++ ) {
-
-			var action = this.actions[i];
-
-			var actionResults = action.update( time );
-
-			foreach( var result in actionResults ) {
-
-				// TODO: do iterative linear interpolator based on cumulative weight ratios
-				mixerResults[result.name].value = result.value;
-
-			}
-
-		}
-
-		// apply to nodes
-		foreach( var mixerResult in mixerResults ) {
-			var trackInfo = this.trackInfos[mixerResult.name];
-
-			// must use copy for Object3D.Euler/Quaternion
-			if( trackInfo.node[trackInfo.propertyName].copy ) {
-				trackInfo.node[trackInfo.propertyName].copy( mixerResult.value );
-			}
-			else {
-				trackInfo.node[trackInfo.propertyName] = mixerResult.value;	
-			}
-
-
-			// material
-			if( trackInfo.node.needsUpdate ) {
-				trackInfo.node.needsUpdate = true;
-			}
-			// node transform
-			if( trackInfo.node.matrixWorldNeedsUpdate && ! this.matrixAutoUpdate ) {
-				trackInfo.node.matrixWorldNeedsUpdate = true;
-			}
-		}
-	},
-
-	// TODO: Cache this at some point
-	findNode: function( name ) {
-
-		if( ! nodeName || nodeName === "" || nodeName === "root" || nodeName === "." || nodeName === -1 ) {
-
-			return this.root;
-
-		}
-
-		// (2) search into skeleton bones.
-		{
-
-			var searchSkeleton = function( skeleton ) {
-
-				for( var i = 0; i < skeleton.bones.length; i ++ ) {
-
-					var bone = skeleton.bones[i];
-
-					if( bone.name === nodeName ) {
-
-						return childNode;
-
-					}
-				}
-
-				return null;
-
-			};
-
-			var boneNode = searchSkeleton( this.skeleton );
-
-			if( boneNode ) return boneNode;
-		}
-
-		// (3) search into node subtree.
-		{
-
-			var searchNodeSubtree = function( currentNode ) {
-
-				for( var i = 0; i < currentNode.children.length; i ++ ) {
-
-					var childNode = currentNode.children[i];
-
-					if( childNode.name === nodeName ) {
-
-						return childNode;
-
-					}
-
-					var result = searchNodeSubtree( childNode );
-
-					if( result ) return result;
-
-				}
-
-				return null;	
-
-			};
-
-			var subTreeNode = searchNodeSubtree( this.root );
-
-			if( subTreeNode ) return subTreeNode;
-
-		}
-
-		throw new Error( "no node found for name: " + name );
-
-		return node;
-	}
-
-
-};
-
-
-THREE.Action = function ( clip, startTime, timeScale, weight, loop ) {
-
-	this.clip = clip;
-	this.startTime = startTime || 0;
-	this.timeScale = timeScale || 1;
-	this.weight = weight || 1;
-	this.loop = loop || false;
-
-	this.cache = {}; // track name, track, last evaluated time, last evaluated value (with weight included), keyIndex.
-};
-
-THREE.Action.prototype = {
-
-	constructor: THREE.Action,
-
-	toClipTime: function( time ) {
-
-		var clipTime = time - this.startTime;
-
-		clipTime *= this.timeScale;
-
-		if( this.loop ) {
-
-			if( clipTime < 0 ) {
-
-				clipTime = clipTime - Math.floor( clipTime / this.clip.duration ) * this.clip.duration;
-
-			}
-
-	   		clipTime = clipTime % this.clip.duration;
-
-	   	}
-	   	else {
-
-	   		clipTime = Math.min( clipTime, this.clip.duration );
-	   		clipTime = Math.max( clipTime, 0 );
-
-	   	}
-
-   		return clipTime;
-	}
-
-	getAt: function( time ) {
-
-		var clipTime = this.toClipTime( time );
-
-		var results = {};
-
-		foreach( var name in clip.tracks ) {
-
-			var track = clip.tracks[name];
-
-			var value = track.getAt( time );
-
-			results[name] = value;
-		}
-
-		return results;
-	}
-
-};
-
-
-THREE.Track = function ( name ) {
-
-	this.name = name;
-
-	var nodeName = "";
-	var propertyName = "";
-
-	if( name.indexOf( '.') >= 0 ) {
-		var nameTokens = name.split( '.' );
-		if( nameTokens.length > 1 ) {
-			nodeName = nameTokens[0];
-		}
-		if( nameTokens.length > 2 ) {
-			propertyName = nameTokens[1];
-		}
-	}
-
-	if( nodeName.indexOf( '/' ) >= 0 ) {
-		var nodeNameTokens = nodeName.split( '/' );
-		if( nameTokens.length > 1 ) {
-			nodeName = nameTokens[nameTokens.length - 1];
-		}		
-	}
-
-	this.nodeName = nodeName;
-	this.propertyName = propertyName;
-
-};
-
-THREE.Track.prototype = {
-
-	constructor: THREE.Track,
-
-	getAt: function( time ) {
-
-		return null;
-
-	}
-
-};
-
-THREE.ConstantTrack = function ( name, value ) {
-
-	this.value = value || null;
-
-	THREE.Track.call( this, name );
-
-};
-
-THREE.ConstantTrack.prototype = {
-
-	constructor: THREE.ConstantTrack,
-
-	getAt: function( time ) {
-
-		return this.value;
-
-	}
-
-};
-
-THREE.KeyframeTrack = function ( name, keys ) {
-
-	this.keys = keys || [];	// time in seconds, value as value
-
-	// TODO: sort keys via their times
-	this.keys.sort( function( a, b ) { return a.time < b.time; } );
-
-	THREE.Track.call( this, name );
-
-};
-
-THREE.KeyframeTrack.prototype = {
-
-	constructor: THREE.Track,
-
-	getAt: function( time ) {
-
-		if( this.keys.length == 0 ) throw new Error( "no keys in track named " + this.name );
-		
-		// before the start of the track, return the first key value
-		if( this.keys[0].time >= time ) {
-
-			return this.keys[0].value;
-
-		}
-
-		// past the end of the track, return the last key value
-		if( this.keys[ this.keys.length - 1 ].time <= time ) {
-
-			return this.keys[ this.keys.length - 1 ].value;
-
-		}
-
-		// interpolate to the required time
-		for( var i = 1; i < this.keys.length; i ++ ) {
-
-			if( time <= this.keys[ i ].time ) {
-
-				// linear interpolation to start with
-				var alpha = ( time - this.keys[ i - 1 ].time ) / ( this.keys[ i ].time - this.keys[ i - 1 ].time );
-
-				return THREE.AnimationMath.lerp( this.keys[ i - 1 ].value, this.keys[ i ].value, alpha );
-
-			}
-		}
-
-		throw new Error( "should never get here." );
-
-	};
-
-};
-
-
-
-
-THREE.Clip = function ( name, duration, tracks, loop ) {
-
-	this.tracks = tracks;
-
-	this.duration = 0;
-	this.timeScale = 1;
-
-	this.loop = true;
-	this.weight = 0;
-
-	this.interpolationType = THREE.AnimationHandler.LINEAR;
-
-};
-
-THREE.Clip.prototype = {
-
-	constructor: THREE.Clip,
-
-	keyTypes:  [ "pos", "rot", "scl" ],
-
-	play:
-
-		init: function ( data ) {
-
-		if ( data.initialized === true ) return data;
-
-		// loop through all keys
-
-		for ( var h = 0; h < data.hierarchy.length; h ++ ) {
-
-			for ( var k = 0; k < data.hierarchy[ h ].keys.length; k ++ ) {
-
-				// remove minus times
-
-				if ( data.hierarchy[ h ].keys[ k ].time < 0 ) {
-
-					 data.hierarchy[ h ].keys[ k ].time = 0;
-
-				}
-
-				// create quaternions
-
-				if ( data.hierarchy[ h ].keys[ k ].rot !== undefined &&
-				  ! ( data.hierarchy[ h ].keys[ k ].rot instanceof THREE.Quaternion ) ) {
-
-					var quat = data.hierarchy[ h ].keys[ k ].rot;
-					data.hierarchy[ h ].keys[ k ].rot = new THREE.Quaternion().fromArray( quat );
-
-				}
-
-			}
-
-			// prepare morph target keys
-
-			if ( data.hierarchy[ h ].keys.length && data.hierarchy[ h ].keys[ 0 ].morphTargets !== undefined ) {
-
-				// get all used
-
-				var usedMorphTargets = {};
-
-				for ( var k = 0; k < data.hierarchy[ h ].keys.length; k ++ ) {
-
-					for ( var m = 0; m < data.hierarchy[ h ].keys[ k ].morphTargets.length; m ++ ) {
-
-						var morphTargetName = data.hierarchy[ h ].keys[ k ].morphTargets[ m ];
-						usedMorphTargets[ morphTargetName ] = - 1;
-
-					}
-
-				}
-
-				data.hierarchy[ h ].usedMorphTargets = usedMorphTargets;
-
-
-				// set all used on all frames
-
-				for ( var k = 0; k < data.hierarchy[ h ].keys.length; k ++ ) {
-
-					var influences = {};
-
-					for ( var morphTargetName in usedMorphTargets ) {
-
-						for ( var m = 0; m < data.hierarchy[ h ].keys[ k ].morphTargets.length; m ++ ) {
-
-							if ( data.hierarchy[ h ].keys[ k ].morphTargets[ m ] === morphTargetName ) {
-
-								influences[ morphTargetName ] = data.hierarchy[ h ].keys[ k ].morphTargetsInfluences[ m ];
-								break;
-
-							}
-
-						}
-
-						if ( m === data.hierarchy[ h ].keys[ k ].morphTargets.length ) {
-
-							influences[ morphTargetName ] = 0;
-
-						}
-
-					}
-
-					data.hierarchy[ h ].keys[ k ].morphTargetsInfluences = influences;
-
-				}
-
-			}
-
-
-			// remove all keys that are on the same time
-
-			for ( var k = 1; k < data.hierarchy[ h ].keys.length; k ++ ) {
-
-				if ( data.hierarchy[ h ].keys[ k ].time === data.hierarchy[ h ].keys[ k - 1 ].time ) {
-
-					data.hierarchy[ h ].keys.splice( k, 1 );
-					k --;
-
-				}
-
-			}
-
-
-			// set index
-
-			for ( var k = 0; k < data.hierarchy[ h ].keys.length; k ++ ) {
-
-				data.hierarchy[ h ].keys[ k ].index = k;
-
-			}
-
-		}
-
-		data.initialized = true;
-
-		return data;
-
-	},