root/OpenSceneGraph/trunk/src/osgPlugins/3ds/lib3ds/lib3ds_track.c @ 10853

Revision 10853, 15.4 kB (checked in by robert, 4 years ago)

From Sukender,
"Here is our freshly baked 3DS reader/writer (named 'v0.5' to differentiate from previous one). Changes are against trunk rev. 10819.
Short changelog (from rev 10819):
- Added 3DS writer
- Sync'd with latest lib3DS
- Added options, especially "flattenMatrixTransforms" to get the "old" behaviour (else the reader correctly maps to OSG the transforms from the 3DS file).

What should be done:
- Check with pivot points, with and without "flattenMatrixTransforms" option.
- We ran tests on it, but we can never be 100% sure there is no bug. Testing from the community would of course be helpful."

RevLine 
[10853]1/*
2    Copyright (C) 1996-2008 by Jan Eric Kyprianidis <www.kyprianidis.com>
3    All rights reserved.
4   
5    This program is free  software: you can redistribute it and/or modify
6    it under the terms of the GNU Lesser General Public License as published
7    by the Free Software Foundation, either version 2.1 of the License, or
8    (at your option) any later version.
9
10    Thisprogram  is  distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13    GNU Lesser General Public License for more details.
14   
15    You should  have received a copy of the GNU Lesser General Public License
16    along with  this program; If not, see <http://www.gnu.org/licenses/>.
17*/
18#include "lib3ds_impl.h"
19
20
21Lib3dsTrack*
22lib3ds_track_new(Lib3dsTrackType type, int nkeys) {
23    Lib3dsTrack *track = (Lib3dsTrack*)calloc(sizeof(Lib3dsTrack), 1);
24    track->type = type;
25    lib3ds_track_resize(track, nkeys);
26    return track;
27}
28
29
30void 
31lib3ds_track_free(Lib3dsTrack *track) {
32    assert(track);
33    lib3ds_track_resize(track, 0);
34    memset(track, 0, sizeof(Lib3dsTrack));
35    free(track);
36}
37
38
39void 
40lib3ds_track_resize(Lib3dsTrack *track, int nkeys) {
41    char *p;
42
43    assert(track);
44    if (track->nkeys == nkeys)
45        return;
46
47    p = (char*)realloc(track->keys, sizeof(Lib3dsKey) * nkeys);
48    if (nkeys > track->nkeys) {
49        memset(p + (sizeof(Lib3dsKey)*track->nkeys), 0, sizeof(Lib3dsKey)*(nkeys - track->nkeys));
50    }
51    track->keys = (Lib3dsKey*)p;
52    track->nkeys = nkeys;
53}
54
55
56static void 
57pos_key_setup(int n, Lib3dsKey *pp, Lib3dsKey *pc, Lib3dsKey *pn, float *dd, float *ds) {
58    float tm, cm, cp, bm, bp, tmcm, tmcp, ksm, ksp, kdm, kdp, c;
59    float dt, fp, fn;
60    float delm[3], delp[3];
61    int i;
62
63    assert(pc);
64    fp = fn = 1.0f;
65    if (pp && pn) {
66        dt = 0.5f * (pn->frame - pp->frame);
67        fp = (float)(pc->frame - pp->frame) / dt;
68        fn = (float)(pn->frame - pc->frame) / dt;
69        c  = (float)fabs(pc->cont);
70        fp = fp + c - c * fp;
71        fn = fn + c - c * fn;
72    }
73
74    cm = 1.0f - pc->cont;
75    tm = 0.5f * (1.0f - pc->tens);
76    cp = 2.0f - cm;
77    bm = 1.0f - pc->bias;
78    bp = 2.0f - bm;
79    tmcm = tm * cm;
80    tmcp = tm * cp;
81    ksm = tmcm * bp * fp;
82    ksp = tmcp * bm * fp;
83    kdm = tmcp * bp * fn;
84    kdp = tmcm * bm * fn;
85
86    for (i = 0; i < n; ++i) delm[i] = delp[i] = 0;
87    if (pp) {
88        for (i = 0; i < n; ++i) delm[i] = pc->value[i] - pp->value[i];
89    }
90    if (pn) {
91        for (i = 0; i < n; ++i) delp[i] = pn->value[i] - pc->value[i];
92    }
93    if (!pp) {
94        for (i = 0; i < n; ++i) delm[i] = delp[i];
95    }
96    if (!pn) {
97        for (i = 0; i < n; ++i) delp[i] = delm[i];
98    }
99
100    for (i = 0; i < n; ++i) {
101        ds[i] = ksm * delm[i] + ksp * delp[i];
102        dd[i] = kdm * delm[i] + kdp * delp[i];
103    }
104}
105
106
107static void 
108rot_key_setup(Lib3dsKey *prev, Lib3dsKey *cur, Lib3dsKey *next, float a[4], float b[4]) {
109    float tm, cm, cp, bm, bp, tmcm, tmcp, ksm, ksp, kdm, kdp, c;
110    float dt, fp, fn;
111    float q[4], qm[4], qp[4], qa[4], qb[4];
112    int i;
113
114    assert(cur);
115    if (prev) {
116        if (cur->value[3] > LIB3DS_TWOPI - LIB3DS_EPSILON) {
117            lib3ds_quat_axis_angle(qm, cur->value, 0.0f);
118            lib3ds_quat_ln(qm);
119        } else {
120            lib3ds_quat_copy(q, prev->value);
121            if (lib3ds_quat_dot(q, cur->value) < 0) lib3ds_quat_neg(q);
122            lib3ds_quat_ln_dif(qm, q, cur->value);
123        }
124    }
125    if (next) {
126        if (next->value[3] > LIB3DS_TWOPI - LIB3DS_EPSILON) {
127            lib3ds_quat_axis_angle(qp, next->value, 0.0f);
128            lib3ds_quat_ln(qp);
129        } else {
130            lib3ds_quat_copy(q, next->value);
131            if (lib3ds_quat_dot(q, cur->value) < 0) lib3ds_quat_neg(q);
132            lib3ds_quat_ln_dif(qp, cur->value, q);
133        }
134    }
135    if (!prev) lib3ds_quat_copy(qm, qp);
136    if (!next) lib3ds_quat_copy(qp, qm);
137
138    fp = fn = 1.0f;
139    cm = 1.0f - cur->cont;
140    if (prev && next) {
141        dt = 0.5f * (next->frame - prev->frame);
142        fp = (float)(cur->frame - prev->frame) / dt;
143        fn = (float)(next->frame - cur->frame) / dt;
144        c  = (float)fabs(cur->cont);
145        fp = fp + c - c * fp;
146        fn = fn + c - c * fn;
147    }
148
149    tm = 0.5f * (1.0f - cur->tens);
150    cp = 2.0f - cm;
151    bm = 1.0f - cur->bias;
152    bp = 2.0f - bm;
153    tmcm = tm * cm;
154    tmcp = tm * cp;
155    ksm = 1.0f - tmcm * bp * fp;
156    ksp = -tmcp * bm * fp;
157    kdm = tmcp * bp * fn;
158    kdp = tmcm * bm * fn - 1.0f;
159
160    for (i = 0; i < 4; i++) {
161        qa[i] = 0.5f * (kdm * qm[i] + kdp * qp[i]);
162        qb[i] = 0.5f * (ksm * qm[i] + ksp * qp[i]);
163    }
164    lib3ds_quat_exp(qa);
165    lib3ds_quat_exp(qb);
166
167    lib3ds_quat_mul(a, cur->value, qa);
168    lib3ds_quat_mul(b, cur->value, qb);
169}
170
171
172static void
173quat_for_index(Lib3dsTrack *track, int index, float q[4]) {
174    float p[4];
175    int i;
176    lib3ds_quat_identity(q);
177    for (i = 0; i <= index; ++i) {
178        lib3ds_quat_axis_angle(p, track->keys[i].value, track->keys[i].value[3]);
179        lib3ds_quat_mul(q, p, q);
180    }
181}
182
183
184static int 
185find_index(Lib3dsTrack *track, float t, float *u) {
186    int i;
187    float nt;
188    int t0, t1;
189
190    assert(track);
191    assert(track->nkeys > 0);
192   
193    if (track->nkeys <= 1)
194        return -1;
195   
196    t0 = track->keys[0].frame;
197    t1 = track->keys[track->nkeys-1].frame;
198    if (track->flags & LIB3DS_TRACK_REPEAT) {
199        nt = (float)fmod(t - t0, t1 - t0) + t0;
200    } else {
201        nt = t;
202    }
203
204    if (nt <= t0) {
205        return -1;
206    }
207    if (nt >= t1) {
208        return track->nkeys;
209    }
210
211    for (i = 1; i < track->nkeys; ++i) {
212        if (nt < track->keys[i].frame)
213            break;
214    }
215
216    *u = nt - (float)track->keys[i-1].frame;
217    *u /= (float)(track->keys[i].frame - track->keys[i-1].frame);
218
219    assert((*u >= 0.0f) && (*u <= 1.0f));
220    return i;
221}
222
223
224static void 
225setup_segment(Lib3dsTrack *track, int index, Lib3dsKey *pp, Lib3dsKey *p0, Lib3dsKey *p1, Lib3dsKey *pn) {
226    int ip, in;
227   
228    pp->frame = pn->frame = -1;
229    if (index >= 2) {
230        ip = index - 2;
231        *pp = track->keys[index - 2];
232    } else {
233        if (track->flags & LIB3DS_TRACK_SMOOTH) {
234            ip = track->nkeys - 2;
235            *pp = track->keys[track->nkeys - 2];
236            pp->frame = track->keys[track->nkeys - 2].frame - (track->keys[track->nkeys - 1].frame - track->keys[0].frame);
237        }
238                else ip = -1;           // Avoids a compiler warning
239    }
240
241    *p0 = track->keys[index - 1];
242    *p1 = track->keys[index];
243
244    if (index < (int)track->nkeys - 1) {
245        in = index + 1;
246        *pn = track->keys[index + 1];
247    } else {
248        if (track->flags & LIB3DS_TRACK_SMOOTH) {
249            in = 1;
250            *pn = track->keys[1];
251            pn->frame = track->keys[1].frame + (track->keys[track->nkeys-1].frame - track->keys[0].frame);
252        }
253    }
254
255    if (track->type == LIB3DS_TRACK_QUAT) {
256        float q[4];
257        if (pp->frame >= 0) {
258            quat_for_index(track, ip, pp->value);
259        } else {
260            lib3ds_quat_identity(pp->value);
261        }
262
263        quat_for_index(track, index - 1, p0->value);
264        lib3ds_quat_axis_angle(q, track->keys[index].value, track->keys[index].value[3]);
265        lib3ds_quat_mul(p1->value, q, p0->value);
266
267        if (pn->frame >= 0) {
268            lib3ds_quat_axis_angle(q, track->keys[in].value, track->keys[in].value[3]);
269            lib3ds_quat_mul(pn->value, q, p1->value);
270        } else {
271            lib3ds_quat_identity(pn->value);
272        }
273    }
274}
275
276
277void 
278lib3ds_track_eval_bool(Lib3dsTrack *track, int *b, float t) {
279    *b = FALSE;
280    if (track) {
281        int index;
282        float u;
283
284        assert(track->type == LIB3DS_TRACK_BOOL);
285        if (!track->nkeys) {
286            return;
287        }
288
289        index = find_index(track, t, &u);
290        if (index < 0) {
291            *b = FALSE;
292            return;
293        }
294        if (index >= track->nkeys) {
295            *b = !(track->nkeys & 1);
296            return;
297        }
298        *b = !(index & 1);
299    }
300}
301
302
303static void 
304track_eval_linear(Lib3dsTrack *track, float *value, float t) {
305    Lib3dsKey pp, p0, p1, pn;
306    float u;
307    int index;
308    float dsp[3], ddp[3], dsn[3], ddn[3];
309
310    assert(track);
311    if (!track->nkeys) {
312        int i;
313        for (i = 0; i < track->type; ++i) value[i] = 0.0f;
314        return;
315    }
316
317    index = find_index(track, t, &u);
318
319    if (index < 0) {
320        int i;
321        for (i = 0; i < track->type; ++i) value[i] = track->keys[0].value[i];
322        return;
323    }
324    if (index >= track->nkeys) {
325        int i;
326        for (i = 0; i < track->type; ++i) value[i] = track->keys[track->nkeys-1].value[i];
327        return;
328    }
329
330    setup_segment(track, index, &pp, &p0, &p1, &pn);
331
332    pos_key_setup(track->type, pp.frame>=0? &pp : NULL, &p0, &p1, ddp, dsp);
333    pos_key_setup(track->type, &p0, &p1, pn.frame>=0? &pn : NULL, ddn, dsn);
334
335    lib3ds_math_cubic_interp(
336        value,
337        p0.value,
338        ddp,
339        dsn,
340        p1.value,
341        track->type,
342        u
343    );
344}
345
346
347void 
348lib3ds_track_eval_float(Lib3dsTrack *track, float *f, float t) {
349    *f = 0;
350    if (track) {
351        assert(track->type == LIB3DS_TRACK_FLOAT);
352        track_eval_linear(track, f, t);
353    }
354}
355
356
357void 
358lib3ds_track_eval_vector(Lib3dsTrack *track, float v[3], float t) {
359    lib3ds_vector_zero(v);
360    if (track) {
361        assert(track->type == LIB3DS_TRACK_VECTOR);
362        track_eval_linear(track, v, t);
363    }
364}
365
366
367void 
368lib3ds_track_eval_quat(Lib3dsTrack *track, float q[4], float t) {
369    lib3ds_quat_identity(q);
370    if (track) {
371        Lib3dsKey pp, p0, p1, pn;
372        float u;
373        int index;
374        float ap[4], bp[4], an[4], bn[4];
375
376        assert(track->type == LIB3DS_TRACK_QUAT);
377        if (!track->nkeys) {
378            return;
379        }
380
381        index = find_index(track, t, &u);
382        if (index < 0) {
383            lib3ds_quat_axis_angle(q, track->keys[0].value, track->keys[0].value[3]);
384            return;
385        }
386        if (index >= track->nkeys) {
387            quat_for_index(track, track->nkeys - 1, q);
388            return;
389        }
390
391        setup_segment(track, index, &pp, &p0, &p1, &pn);
392
393        rot_key_setup(pp.frame>=0? &pp : NULL, &p0, &p1, ap, bp);
394        rot_key_setup(&p0, &p1, pn.frame>=0? &pn : NULL, an, bn);
395
396        lib3ds_quat_squad(q, p0.value, ap, bn, p1.value, u);
397    }
398}
399
400
401static void 
402tcb_read(Lib3dsKey *key, Lib3dsIo *io) {
403    key->flags = lib3ds_io_read_word(io);
404    if (key->flags & LIB3DS_KEY_USE_TENS) {
405        key->tens = lib3ds_io_read_float(io);
406    }
407    if (key->flags & LIB3DS_KEY_USE_CONT) {
408        key->cont = lib3ds_io_read_float(io);
409    }
410    if (key->flags & LIB3DS_KEY_USE_BIAS) {
411        key->bias = lib3ds_io_read_float(io);
412    }
413    if (key->flags & LIB3DS_KEY_USE_EASE_TO) {
414        key->ease_to = lib3ds_io_read_float(io);
415    }
416    if (key->flags & LIB3DS_KEY_USE_EASE_FROM) {
417        key->ease_from = lib3ds_io_read_float(io);
418    }
419}
420
421
422void 
423lib3ds_track_read(Lib3dsTrack *track, Lib3dsIo *io) {
424    unsigned nkeys;
425    unsigned i;
426
427    track->flags = lib3ds_io_read_word(io);
428    lib3ds_io_read_dword(io);
429    lib3ds_io_read_dword(io);
430    nkeys = lib3ds_io_read_intd(io);
431    lib3ds_track_resize(track, nkeys);
432
433    switch (track->type) {
434        case LIB3DS_TRACK_BOOL:
435            for (i = 0; i < nkeys; ++i) {
436                track->keys[i].frame = lib3ds_io_read_intd(io);
437                tcb_read(&track->keys[i], io);
438            }
439            break;
440
441        case LIB3DS_TRACK_FLOAT:
442            for (i = 0; i < nkeys; ++i) {
443                track->keys[i].frame = lib3ds_io_read_intd(io);
444                tcb_read(&track->keys[i], io);
445                track->keys[i].value[0] = lib3ds_io_read_float(io);
446            }
447            break;
448
449        case LIB3DS_TRACK_VECTOR:
450            for (i = 0; i < nkeys; ++i) {
451                track->keys[i].frame = lib3ds_io_read_intd(io);
452                tcb_read(&track->keys[i], io);
453                lib3ds_io_read_vector(io, track->keys[i].value);
454            }
455            break;
456
457        case LIB3DS_TRACK_QUAT:
458            for (i = 0; i < nkeys; ++i) {
459                track->keys[i].frame = lib3ds_io_read_intd(io);
460                tcb_read(&track->keys[i], io);
461                track->keys[i].value[3] = lib3ds_io_read_float(io);
462                lib3ds_io_read_vector(io, track->keys[i].value);
463            }
464            break;
465
466        /*case LIB3DS_TRACK_MORPH:
467            for (i = 0; i < nkeys; ++i) {
468                track->keys[i].frame = lib3ds_io_read_intd(io);
469                tcb_read(&track->keys[i].tcb, io);
470                lib3ds_io_read_string(io, track->keys[i].data.m.name, 64);
471            }
472            break;*/
473
474        default:
475            break;
476    }
477}
478
479
480void
481tcb_write(Lib3dsKey *key, Lib3dsIo *io) {
482    lib3ds_io_write_word(io, (uint16_t)key->flags);
483    if (key->flags & LIB3DS_KEY_USE_TENS) {
484        lib3ds_io_write_float(io, key->tens);
485    }
486    if (key->flags & LIB3DS_KEY_USE_CONT) {
487        lib3ds_io_write_float(io, key->cont);
488    }
489    if (key->flags & LIB3DS_KEY_USE_BIAS) {
490        lib3ds_io_write_float(io, key->bias);
491    }
492    if (key->flags & LIB3DS_KEY_USE_EASE_TO) {
493        lib3ds_io_write_float(io, key->ease_to);
494    }
495    if (key->flags & LIB3DS_KEY_USE_EASE_FROM) {
496        lib3ds_io_write_float(io, key->ease_from);
497    }
498}
499
500
501void
502lib3ds_track_write(Lib3dsTrack *track, Lib3dsIo *io) {
503    int i;
504
505    lib3ds_io_write_word(io, (uint16_t)track->flags);
506    lib3ds_io_write_dword(io, 0);
507    lib3ds_io_write_dword(io, 0);
508    lib3ds_io_write_dword(io, track->nkeys);
509
510    switch (track->type) {
511        case LIB3DS_TRACK_BOOL:
512            for (i = 0; i < track->nkeys; ++i) {
513                lib3ds_io_write_intd(io, track->keys[i].frame);
514                tcb_write(&track->keys[i], io);
515            }
516            break;
517
518        case LIB3DS_TRACK_FLOAT:
519            for (i = 0; i < track->nkeys; ++i) {
520                lib3ds_io_write_intd(io, track->keys[i].frame);
521                tcb_write(&track->keys[i], io);
522                lib3ds_io_write_float(io, track->keys[i].value[0]);
523            }
524            break;
525
526        case LIB3DS_TRACK_VECTOR:
527            for (i = 0; i < track->nkeys; ++i) {
528                lib3ds_io_write_intd(io, track->keys[i].frame);
529                tcb_write(&track->keys[i], io);
530                lib3ds_io_write_vector(io, track->keys[i].value);
531            }
532            break;
533
534        case LIB3DS_TRACK_QUAT:
535            for (i = 0; i < track->nkeys; ++i) {
536                lib3ds_io_write_intd(io, track->keys[i].frame);
537                tcb_write(&track->keys[i], io);
538                lib3ds_io_write_float(io, track->keys[i].value[3]);
539                lib3ds_io_write_vector(io, track->keys[i].value);
540            }
541            break;
542
543        /*case LIB3DS_TRACK_MORPH:
544            for (i = 0; i < track->nkeys; ++i) {
545                lib3ds_io_write_intd(io, track->keys[i].frame);
546                tcb_write(&track->keys[i].tcb, io);
547                lib3ds_io_write_string(io, track->keys[i].data.m.name);
548            }
549            break;*/
550    }
551}
Note: See TracBrowser for help on using the browser.