1 /*
2 * The 3D Studio File Format Library
3 * Copyright (C) 1996-2007 by Jan Eric Kyprianidis <www.kyprianidis.com>
4 * All rights reserved.
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU Lesser General Public License as published by
8 * the Free Software Foundation; either version 2.1 of the License, or (at
9 * your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
14 * License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 *
20 * $Id: tracks.c,v 1.20 2007/06/15 09:33:19 jeh Exp $
21 */
22 #include <lib3ds/tracks.h>
23 #include <lib3ds/io.h>
24 #include <lib3ds/chunk.h>
25 #include <lib3ds/vector.h>
26 #include <lib3ds/quat.h>
27 #include <lib3ds/node.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <math.h>
31
32
33 /*!
34 * \defgroup tracks Keyframing Tracks
35 */
36
37
38 /*!
39 * \ingroup tracks
40 */
41 Lib3dsBoolKey*
lib3ds_bool_key_new()42 lib3ds_bool_key_new()
43 {
44 Lib3dsBoolKey* k;
45 k=(Lib3dsBoolKey*)calloc(sizeof(Lib3dsBoolKey), 1);
46 return(k);
47 }
48
49
50 /*!
51 * \ingroup tracks
52 */
53 void
lib3ds_bool_key_free(Lib3dsBoolKey * key)54 lib3ds_bool_key_free(Lib3dsBoolKey *key)
55 {
56 ASSERT(key);
57 free(key);
58 }
59
60
61 /*!
62 * \ingroup tracks
63 */
64 void
lib3ds_bool_track_free_keys(Lib3dsBoolTrack * track)65 lib3ds_bool_track_free_keys(Lib3dsBoolTrack *track)
66 {
67 Lib3dsBoolKey *p,*q;
68
69 ASSERT(track);
70 for (p=track->keyL; p; p=q) {
71 q=p->next;
72 lib3ds_bool_key_free(p);
73 }
74 }
75
76
77 /*!
78 * \ingroup tracks
79 */
80 void
lib3ds_bool_track_insert(Lib3dsBoolTrack * track,Lib3dsBoolKey * key)81 lib3ds_bool_track_insert(Lib3dsBoolTrack *track, Lib3dsBoolKey *key)
82 {
83 ASSERT(track);
84 ASSERT(key);
85 ASSERT(!key->next);
86
87 if (!track->keyL) {
88 track->keyL=key;
89 key->next=0;
90 }
91 else {
92 Lib3dsBoolKey *k,*p;
93
94 for (p=0,k=track->keyL; k!=0; p=k, k=k->next) {
95 if (k->tcb.frame>key->tcb.frame) {
96 break;
97 }
98 }
99 if (!p) {
100 key->next=track->keyL;
101 track->keyL=key;
102 }
103 else {
104 key->next=k;
105 p->next=key;
106 }
107
108 if (k && (key->tcb.frame==k->tcb.frame)) {
109 key->next=k->next;
110 lib3ds_bool_key_free(k);
111 }
112 }
113 }
114
115
116 /*!
117 * \ingroup tracks
118 */
119 void
lib3ds_bool_track_remove(Lib3dsBoolTrack * track,Lib3dsIntd frame)120 lib3ds_bool_track_remove(Lib3dsBoolTrack *track, Lib3dsIntd frame)
121 {
122 Lib3dsBoolKey *k,*p;
123
124 ASSERT(track);
125 if (!track->keyL) {
126 return;
127 }
128 for (p=0,k=track->keyL; k!=0; p=k, k=k->next) {
129 if (k->tcb.frame==frame) {
130 if (!p) {
131 track->keyL=track->keyL->next;
132 }
133 else {
134 p->next=k->next;
135 }
136 lib3ds_bool_key_free(k);
137 break;
138 }
139 }
140 }
141
142
143 /*!
144 * \ingroup tracks
145 */
146 void
lib3ds_bool_track_eval(Lib3dsBoolTrack * track,Lib3dsBool * p,Lib3dsFloat t)147 lib3ds_bool_track_eval(Lib3dsBoolTrack *track, Lib3dsBool *p, Lib3dsFloat t)
148 {
149 Lib3dsBoolKey *k;
150 Lib3dsBool result;
151
152 ASSERT(p);
153 if (!track->keyL) {
154 *p=LIB3DS_FALSE;
155 return;
156 }
157 if (!track->keyL->next) {
158 *p = LIB3DS_TRUE;
159 return;
160 }
161
162 result=LIB3DS_FALSE;
163 k=track->keyL;
164 while ((t<(Lib3dsFloat)k->tcb.frame) && (t>=(Lib3dsFloat)k->next->tcb.frame)) {
165 if (result) {
166 result=LIB3DS_FALSE;
167 }
168 else {
169 result=LIB3DS_TRUE;
170 }
171 if (!k->next) {
172 if (track->flags&LIB3DS_REPEAT) {
173 t-=(Lib3dsFloat)k->tcb.frame;
174 k=track->keyL;
175 }
176 else {
177 break;
178 }
179 }
180 else {
181 k=k->next;
182 }
183 }
184 *p=result;
185 }
186
187
188 /*!
189 * \ingroup tracks
190 */
191 Lib3dsBool
lib3ds_bool_track_read(Lib3dsBoolTrack * track,Lib3dsIo * io)192 lib3ds_bool_track_read(Lib3dsBoolTrack *track, Lib3dsIo *io)
193 {
194 int keys;
195 int i;
196 Lib3dsBoolKey *k;
197
198 track->flags=lib3ds_io_read_word(io);
199 lib3ds_io_read_dword(io);
200 lib3ds_io_read_dword(io);
201 keys=lib3ds_io_read_intd(io);
202
203 for (i=0; i<keys; ++i) {
204 k=lib3ds_bool_key_new();
205 if (!lib3ds_tcb_read(&k->tcb, io)) {
206 return(LIB3DS_FALSE);
207 }
208 lib3ds_bool_track_insert(track, k);
209 }
210
211 return(LIB3DS_TRUE);
212 }
213
214
215 /*!
216 * \ingroup tracks
217 */
218 Lib3dsBool
lib3ds_bool_track_write(Lib3dsBoolTrack * track,Lib3dsIo * io)219 lib3ds_bool_track_write(Lib3dsBoolTrack *track, Lib3dsIo *io)
220 {
221 Lib3dsBoolKey *k;
222 Lib3dsDword num=0;
223 for (k=track->keyL; k; k=k->next) {
224 ++num;
225 }
226 lib3ds_io_write_word(io, (Lib3dsWord)track->flags);
227 lib3ds_io_write_dword(io, 0);
228 lib3ds_io_write_dword(io, 0);
229 lib3ds_io_write_dword(io, num);
230
231 for (k=track->keyL; k; k=k->next) {
232 if (!lib3ds_tcb_write(&k->tcb,io)) {
233 return(LIB3DS_FALSE);
234 }
235 }
236 return(LIB3DS_TRUE);
237 }
238
239
240 /*!
241 * \ingroup tracks
242 */
243 Lib3dsLin1Key*
lib3ds_lin1_key_new()244 lib3ds_lin1_key_new()
245 {
246 Lib3dsLin1Key* k;
247 k=(Lib3dsLin1Key*)calloc(sizeof(Lib3dsLin1Key), 1);
248 return(k);
249 }
250
251
252 /*!
253 * \ingroup tracks
254 */
255 void
lib3ds_lin1_key_free(Lib3dsLin1Key * key)256 lib3ds_lin1_key_free(Lib3dsLin1Key *key)
257 {
258 ASSERT(key);
259 free(key);
260 }
261
262
263 /*!
264 * \ingroup tracks
265 */
266 void
lib3ds_lin1_track_free_keys(Lib3dsLin1Track * track)267 lib3ds_lin1_track_free_keys(Lib3dsLin1Track *track)
268 {
269 Lib3dsLin1Key *p,*q;
270
271 ASSERT(track);
272 for (p=track->keyL; p; p=q) {
273 q=p->next;
274 lib3ds_lin1_key_free(p);
275 }
276 }
277
278
279 /*!
280 * \ingroup tracks
281 */
282 void
lib3ds_lin1_key_setup(Lib3dsLin1Key * p,Lib3dsLin1Key * cp,Lib3dsLin1Key * c,Lib3dsLin1Key * cn,Lib3dsLin1Key * n)283 lib3ds_lin1_key_setup(Lib3dsLin1Key *p, Lib3dsLin1Key *cp, Lib3dsLin1Key *c,
284 Lib3dsLin1Key *cn, Lib3dsLin1Key *n)
285 {
286 Lib3dsFloat np,nn;
287 Lib3dsFloat ksm,ksp,kdm,kdp;
288
289 ASSERT(c);
290 if (!cp) {
291 cp=c;
292 }
293 if (!cn) {
294 cn=c;
295 }
296 if (!p && !n) {
297 c->ds=0;
298 c->dd=0;
299 return;
300 }
301
302 if (n && p) {
303 lib3ds_tcb(&p->tcb, &cp->tcb, &c->tcb, &cn->tcb, &n->tcb, &ksm, &ksp, &kdm, &kdp);
304 np = c->value - p->value;
305 nn = n->value - c->value;
306
307 c->ds=ksm*np + ksp*nn;
308 c->dd=kdm*np + kdp*nn;
309 }
310 else {
311 if (p) {
312 np = c->value - p->value;
313 c->ds = np;
314 c->dd = np;
315 }
316 if (n) {
317 nn = n->value - c->value;
318 c->ds = nn;
319 c->dd = nn;
320 }
321 }
322 }
323
324
325 /*!
326 * \ingroup tracks
327 */
328 void
lib3ds_lin1_track_setup(Lib3dsLin1Track * track)329 lib3ds_lin1_track_setup(Lib3dsLin1Track *track)
330 {
331 Lib3dsLin1Key *pp,*pc,*pn,*pl;
332
333 ASSERT(track);
334 pc=track->keyL;
335 if (!pc) {
336 return;
337 }
338 if (!pc->next) {
339 pc->ds=0;
340 pc->dd=0;
341 return;
342 }
343
344 if (track->flags&LIB3DS_SMOOTH) {
345 for (pl=track->keyL; pl->next->next; pl=pl->next);
346 lib3ds_lin1_key_setup(pl, pl->next, pc, 0, pc->next);
347 }
348 else {
349 lib3ds_lin1_key_setup(0, 0, pc, 0, pc->next);
350 }
351 for (;;) {
352 pp=pc;
353 pc=pc->next;
354 pn=pc->next;
355 if (!pn) {
356 break;
357 }
358 lib3ds_lin1_key_setup(pp, 0, pc, 0, pn);
359 }
360
361 if (track->flags&LIB3DS_SMOOTH) {
362 lib3ds_lin1_key_setup(pp, 0, pc, track->keyL, track->keyL->next);
363 }
364 else {
365 lib3ds_lin1_key_setup(pp, 0, pc, 0, 0);
366 }
367 }
368
369
370 /*!
371 * \ingroup tracks
372 */
373 void
lib3ds_lin1_track_insert(Lib3dsLin1Track * track,Lib3dsLin1Key * key)374 lib3ds_lin1_track_insert(Lib3dsLin1Track *track, Lib3dsLin1Key *key)
375 {
376 ASSERT(track);
377 ASSERT(key);
378 ASSERT(!key->next);
379
380 if (!track->keyL) {
381 track->keyL=key;
382 key->next=0;
383 }
384 else {
385 Lib3dsLin1Key *k,*p;
386
387 for (p=0,k=track->keyL; k!=0; p=k, k=k->next) {
388 if (k->tcb.frame>key->tcb.frame) {
389 break;
390 }
391 }
392 if (!p) {
393 key->next=track->keyL;
394 track->keyL=key;
395 }
396 else {
397 key->next=k;
398 p->next=key;
399 }
400
401 if (k && (key->tcb.frame==k->tcb.frame)) {
402 key->next=k->next;
403 lib3ds_lin1_key_free(k);
404 }
405 }
406 }
407
408
409 /*!
410 * \ingroup tracks
411 */
412 void
lib3ds_lin1_track_remove(Lib3dsLin1Track * track,Lib3dsIntd frame)413 lib3ds_lin1_track_remove(Lib3dsLin1Track *track, Lib3dsIntd frame)
414 {
415 Lib3dsLin1Key *k,*p;
416
417 ASSERT(track);
418 if (!track->keyL) {
419 return;
420 }
421 for (p=0,k=track->keyL; k!=0; p=k, k=k->next) {
422 if (k->tcb.frame==frame) {
423 if (!p) {
424 track->keyL=track->keyL->next;
425 }
426 else {
427 p->next=k->next;
428 }
429 lib3ds_lin1_key_free(k);
430 break;
431 }
432 }
433 }
434
435
436 static Lib3dsFloat
lib3ds_float_cubic(Lib3dsFloat a,Lib3dsFloat p,Lib3dsFloat q,Lib3dsFloat b,Lib3dsFloat t)437 lib3ds_float_cubic(Lib3dsFloat a, Lib3dsFloat p, Lib3dsFloat q, Lib3dsFloat b, Lib3dsFloat t)
438 {
439 Lib3dsDouble x,y,z,w;
440
441 x=2*t*t*t - 3*t*t + 1;
442 y=-2*t*t*t + 3*t*t;
443 z=t*t*t - 2*t*t + t;
444 w=t*t*t - t*t;
445 return((Lib3dsFloat)(x*a + y*b + z*p + w*q));
446 }
447
448
449 /*!
450 * \ingroup tracks
451 */
452 void
lib3ds_lin1_track_eval(Lib3dsLin1Track * track,Lib3dsFloat * p,Lib3dsFloat t)453 lib3ds_lin1_track_eval(Lib3dsLin1Track *track, Lib3dsFloat *p, Lib3dsFloat t)
454 {
455 Lib3dsLin1Key *k;
456 Lib3dsFloat nt;
457 Lib3dsFloat u;
458
459 ASSERT(p);
460 if (!track->keyL) {
461 *p=0;
462 return;
463 }
464 if (!track->keyL->next || ((t<track->keyL->tcb.frame) && ((track->flags&LIB3DS_REPEAT) != 0))) {
465 *p = track->keyL->value;
466 return;
467 }
468
469 for (k=track->keyL; k->next!=0; k=k->next) {
470 if ((t>=(Lib3dsFloat)k->tcb.frame) && (t<(Lib3dsFloat)k->next->tcb.frame)) {
471 break;
472 }
473 }
474 if (!k->next) {
475 if (track->flags&LIB3DS_REPEAT) {
476 nt=(Lib3dsFloat)fmod(t - track->keyL->tcb.frame, k->tcb.frame - track->keyL->tcb.frame) + track->keyL->tcb.frame;
477 for (k=track->keyL; k->next!=0; k=k->next) {
478 if ((nt>=(Lib3dsFloat)k->tcb.frame) && (nt<(Lib3dsFloat)k->next->tcb.frame)) {
479 break;
480 }
481 }
482 ASSERT(k->next);
483 }
484 else {
485 *p = k->value;
486 return;
487 }
488 }
489 else {
490 nt=t;
491 }
492 u=nt - (Lib3dsFloat)k->tcb.frame;
493 u/=(Lib3dsFloat)(k->next->tcb.frame - k->tcb.frame);
494
495 *p = lib3ds_float_cubic(
496 k->value,
497 k->dd,
498 k->next->ds,
499 k->next->value,
500 u
501 );
502 }
503
504
505 /*!
506 * \ingroup tracks
507 */
508 Lib3dsBool
lib3ds_lin1_track_read(Lib3dsLin1Track * track,Lib3dsIo * io)509 lib3ds_lin1_track_read(Lib3dsLin1Track *track, Lib3dsIo *io)
510 {
511 int keys;
512 int i;
513 Lib3dsLin1Key *k;
514
515 track->flags=lib3ds_io_read_word(io);
516 lib3ds_io_read_dword(io);
517 lib3ds_io_read_dword(io);
518 keys=lib3ds_io_read_intd(io);
519
520 for (i=0; i<keys; ++i) {
521 k=lib3ds_lin1_key_new();
522 if (!lib3ds_tcb_read(&k->tcb, io)) {
523 return(LIB3DS_FALSE);
524 }
525 k->value=lib3ds_io_read_float(io);
526 lib3ds_lin1_track_insert(track, k);
527 }
528 lib3ds_lin1_track_setup(track);
529 return(LIB3DS_TRUE);
530 }
531
532
533 /*!
534 * \ingroup tracks
535 */
536 Lib3dsBool
lib3ds_lin1_track_write(Lib3dsLin1Track * track,Lib3dsIo * io)537 lib3ds_lin1_track_write(Lib3dsLin1Track *track, Lib3dsIo *io)
538 {
539 Lib3dsLin1Key *k;
540 Lib3dsDword num=0;
541 for (k=track->keyL; k; k=k->next) {
542 ++num;
543 }
544 lib3ds_io_write_word(io, (Lib3dsWord)track->flags);
545 lib3ds_io_write_dword(io, 0);
546 lib3ds_io_write_dword(io, 0);
547 lib3ds_io_write_dword(io, num);
548
549 for (k=track->keyL; k; k=k->next) {
550 if (!lib3ds_tcb_write(&k->tcb,io)) {
551 return(LIB3DS_FALSE);
552 }
553 lib3ds_io_write_float(io, k->value);
554 }
555 return(LIB3DS_TRUE);
556 }
557
558
559 /*!
560 * Create and return one keyframe in a Lin3 track. All values are
561 * initialized to zero.
562 *
563 * \ingroup tracks
564 */
565 Lib3dsLin3Key*
lib3ds_lin3_key_new()566 lib3ds_lin3_key_new()
567 {
568 Lib3dsLin3Key* k;
569 k=(Lib3dsLin3Key*)calloc(sizeof(Lib3dsLin3Key), 1);
570 return(k);
571 }
572
573
574 /*!
575 * Free a Lin3 keyframe.
576 *
577 * \ingroup tracks
578 */
579 void
lib3ds_lin3_key_free(Lib3dsLin3Key * key)580 lib3ds_lin3_key_free(Lib3dsLin3Key *key)
581 {
582 ASSERT(key);
583 free(key);
584 }
585
586
587 /*!
588 * Free all keyframes in a Lin3 track.
589 *
590 * \ingroup tracks
591 */
592 void
lib3ds_lin3_track_free_keys(Lib3dsLin3Track * track)593 lib3ds_lin3_track_free_keys(Lib3dsLin3Track *track)
594 {
595 Lib3dsLin3Key *p,*q;
596
597 ASSERT(track);
598 for (p=track->keyL; p; p=q) {
599 q=p->next;
600 lib3ds_lin3_key_free(p);
601 }
602 }
603
604
605 /*!
606 * \ingroup tracks
607 */
608 void
lib3ds_lin3_key_setup(Lib3dsLin3Key * p,Lib3dsLin3Key * cp,Lib3dsLin3Key * c,Lib3dsLin3Key * cn,Lib3dsLin3Key * n)609 lib3ds_lin3_key_setup(Lib3dsLin3Key *p, Lib3dsLin3Key *cp, Lib3dsLin3Key *c,
610 Lib3dsLin3Key *cn, Lib3dsLin3Key *n)
611 {
612 Lib3dsVector np,nn;
613 Lib3dsFloat ksm,ksp,kdm,kdp;
614 int i;
615
616 ASSERT(c);
617 if (!cp) {
618 cp=c;
619 }
620 if (!cn) {
621 cn=c;
622 }
623 if (!p && !n) {
624 lib3ds_vector_zero(c->ds);
625 lib3ds_vector_zero(c->dd);
626 return;
627 }
628
629 if (n && p) {
630 lib3ds_tcb(&p->tcb, &cp->tcb, &c->tcb, &cn->tcb, &n->tcb, &ksm, &ksp, &kdm, &kdp);
631 lib3ds_vector_sub(np, c->value, p->value);
632 lib3ds_vector_sub(nn, n->value, c->value);
633
634 for(i=0; i<3; ++i) {
635 c->ds[i]=ksm*np[i] + ksp*nn[i];
636 c->dd[i]=kdm*np[i] + kdp*nn[i];
637 }
638 }
639 else {
640 if (p) {
641 lib3ds_vector_sub(np, c->value, p->value);
642 lib3ds_vector_copy(c->ds, np);
643 lib3ds_vector_copy(c->dd, np);
644 }
645 if (n) {
646 lib3ds_vector_sub(nn, n->value, c->value);
647 lib3ds_vector_copy(c->ds, nn);
648 lib3ds_vector_copy(c->dd, nn);
649 }
650 }
651 }
652
653
654 /*!
655 * \ingroup tracks
656 */
657 void
lib3ds_lin3_track_setup(Lib3dsLin3Track * track)658 lib3ds_lin3_track_setup(Lib3dsLin3Track *track)
659 {
660 Lib3dsLin3Key *pp,*pc,*pn,*pl;
661
662 ASSERT(track);
663 pc=track->keyL;
664 if (!pc) {
665 return;
666 }
667 if (!pc->next) {
668 lib3ds_vector_zero(pc->ds);
669 lib3ds_vector_zero(pc->dd);
670 return;
671 }
672
673 if (track->flags&LIB3DS_SMOOTH) {
674 for (pl=track->keyL; pl->next->next; pl=pl->next);
675 lib3ds_lin3_key_setup(pl, pl->next, pc, 0, pc->next);
676 }
677 else {
678 lib3ds_lin3_key_setup(0, 0, pc, 0, pc->next);
679 }
680 for (;;) {
681 pp=pc;
682 pc=pc->next;
683 pn=pc->next;
684 if (!pn) {
685 break;
686 }
687 lib3ds_lin3_key_setup(pp, 0, pc, 0, pn);
688 }
689
690 if (track->flags&LIB3DS_SMOOTH) {
691 lib3ds_lin3_key_setup(pp, 0, pc, track->keyL, track->keyL->next);
692 }
693 else {
694 lib3ds_lin3_key_setup(pp, 0, pc, 0, 0);
695 }
696 }
697
698
699 /*!
700 * \ingroup tracks
701 */
702 void
lib3ds_lin3_track_insert(Lib3dsLin3Track * track,Lib3dsLin3Key * key)703 lib3ds_lin3_track_insert(Lib3dsLin3Track *track, Lib3dsLin3Key *key)
704 {
705 ASSERT(track);
706 ASSERT(key);
707 ASSERT(!key->next);
708
709 if (!track->keyL) {
710 track->keyL=key;
711 key->next=0;
712 }
713 else {
714 Lib3dsLin3Key *k,*p;
715
716 for (p=0,k=track->keyL; k!=0; p=k, k=k->next) {
717 if (k->tcb.frame>key->tcb.frame) {
718 break;
719 }
720 }
721 if (!p) {
722 key->next=track->keyL;
723 track->keyL=key;
724 }
725 else {
726 key->next=k;
727 p->next=key;
728 }
729
730 if (k && (key->tcb.frame==k->tcb.frame)) {
731 key->next=k->next;
732 lib3ds_lin3_key_free(k);
733 }
734 }
735 }
736
737
738 /*!
739 * \ingroup tracks
740 */
741 void
lib3ds_lin3_track_remove(Lib3dsLin3Track * track,Lib3dsIntd frame)742 lib3ds_lin3_track_remove(Lib3dsLin3Track *track, Lib3dsIntd frame)
743 {
744 Lib3dsLin3Key *k,*p;
745
746 ASSERT(track);
747 if (!track->keyL) {
748 return;
749 }
750 for (p=0,k=track->keyL; k!=0; p=k, k=k->next) {
751 if (k->tcb.frame==frame) {
752 if (!p) {
753 track->keyL=track->keyL->next;
754 }
755 else {
756 p->next=k->next;
757 }
758 lib3ds_lin3_key_free(k);
759 break;
760 }
761 }
762 }
763
764
765 /*!
766 * \ingroup tracks
767 */
768 void
lib3ds_lin3_track_eval(Lib3dsLin3Track * track,Lib3dsVector p,Lib3dsFloat t)769 lib3ds_lin3_track_eval(Lib3dsLin3Track *track, Lib3dsVector p, Lib3dsFloat t)
770 {
771 Lib3dsLin3Key *k;
772 Lib3dsFloat nt;
773 Lib3dsFloat u;
774
775 if (!track->keyL) {
776 lib3ds_vector_zero(p);
777 return;
778 }
779 if (!track->keyL->next || ((t<track->keyL->tcb.frame) && ((track->flags&LIB3DS_REPEAT) != 0))) {
780 lib3ds_vector_copy(p, track->keyL->value);
781 return;
782 }
783
784 for (k=track->keyL; k->next!=0; k=k->next) {
785 if ((t>=(Lib3dsFloat)k->tcb.frame) && (t<(Lib3dsFloat)k->next->tcb.frame)) {
786 break;
787 }
788 }
789 if (!k->next) {
790 if (track->flags&LIB3DS_REPEAT) {
791 nt=(Lib3dsFloat)fmod(t - track->keyL->tcb.frame, k->tcb.frame - track->keyL->tcb.frame) + track->keyL->tcb.frame;
792 for (k=track->keyL; k->next!=0; k=k->next) {
793 if ((nt>=(Lib3dsFloat)k->tcb.frame) && (nt<(Lib3dsFloat)k->next->tcb.frame)) {
794 break;
795 }
796 }
797 ASSERT(k->next);
798 }
799 else {
800 lib3ds_vector_copy(p, k->value);
801 return;
802 }
803 }
804 else {
805 nt=t;
806 }
807 u=nt - (Lib3dsFloat)k->tcb.frame;
808 u/=(Lib3dsFloat)(k->next->tcb.frame - k->tcb.frame);
809
810 lib3ds_vector_cubic(
811 p,
812 k->value,
813 k->dd,
814 k->next->ds,
815 k->next->value,
816 u
817 );
818 }
819
820
821 /*!
822 * \ingroup tracks
823 */
824 Lib3dsBool
lib3ds_lin3_track_read(Lib3dsLin3Track * track,Lib3dsIo * io)825 lib3ds_lin3_track_read(Lib3dsLin3Track *track, Lib3dsIo *io)
826 {
827 int keys;
828 int i,j;
829 Lib3dsLin3Key *k;
830
831 track->flags=lib3ds_io_read_word(io);
832 lib3ds_io_read_dword(io);
833 lib3ds_io_read_dword(io);
834 keys=lib3ds_io_read_intd(io);
835
836 for (i=0; i<keys; ++i) {
837 k=lib3ds_lin3_key_new();
838 if (!lib3ds_tcb_read(&k->tcb, io)) {
839 return(LIB3DS_FALSE);
840 }
841 for (j=0; j<3; ++j) {
842 k->value[j]=lib3ds_io_read_float(io);
843 }
844 lib3ds_lin3_track_insert(track, k);
845 }
846 lib3ds_lin3_track_setup(track);
847 return(LIB3DS_TRUE);
848 }
849
850
851 /*!
852 * \ingroup tracks
853 */
854 Lib3dsBool
lib3ds_lin3_track_write(Lib3dsLin3Track * track,Lib3dsIo * io)855 lib3ds_lin3_track_write(Lib3dsLin3Track *track, Lib3dsIo *io)
856 {
857 Lib3dsLin3Key *k;
858 Lib3dsDword num=0;
859 for (k=track->keyL; k; k=k->next) {
860 ++num;
861 }
862 lib3ds_io_write_word(io, (Lib3dsWord)track->flags);
863 lib3ds_io_write_dword(io, 0);
864 lib3ds_io_write_dword(io, 0);
865 lib3ds_io_write_dword(io, num);
866
867 for (k=track->keyL; k; k=k->next) {
868 if (!lib3ds_tcb_write(&k->tcb,io)) {
869 return(LIB3DS_FALSE);
870 }
871 lib3ds_io_write_vector(io, k->value);
872 }
873 return(LIB3DS_TRUE);
874 }
875
876
877 /*!
878 * \ingroup tracks
879 */
880 Lib3dsQuatKey*
lib3ds_quat_key_new()881 lib3ds_quat_key_new()
882 {
883 Lib3dsQuatKey* k;
884 k=(Lib3dsQuatKey*)calloc(sizeof(Lib3dsQuatKey), 1);
885 return(k);
886 }
887
888
889 /*!
890 * \ingroup tracks
891 */
892 void
lib3ds_quat_key_free(Lib3dsQuatKey * key)893 lib3ds_quat_key_free(Lib3dsQuatKey *key)
894 {
895 ASSERT(key);
896 free(key);
897 }
898
899
900 /*!
901 * \ingroup tracks
902 */
903 void
lib3ds_quat_track_free_keys(Lib3dsQuatTrack * track)904 lib3ds_quat_track_free_keys(Lib3dsQuatTrack *track)
905 {
906 Lib3dsQuatKey *p,*q;
907
908 ASSERT(track);
909 for (p=track->keyL; p; p=q) {
910 q=p->next;
911 lib3ds_quat_key_free(p);
912 }
913 }
914
915
916 /*!
917 * \ingroup tracks
918 */
919 void
lib3ds_quat_key_setup(Lib3dsQuatKey * p,Lib3dsQuatKey * cp,Lib3dsQuatKey * c,Lib3dsQuatKey * cn,Lib3dsQuatKey * n)920 lib3ds_quat_key_setup(Lib3dsQuatKey *p, Lib3dsQuatKey *cp, Lib3dsQuatKey *c,
921 Lib3dsQuatKey *cn, Lib3dsQuatKey *n)
922 {
923 Lib3dsFloat ksm,ksp,kdm,kdp;
924 Lib3dsQuat q,qp,qn,qa,qb;
925 int i;
926
927 ASSERT(c);
928 if (!cp) {
929 cp=c;
930 }
931 if (!cn) {
932 cn=c;
933 }
934 if (!p || !n) {
935 lib3ds_quat_copy(c->ds, c->q);
936 lib3ds_quat_copy(c->dd, c->q);
937 return;
938 }
939
940 if (p) {
941 if (p->angle>LIB3DS_TWOPI-LIB3DS_EPSILON) {
942 lib3ds_quat_axis_angle(qp, p->axis, 0.0f);
943 lib3ds_quat_ln(qp);
944 }
945 else {
946 lib3ds_quat_copy(q, p->q);
947 if (lib3ds_quat_dot(q,c->q)<0) lib3ds_quat_neg(q);
948
949 lib3ds_quat_ln_dif(qp, q, c->q);
950 }
951 }
952 if (n) {
953 if (n->angle>LIB3DS_TWOPI-LIB3DS_EPSILON) {
954 lib3ds_quat_axis_angle(qn, n->axis, 0.0f);
955 lib3ds_quat_ln(qn);
956 }
957 else {
958 lib3ds_quat_copy(q, n->q);
959 if (lib3ds_quat_dot(q,c->q)<0) lib3ds_quat_neg(q);
960 lib3ds_quat_ln_dif(qn, c->q, q);
961 }
962 }
963
964 if (n && p) {
965 lib3ds_tcb(&p->tcb, &cp->tcb, &c->tcb, &cn->tcb, &n->tcb, &ksm, &ksp, &kdm, &kdp);
966 for(i=0; i<4; i++) {
967 qa[i]=0.5f*(kdm*qp[i]+(kdp-1.f)*qn[i]);
968 qb[i]=0.5f*((1.f-ksm)*qp[i]-ksp*qn[i]);
969 }
970 lib3ds_quat_exp(qa);
971 lib3ds_quat_exp(qb);
972
973 lib3ds_quat_mul(c->ds, c->q, qb);
974 lib3ds_quat_mul(c->dd, c->q, qa);
975 }
976 else {
977 if (p) {
978 lib3ds_quat_exp(qp);
979 lib3ds_quat_mul(c->ds, c->q, qp);
980 lib3ds_quat_mul(c->dd, c->q, qp);
981 }
982 if (n) {
983 lib3ds_quat_exp(qn);
984 lib3ds_quat_mul(c->ds, c->q, qn);
985 lib3ds_quat_mul(c->dd, c->q, qn);
986 }
987 }
988 }
989
990
991 /*!
992 * \ingroup tracks
993 */
994 void
lib3ds_quat_track_setup(Lib3dsQuatTrack * track)995 lib3ds_quat_track_setup(Lib3dsQuatTrack *track)
996 {
997 Lib3dsQuatKey *pp,*pc,*pn,*pl;
998 Lib3dsQuat q;
999
1000 ASSERT(track);
1001 for (pp=0,pc=track->keyL; pc; pp=pc,pc=pc->next) {
1002 lib3ds_quat_axis_angle(q, pc->axis, pc->angle);
1003 if (pp) {
1004 lib3ds_quat_mul(pc->q, q, pp->q);
1005 }
1006 else {
1007 lib3ds_quat_copy(pc->q, q);
1008 }
1009 }
1010
1011 pc=track->keyL;
1012 if (!pc) {
1013 return;
1014 }
1015 if (!pc->next) {
1016 lib3ds_quat_copy(pc->ds, pc->q);
1017 lib3ds_quat_copy(pc->dd, pc->q);
1018 return;
1019 }
1020
1021 if (track->flags&LIB3DS_SMOOTH) {
1022 for (pl=track->keyL; pl->next->next; pl=pl->next);
1023 lib3ds_quat_key_setup(pl, pl->next, pc, 0, pc->next);
1024 }
1025 else {
1026 lib3ds_quat_key_setup(0, 0, pc, 0, pc->next);
1027 }
1028 for (;;) {
1029 pp=pc;
1030 pc=pc->next;
1031 pn=pc->next;
1032 if (!pn) {
1033 break;
1034 }
1035 lib3ds_quat_key_setup(pp, 0, pc, 0, pn);
1036 }
1037
1038 if (track->flags&LIB3DS_SMOOTH) {
1039 lib3ds_quat_key_setup(pp, 0, pc, track->keyL, track->keyL->next);
1040 }
1041 else {
1042 lib3ds_quat_key_setup(pp, 0, pc, 0, 0);
1043 }
1044 }
1045
1046
1047 /*!
1048 * \ingroup tracks
1049 */
1050 void
lib3ds_quat_track_insert(Lib3dsQuatTrack * track,Lib3dsQuatKey * key)1051 lib3ds_quat_track_insert(Lib3dsQuatTrack *track, Lib3dsQuatKey *key)
1052 {
1053 ASSERT(track);
1054 ASSERT(key);
1055 ASSERT(!key->next);
1056
1057 if (!track->keyL) {
1058 track->keyL=key;
1059 key->next=0;
1060 }
1061 else {
1062 Lib3dsQuatKey *k,*p;
1063
1064 for (p=0,k=track->keyL; k!=0; p=k, k=k->next) {
1065 if (k->tcb.frame>key->tcb.frame) {
1066 break;
1067 }
1068 }
1069 if (!p) {
1070 key->next=track->keyL;
1071 track->keyL=key;
1072 }
1073 else {
1074 key->next=k;
1075 p->next=key;
1076 }
1077
1078 if (k && (key->tcb.frame==k->tcb.frame)) {
1079 key->next=k->next;
1080 lib3ds_quat_key_free(k);
1081 }
1082 }
1083 }
1084
1085
1086 /*!
1087 * \ingroup tracks
1088 */
1089 void
lib3ds_quat_track_remove(Lib3dsQuatTrack * track,Lib3dsIntd frame)1090 lib3ds_quat_track_remove(Lib3dsQuatTrack *track, Lib3dsIntd frame)
1091 {
1092 Lib3dsQuatKey *k,*p;
1093
1094 ASSERT(track);
1095 if (!track->keyL) {
1096 return;
1097 }
1098 for (p=0,k=track->keyL; k!=0; p=k, k=k->next) {
1099 if (k->tcb.frame==frame) {
1100 if (!p) {
1101 track->keyL=track->keyL->next;
1102 }
1103 else {
1104 p->next=k->next;
1105 }
1106 lib3ds_quat_key_free(k);
1107 break;
1108 }
1109 }
1110 }
1111
1112
1113 /*!
1114 * \ingroup tracks
1115 */
1116 void
lib3ds_quat_track_eval(Lib3dsQuatTrack * track,Lib3dsQuat q,Lib3dsFloat t)1117 lib3ds_quat_track_eval(Lib3dsQuatTrack *track, Lib3dsQuat q, Lib3dsFloat t)
1118 {
1119 Lib3dsQuatKey *k;
1120 Lib3dsFloat nt;
1121 Lib3dsFloat u;
1122
1123 if (!track->keyL) {
1124 lib3ds_quat_identity(q);
1125 return;
1126 }
1127 if (!track->keyL->next || ((t<track->keyL->tcb.frame) && ((track->flags&LIB3DS_REPEAT) != 0))) {
1128 lib3ds_quat_copy(q, track->keyL->q);
1129 return;
1130 }
1131
1132 for (k=track->keyL; k->next!=0; k=k->next) {
1133 if ((t>=k->tcb.frame) && (t<k->next->tcb.frame)) {
1134 break;
1135 }
1136 }
1137 if (!k->next) {
1138 if (track->flags&LIB3DS_REPEAT) {
1139 nt=(Lib3dsFloat)fmod(t - track->keyL->tcb.frame, k->tcb.frame - track->keyL->tcb.frame) + track->keyL->tcb.frame;
1140 for (k=track->keyL; k->next!=0; k=k->next) {
1141 if ((nt>=k->tcb.frame) && (nt<k->next->tcb.frame)) {
1142 break;
1143 }
1144 }
1145 ASSERT(k->next);
1146 }
1147 else {
1148 lib3ds_quat_copy(q, k->q);
1149 return;
1150 }
1151 }
1152 else {
1153 nt=t;
1154 }
1155 u=nt - k->tcb.frame;
1156 u/=(k->next->tcb.frame - k->tcb.frame);
1157
1158 lib3ds_quat_squad(
1159 q,
1160 k->q,
1161 k->dd,
1162 k->next->ds,
1163 k->next->q,
1164 u
1165 );
1166 }
1167
1168
1169 /*!
1170 * \ingroup tracks
1171 */
1172 Lib3dsBool
lib3ds_quat_track_read(Lib3dsQuatTrack * track,Lib3dsIo * io)1173 lib3ds_quat_track_read(Lib3dsQuatTrack *track, Lib3dsIo *io)
1174 {
1175 int keys;
1176 int i,j;
1177 Lib3dsQuatKey *p,*k;
1178
1179 track->flags=lib3ds_io_read_word(io);
1180 lib3ds_io_read_dword(io);
1181 lib3ds_io_read_dword(io);
1182 keys=lib3ds_io_read_intd(io);
1183
1184 for (p=0,i=0; i<keys; p=k,++i) {
1185 k=lib3ds_quat_key_new();
1186 if (!lib3ds_tcb_read(&k->tcb, io)) {
1187 return(LIB3DS_FALSE);
1188 }
1189 k->angle=lib3ds_io_read_float(io);
1190 for (j=0; j<3; ++j) {
1191 k->axis[j]=lib3ds_io_read_float(io);
1192 }
1193 lib3ds_quat_track_insert(track, k);
1194 }
1195 lib3ds_quat_track_setup(track);
1196 return(LIB3DS_TRUE);
1197 }
1198
1199
1200 /*!
1201 * \ingroup tracks
1202 */
1203 Lib3dsBool
lib3ds_quat_track_write(Lib3dsQuatTrack * track,Lib3dsIo * io)1204 lib3ds_quat_track_write(Lib3dsQuatTrack *track, Lib3dsIo *io)
1205 {
1206 Lib3dsQuatKey *k;
1207 Lib3dsDword num=0;
1208 for (k=track->keyL; k; k=k->next) {
1209 ++num;
1210 }
1211 lib3ds_io_write_word(io, (Lib3dsWord)track->flags);
1212 lib3ds_io_write_dword(io, 0);
1213 lib3ds_io_write_dword(io, 0);
1214 lib3ds_io_write_dword(io, num);
1215
1216 for (k=track->keyL; k; k=k->next) {
1217 if (!lib3ds_tcb_write(&k->tcb,io)) {
1218 return(LIB3DS_FALSE);
1219 }
1220 lib3ds_io_write_float(io, k->angle);
1221 lib3ds_io_write_vector(io, k->axis);
1222 }
1223 return(LIB3DS_TRUE);
1224 }
1225
1226
1227 /*!
1228 * \ingroup tracks
1229 */
1230 Lib3dsMorphKey*
lib3ds_morph_key_new()1231 lib3ds_morph_key_new()
1232 {
1233 Lib3dsMorphKey* k;
1234 k=(Lib3dsMorphKey*)calloc(sizeof(Lib3dsMorphKey), 1);
1235 return(k);
1236 }
1237
1238
1239 /*!
1240 * \ingroup tracks
1241 */
1242 void
lib3ds_morph_key_free(Lib3dsMorphKey * key)1243 lib3ds_morph_key_free(Lib3dsMorphKey *key)
1244 {
1245 ASSERT(key);
1246 free(key);
1247 }
1248
1249
1250 /*!
1251 * \ingroup tracks
1252 */
1253 void
lib3ds_morph_track_free_keys(Lib3dsMorphTrack * track)1254 lib3ds_morph_track_free_keys(Lib3dsMorphTrack *track)
1255 {
1256 Lib3dsMorphKey *p,*q;
1257
1258 ASSERT(track);
1259 for (p=track->keyL; p; p=q) {
1260 q=p->next;
1261 lib3ds_morph_key_free(p);
1262 }
1263 }
1264
1265
1266 /*!
1267 * \ingroup tracks
1268 */
1269 void
lib3ds_morph_track_insert(Lib3dsMorphTrack * track,Lib3dsMorphKey * key)1270 lib3ds_morph_track_insert(Lib3dsMorphTrack *track, Lib3dsMorphKey *key)
1271 {
1272 ASSERT(track);
1273 ASSERT(key);
1274 ASSERT(!key->next);
1275
1276 if (!track->keyL) {
1277 track->keyL=key;
1278 key->next=0;
1279 }
1280 else {
1281 Lib3dsMorphKey *k,*p;
1282
1283 for (p=0,k=track->keyL; k!=0; p=k, k=k->next) {
1284 if (k->tcb.frame>key->tcb.frame) {
1285 break;
1286 }
1287 }
1288 if (!p) {
1289 key->next=track->keyL;
1290 track->keyL=key;
1291 }
1292 else {
1293 key->next=k;
1294 p->next=key;
1295 }
1296
1297 if (k && (key->tcb.frame==k->tcb.frame)) {
1298 key->next=k->next;
1299 lib3ds_morph_key_free(k);
1300 }
1301 }
1302 }
1303
1304
1305 /*!
1306 * \ingroup tracks
1307 */
1308 void
lib3ds_morph_track_remove(Lib3dsMorphTrack * track,Lib3dsIntd frame)1309 lib3ds_morph_track_remove(Lib3dsMorphTrack *track, Lib3dsIntd frame)
1310 {
1311 Lib3dsMorphKey *k,*p;
1312
1313 ASSERT(track);
1314 if (!track->keyL) {
1315 return;
1316 }
1317 for (p=0,k=track->keyL; k!=0; p=k, k=k->next) {
1318 if (k->tcb.frame==frame) {
1319 if (!p) {
1320 track->keyL=track->keyL->next;
1321 }
1322 else {
1323 p->next=k->next;
1324 }
1325 lib3ds_morph_key_free(k);
1326 break;
1327 }
1328 }
1329 }
1330
1331
1332 /*!
1333 * \ingroup tracks
1334 */
1335 void
lib3ds_morph_track_eval(Lib3dsMorphTrack * track,char * p,Lib3dsFloat t)1336 lib3ds_morph_track_eval(Lib3dsMorphTrack *track, char *p, Lib3dsFloat t)
1337 {
1338 Lib3dsMorphKey *k;
1339 char* result;
1340
1341 ASSERT(p);
1342 if (!track->keyL) {
1343 strcpy(p,"");
1344 return;
1345 }
1346 if (!track->keyL->next) {
1347 strcpy(p,track->keyL->name);
1348 return;
1349 }
1350
1351
1352 /* TODO: this function finds the mesh frame that corresponds to this
1353 * timeframe. It would be better to actually interpolate the mesh.
1354 */
1355
1356 result=0;
1357
1358 for(k = track->keyL;
1359 k->next != NULL && t >= k->next->tcb.frame;
1360 k = k->next);
1361
1362 result=k->name;
1363
1364 if (result) {
1365 strcpy(p,result);
1366 }
1367 else {
1368 strcpy(p,"");
1369 }
1370 }
1371
1372
1373 /*!
1374 * \ingroup tracks
1375 */
1376 Lib3dsBool
lib3ds_morph_track_read(Lib3dsMorphTrack * track,Lib3dsIo * io)1377 lib3ds_morph_track_read(Lib3dsMorphTrack *track, Lib3dsIo *io)
1378 {
1379 /* This function was written by Stephane Denis on 5-18-04 */
1380 int i;
1381 Lib3dsMorphKey *k, *pk;
1382 int keys;
1383 track->flags=lib3ds_io_read_word(io);
1384 lib3ds_io_read_dword(io);
1385 lib3ds_io_read_dword(io);
1386 keys=lib3ds_io_read_intd(io);
1387
1388 for (i=0; i<keys; ++i) {
1389 k=lib3ds_morph_key_new();
1390 if (!lib3ds_tcb_read(&k->tcb, io)) {
1391 return(LIB3DS_FALSE);
1392 }
1393 if (!lib3ds_io_read_string(io, k->name, 11)) {
1394 return(LIB3DS_FALSE);
1395 }
1396 if (!track->keyL)
1397 track->keyL = k;
1398 else
1399 pk->next = k;
1400 pk = k;
1401 }
1402 return(LIB3DS_TRUE);
1403 }
1404
1405
1406 /*!
1407 * \ingroup tracks
1408 */
1409 Lib3dsBool
lib3ds_morph_track_write(Lib3dsMorphTrack * track,Lib3dsIo * io)1410 lib3ds_morph_track_write(Lib3dsMorphTrack *track, Lib3dsIo *io)
1411 {
1412 /* FIXME: */
1413 ASSERT(0);
1414 return(LIB3DS_FALSE);
1415 }
1416
1417
1418
1419 void
tcb_dump(Lib3dsTcb * tcb)1420 tcb_dump(Lib3dsTcb *tcb)
1421 {
1422 printf(" tcb: frame=%d, flags=%04x, tens=%g, cont=%g, ",
1423 tcb->frame, tcb->flags, tcb->tens, tcb->cont);
1424 printf("bias=%g, ease_to=%g, ease_from=%g\n",
1425 tcb->bias, tcb->ease_to, tcb->ease_from);
1426 }
1427
1428
1429 void
lib3ds_boolTrack_dump(Lib3dsBoolTrack * track)1430 lib3ds_boolTrack_dump(Lib3dsBoolTrack *track)
1431 {
1432 Lib3dsBoolKey *key;
1433 printf("flags: %08x, keys:\n", track->flags);
1434 for( key = track->keyL; key != NULL; key = key->next)
1435 {
1436 tcb_dump(&key->tcb);
1437 }
1438 }
1439
1440
1441 void
lib3ds_lin1Track_dump(Lib3dsLin1Track * track)1442 lib3ds_lin1Track_dump(Lib3dsLin1Track *track)
1443 {
1444 Lib3dsLin1Key *key;
1445 printf("flags: %08x, keys:\n", track->flags);
1446 for( key = track->keyL; key != NULL; key = key->next)
1447 {
1448 tcb_dump(&key->tcb);
1449 printf(" value = %g, dd=%g, ds=%g\n",
1450 key->value, key->dd, key->ds);
1451 }
1452 }
1453
1454
1455 void
lib3ds_lin3Track_dump(Lib3dsLin3Track * track)1456 lib3ds_lin3Track_dump(Lib3dsLin3Track *track)
1457 {
1458 Lib3dsLin3Key *key;
1459 printf("flags: %08x, keys:\n", track->flags);
1460 for( key = track->keyL; key != NULL; key = key->next)
1461 {
1462 tcb_dump(&key->tcb);
1463 printf(" value = %g,%g,%g, dd=%g,%g,%g, ds=%g,%g,%g\n",
1464 key->value[0], key->value[1], key->value[2],
1465 key->dd[0], key->dd[1], key->dd[2],
1466 key->ds[0], key->ds[1], key->ds[2]);
1467 }
1468 }
1469
1470
1471 void
lib3ds_quatTrack_dump(Lib3dsQuatTrack * track)1472 lib3ds_quatTrack_dump(Lib3dsQuatTrack *track)
1473 {
1474 Lib3dsQuatKey *key;
1475 printf("flags: %08x, keys:\n", track->flags);
1476 for( key = track->keyL; key != NULL; key = key->next)
1477 {
1478 tcb_dump(&key->tcb);
1479 printf(" axis = %g,%g,%g, angle=%g, q=%g,%g,%g,%g\n",
1480 key->axis[0], key->axis[1], key->axis[2], key->angle,
1481 key->q[0], key->q[1], key->q[2], key->q[3]);
1482 printf(" dd = %g,%g,%g,%g, ds=%g,%g,%g,%g\n",
1483 key->dd[0], key->dd[1], key->dd[2], key->dd[3],
1484 key->ds[0], key->ds[1], key->ds[2], key->ds[3]);
1485 }
1486 }
1487
1488
1489 void
lib3ds_morphTrack_dump(Lib3dsMorphTrack * track)1490 lib3ds_morphTrack_dump(Lib3dsMorphTrack *track)
1491 {
1492 Lib3dsMorphKey *key;
1493 printf("flags: %08x, keys:\n", track->flags);
1494 for( key = track->keyL; key != NULL; key = key->next)
1495 {
1496 tcb_dump(&key->tcb);
1497 printf(" name = %s\n", key->name);
1498 }
1499 }
1500
1501
1502
1503 void
lib3ds_dump_tracks(Lib3dsNode * node)1504 lib3ds_dump_tracks(Lib3dsNode *node)
1505 {
1506 switch( node->type ) {
1507 case LIB3DS_AMBIENT_NODE:
1508 printf("ambient: ");
1509 lib3ds_lin3Track_dump(&node->data.ambient.col_track);
1510 break;
1511 case LIB3DS_OBJECT_NODE:
1512 printf("pos: ");
1513 lib3ds_lin3Track_dump(&node->data.object.pos_track);
1514 printf("rot: ");
1515 lib3ds_quatTrack_dump(&node->data.object.rot_track);
1516 printf("scl: ");
1517 lib3ds_lin3Track_dump(&node->data.object.scl_track);
1518 printf("morph: ");
1519 lib3ds_morphTrack_dump(&node->data.object.morph_track);
1520 printf("hide: ");
1521 lib3ds_boolTrack_dump(&node->data.object.hide_track);
1522 break;
1523 case LIB3DS_CAMERA_NODE:
1524 printf("pos: ");
1525 lib3ds_lin3Track_dump(&node->data.camera.pos_track);
1526 printf("fov: ");
1527 lib3ds_lin1Track_dump(&node->data.camera.fov_track);
1528 printf("roll: ");
1529 lib3ds_lin1Track_dump(&node->data.camera.roll_track);
1530 break;
1531 case LIB3DS_TARGET_NODE:
1532 printf("pos: ");
1533 lib3ds_lin3Track_dump(&node->data.target.pos_track);
1534 break;
1535 case LIB3DS_LIGHT_NODE:
1536 printf("pos: ");
1537 lib3ds_lin3Track_dump(&node->data.light.pos_track);
1538 printf("col: ");
1539 lib3ds_lin3Track_dump(&node->data.light.col_track);
1540 printf("hotspot: ");
1541 lib3ds_lin1Track_dump(&node->data.light.hotspot_track);
1542 printf("falloff: ");
1543 lib3ds_lin1Track_dump(&node->data.light.falloff_track);
1544 printf("roll: ");
1545 lib3ds_lin1Track_dump(&node->data.light.roll_track);
1546 break;
1547 case LIB3DS_SPOT_NODE:
1548 printf("pos: ");
1549 lib3ds_lin3Track_dump(&node->data.spot.pos_track);
1550 break;
1551 }
1552 }
1553