|
1 /* |
|
2 * Copyright (c) 2003 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of the License "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: KeyframeSequence implementation |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 /*! |
|
20 * \internal |
|
21 * \file |
|
22 * \brief KeyframeSequence implementation |
|
23 */ |
|
24 |
|
25 #ifndef M3G_CORE_INCLUDE |
|
26 # error included by m3g_core.c; do not compile separately. |
|
27 #endif |
|
28 |
|
29 #include "m3g_keyframesequence.h" |
|
30 #include "m3g_memory.h" |
|
31 |
|
32 /*---------------------------------------------------------------------- |
|
33 * Internal functions |
|
34 *--------------------------------------------------------------------*/ |
|
35 |
|
36 /*! |
|
37 * \internal |
|
38 * \brief Destroys this KeyframeSequence object. |
|
39 * |
|
40 * \param obj KeyframeSequence object |
|
41 */ |
|
42 static void m3gDestroyKeyframeSequence(Object *obj) |
|
43 { |
|
44 KeyframeSequence *sequence = (KeyframeSequence *) obj; |
|
45 M3G_VALIDATE_OBJECT(sequence); |
|
46 { |
|
47 Interface *m3g = M3G_INTERFACE(sequence); |
|
48 m3gFree(m3g, sequence->keyframes); |
|
49 m3gFree(m3g, sequence->keyframeTimes); |
|
50 m3gFree(m3g, sequence->inTangents); |
|
51 m3gFree(m3g, sequence->outTangents); |
|
52 m3gFree(m3g, sequence->a); |
|
53 m3gFree(m3g, sequence->b); |
|
54 } |
|
55 m3gDestroyObject(&sequence->object); |
|
56 } |
|
57 |
|
58 /*! |
|
59 * \internal |
|
60 * \brief Overloaded Object3D method. |
|
61 * |
|
62 * \param originalObj original KeyframeSequence object |
|
63 * \param cloneObj pointer to cloned KeyframeSequence object |
|
64 * \param pairs array for all object-duplicate pairs |
|
65 * \param numPairs number of pairs |
|
66 */ |
|
67 static M3Gbool m3gKeyframeSequenceDuplicate(const Object *originalObj, |
|
68 Object **cloneObj, |
|
69 Object **pairs, |
|
70 M3Gint *numPairs) |
|
71 { |
|
72 KeyframeSequence *original = (KeyframeSequence *)originalObj; |
|
73 KeyframeSequence *clone = |
|
74 (KeyframeSequence *)m3gCreateKeyframeSequence(originalObj->interface, |
|
75 original->numKeyframes, |
|
76 original->numComponents, |
|
77 original->interpolation); |
|
78 *cloneObj = (Object *)clone; |
|
79 if (*cloneObj == NULL) { |
|
80 return M3G_FALSE; |
|
81 } |
|
82 |
|
83 if(m3gObjectDuplicate(originalObj, cloneObj, pairs, numPairs)) { |
|
84 M3Gsizei n = original->numKeyframes * original->numComponents; |
|
85 |
|
86 m3gCopy(clone->keyframes, original->keyframes, n * sizeof(M3Gfloat)); |
|
87 m3gCopy(clone->keyframeTimes, original->keyframeTimes, original->numKeyframes * sizeof(M3Gint)); |
|
88 if (original->dirty == M3G_FALSE) { |
|
89 if (original->inTangents) { |
|
90 m3gCopy(clone->inTangents, original->inTangents, n * sizeof(M3Gfloat)); |
|
91 m3gCopy(clone->outTangents, original->outTangents, n * sizeof(M3Gfloat)); |
|
92 } |
|
93 if (original->a) { |
|
94 m3gCopy(clone->a, original->a, original->numKeyframes * sizeof(Quat)); |
|
95 m3gCopy(clone->b, original->b, original->numKeyframes * sizeof(Quat)); |
|
96 } |
|
97 } |
|
98 else { |
|
99 clone->dirty = M3G_TRUE; |
|
100 } |
|
101 |
|
102 clone->duration = original->duration; |
|
103 clone->closed = original->closed; |
|
104 clone->firstValid = original->firstValid; |
|
105 clone->lastValid = original->lastValid; |
|
106 return M3G_TRUE; |
|
107 } |
|
108 else { |
|
109 return M3G_FALSE; |
|
110 } |
|
111 } |
|
112 |
|
113 /*! |
|
114 * \internal |
|
115 * \brief Initializes a KeyframeSequence object. See specification |
|
116 * for default values. |
|
117 * |
|
118 * \param m3g M3G interface |
|
119 * \param sequence KeyframeSequence object |
|
120 * \param numKeyframes number of keyframes |
|
121 * \param numComponents number of components |
|
122 * \param interpolation interpolation type |
|
123 * \retval KeyframeSequence initialized KeyframeSequence object |
|
124 * \retval NULL initialization failed |
|
125 */ |
|
126 static KeyframeSequence *m3gInitKeyframeSequence(Interface *m3g, |
|
127 KeyframeSequence *sequence, |
|
128 M3Gint numKeyframes, |
|
129 M3Gint numComponents, |
|
130 M3Gint interpolation) |
|
131 { |
|
132 m3gInitObject(&sequence->object, m3g, M3G_CLASS_KEYFRAME_SEQUENCE); |
|
133 |
|
134 /* Set keyframe parameters */ |
|
135 |
|
136 sequence->numKeyframes = numKeyframes; |
|
137 sequence->numComponents = numComponents; |
|
138 sequence->interpolation = interpolation; |
|
139 sequence->lastValid = numKeyframes - 1; /* firstValid defaults to 0 */ |
|
140 |
|
141 /* Allocate keyframe and tangent data */ |
|
142 { |
|
143 M3Gsizei n = numKeyframes * numComponents; |
|
144 |
|
145 sequence->keyframes = (M3Gfloat *)m3gAllocZ(m3g, n * sizeof(M3Gfloat)); |
|
146 if (sequence->keyframes == NULL) { |
|
147 goto AllocFailed; |
|
148 } |
|
149 sequence->keyframeTimes = (M3Gint *)m3gAllocZ(m3g, numKeyframes * sizeof(M3Gint)); |
|
150 if (sequence->keyframeTimes == NULL) { |
|
151 goto AllocFailed; |
|
152 } |
|
153 |
|
154 if (interpolation == M3G_SPLINE) { |
|
155 sequence->inTangents = (M3Gfloat *)m3gAllocZ(m3g, n * sizeof(M3Gfloat)); |
|
156 sequence->outTangents = (M3Gfloat *)m3gAllocZ(m3g, n * sizeof(M3Gfloat)); |
|
157 if (sequence->inTangents == NULL || sequence->outTangents == NULL) { |
|
158 goto AllocFailed; |
|
159 } |
|
160 } |
|
161 else if (interpolation == M3G_SQUAD) { |
|
162 sequence->a = (Quat *)m3gAlloc(m3g, numKeyframes * sizeof(Quat)); |
|
163 sequence->b = (Quat *)m3gAlloc(m3g, numKeyframes * sizeof(Quat)); |
|
164 if (sequence->a == NULL || sequence->b == NULL) { |
|
165 goto AllocFailed; |
|
166 } |
|
167 } |
|
168 |
|
169 /* Success; just make a note that the data is not valid yet */ |
|
170 |
|
171 sequence->dirty = M3G_TRUE; |
|
172 return sequence; |
|
173 |
|
174 AllocFailed: |
|
175 /* The destructor contains exactly the code we need for this, |
|
176 * so just call that */ |
|
177 |
|
178 m3gDestroyKeyframeSequence((Object*) sequence); |
|
179 return NULL; |
|
180 } |
|
181 } |
|
182 |
|
183 /*! |
|
184 * \internal |
|
185 * \brief Checks the validity of keyframe timings |
|
186 * |
|
187 * \param sequence KeyframeSequence object |
|
188 * \retval M3G_TRUE sequence valid |
|
189 * \retval M3G_FALSE sequence invalid |
|
190 */ |
|
191 static M3Gbool m3gValidSequence(const KeyframeSequence *sequence) |
|
192 { |
|
193 const M3Gint last = sequence->lastValid; |
|
194 M3Gint current = sequence->firstValid; |
|
195 |
|
196 while (current != last) { |
|
197 M3Gint next = (current < sequence->numKeyframes-1) ? current + 1 : 0; |
|
198 if (sequence->keyframeTimes[next] < sequence->keyframeTimes[current]) { |
|
199 return M3G_FALSE; |
|
200 } |
|
201 current = next; |
|
202 } |
|
203 return (sequence->keyframeTimes[last] <= sequence->duration); |
|
204 } |
|
205 |
|
206 |
|
207 /*! |
|
208 * \internal |
|
209 * \brief Get number of components |
|
210 * |
|
211 * \param sequence KeyframeSequence object |
|
212 * \return number of components |
|
213 */ |
|
214 static M3Gint m3gGetNumComponents(const KeyframeSequence *sequence) |
|
215 { |
|
216 return sequence->numComponents; |
|
217 } |
|
218 |
|
219 /*! |
|
220 * \internal |
|
221 * \brief Get next keyframe index |
|
222 * |
|
223 * \param sequence KeyframeSequence object |
|
224 * \param ind current index |
|
225 * \return next index |
|
226 */ |
|
227 static M3Gint m3gNextKeyframeIndex(const KeyframeSequence *sequence, M3Gint ind) |
|
228 { |
|
229 if (ind == sequence->lastValid) { |
|
230 return sequence->firstValid; |
|
231 } |
|
232 else if (ind == sequence->numKeyframes - 1) { |
|
233 return 0; |
|
234 } |
|
235 else { |
|
236 return (ind + 1); |
|
237 } |
|
238 } |
|
239 |
|
240 /*! |
|
241 * \internal |
|
242 * \brief Get previous keyframe index |
|
243 * |
|
244 * \param sequence KeyframeSequence object |
|
245 * \param ind current index |
|
246 * \return previous index |
|
247 */ |
|
248 static M3Gint m3gPreviousKeyframeIndex(const KeyframeSequence *sequence, M3Gint ind) |
|
249 { |
|
250 if (ind == sequence->firstValid) { |
|
251 return sequence->lastValid; |
|
252 } |
|
253 else if (ind == 0) { |
|
254 return (sequence->numKeyframes - 1); |
|
255 } |
|
256 else { |
|
257 return (ind - 1); |
|
258 } |
|
259 } |
|
260 |
|
261 /*! |
|
262 * \internal |
|
263 * \brief Get keyframe at index |
|
264 * |
|
265 * \param seq KeyframeSequence object |
|
266 * \param idx keyframe index |
|
267 * \return keyframe value |
|
268 */ |
|
269 static M3G_INLINE const M3Gfloat *m3gKeyframeAt(const KeyframeSequence *seq, M3Gint idx) |
|
270 { |
|
271 return seq->keyframes + idx * seq->numComponents; |
|
272 } |
|
273 |
|
274 /*! |
|
275 * \internal |
|
276 * \brief Get keyframe at index -1 |
|
277 * |
|
278 * \param seq KeyframeSequence object |
|
279 * \param idx keyframe index |
|
280 * \return keyframe value |
|
281 */ |
|
282 static M3G_INLINE const M3Gfloat *m3gKeyframeBefore(const KeyframeSequence *seq, M3Gint idx) |
|
283 { |
|
284 return m3gKeyframeAt(seq, m3gPreviousKeyframeIndex(seq, idx)); |
|
285 } |
|
286 |
|
287 /*! |
|
288 * \internal |
|
289 * \brief Get keyframe at index + 1 |
|
290 * |
|
291 * \param seq KeyframeSequence object |
|
292 * \param idx keyframe index |
|
293 * \return keyframe value |
|
294 */ |
|
295 static M3G_INLINE const M3Gfloat *m3gKeyframeAfter(const KeyframeSequence *seq, M3Gint idx) |
|
296 { |
|
297 return m3gKeyframeAt(seq, m3gNextKeyframeIndex(seq, idx)); |
|
298 } |
|
299 |
|
300 /*! |
|
301 * \internal |
|
302 * \brief Get tangent to index |
|
303 * |
|
304 * \param seq KeyframeSequence object |
|
305 * \param idx keyframe index |
|
306 * \return tangent value |
|
307 */ |
|
308 static M3G_INLINE const M3Gfloat *m3gTangentTo(const KeyframeSequence *seq, M3Gint idx) |
|
309 { |
|
310 M3G_ASSERT(seq->inTangents != NULL); |
|
311 return seq->inTangents + idx * seq->numComponents; |
|
312 } |
|
313 |
|
314 /*! |
|
315 * \internal |
|
316 * \brief Get tangent from index |
|
317 * |
|
318 * \param seq KeyframeSequence object |
|
319 * \param idx keyframe index |
|
320 * \return tangent value |
|
321 */ |
|
322 static M3G_INLINE const M3Gfloat *m3gTangentFrom(const KeyframeSequence *seq, M3Gint idx) |
|
323 { |
|
324 M3G_ASSERT(seq->outTangents != NULL); |
|
325 return seq->outTangents + idx * seq->numComponents; |
|
326 } |
|
327 |
|
328 /*! |
|
329 * \internal |
|
330 * \brief Get time delta |
|
331 * |
|
332 * \param sequence KeyframeSequence object |
|
333 * \param ind keyframe index |
|
334 * \return time delta |
|
335 */ |
|
336 static M3Gint m3gTimeDelta(const KeyframeSequence *sequence, M3Gint ind) |
|
337 { |
|
338 if (ind == sequence->lastValid) { |
|
339 return |
|
340 (sequence->duration |
|
341 - sequence->keyframeTimes[sequence->lastValid]) |
|
342 + sequence->keyframeTimes[sequence->firstValid]; |
|
343 } |
|
344 return sequence->keyframeTimes[m3gNextKeyframeIndex(sequence, ind)] |
|
345 - sequence->keyframeTimes[ind]; |
|
346 } |
|
347 |
|
348 /*! |
|
349 * \internal |
|
350 * \brief Get incoming tangent scale |
|
351 * |
|
352 * \param sequence KeyframeSequence object |
|
353 * \param ind keyframe index |
|
354 * \return tangent scale |
|
355 */ |
|
356 static M3Gfloat m3gIncomingTangentScale(const KeyframeSequence *sequence, |
|
357 M3Gint ind) |
|
358 { |
|
359 if (!sequence->closed |
|
360 && (ind == sequence->firstValid || ind == sequence->lastValid)) { |
|
361 return 0; |
|
362 } |
|
363 else { |
|
364 M3Gint prevind = m3gPreviousKeyframeIndex(sequence, ind); |
|
365 return m3gDiv(m3gMul(2.0f, (M3Gfloat) m3gTimeDelta(sequence, prevind)), |
|
366 (M3Gfloat)(m3gTimeDelta(sequence, ind) |
|
367 + m3gTimeDelta(sequence, prevind))); |
|
368 } |
|
369 } |
|
370 |
|
371 /*! |
|
372 * \internal |
|
373 * \brief Get outgoing tangent scale |
|
374 * |
|
375 * \param sequence KeyframeSequence object |
|
376 * \param ind keyframe index |
|
377 * \return tangent scale |
|
378 */ |
|
379 static M3Gfloat m3gOutgoingTangentScale(const KeyframeSequence *sequence, |
|
380 M3Gint ind) |
|
381 { |
|
382 if (!sequence->closed |
|
383 && (ind == sequence->firstValid || ind == sequence->lastValid)) { |
|
384 return 0; |
|
385 } |
|
386 else { |
|
387 M3Gint prevind = m3gPreviousKeyframeIndex(sequence, ind); |
|
388 return m3gDiv(m3gMul(2.0f, (M3Gfloat) m3gTimeDelta(sequence, ind)), |
|
389 (M3Gfloat)(m3gTimeDelta(sequence, ind) |
|
390 + m3gTimeDelta(sequence, prevind))); |
|
391 } |
|
392 } |
|
393 |
|
394 /*! |
|
395 * \internal |
|
396 * \brief Precalculate all tangents |
|
397 * |
|
398 * \param sequence KeyframeSequence object |
|
399 */ |
|
400 static void m3gPrecalculateTangents(KeyframeSequence *sequence) |
|
401 { |
|
402 M3Gint i, kf = sequence->firstValid; |
|
403 do { |
|
404 const M3Gfloat *prev = m3gKeyframeBefore(sequence, kf); |
|
405 const M3Gfloat *next = m3gKeyframeAfter(sequence, kf); |
|
406 const M3Gfloat sIn = m3gIncomingTangentScale(sequence, kf); |
|
407 const M3Gfloat sOut = m3gOutgoingTangentScale(sequence, kf); |
|
408 M3Gfloat *in = (M3Gfloat *) m3gTangentTo(sequence, kf); |
|
409 M3Gfloat *out = (M3Gfloat *) m3gTangentFrom(sequence, kf); |
|
410 |
|
411 for (i = 0; i < sequence->numComponents; ++i) { |
|
412 in[i] = m3gMul(m3gMul(0.5f, (m3gSub(next[i], prev[i]))), sIn); |
|
413 out[i] = m3gMul(m3gMul(0.5f, (m3gSub(next[i], prev[i]))), sOut); |
|
414 } |
|
415 |
|
416 kf = m3gNextKeyframeIndex(sequence, kf); |
|
417 } while (kf != sequence->firstValid); |
|
418 } |
|
419 |
|
420 /*! |
|
421 * \internal |
|
422 * \brief Precalculate A and B |
|
423 * |
|
424 * \param sequence KeyframeSequence object |
|
425 */ |
|
426 static void m3gPrecalculateAB(KeyframeSequence *sequence) |
|
427 { |
|
428 Quat start, end, prev, next; |
|
429 Vec3 tangent, cfd; |
|
430 M3Gfloat temp[4]; /* used for both quats and vectors */ |
|
431 |
|
432 M3Gint kf = sequence->firstValid; |
|
433 do { |
|
434 |
|
435 m3gSetQuat(&prev, m3gKeyframeBefore(sequence, kf)); |
|
436 m3gSetQuat(&start, m3gKeyframeAt(sequence, kf)); |
|
437 m3gSetQuat(&end, m3gKeyframeAfter(sequence, kf)); |
|
438 m3gSetQuat(&next, m3gKeyframeAfter(sequence, m3gNextKeyframeIndex(sequence, kf))); |
|
439 |
|
440 /* Compute the centered finite difference at this |
|
441 keyframe; note that this would be the tangent for basic |
|
442 Catmull-Rom interpolation. */ |
|
443 |
|
444 m3gLogDiffQuat(&cfd, &start, &end); |
|
445 m3gLogDiffQuat((Vec3*)temp, &prev, &start); |
|
446 m3gAddVec3(&cfd, (Vec3*)temp); |
|
447 m3gScaleVec3(&cfd, 0.5f); |
|
448 |
|
449 /* Compute the outgoing tangent, scaled to compensate for |
|
450 keyframe timing, then compute the "A" intermediate |
|
451 quaternion. */ |
|
452 |
|
453 tangent = cfd; |
|
454 m3gScaleVec3(&tangent, m3gOutgoingTangentScale(sequence, kf)); |
|
455 |
|
456 m3gLogDiffQuat((Vec3*)temp, &start, &end); |
|
457 m3gSubVec3(&tangent, (Vec3*)temp); |
|
458 m3gScaleVec3(&tangent, 0.5f); |
|
459 m3gExpQuat((Quat*)temp, &tangent); |
|
460 sequence->a[kf] = start; |
|
461 m3gMulQuat(&(sequence->a[kf]), (Quat*)temp); |
|
462 |
|
463 /* Then repeat the same steps for the incoming tangent and |
|
464 the "B" intermediate quaternion. */ |
|
465 |
|
466 tangent = cfd; |
|
467 m3gScaleVec3(&tangent, m3gIncomingTangentScale(sequence, kf)); |
|
468 |
|
469 m3gLogDiffQuat((Vec3*)temp, &prev, &start); |
|
470 m3gSubVec3((Vec3*)temp, &tangent); |
|
471 m3gScaleVec3((Vec3*)temp, 0.5f); |
|
472 m3gExpQuat((Quat*)temp, (Vec3*)temp); |
|
473 sequence->b[kf] = start; |
|
474 m3gMulQuat(&(sequence->b[kf]), (Quat*)temp); |
|
475 |
|
476 kf = m3gNextKeyframeIndex(sequence, kf); |
|
477 } while (kf != sequence->firstValid); |
|
478 } |
|
479 |
|
480 /*! |
|
481 * \internal |
|
482 * \brief Update all tangents |
|
483 * |
|
484 * \param sequence KeyframeSequence object |
|
485 */ |
|
486 static void m3gUpdateTangents(KeyframeSequence *sequence) |
|
487 { |
|
488 if (sequence->interpolation == M3G_SPLINE) { |
|
489 m3gPrecalculateTangents(sequence); |
|
490 } |
|
491 else if (sequence->interpolation == M3G_SQUAD) { |
|
492 m3gPrecalculateAB(sequence); |
|
493 } |
|
494 } |
|
495 |
|
496 /*! |
|
497 * \internal |
|
498 * \brief Linear interpolate |
|
499 * |
|
500 * \param sequence KeyframeSequence object |
|
501 * \param sample input samples |
|
502 * \param s speed |
|
503 * \param startIndex start index |
|
504 * \param endIndex end index |
|
505 */ |
|
506 static M3G_INLINE void m3gLerpSample(const KeyframeSequence *sequence, |
|
507 M3Gfloat *sample, |
|
508 M3Gfloat s, |
|
509 M3Gint startIndex, M3Gint endIndex) |
|
510 { |
|
511 const M3Gfloat *start = m3gKeyframeAt(sequence, startIndex); |
|
512 const M3Gfloat *end = m3gKeyframeAt(sequence, endIndex); |
|
513 |
|
514 m3gLerp(sequence->numComponents, sample, s, start, end); |
|
515 } |
|
516 |
|
517 /*! |
|
518 * \internal |
|
519 * \brief Spline interpolate |
|
520 * |
|
521 * \param sequence KeyframeSequence object |
|
522 * \param sample input samples |
|
523 * \param s speed |
|
524 * \param startIndex start index |
|
525 * \param endIndex end index |
|
526 */ |
|
527 static M3G_INLINE void m3gSplineSample(const KeyframeSequence *sequence, |
|
528 M3Gfloat *sample, |
|
529 M3Gfloat s, |
|
530 M3Gint startIndex, M3Gint endIndex) |
|
531 { |
|
532 const M3Gfloat *start, *end; |
|
533 const M3Gfloat *tStart, *tEnd; |
|
534 |
|
535 /* Get the required keyframe values and the (one-sided) tangents |
|
536 * at the ends of the segment. */ |
|
537 |
|
538 start = m3gKeyframeAt(sequence, startIndex); |
|
539 end = m3gKeyframeAt(sequence, endIndex); |
|
540 |
|
541 tStart = m3gTangentFrom(sequence, startIndex); |
|
542 tEnd = m3gTangentTo(sequence, endIndex); |
|
543 |
|
544 /* Interpolate the final value using a Hermite spline. */ |
|
545 |
|
546 m3gHermite(sequence->numComponents, sample, s, start, end, tStart, tEnd); |
|
547 } |
|
548 |
|
549 /*! |
|
550 * \internal |
|
551 * \brief Spherical linear interpolate |
|
552 * |
|
553 * \param sequence KeyframeSequence object |
|
554 * \param sample input samples |
|
555 * \param s speed |
|
556 * \param startIndex start index |
|
557 * \param endIndex end index |
|
558 */ |
|
559 static M3G_INLINE void m3gSlerpSample(const KeyframeSequence *sequence, |
|
560 M3Gfloat *sample, |
|
561 M3Gfloat s, |
|
562 M3Gint startIndex, M3Gint endIndex) |
|
563 { |
|
564 if (sequence->numComponents != 4) { |
|
565 m3gRaiseError(M3G_INTERFACE(sequence), M3G_INVALID_VALUE); |
|
566 return; |
|
567 } |
|
568 |
|
569 m3gSlerpQuat((Quat *) sample, |
|
570 s, |
|
571 (const Quat *) m3gKeyframeAt(sequence, startIndex), |
|
572 (const Quat *) m3gKeyframeAt(sequence, endIndex)); |
|
573 } |
|
574 |
|
575 /*! |
|
576 * \internal |
|
577 * \brief Spline interpolate quats |
|
578 * |
|
579 * \param sequence KeyframeSequence object |
|
580 * \param sample input samples |
|
581 * \param s speed |
|
582 * \param startIndex start index |
|
583 * \param endIndex end index |
|
584 */ |
|
585 static M3G_INLINE void m3gSquadSample(const KeyframeSequence *sequence, |
|
586 M3Gfloat *sample, |
|
587 M3Gfloat s, |
|
588 M3Gint startIndex, M3Gint endIndex) |
|
589 { |
|
590 if (sequence->numComponents != 4) { |
|
591 m3gRaiseError(M3G_INTERFACE(sequence), M3G_INVALID_VALUE); |
|
592 return; |
|
593 } |
|
594 |
|
595 m3gSquadQuat((Quat *) sample, |
|
596 s, |
|
597 (const Quat *) m3gKeyframeAt(sequence, startIndex), |
|
598 &(sequence->a[startIndex]), |
|
599 &(sequence->b[endIndex]), |
|
600 (const Quat *) m3gKeyframeAt(sequence, endIndex)); |
|
601 } |
|
602 |
|
603 /*! |
|
604 * \internal |
|
605 * \brief Get sample |
|
606 * |
|
607 * \param sequence KeyframeSequence object |
|
608 * \param time time |
|
609 * \param sample pointer to sample |
|
610 * \return sample validity |
|
611 */ |
|
612 static M3Gint m3gGetSample(KeyframeSequence *sequence, |
|
613 M3Gint time, |
|
614 M3Gfloat *sample) |
|
615 { |
|
616 M3Gint start, end, i; |
|
617 const M3Gfloat *value; |
|
618 M3Gfloat s; |
|
619 |
|
620 M3G_VALIDATE_OBJECT(sequence); |
|
621 |
|
622 if (sequence->dirty == M3G_TRUE) { |
|
623 if (!m3gValidSequence(sequence)) { |
|
624 m3gRaiseError(M3G_INTERFACE(sequence), M3G_INVALID_OPERATION); |
|
625 return 0; |
|
626 } |
|
627 m3gUpdateTangents(sequence); |
|
628 sequence->dirty = M3G_FALSE; |
|
629 sequence->probablyNext = sequence->firstValid; |
|
630 } |
|
631 |
|
632 /* First, map the time to the valid range of a repeating |
|
633 sequence, or handle the special end cases of an open-ended |
|
634 sequence. */ |
|
635 |
|
636 if (sequence->closed) { |
|
637 if (time < 0) |
|
638 time = (time % sequence->duration) + sequence->duration; |
|
639 else |
|
640 time = time % sequence->duration; |
|
641 if (time < sequence->keyframeTimes[sequence->firstValid]) { |
|
642 time += sequence->duration; |
|
643 } |
|
644 } |
|
645 else { |
|
646 if (time < sequence->keyframeTimes[sequence->firstValid]) { |
|
647 value = m3gKeyframeAt(sequence, sequence->firstValid); |
|
648 for (i = 0; i < sequence->numComponents; i++) |
|
649 sample[i] = value[i]; |
|
650 return (sequence->keyframeTimes[sequence->firstValid] - time); |
|
651 } |
|
652 else if (time >= sequence->keyframeTimes[sequence->lastValid]) { |
|
653 value = m3gKeyframeAt(sequence, sequence->lastValid); |
|
654 for (i = 0; i < sequence->numComponents; i++) |
|
655 sample[i] = value[i]; |
|
656 /* \ define a meaningful constant */ |
|
657 return 0x7FFFFFFF; |
|
658 } |
|
659 } |
|
660 |
|
661 /* Search for the starting keyframe of the segment to |
|
662 interpolate. Starting the search from the previously |
|
663 used keyframe, we are very likely to find the match |
|
664 sooner than if we'd start from the first keyframe. */ |
|
665 |
|
666 start = sequence->probablyNext; |
|
667 if (sequence->keyframeTimes[start] > time) |
|
668 start = sequence->firstValid; |
|
669 while (start != sequence->lastValid && |
|
670 sequence->keyframeTimes[m3gNextKeyframeIndex(sequence, start)] <= time) { |
|
671 start = m3gNextKeyframeIndex(sequence, start); |
|
672 } |
|
673 sequence->probablyNext = start; |
|
674 |
|
675 /* Calculate the interpolation factor if necessary; the quick |
|
676 exit also avoids a division by zero in the case that we |
|
677 have a quirky sequence with only multiple coincident |
|
678 keyframes. */ |
|
679 |
|
680 if (time == sequence->keyframeTimes[start] || sequence->interpolation == M3G_STEP) { |
|
681 value = m3gKeyframeAt(sequence, start); |
|
682 for (i = 0; i < sequence->numComponents; i++) |
|
683 sample[i] = value[i]; |
|
684 return (sequence->interpolation == M3G_STEP) |
|
685 ? (m3gTimeDelta(sequence, start) - (time - sequence->keyframeTimes[start])) |
|
686 : 1; |
|
687 } |
|
688 s = m3gDivif(time - sequence->keyframeTimes[start], m3gTimeDelta(sequence, start)); |
|
689 |
|
690 /* Pick the correct interpolation function and pass the |
|
691 segment start and end keyframe indices. */ |
|
692 |
|
693 end = m3gNextKeyframeIndex(sequence, start); |
|
694 |
|
695 switch (sequence->interpolation) { |
|
696 case M3G_LINEAR: |
|
697 m3gLerpSample(sequence, sample, s, start, end); |
|
698 break; |
|
699 case M3G_SLERP: |
|
700 m3gSlerpSample(sequence, sample, s, start, end); |
|
701 break; |
|
702 case M3G_SPLINE: |
|
703 m3gSplineSample(sequence, sample, s, start, end); |
|
704 break; |
|
705 case M3G_SQUAD: |
|
706 m3gSquadSample(sequence, sample, s, start, end); |
|
707 break; |
|
708 default: |
|
709 m3gRaiseError(M3G_INTERFACE(sequence), M3G_INVALID_ENUM); |
|
710 return 0; |
|
711 } |
|
712 |
|
713 return 1; |
|
714 } |
|
715 |
|
716 /*---------------------------------------------------------------------- |
|
717 * Virtual function table |
|
718 *--------------------------------------------------------------------*/ |
|
719 |
|
720 static const ObjectVFTable m3gvf_KeyframeSequence = { |
|
721 m3gObjectApplyAnimation, |
|
722 m3gObjectIsCompatible, |
|
723 m3gObjectUpdateProperty, |
|
724 m3gObjectDoGetReferences, |
|
725 m3gObjectFindID, |
|
726 m3gKeyframeSequenceDuplicate, |
|
727 m3gDestroyKeyframeSequence |
|
728 }; |
|
729 |
|
730 |
|
731 /*---------------------------------------------------------------------- |
|
732 * Public API functions |
|
733 *--------------------------------------------------------------------*/ |
|
734 |
|
735 /*! |
|
736 * \brief Creates a new KeyframeSequence with default values |
|
737 * |
|
738 * \param hInterface M3G interface |
|
739 * \param numKeyframes number of keyframes |
|
740 * \param numComponents number of components |
|
741 * \param interpolation interpolation type |
|
742 * \retval KeyframeSequence new KeyframeSequence object |
|
743 * \retval NULL KeyframeSequence creating failed |
|
744 */ |
|
745 /*@access M3GInterface@*/ |
|
746 /*@access M3Gappearance@*/ |
|
747 M3G_API M3GKeyframeSequence m3gCreateKeyframeSequence(M3GInterface hInterface, |
|
748 M3Gint numKeyframes, |
|
749 M3Gint numComponents, |
|
750 M3Gint interpolation) |
|
751 { |
|
752 Interface *m3g = (Interface *) hInterface; |
|
753 M3G_VALIDATE_INTERFACE(m3g); |
|
754 |
|
755 if (numKeyframes < 1 || numComponents < 1 |
|
756 || interpolation < M3G_LINEAR || interpolation > M3G_STEP |
|
757 || ((interpolation == M3G_SLERP || interpolation == M3G_SQUAD) |
|
758 && numComponents != 4)) { |
|
759 m3gRaiseError(m3g, M3G_INVALID_VALUE); |
|
760 return NULL; |
|
761 } |
|
762 |
|
763 { |
|
764 KeyframeSequence *sequence = m3gAllocZ(m3g, sizeof(KeyframeSequence)); |
|
765 |
|
766 if (sequence != NULL) { |
|
767 if (m3gInitKeyframeSequence(m3g, |
|
768 sequence, |
|
769 numKeyframes, numComponents, |
|
770 interpolation) == NULL) { |
|
771 m3gFree(m3g, sequence); |
|
772 return NULL; |
|
773 } |
|
774 } |
|
775 |
|
776 return (M3GKeyframeSequence) sequence; |
|
777 } |
|
778 } |
|
779 |
|
780 /*! |
|
781 * \brief Assigns a time and value to a keyframe sequence entry |
|
782 * |
|
783 * \param handle handle of the keyframe sequence object |
|
784 * \param ind index of the entry to set |
|
785 * \param time time to set in the entry |
|
786 * \param valueSize number of elements in the value; this must match |
|
787 * the number of elements given when constructing |
|
788 * the sequence |
|
789 * \param value pointer to an array of \c valueSize floats |
|
790 */ |
|
791 M3G_API void m3gSetKeyframe(M3GKeyframeSequence handle, |
|
792 M3Gint ind, |
|
793 M3Gint time, |
|
794 M3Gint valueSize, const M3Gfloat *value) |
|
795 { |
|
796 KeyframeSequence *sequence = (KeyframeSequence *)handle; |
|
797 M3G_VALIDATE_OBJECT(sequence); |
|
798 |
|
799 /* Check for invalid inputs */ |
|
800 |
|
801 if (value == NULL) { |
|
802 m3gRaiseError(M3G_INTERFACE(sequence), M3G_NULL_POINTER); |
|
803 return; |
|
804 } |
|
805 if (valueSize < sequence->numComponents || time < 0) { |
|
806 m3gRaiseError(M3G_INTERFACE(sequence), M3G_INVALID_VALUE); |
|
807 return; |
|
808 } |
|
809 if (ind < 0 || ind >= sequence->numKeyframes) { |
|
810 m3gRaiseError(M3G_INTERFACE(sequence), M3G_INVALID_INDEX); |
|
811 return; |
|
812 } |
|
813 |
|
814 /* Assign the time and value. Quaternion keyframes are also |
|
815 * normalized, as indicated in the specification. */ |
|
816 { |
|
817 M3Gfloat *kf = (M3Gfloat *) m3gKeyframeAt(sequence, ind); |
|
818 int c; |
|
819 |
|
820 sequence->keyframeTimes[ind] = time; |
|
821 |
|
822 for (c = 0; c < sequence->numComponents; ++c) { |
|
823 kf[c] = value[c]; |
|
824 } |
|
825 |
|
826 if (sequence->interpolation == M3G_SLERP |
|
827 || sequence->interpolation == M3G_SQUAD) { |
|
828 m3gNormalizeQuat((Quat*) kf); |
|
829 } |
|
830 } |
|
831 |
|
832 sequence->dirty = M3G_TRUE; |
|
833 } |
|
834 |
|
835 /*! |
|
836 * \brief Set valid range |
|
837 * |
|
838 * \param handle handle of the keyframe sequence object |
|
839 * \param first first valid keyframe |
|
840 * \param last last valid keyframe |
|
841 */ |
|
842 M3G_API void m3gSetValidRange(M3GKeyframeSequence handle, |
|
843 M3Gint first, M3Gint last) |
|
844 { |
|
845 KeyframeSequence *sequence = (KeyframeSequence *)handle; |
|
846 M3G_VALIDATE_OBJECT(sequence); |
|
847 |
|
848 if (first < 0 || first >= sequence->numKeyframes || |
|
849 last < 0 || last >= sequence->numKeyframes) { |
|
850 m3gRaiseError(M3G_INTERFACE(sequence), M3G_INVALID_INDEX); |
|
851 return; |
|
852 } |
|
853 |
|
854 sequence->firstValid = first; |
|
855 sequence->lastValid = last; |
|
856 sequence->dirty = M3G_TRUE; |
|
857 } |
|
858 |
|
859 /*! |
|
860 * \brief Set duration |
|
861 * |
|
862 * \param handle handle of the keyframe sequence object |
|
863 * \param duration duration |
|
864 */ |
|
865 M3G_API void m3gSetDuration(M3GKeyframeSequence handle, M3Gint duration) |
|
866 { |
|
867 KeyframeSequence *sequence = (KeyframeSequence *)handle; |
|
868 M3G_VALIDATE_OBJECT(sequence); |
|
869 |
|
870 /* Check for errors */ |
|
871 if (duration <= 0) { |
|
872 m3gRaiseError(M3G_INTERFACE(sequence), M3G_INVALID_VALUE); |
|
873 return; |
|
874 } |
|
875 |
|
876 sequence->duration = duration; |
|
877 sequence->dirty = M3G_TRUE; |
|
878 } |
|
879 |
|
880 /*! |
|
881 * \brief Get duration |
|
882 * |
|
883 * \param handle handle of the keyframe sequence object |
|
884 * \return duration |
|
885 */ |
|
886 M3G_API M3Gint m3gGetDuration(M3GKeyframeSequence handle) |
|
887 { |
|
888 KeyframeSequence *sequence = (KeyframeSequence *)handle; |
|
889 M3G_VALIDATE_OBJECT(sequence); |
|
890 return sequence->duration; |
|
891 } |
|
892 |
|
893 /*! |
|
894 * \brief Get component count |
|
895 * |
|
896 * \param handle handle of the keyframe sequence object |
|
897 * \return component count |
|
898 */ |
|
899 M3G_API M3Gint m3gGetComponentCount(M3GKeyframeSequence handle) |
|
900 { |
|
901 KeyframeSequence *sequence = (KeyframeSequence *)handle; |
|
902 M3G_VALIDATE_OBJECT(sequence); |
|
903 return sequence->numComponents; |
|
904 } |
|
905 |
|
906 /*! |
|
907 * \brief Get interpolation type |
|
908 * |
|
909 * \param handle handle of the keyframe sequence object |
|
910 * \return interpolation type |
|
911 */ |
|
912 M3G_API M3Gint m3gGetInterpolationType(M3GKeyframeSequence handle) |
|
913 { |
|
914 KeyframeSequence *sequence = (KeyframeSequence *)handle; |
|
915 M3G_VALIDATE_OBJECT(sequence); |
|
916 return sequence->interpolation; |
|
917 } |
|
918 |
|
919 /*! |
|
920 * \brief Get keyframe value |
|
921 * |
|
922 * \param handle handle of the keyframe sequence object |
|
923 * \param frameIndex keyframe index |
|
924 * \param value value array |
|
925 |
|
926 * \return time value of the keyframe |
|
927 */ |
|
928 M3G_API M3Gint m3gGetKeyframe (M3GKeyframeSequence handle, M3Gint frameIndex, M3Gfloat *value) |
|
929 { |
|
930 KeyframeSequence *sequence = (KeyframeSequence *)handle; |
|
931 M3G_VALIDATE_OBJECT(sequence); |
|
932 |
|
933 if (frameIndex < 0 || frameIndex >= sequence->numKeyframes) { |
|
934 m3gRaiseError(M3G_INTERFACE(sequence), M3G_INVALID_INDEX); |
|
935 return 0; |
|
936 } |
|
937 |
|
938 if (value != NULL) { |
|
939 m3gCopy( value, |
|
940 sequence->keyframes + frameIndex * sequence->numComponents, |
|
941 sequence->numComponents * sizeof(M3Gfloat)); |
|
942 } |
|
943 |
|
944 return sequence->keyframeTimes[frameIndex]; |
|
945 } |
|
946 |
|
947 /*! |
|
948 * \brief Get keyframe count |
|
949 * |
|
950 * \param handle handle of the keyframe sequence object |
|
951 * \return keyframe count |
|
952 */ |
|
953 M3G_API M3Gint m3gGetKeyframeCount(M3GKeyframeSequence handle) |
|
954 { |
|
955 KeyframeSequence *sequence = (KeyframeSequence *)handle; |
|
956 M3G_VALIDATE_OBJECT(sequence); |
|
957 return sequence->numKeyframes; |
|
958 } |
|
959 |
|
960 /*! |
|
961 * \brief Get valid range |
|
962 * |
|
963 * \param handle handle of the keyframe sequence object |
|
964 * \param first pointer to valid range start |
|
965 * \param last pointer to valid range end |
|
966 */ |
|
967 M3G_API void m3gGetValidRange(M3GKeyframeSequence handle, M3Gint *first, M3Gint *last) |
|
968 { |
|
969 KeyframeSequence *sequence = (KeyframeSequence *)handle; |
|
970 M3G_VALIDATE_OBJECT(sequence); |
|
971 *first = sequence->firstValid; |
|
972 *last = sequence->lastValid; |
|
973 } |
|
974 |
|
975 /*! |
|
976 * \brief Set repeat mode |
|
977 * |
|
978 * \param handle handle of the keyframe sequence object |
|
979 * \param mode repeat mode |
|
980 */ |
|
981 M3G_API void m3gSetRepeatMode(M3GKeyframeSequence handle, M3Genum mode) |
|
982 { |
|
983 KeyframeSequence *sequence = (KeyframeSequence *)handle; |
|
984 M3G_VALIDATE_OBJECT(sequence); |
|
985 if (mode != M3G_CONSTANT && mode != M3G_LOOP) { |
|
986 m3gRaiseError(M3G_INTERFACE(sequence), M3G_INVALID_ENUM); |
|
987 return; |
|
988 } |
|
989 sequence->closed = (mode == M3G_LOOP) ? M3G_TRUE : M3G_FALSE; |
|
990 } |
|
991 |
|
992 /*! |
|
993 * \brief Get repeat mode |
|
994 * |
|
995 * \param handle handle of the keyframe sequence object |
|
996 * \return repeat mode |
|
997 */ |
|
998 M3G_API M3Genum m3gGetRepeatMode(M3GKeyframeSequence handle) |
|
999 { |
|
1000 KeyframeSequence *sequence = (KeyframeSequence *)handle; |
|
1001 M3G_VALIDATE_OBJECT(sequence); |
|
1002 return (sequence->closed ? M3G_LOOP : M3G_CONSTANT); |
|
1003 } |
|
1004 |