KeyFrameAnimation.js 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
  1. /**
  2. * @author mikael emtinger / http://gomo.se/
  3. * @author mrdoob / http://mrdoob.com/
  4. * @author alteredq / http://alteredqualia.com/
  5. * @author khang duong
  6. * @author erik kitson
  7. */
  8. THREE.KeyFrameAnimation = function ( data ) {
  9. this.root = data.node;
  10. this.data = THREE.AnimationHandler.init( data );
  11. this.hierarchy = THREE.AnimationHandler.parse( this.root );
  12. this.currentTime = 0;
  13. this.timeScale = 0.001;
  14. this.isPlaying = false;
  15. this.isPaused = true;
  16. this.loop = true;
  17. // initialize to first keyframes
  18. for ( var h = 0, hl = this.hierarchy.length; h < hl; h ++ ) {
  19. var keys = this.data.hierarchy[h].keys,
  20. sids = this.data.hierarchy[h].sids,
  21. obj = this.hierarchy[h];
  22. if ( keys.length && sids ) {
  23. for ( var s = 0; s < sids.length; s++ ) {
  24. var sid = sids[ s ],
  25. next = this.getNextKeyWith( sid, h, 0 );
  26. if ( next ) {
  27. next.apply( sid );
  28. }
  29. }
  30. obj.matrixAutoUpdate = false;
  31. this.data.hierarchy[h].node.updateMatrix();
  32. obj.matrixWorldNeedsUpdate = true;
  33. }
  34. }
  35. };
  36. THREE.KeyFrameAnimation.prototype.play = function ( startTime ) {
  37. this.currentTime = startTime !== undefined ? startTime : 0;
  38. if ( this.isPlaying === false ) {
  39. this.isPlaying = true;
  40. // reset key cache
  41. var h, hl = this.hierarchy.length,
  42. object,
  43. node;
  44. for ( h = 0; h < hl; h++ ) {
  45. object = this.hierarchy[ h ];
  46. node = this.data.hierarchy[ h ];
  47. if ( node.animationCache === undefined ) {
  48. node.animationCache = {};
  49. node.animationCache.prevKey = null;
  50. node.animationCache.nextKey = null;
  51. node.animationCache.originalMatrix = object instanceof THREE.Bone ? object.skinMatrix : object.matrix;
  52. }
  53. var keys = this.data.hierarchy[h].keys;
  54. if (keys.length) {
  55. node.animationCache.prevKey = keys[ 0 ];
  56. node.animationCache.nextKey = keys[ 1 ];
  57. this.startTime = Math.min( keys[0].time, this.startTime );
  58. this.endTime = Math.max( keys[keys.length - 1].time, this.endTime );
  59. }
  60. }
  61. this.update( 0 );
  62. }
  63. this.isPaused = false;
  64. THREE.AnimationHandler.play( this );
  65. };
  66. THREE.KeyFrameAnimation.prototype.stop = function() {
  67. this.isPlaying = false;
  68. this.isPaused = false;
  69. THREE.AnimationHandler.stop( this );
  70. // reset JIT matrix and remove cache
  71. for ( var h = 0; h < this.data.hierarchy.length; h++ ) {
  72. var obj = this.hierarchy[ h ];
  73. var node = this.data.hierarchy[ h ];
  74. if ( node.animationCache !== undefined ) {
  75. var original = node.animationCache.originalMatrix;
  76. if( obj instanceof THREE.Bone ) {
  77. original.copy( obj.skinMatrix );
  78. obj.skinMatrix = original;
  79. } else {
  80. original.copy( obj.matrix );
  81. obj.matrix = original;
  82. }
  83. delete node.animationCache;
  84. }
  85. }
  86. };
  87. // Update
  88. THREE.KeyFrameAnimation.prototype.update = function ( delta ) {
  89. if ( this.isPlaying === false ) return;
  90. this.currentTime += delta * this.timeScale;
  91. //
  92. var duration = this.data.length;
  93. if ( this.loop === true && this.currentTime > duration ) {
  94. this.currentTime %= duration;
  95. }
  96. this.currentTime = Math.min( this.currentTime, duration );
  97. for ( var h = 0, hl = this.hierarchy.length; h < hl; h++ ) {
  98. var object = this.hierarchy[ h ];
  99. var node = this.data.hierarchy[ h ];
  100. var keys = node.keys,
  101. animationCache = node.animationCache;
  102. if ( keys.length ) {
  103. var prevKey = animationCache.prevKey;
  104. var nextKey = animationCache.nextKey;
  105. if ( nextKey.time <= this.currentTime ) {
  106. while ( nextKey.time < this.currentTime && nextKey.index > prevKey.index ) {
  107. prevKey = nextKey;
  108. nextKey = keys[ prevKey.index + 1 ];
  109. }
  110. animationCache.prevKey = prevKey;
  111. animationCache.nextKey = nextKey;
  112. }
  113. if ( nextKey.time >= this.currentTime ) {
  114. prevKey.interpolate( nextKey, this.currentTime );
  115. } else {
  116. prevKey.interpolate( nextKey, nextKey.time );
  117. }
  118. this.data.hierarchy[ h ].node.updateMatrix();
  119. object.matrixWorldNeedsUpdate = true;
  120. }
  121. }
  122. };
  123. // Get next key with
  124. THREE.KeyFrameAnimation.prototype.getNextKeyWith = function( sid, h, key ) {
  125. var keys = this.data.hierarchy[ h ].keys;
  126. key = key % keys.length;
  127. for ( ; key < keys.length; key++ ) {
  128. if ( keys[ key ].hasTarget( sid ) ) {
  129. return keys[ key ];
  130. }
  131. }
  132. return keys[ 0 ];
  133. };
  134. // Get previous key with
  135. THREE.KeyFrameAnimation.prototype.getPrevKeyWith = function( sid, h, key ) {
  136. var keys = this.data.hierarchy[ h ].keys;
  137. key = key >= 0 ? key : key + keys.length;
  138. for ( ; key >= 0; key-- ) {
  139. if ( keys[ key ].hasTarget( sid ) ) {
  140. return keys[ key ];
  141. }
  142. }
  143. return keys[ keys.length - 1 ];
  144. };