123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422 |
- /**
- * @author mikael emtinger / http://gomo.se/
- * @author mrdoob / http://mrdoob.com/
- * @author alteredq / http://alteredqualia.com/
- * @author khang duong
- * @author erik kitson
- */
- THREE.KeyFrameAnimation = function( root, data, JITCompile ) {
- this.root = root;
- this.data = THREE.AnimationHandler.get( data );
- this.hierarchy = THREE.AnimationHandler.parse( root );
- this.currentTime = 0;
- this.timeScale = 0.001;
- this.isPlaying = false;
- this.isPaused = true;
- this.loop = true;
- this.JITCompile = JITCompile !== undefined ? JITCompile : true;
- // initialize to first keyframes
- for ( var h = 0, hl = this.hierarchy.length; h < hl; h++ ) {
- var keys = this.data.hierarchy[h].keys,
- sids = this.data.hierarchy[h].sids,
- obj = this.hierarchy[h];
- if ( keys.length && sids ) {
- for ( var s = 0; s < sids.length; s++ ) {
- var sid = sids[ s ],
- next = this.getNextKeyWith( sid, h, 0 );
- if ( next ) {
- next.apply( sid );
- }
- }
- obj.matrixAutoUpdate = false;
- this.data.hierarchy[h].node.updateMatrix();
- obj.matrixWorldNeedsUpdate = true;
- }
- }
- };
- // Play
- THREE.KeyFrameAnimation.prototype.play = function( loop, startTimeMS ) {
- if( !this.isPlaying ) {
- this.isPlaying = true;
- this.loop = loop !== undefined ? loop : true;
- this.currentTime = startTimeMS !== undefined ? startTimeMS : 0;
- this.startTimeMs = startTimeMS;
- this.startTime = 10000000;
- this.endTime = -this.startTime;
- // reset key cache
- var h, hl = this.hierarchy.length,
- object,
- node;
- for ( h = 0; h < hl; h++ ) {
- object = this.hierarchy[ h ];
- node = this.data.hierarchy[ h ];
- if ( node.animationCache === undefined ) {
- node.animationCache = {};
- node.animationCache.prevKey = null;
- node.animationCache.nextKey = null;
- node.animationCache.originalMatrix = object instanceof THREE.Bone ? object.skinMatrix : object.matrix;
- }
- var keys = this.data.hierarchy[h].keys;
- if (keys.length) {
- node.animationCache.prevKey = keys[ 0 ];
- node.animationCache.nextKey = keys[ 1 ];
- this.startTime = Math.min( keys[0].time, this.startTime );
- this.endTime = Math.max( keys[keys.length - 1].time, this.endTime );
- }
- }
- this.update( 0 );
- }
- this.isPaused = false;
- THREE.AnimationHandler.addToUpdate( this );
- };
- // Pause
- THREE.KeyFrameAnimation.prototype.pause = function() {
- if( this.isPaused ) {
- THREE.AnimationHandler.addToUpdate( this );
- } else {
- THREE.AnimationHandler.removeFromUpdate( this );
- }
- this.isPaused = !this.isPaused;
- };
- // Stop
- THREE.KeyFrameAnimation.prototype.stop = function() {
- this.isPlaying = false;
- this.isPaused = false;
- THREE.AnimationHandler.removeFromUpdate( this );
- // reset JIT matrix and remove cache
- for ( var h = 0; h < this.data.hierarchy.length; h++ ) {
-
- var obj = this.hierarchy[ h ];
- var node = this.data.hierarchy[ h ];
- if ( node.animationCache !== undefined ) {
- var original = node.animationCache.originalMatrix;
- if( obj instanceof THREE.Bone ) {
- original.copy( obj.skinMatrix );
- obj.skinMatrix = original;
- } else {
- original.copy( obj.matrix );
- obj.matrix = original;
- }
- delete node.animationCache;
- }
- }
- };
- // Update
- THREE.KeyFrameAnimation.prototype.update = function( deltaTimeMS ) {
- // early out
- if( !this.isPlaying ) return;
- // vars
- var prevKey, nextKey;
- var object;
- var node;
- var frame;
- var JIThierarchy = this.data.JIT.hierarchy;
- var currentTime, unloopedCurrentTime;
- var looped;
- // update
- this.currentTime += deltaTimeMS * this.timeScale;
- unloopedCurrentTime = this.currentTime;
- currentTime = this.currentTime = this.currentTime % this.data.length;
- // if looped around, the current time should be based on the startTime
- if ( currentTime < this.startTimeMs ) {
- currentTime = this.currentTime = this.startTimeMs + currentTime;
- }
- frame = parseInt( Math.min( currentTime * this.data.fps, this.data.length * this.data.fps ), 10 );
- looped = currentTime < unloopedCurrentTime;
- if ( looped && !this.loop ) {
- // Set the animation to the last keyframes and stop
- for ( var h = 0, hl = this.hierarchy.length; h < hl; h++ ) {
- var keys = this.data.hierarchy[h].keys,
- sids = this.data.hierarchy[h].sids,
- end = keys.length-1,
- obj = this.hierarchy[h];
- if ( keys.length ) {
- for ( var s = 0; s < sids.length; s++ ) {
- var sid = sids[ s ],
- prev = this.getPrevKeyWith( sid, h, end );
- if ( prev ) {
- prev.apply( sid );
- }
- }
- this.data.hierarchy[h].node.updateMatrix();
- obj.matrixWorldNeedsUpdate = true;
- }
- }
- this.stop();
- return;
- }
- // check pre-infinity
- if ( currentTime < this.startTime ) {
- return;
- }
- // update
- for ( var h = 0, hl = this.hierarchy.length; h < hl; h++ ) {
- object = this.hierarchy[ h ];
- node = this.data.hierarchy[ h ];
- var keys = node.keys,
- animationCache = node.animationCache;
- // use JIT?
- if ( this.JITCompile && JIThierarchy[ h ][ frame ] !== undefined ) {
- if( object instanceof THREE.Bone ) {
- object.skinMatrix = JIThierarchy[ h ][ frame ];
- object.matrixWorldNeedsUpdate = false;
- } else {
- object.matrix = JIThierarchy[ h ][ frame ];
- object.matrixWorldNeedsUpdate = true;
- }
- // use interpolation
- } else if ( keys.length ) {
- // make sure so original matrix and not JIT matrix is set
- if ( this.JITCompile && animationCache ) {
- if( object instanceof THREE.Bone ) {
- object.skinMatrix = animationCache.originalMatrix;
- } else {
- object.matrix = animationCache.originalMatrix;
- }
- }
- prevKey = animationCache.prevKey;
- nextKey = animationCache.nextKey;
- if ( prevKey && nextKey ) {
- // switch keys?
- if ( nextKey.time <= unloopedCurrentTime ) {
- // did we loop?
- if ( looped && this.loop ) {
- prevKey = keys[ 0 ];
- nextKey = keys[ 1 ];
- while ( nextKey.time < currentTime ) {
- prevKey = nextKey;
- nextKey = keys[ prevKey.index + 1 ];
- }
- } else if ( !looped ) {
- var lastIndex = keys.length - 1;
- while ( nextKey.time < currentTime && nextKey.index !== lastIndex ) {
- prevKey = nextKey;
- nextKey = keys[ prevKey.index + 1 ];
- }
- }
- animationCache.prevKey = prevKey;
- animationCache.nextKey = nextKey;
- }
- if(nextKey.time >= currentTime)
- prevKey.interpolate( nextKey, currentTime );
- else
- prevKey.interpolate( nextKey, nextKey.time);
- }
- this.data.hierarchy[h].node.updateMatrix();
- object.matrixWorldNeedsUpdate = true;
- }
- }
- // update JIT?
- if ( this.JITCompile ) {
- if ( JIThierarchy[ 0 ][ frame ] === undefined ) {
- this.hierarchy[ 0 ].updateMatrixWorld( true );
- for ( var h = 0; h < this.hierarchy.length; h++ ) {
- if( this.hierarchy[ h ] instanceof THREE.Bone ) {
- JIThierarchy[ h ][ frame ] = this.hierarchy[ h ].skinMatrix.clone();
- } else {
- JIThierarchy[ h ][ frame ] = this.hierarchy[ h ].matrix.clone();
- }
- }
- }
- }
- };
- // Get next key with
- THREE.KeyFrameAnimation.prototype.getNextKeyWith = function( sid, h, key ) {
- var keys = this.data.hierarchy[ h ].keys;
- key = key % keys.length;
- for ( ; key < keys.length; key++ ) {
- if ( keys[ key ].hasTarget( sid ) ) {
- return keys[ key ];
- }
- }
- return keys[ 0 ];
- };
- // Get previous key with
- THREE.KeyFrameAnimation.prototype.getPrevKeyWith = function( sid, h, key ) {
- var keys = this.data.hierarchy[ h ].keys;
- key = key >= 0 ? key : key + keys.length;
- for ( ; key >= 0; key-- ) {
- if ( keys[ key ].hasTarget( sid ) ) {
- return keys[ key ];
- }
- }
- return keys[ keys.length - 1 ];
- };
|