~ubuntu-branches/ubuntu/wily/opencollada/wily-proposed

« back to all changes in this revision

Viewing changes to Externals/lib3ds/src/lib3ds_track.c

  • Committer: Package Import Robot
  • Author(s): Matteo F. Vescovi
  • Date: 2015-05-14 17:23:27 UTC
  • Revision ID: package-import@ubuntu.com-20150514172327-f862u8envms01fra
Tags: upstream-0.1.0~20140703.ddf8f47+dfsg1
ImportĀ upstreamĀ versionĀ 0.1.0~20140703.ddf8f47+dfsg1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
 
 
21
Lib3dsTrack* 
 
22
lib3ds_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
 
 
30
void 
 
31
lib3ds_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
 
 
39
void 
 
40
lib3ds_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
 
 
56
static void 
 
57
pos_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
 
 
107
static void 
 
108
rot_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
 
 
172
static void
 
173
quat_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
 
 
184
static int 
 
185
find_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((float)(t - t0), (float)(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
 
 
224
static void 
 
225
setup_segment(Lib3dsTrack *track, int index, Lib3dsKey *pp, Lib3dsKey *p0, Lib3dsKey *p1, Lib3dsKey *pn) {
 
226
    int ip = 0;
 
227
    int in = 0;
 
228
    
 
229
    pp->frame = pn->frame = -1;
 
230
    if (index >= 2) {
 
231
        ip = index - 2;
 
232
        *pp = track->keys[index - 2];
 
233
    } else {
 
234
        if (track->flags & LIB3DS_TRACK_SMOOTH) {
 
235
            ip = track->nkeys - 2;
 
236
            *pp = track->keys[track->nkeys - 2];
 
237
            pp->frame = track->keys[track->nkeys - 2].frame - (track->keys[track->nkeys - 1].frame - track->keys[0].frame);
 
238
        }
 
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
 
 
277
void 
 
278
lib3ds_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
 
 
303
static void 
 
304
track_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
 
 
347
void 
 
348
lib3ds_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
 
 
357
void 
 
358
lib3ds_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
 
 
367
void 
 
368
lib3ds_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
 
 
401
static void 
 
402
tcb_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
 
 
422
void 
 
423
lib3ds_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
 
 
480
void
 
481
tcb_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
 
 
501
void
 
502
lib3ds_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
}