source: other-projects/playing-in-the-street/summer-2013/trunk/Playing-in-the-Street-WPF/Content/Web/mrdoob-three.js-4862f5f/src/extras/animation/KeyFrameAnimation.js@ 28897

Last change on this file since 28897 was 28897, checked in by davidb, 10 years ago

GUI front-end to server base plus web page content

File size: 7.6 KB
Line 
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
9THREE.KeyFrameAnimation = function( root, data, JITCompile ) {
10
11 this.root = root;
12 this.data = THREE.AnimationHandler.get( data );
13 this.hierarchy = THREE.AnimationHandler.parse( root );
14 this.currentTime = 0;
15 this.timeScale = 0.001;
16 this.isPlaying = false;
17 this.isPaused = true;
18 this.loop = true;
19 this.JITCompile = JITCompile !== undefined ? JITCompile : true;
20
21 // initialize to first keyframes
22
23 for ( var h = 0, hl = this.hierarchy.length; h < hl; h++ ) {
24
25 var keys = this.data.hierarchy[h].keys,
26 sids = this.data.hierarchy[h].sids,
27 obj = this.hierarchy[h];
28
29 if ( keys.length && sids ) {
30
31 for ( var s = 0; s < sids.length; s++ ) {
32
33 var sid = sids[ s ],
34 next = this.getNextKeyWith( sid, h, 0 );
35
36 if ( next ) {
37
38 next.apply( sid );
39
40 }
41
42 }
43
44 obj.matrixAutoUpdate = false;
45 this.data.hierarchy[h].node.updateMatrix();
46 obj.matrixWorldNeedsUpdate = true;
47
48 }
49
50 }
51
52};
53
54// Play
55
56THREE.KeyFrameAnimation.prototype.play = function( loop, startTimeMS ) {
57
58 if( !this.isPlaying ) {
59
60 this.isPlaying = true;
61 this.loop = loop !== undefined ? loop : true;
62 this.currentTime = startTimeMS !== undefined ? startTimeMS : 0;
63 this.startTimeMs = startTimeMS;
64 this.startTime = 10000000;
65 this.endTime = -this.startTime;
66
67
68 // reset key cache
69
70 var h, hl = this.hierarchy.length,
71 object,
72 node;
73
74 for ( h = 0; h < hl; h++ ) {
75
76 object = this.hierarchy[ h ];
77 node = this.data.hierarchy[ h ];
78
79 if ( node.animationCache === undefined ) {
80
81 node.animationCache = {};
82 node.animationCache.prevKey = null;
83 node.animationCache.nextKey = null;
84 node.animationCache.originalMatrix = object instanceof THREE.Bone ? object.skinMatrix : object.matrix;
85
86 }
87
88 var keys = this.data.hierarchy[h].keys;
89
90 if (keys.length) {
91
92 node.animationCache.prevKey = keys[ 0 ];
93 node.animationCache.nextKey = keys[ 1 ];
94
95 this.startTime = Math.min( keys[0].time, this.startTime );
96 this.endTime = Math.max( keys[keys.length - 1].time, this.endTime );
97
98 }
99
100 }
101
102 this.update( 0 );
103
104 }
105
106 this.isPaused = false;
107
108 THREE.AnimationHandler.addToUpdate( this );
109
110};
111
112
113
114// Pause
115
116THREE.KeyFrameAnimation.prototype.pause = function() {
117
118 if( this.isPaused ) {
119
120 THREE.AnimationHandler.addToUpdate( this );
121
122 } else {
123
124 THREE.AnimationHandler.removeFromUpdate( this );
125
126 }
127
128 this.isPaused = !this.isPaused;
129
130};
131
132
133// Stop
134
135THREE.KeyFrameAnimation.prototype.stop = function() {
136
137 this.isPlaying = false;
138 this.isPaused = false;
139 THREE.AnimationHandler.removeFromUpdate( this );
140
141
142 // reset JIT matrix and remove cache
143
144 for ( var h = 0; h < this.data.hierarchy.length; h++ ) {
145
146 var obj = this.hierarchy[ h ];
147 var node = this.data.hierarchy[ h ];
148
149 if ( node.animationCache !== undefined ) {
150
151 var original = node.animationCache.originalMatrix;
152
153 if( obj instanceof THREE.Bone ) {
154
155 original.copy( obj.skinMatrix );
156 obj.skinMatrix = original;
157
158 } else {
159
160 original.copy( obj.matrix );
161 obj.matrix = original;
162
163 }
164
165 delete node.animationCache;
166
167 }
168
169 }
170
171};
172
173
174// Update
175
176THREE.KeyFrameAnimation.prototype.update = function( deltaTimeMS ) {
177
178 // early out
179
180 if( !this.isPlaying ) return;
181
182
183 // vars
184
185 var prevKey, nextKey;
186 var object;
187 var node;
188 var frame;
189 var JIThierarchy = this.data.JIT.hierarchy;
190 var currentTime, unloopedCurrentTime;
191 var looped;
192
193
194 // update
195
196 this.currentTime += deltaTimeMS * this.timeScale;
197
198 unloopedCurrentTime = this.currentTime;
199 currentTime = this.currentTime = this.currentTime % this.data.length;
200
201 // if looped around, the current time should be based on the startTime
202 if ( currentTime < this.startTimeMs ) {
203
204 currentTime = this.currentTime = this.startTimeMs + currentTime;
205
206 }
207
208 frame = parseInt( Math.min( currentTime * this.data.fps, this.data.length * this.data.fps ), 10 );
209 looped = currentTime < unloopedCurrentTime;
210
211 if ( looped && !this.loop ) {
212
213 // Set the animation to the last keyframes and stop
214 for ( var h = 0, hl = this.hierarchy.length; h < hl; h++ ) {
215
216 var keys = this.data.hierarchy[h].keys,
217 sids = this.data.hierarchy[h].sids,
218 end = keys.length-1,
219 obj = this.hierarchy[h];
220
221 if ( keys.length ) {
222
223 for ( var s = 0; s < sids.length; s++ ) {
224
225 var sid = sids[ s ],
226 prev = this.getPrevKeyWith( sid, h, end );
227
228 if ( prev ) {
229 prev.apply( sid );
230
231 }
232
233 }
234
235 this.data.hierarchy[h].node.updateMatrix();
236 obj.matrixWorldNeedsUpdate = true;
237
238 }
239
240 }
241
242 this.stop();
243 return;
244
245 }
246
247 // check pre-infinity
248 if ( currentTime < this.startTime ) {
249
250 return;
251
252 }
253
254 // update
255
256 for ( var h = 0, hl = this.hierarchy.length; h < hl; h++ ) {
257
258 object = this.hierarchy[ h ];
259 node = this.data.hierarchy[ h ];
260
261 var keys = node.keys,
262 animationCache = node.animationCache;
263
264 // use JIT?
265
266 if ( this.JITCompile && JIThierarchy[ h ][ frame ] !== undefined ) {
267
268 if( object instanceof THREE.Bone ) {
269
270 object.skinMatrix = JIThierarchy[ h ][ frame ];
271 object.matrixWorldNeedsUpdate = false;
272
273 } else {
274
275 object.matrix = JIThierarchy[ h ][ frame ];
276 object.matrixWorldNeedsUpdate = true;
277
278 }
279
280 // use interpolation
281
282 } else if ( keys.length ) {
283
284 // make sure so original matrix and not JIT matrix is set
285
286 if ( this.JITCompile && animationCache ) {
287
288 if( object instanceof THREE.Bone ) {
289
290 object.skinMatrix = animationCache.originalMatrix;
291
292 } else {
293
294 object.matrix = animationCache.originalMatrix;
295
296 }
297
298 }
299
300 prevKey = animationCache.prevKey;
301 nextKey = animationCache.nextKey;
302
303 if ( prevKey && nextKey ) {
304
305 // switch keys?
306
307 if ( nextKey.time <= unloopedCurrentTime ) {
308
309 // did we loop?
310
311 if ( looped && this.loop ) {
312
313 prevKey = keys[ 0 ];
314 nextKey = keys[ 1 ];
315
316 while ( nextKey.time < currentTime ) {
317
318 prevKey = nextKey;
319 nextKey = keys[ prevKey.index + 1 ];
320
321 }
322
323 } else if ( !looped ) {
324
325 var lastIndex = keys.length - 1;
326
327 while ( nextKey.time < currentTime && nextKey.index !== lastIndex ) {
328
329 prevKey = nextKey;
330 nextKey = keys[ prevKey.index + 1 ];
331
332 }
333
334 }
335
336 animationCache.prevKey = prevKey;
337 animationCache.nextKey = nextKey;
338
339 }
340 if(nextKey.time >= currentTime)
341 prevKey.interpolate( nextKey, currentTime );
342 else
343 prevKey.interpolate( nextKey, nextKey.time);
344
345 }
346
347 this.data.hierarchy[h].node.updateMatrix();
348 object.matrixWorldNeedsUpdate = true;
349
350 }
351
352 }
353
354 // update JIT?
355
356 if ( this.JITCompile ) {
357
358 if ( JIThierarchy[ 0 ][ frame ] === undefined ) {
359
360 this.hierarchy[ 0 ].updateMatrixWorld( true );
361
362 for ( var h = 0; h < this.hierarchy.length; h++ ) {
363
364 if( this.hierarchy[ h ] instanceof THREE.Bone ) {
365
366 JIThierarchy[ h ][ frame ] = this.hierarchy[ h ].skinMatrix.clone();
367
368 } else {
369
370 JIThierarchy[ h ][ frame ] = this.hierarchy[ h ].matrix.clone();
371
372 }
373
374 }
375
376 }
377
378 }
379
380};
381
382// Get next key with
383
384THREE.KeyFrameAnimation.prototype.getNextKeyWith = function( sid, h, key ) {
385
386 var keys = this.data.hierarchy[ h ].keys;
387 key = key % keys.length;
388
389 for ( ; key < keys.length; key++ ) {
390
391 if ( keys[ key ].hasTarget( sid ) ) {
392
393 return keys[ key ];
394
395 }
396
397 }
398
399 return keys[ 0 ];
400
401};
402
403// Get previous key with
404
405THREE.KeyFrameAnimation.prototype.getPrevKeyWith = function( sid, h, key ) {
406
407 var keys = this.data.hierarchy[ h ].keys;
408 key = key >= 0 ? key : key + keys.length;
409
410 for ( ; key >= 0; key-- ) {
411
412 if ( keys[ key ].hasTarget( sid ) ) {
413
414 return keys[ key ];
415
416 }
417
418 }
419
420 return keys[ keys.length - 1 ];
421
422};
Note: See TracBrowser for help on using the repository browser.