00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "lib3ds_impl.h"
00019
00020
00021 Lib3dsTrack*
00022 lib3ds_track_new(Lib3dsTrackType type, int nkeys) {
00023 Lib3dsTrack *track = (Lib3dsTrack*)calloc(sizeof(Lib3dsTrack), 1);
00024 track->type = type;
00025 lib3ds_track_resize(track, nkeys);
00026 return track;
00027 }
00028
00029
00030 void
00031 lib3ds_track_free(Lib3dsTrack *track) {
00032 assert(track);
00033 lib3ds_track_resize(track, 0);
00034 memset(track, 0, sizeof(Lib3dsTrack));
00035 free(track);
00036 }
00037
00038
00039 void
00040 lib3ds_track_resize(Lib3dsTrack *track, int nkeys) {
00041 char *p;
00042
00043 assert(track);
00044 if (track->nkeys == nkeys)
00045 return;
00046
00047 p = (char*)realloc(track->keys, sizeof(Lib3dsKey) * nkeys);
00048 if (nkeys > track->nkeys) {
00049 memset(p + (sizeof(Lib3dsKey)*track->nkeys), 0, sizeof(Lib3dsKey)*(nkeys - track->nkeys));
00050 }
00051 track->keys = (Lib3dsKey*)p;
00052 track->nkeys = nkeys;
00053 }
00054
00055
00056 static void
00057 pos_key_setup(int n, Lib3dsKey *pp, Lib3dsKey *pc, Lib3dsKey *pn, float *dd, float *ds) {
00058 float tm, cm, cp, bm, bp, tmcm, tmcp, ksm, ksp, kdm, kdp, c;
00059 float dt, fp, fn;
00060 float delm[3], delp[3];
00061 int i;
00062
00063 assert(pc);
00064 fp = fn = 1.0f;
00065 if (pp && pn) {
00066 dt = 0.5f * (pn->frame - pp->frame);
00067 fp = (float)(pc->frame - pp->frame) / dt;
00068 fn = (float)(pn->frame - pc->frame) / dt;
00069 c = (float)fabs(pc->cont);
00070 fp = fp + c - c * fp;
00071 fn = fn + c - c * fn;
00072 }
00073
00074 cm = 1.0f - pc->cont;
00075 tm = 0.5f * (1.0f - pc->tens);
00076 cp = 2.0f - cm;
00077 bm = 1.0f - pc->bias;
00078 bp = 2.0f - bm;
00079 tmcm = tm * cm;
00080 tmcp = tm * cp;
00081 ksm = tmcm * bp * fp;
00082 ksp = tmcp * bm * fp;
00083 kdm = tmcp * bp * fn;
00084 kdp = tmcm * bm * fn;
00085
00086 for (i = 0; i < n; ++i) delm[i] = delp[i] = 0;
00087 if (pp) {
00088 for (i = 0; i < n; ++i) delm[i] = pc->value[i] - pp->value[i];
00089 }
00090 if (pn) {
00091 for (i = 0; i < n; ++i) delp[i] = pn->value[i] - pc->value[i];
00092 }
00093 if (!pp) {
00094 for (i = 0; i < n; ++i) delm[i] = delp[i];
00095 }
00096 if (!pn) {
00097 for (i = 0; i < n; ++i) delp[i] = delm[i];
00098 }
00099
00100 for (i = 0; i < n; ++i) {
00101 ds[i] = ksm * delm[i] + ksp * delp[i];
00102 dd[i] = kdm * delm[i] + kdp * delp[i];
00103 }
00104 }
00105
00106
00107 static void
00108 rot_key_setup(Lib3dsKey *prev, Lib3dsKey *cur, Lib3dsKey *next, float a[4], float b[4]) {
00109 float tm, cm, cp, bm, bp, tmcm, tmcp, ksm, ksp, kdm, kdp, c;
00110 float dt, fp, fn;
00111 float q[4], qm[4], qp[4], qa[4], qb[4];
00112 int i;
00113
00114 assert(cur);
00115 if (prev) {
00116 if (cur->value[3] > LIB3DS_TWOPI - LIB3DS_EPSILON) {
00117 lib3ds_quat_axis_angle(qm, cur->value, 0.0f);
00118 lib3ds_quat_ln(qm);
00119 } else {
00120 lib3ds_quat_copy(q, prev->value);
00121 if (lib3ds_quat_dot(q, cur->value) < 0) lib3ds_quat_neg(q);
00122 lib3ds_quat_ln_dif(qm, q, cur->value);
00123 }
00124 }
00125 if (next) {
00126 if (next->value[3] > LIB3DS_TWOPI - LIB3DS_EPSILON) {
00127 lib3ds_quat_axis_angle(qp, next->value, 0.0f);
00128 lib3ds_quat_ln(qp);
00129 } else {
00130 lib3ds_quat_copy(q, next->value);
00131 if (lib3ds_quat_dot(q, cur->value) < 0) lib3ds_quat_neg(q);
00132 lib3ds_quat_ln_dif(qp, cur->value, q);
00133 }
00134 }
00135 if (!prev) lib3ds_quat_copy(qm, qp);
00136 if (!next) lib3ds_quat_copy(qp, qm);
00137
00138 fp = fn = 1.0f;
00139 cm = 1.0f - cur->cont;
00140 if (prev && next) {
00141 dt = 0.5f * (next->frame - prev->frame);
00142 fp = (float)(cur->frame - prev->frame) / dt;
00143 fn = (float)(next->frame - cur->frame) / dt;
00144 c = (float)fabs(cur->cont);
00145 fp = fp + c - c * fp;
00146 fn = fn + c - c * fn;
00147 }
00148
00149 tm = 0.5f * (1.0f - cur->tens);
00150 cp = 2.0f - cm;
00151 bm = 1.0f - cur->bias;
00152 bp = 2.0f - bm;
00153 tmcm = tm * cm;
00154 tmcp = tm * cp;
00155 ksm = 1.0f - tmcm * bp * fp;
00156 ksp = -tmcp * bm * fp;
00157 kdm = tmcp * bp * fn;
00158 kdp = tmcm * bm * fn - 1.0f;
00159
00160 for (i = 0; i < 4; i++) {
00161 qa[i] = 0.5f * (kdm * qm[i] + kdp * qp[i]);
00162 qb[i] = 0.5f * (ksm * qm[i] + ksp * qp[i]);
00163 }
00164 lib3ds_quat_exp(qa);
00165 lib3ds_quat_exp(qb);
00166
00167 lib3ds_quat_mul(a, cur->value, qa);
00168 lib3ds_quat_mul(b, cur->value, qb);
00169 }
00170
00171
00172 static void
00173 quat_for_index(Lib3dsTrack *track, int index, float q[4]) {
00174 float p[4];
00175 int i;
00176 lib3ds_quat_identity(q);
00177 for (i = 0; i <= index; ++i) {
00178 lib3ds_quat_axis_angle(p, track->keys[i].value, track->keys[i].value[3]);
00179 lib3ds_quat_mul(q, p, q);
00180 }
00181 }
00182
00183
00184 static int
00185 find_index(Lib3dsTrack *track, float t, float *u) {
00186 int i;
00187 float nt;
00188 int t0, t1;
00189
00190 assert(track);
00191 assert(track->nkeys > 0);
00192
00193 if (track->nkeys <= 1)
00194 return -1;
00195
00196 t0 = track->keys[0].frame;
00197 t1 = track->keys[track->nkeys-1].frame;
00198 if (track->flags & LIB3DS_TRACK_REPEAT) {
00199 nt = (float)fmod(t - t0, t1 - t0) + t0;
00200 } else {
00201 nt = t;
00202 }
00203
00204 if (nt <= t0) {
00205 return -1;
00206 }
00207 if (nt >= t1) {
00208 return track->nkeys;
00209 }
00210
00211 for (i = 1; i < track->nkeys; ++i) {
00212 if (nt < track->keys[i].frame)
00213 break;
00214 }
00215
00216 *u = nt - (float)track->keys[i-1].frame;
00217 *u /= (float)(track->keys[i].frame - track->keys[i-1].frame);
00218
00219 assert((*u >= 0.0f) && (*u <= 1.0f));
00220 return i;
00221 }
00222
00223
00224 static void
00225 setup_segment(Lib3dsTrack *track, int index, Lib3dsKey *pp, Lib3dsKey *p0, Lib3dsKey *p1, Lib3dsKey *pn) {
00226 int ip, in;
00227
00228 pp->frame = pn->frame = -1;
00229 if (index >= 2) {
00230 ip = index - 2;
00231 *pp = track->keys[index - 2];
00232 } else {
00233 if (track->flags & LIB3DS_TRACK_SMOOTH) {
00234 ip = track->nkeys - 2;
00235 *pp = track->keys[track->nkeys - 2];
00236 pp->frame = track->keys[track->nkeys - 2].frame - (track->keys[track->nkeys - 1].frame - track->keys[0].frame);
00237 }
00238 }
00239
00240 *p0 = track->keys[index - 1];
00241 *p1 = track->keys[index];
00242
00243 if (index < (int)track->nkeys - 1) {
00244 in = index + 1;
00245 *pn = track->keys[index + 1];
00246 } else {
00247 if (track->flags & LIB3DS_TRACK_SMOOTH) {
00248 in = 1;
00249 *pn = track->keys[1];
00250 pn->frame = track->keys[1].frame + (track->keys[track->nkeys-1].frame - track->keys[0].frame);
00251 }
00252 }
00253
00254 if (track->type == LIB3DS_TRACK_QUAT) {
00255 float q[4];
00256 if (pp->frame >= 0) {
00257 quat_for_index(track, ip, pp->value);
00258 } else {
00259 lib3ds_quat_identity(pp->value);
00260 }
00261
00262 quat_for_index(track, index - 1, p0->value);
00263 lib3ds_quat_axis_angle(q, track->keys[index].value, track->keys[index].value[3]);
00264 lib3ds_quat_mul(p1->value, q, p0->value);
00265
00266 if (pn->frame >= 0) {
00267 lib3ds_quat_axis_angle(q, track->keys[in].value, track->keys[in].value[3]);
00268 lib3ds_quat_mul(pn->value, q, p1->value);
00269 } else {
00270 lib3ds_quat_identity(pn->value);
00271 }
00272 }
00273 }
00274
00275
00276 void
00277 lib3ds_track_eval_bool(Lib3dsTrack *track, int *b, float t) {
00278 *b = FALSE;
00279 if (track) {
00280 int index;
00281 float u;
00282
00283 assert(track->type == LIB3DS_TRACK_BOOL);
00284 if (!track->nkeys) {
00285 return;
00286 }
00287
00288 index = find_index(track, t, &u);
00289 if (index < 0) {
00290 *b = FALSE;
00291 return;
00292 }
00293 if (index >= track->nkeys) {
00294 *b = !(track->nkeys & 1);
00295 return;
00296 }
00297 *b = !(index & 1);
00298 }
00299 }
00300
00301
00302 static void
00303 track_eval_linear(Lib3dsTrack *track, float *value, float t) {
00304 Lib3dsKey pp, p0, p1, pn;
00305 float u;
00306 int index;
00307 float dsp[3], ddp[3], dsn[3], ddn[3];
00308
00309 assert(track);
00310 if (!track->nkeys) {
00311 int i;
00312 for (i = 0; i < track->type; ++i) value[i] = 0.0f;
00313 return;
00314 }
00315
00316 index = find_index(track, t, &u);
00317
00318 if (index < 0) {
00319 int i;
00320 for (i = 0; i < track->type; ++i) value[i] = track->keys[0].value[i];
00321 return;
00322 }
00323 if (index >= track->nkeys) {
00324 int i;
00325 for (i = 0; i < track->type; ++i) value[i] = track->keys[track->nkeys-1].value[i];
00326 return;
00327 }
00328
00329 setup_segment(track, index, &pp, &p0, &p1, &pn);
00330
00331 pos_key_setup(track->type, pp.frame>=0? &pp : NULL, &p0, &p1, ddp, dsp);
00332 pos_key_setup(track->type, &p0, &p1, pn.frame>=0? &pn : NULL, ddn, dsn);
00333
00334 lib3ds_math_cubic_interp(
00335 value,
00336 p0.value,
00337 ddp,
00338 dsn,
00339 p1.value,
00340 track->type,
00341 u
00342 );
00343 }
00344
00345
00346 void
00347 lib3ds_track_eval_float(Lib3dsTrack *track, float *f, float t) {
00348 *f = 0;
00349 if (track) {
00350 assert(track->type == LIB3DS_TRACK_FLOAT);
00351 track_eval_linear(track, f, t);
00352 }
00353 }
00354
00355
00356 void
00357 lib3ds_track_eval_vector(Lib3dsTrack *track, float v[3], float t) {
00358 lib3ds_vector_zero(v);
00359 if (track) {
00360 assert(track->type == LIB3DS_TRACK_VECTOR);
00361 track_eval_linear(track, v, t);
00362 }
00363 }
00364
00365
00366 void
00367 lib3ds_track_eval_quat(Lib3dsTrack *track, float q[4], float t) {
00368 lib3ds_quat_identity(q);
00369 if (track) {
00370 Lib3dsKey pp, p0, p1, pn;
00371 float u;
00372 int index;
00373 float ap[4], bp[4], an[4], bn[4];
00374
00375 assert(track->type == LIB3DS_TRACK_QUAT);
00376 if (!track->nkeys) {
00377 return;
00378 }
00379
00380 index = find_index(track, t, &u);
00381 if (index < 0) {
00382 lib3ds_quat_axis_angle(q, track->keys[0].value, track->keys[0].value[3]);
00383 return;
00384 }
00385 if (index >= track->nkeys) {
00386 quat_for_index(track, track->nkeys - 1, q);
00387 return;
00388 }
00389
00390 setup_segment(track, index, &pp, &p0, &p1, &pn);
00391
00392 rot_key_setup(pp.frame>=0? &pp : NULL, &p0, &p1, ap, bp);
00393 rot_key_setup(&p0, &p1, pn.frame>=0? &pn : NULL, an, bn);
00394
00395 lib3ds_quat_squad(q, p0.value, ap, bn, p1.value, u);
00396 }
00397 }
00398
00399
00400 static void
00401 tcb_read(Lib3dsKey *key, Lib3dsIo *io) {
00402 key->flags = lib3ds_io_read_word(io);
00403 if (key->flags & LIB3DS_KEY_USE_TENS) {
00404 key->tens = lib3ds_io_read_float(io);
00405 }
00406 if (key->flags & LIB3DS_KEY_USE_CONT) {
00407 key->cont = lib3ds_io_read_float(io);
00408 }
00409 if (key->flags & LIB3DS_KEY_USE_BIAS) {
00410 key->bias = lib3ds_io_read_float(io);
00411 }
00412 if (key->flags & LIB3DS_KEY_USE_EASE_TO) {
00413 key->ease_to = lib3ds_io_read_float(io);
00414 }
00415 if (key->flags & LIB3DS_KEY_USE_EASE_FROM) {
00416 key->ease_from = lib3ds_io_read_float(io);
00417 }
00418 }
00419
00420
00421 void
00422 lib3ds_track_read(Lib3dsTrack *track, Lib3dsIo *io) {
00423 unsigned nkeys;
00424 unsigned i;
00425
00426 track->flags = lib3ds_io_read_word(io);
00427 lib3ds_io_read_dword(io);
00428 lib3ds_io_read_dword(io);
00429 nkeys = lib3ds_io_read_intd(io);
00430 lib3ds_track_resize(track, nkeys);
00431
00432 switch (track->type) {
00433 case LIB3DS_TRACK_BOOL:
00434 for (i = 0; i < nkeys; ++i) {
00435 track->keys[i].frame = lib3ds_io_read_intd(io);
00436 tcb_read(&track->keys[i], io);
00437 }
00438 break;
00439
00440 case LIB3DS_TRACK_FLOAT:
00441 for (i = 0; i < nkeys; ++i) {
00442 track->keys[i].frame = lib3ds_io_read_intd(io);
00443 tcb_read(&track->keys[i], io);
00444 track->keys[i].value[0] = lib3ds_io_read_float(io);
00445 }
00446 break;
00447
00448 case LIB3DS_TRACK_VECTOR:
00449 for (i = 0; i < nkeys; ++i) {
00450 track->keys[i].frame = lib3ds_io_read_intd(io);
00451 tcb_read(&track->keys[i], io);
00452 lib3ds_io_read_vector(io, track->keys[i].value);
00453 }
00454 break;
00455
00456 case LIB3DS_TRACK_QUAT:
00457 for (i = 0; i < nkeys; ++i) {
00458 track->keys[i].frame = lib3ds_io_read_intd(io);
00459 tcb_read(&track->keys[i], io);
00460 track->keys[i].value[3] = lib3ds_io_read_float(io);
00461 lib3ds_io_read_vector(io, track->keys[i].value);
00462 }
00463 break;
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473 default:
00474 break;
00475 }
00476 }
00477
00478
00479 void
00480 tcb_write(Lib3dsKey *key, Lib3dsIo *io) {
00481 lib3ds_io_write_word(io, key->flags);
00482 if (key->flags & LIB3DS_KEY_USE_TENS) {
00483 lib3ds_io_write_float(io, key->tens);
00484 }
00485 if (key->flags & LIB3DS_KEY_USE_CONT) {
00486 lib3ds_io_write_float(io, key->cont);
00487 }
00488 if (key->flags & LIB3DS_KEY_USE_BIAS) {
00489 lib3ds_io_write_float(io, key->bias);
00490 }
00491 if (key->flags & LIB3DS_KEY_USE_EASE_TO) {
00492 lib3ds_io_write_float(io, key->ease_to);
00493 }
00494 if (key->flags & LIB3DS_KEY_USE_EASE_FROM) {
00495 lib3ds_io_write_float(io, key->ease_from);
00496 }
00497 }
00498
00499
00500 void
00501 lib3ds_track_write(Lib3dsTrack *track, Lib3dsIo *io) {
00502 int i;
00503
00504 lib3ds_io_write_word(io, (uint16_t)track->flags);
00505 lib3ds_io_write_dword(io, 0);
00506 lib3ds_io_write_dword(io, 0);
00507 lib3ds_io_write_dword(io, track->nkeys);
00508
00509 switch (track->type) {
00510 case LIB3DS_TRACK_BOOL:
00511 for (i = 0; i < track->nkeys; ++i) {
00512 lib3ds_io_write_intd(io, track->keys[i].frame);
00513 tcb_write(&track->keys[i], io);
00514 }
00515 break;
00516
00517 case LIB3DS_TRACK_FLOAT:
00518 for (i = 0; i < track->nkeys; ++i) {
00519 lib3ds_io_write_intd(io, track->keys[i].frame);
00520 tcb_write(&track->keys[i], io);
00521 lib3ds_io_write_float(io, track->keys[i].value[0]);
00522 }
00523 break;
00524
00525 case LIB3DS_TRACK_VECTOR:
00526 for (i = 0; i < track->nkeys; ++i) {
00527 lib3ds_io_write_intd(io, track->keys[i].frame);
00528 tcb_write(&track->keys[i], io);
00529 lib3ds_io_write_vector(io, track->keys[i].value);
00530 }
00531 break;
00532
00533 case LIB3DS_TRACK_QUAT:
00534 for (i = 0; i < track->nkeys; ++i) {
00535 lib3ds_io_write_intd(io, track->keys[i].frame);
00536 tcb_write(&track->keys[i], io);
00537 lib3ds_io_write_float(io, track->keys[i].value[3]);
00538 lib3ds_io_write_vector(io, track->keys[i].value);
00539 }
00540 break;
00541
00542
00543
00544
00545
00546
00547
00548
00549 }
00550 }