KeyFrameAnimation.js 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  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 = {
  37. constructor: THREE.KeyFrameAnimation,
  38. play: function ( startTime ) {
  39. this.currentTime = startTime !== undefined ? startTime : 0;
  40. if ( this.isPlaying === false ) {
  41. this.isPlaying = true;
  42. // reset key cache
  43. var h, hl = this.hierarchy.length,
  44. object,
  45. node;
  46. for ( h = 0; h < hl; h ++ ) {
  47. object = this.hierarchy[ h ];
  48. node = this.data.hierarchy[ h ];
  49. if ( node.animationCache === undefined ) {
  50. node.animationCache = {};
  51. node.animationCache.prevKey = null;
  52. node.animationCache.nextKey = null;
  53. node.animationCache.originalMatrix = object.matrix;
  54. }
  55. var keys = this.data.hierarchy[ h ].keys;
  56. if ( keys.length > 1 ) {
  57. node.animationCache.prevKey = keys[ 0 ];
  58. node.animationCache.nextKey = keys[ 1 ];
  59. this.startTime = Math.min( keys[ 0 ].time, this.startTime );
  60. this.endTime = Math.max( keys[ keys.length - 1 ].time, this.endTime );
  61. }
  62. }
  63. this.update( 0 );
  64. }
  65. this.isPaused = false;
  66. },
  67. stop: function () {
  68. this.isPlaying = false;
  69. this.isPaused = false;
  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. original.copy( obj.matrix );
  77. obj.matrix = original;
  78. delete node.animationCache;
  79. }
  80. }
  81. },
  82. update: function ( delta ) {
  83. if ( this.isPlaying === false ) return;
  84. this.currentTime += delta * this.timeScale;
  85. //
  86. var duration = this.data.length;
  87. if ( this.loop === true && this.currentTime > duration ) {
  88. this.currentTime %= duration;
  89. }
  90. this.currentTime = Math.min( this.currentTime, duration );
  91. for ( var h = 0, hl = this.hierarchy.length; h < hl; h ++ ) {
  92. var object = this.hierarchy[ h ];
  93. var node = this.data.hierarchy[ h ];
  94. var keys = node.keys,
  95. animationCache = node.animationCache;
  96. if ( keys.length ) {
  97. var prevKey = animationCache.prevKey;
  98. var nextKey = animationCache.nextKey;
  99. if ( nextKey.time <= this.currentTime ) {
  100. while ( nextKey.time < this.currentTime && nextKey.index > prevKey.index ) {
  101. prevKey = nextKey;
  102. nextKey = keys[ prevKey.index + 1 ];
  103. }
  104. animationCache.prevKey = prevKey;
  105. animationCache.nextKey = nextKey;
  106. }
  107. if ( nextKey.time >= this.currentTime ) {
  108. prevKey.interpolate( nextKey, this.currentTime );
  109. } else {
  110. prevKey.interpolate( nextKey, nextKey.time );
  111. }
  112. this.data.hierarchy[ h ].node.updateMatrix();
  113. object.matrixWorldNeedsUpdate = true;
  114. }
  115. }
  116. },
  117. getNextKeyWith: function ( sid, h, key ) {
  118. var keys = this.data.hierarchy[ h ].keys;
  119. key = key % keys.length;
  120. for ( ; key < keys.length; key ++ ) {
  121. if ( keys[ key ].hasTarget( sid ) ) {
  122. return keys[ key ];
  123. }
  124. }
  125. return keys[ 0 ];
  126. },
  127. getPrevKeyWith: function ( sid, h, key ) {
  128. var keys = this.data.hierarchy[ h ].keys;
  129. key = key >= 0 ? key : key + keys.length;
  130. for ( ; key >= 0; key -- ) {
  131. if ( keys[ key ].hasTarget( sid ) ) {
  132. return keys[ key ];
  133. }
  134. }
  135. return keys[ keys.length - 1 ];
  136. }
  137. };