rev |
line source |
nuclear@27
|
1 #include <stdlib.h>
|
nuclear@27
|
2 #include <limits.h>
|
nuclear@27
|
3 #include <assert.h>
|
nuclear@27
|
4 #include "anim.h"
|
nuclear@27
|
5 #include "dynarr.h"
|
nuclear@27
|
6
|
nuclear@27
|
7 #define ROT_USE_SLERP
|
nuclear@27
|
8
|
nuclear@27
|
9 static void invalidate_cache(struct anm_node *node);
|
nuclear@27
|
10
|
nuclear@27
|
11 int anm_init_node(struct anm_node *node)
|
nuclear@27
|
12 {
|
nuclear@27
|
13 int i, j;
|
nuclear@27
|
14 static const float defaults[] = {
|
nuclear@27
|
15 0.0f, 0.0f, 0.0f, /* default position */
|
nuclear@27
|
16 0.0f, 0.0f, 0.0f, 1.0f, /* default rotation quat */
|
nuclear@27
|
17 1.0f, 1.0f, 1.0f /* default scale factor */
|
nuclear@27
|
18 };
|
nuclear@27
|
19
|
nuclear@27
|
20 memset(node, 0, sizeof *node);
|
nuclear@27
|
21
|
nuclear@27
|
22 for(i=0; i<ANM_NUM_TRACKS; i++) {
|
nuclear@27
|
23 if(anm_init_track(node->tracks + i) == -1) {
|
nuclear@27
|
24 for(j=0; j<i; j++) {
|
nuclear@27
|
25 anm_destroy_track(node->tracks + i);
|
nuclear@27
|
26 }
|
nuclear@27
|
27 }
|
nuclear@27
|
28 anm_set_track_default(node->tracks + i, defaults[i]);
|
nuclear@27
|
29 }
|
nuclear@27
|
30
|
nuclear@27
|
31 node->cache.time = ANM_TIME_INVAL;
|
nuclear@27
|
32 node->cache.inv_time = ANM_TIME_INVAL;
|
nuclear@27
|
33 return 0;
|
nuclear@27
|
34 }
|
nuclear@27
|
35
|
nuclear@27
|
36 void anm_destroy_node(struct anm_node *node)
|
nuclear@27
|
37 {
|
nuclear@27
|
38 int i;
|
nuclear@27
|
39 free(node->name);
|
nuclear@27
|
40
|
nuclear@27
|
41 for(i=0; i<ANM_NUM_TRACKS; i++) {
|
nuclear@27
|
42 anm_destroy_track(node->tracks + i);
|
nuclear@27
|
43 }
|
nuclear@27
|
44 }
|
nuclear@27
|
45
|
nuclear@27
|
46 void anm_destroy_node_tree(struct anm_node *tree)
|
nuclear@27
|
47 {
|
nuclear@27
|
48 struct anm_node *c, *tmp;
|
nuclear@27
|
49
|
nuclear@27
|
50 if(!tree) return;
|
nuclear@27
|
51
|
nuclear@27
|
52 c = tree->child;
|
nuclear@27
|
53 while(c) {
|
nuclear@27
|
54 tmp = c;
|
nuclear@27
|
55 c = c->next;
|
nuclear@27
|
56
|
nuclear@27
|
57 anm_destroy_node_tree(tmp);
|
nuclear@27
|
58 }
|
nuclear@27
|
59 anm_destroy_node(tree);
|
nuclear@27
|
60 }
|
nuclear@27
|
61
|
nuclear@27
|
62 struct anm_node *anm_create_node(void)
|
nuclear@27
|
63 {
|
nuclear@27
|
64 struct anm_node *n;
|
nuclear@27
|
65
|
nuclear@27
|
66 if((n = malloc(sizeof *n))) {
|
nuclear@27
|
67 if(anm_init_node(n) == -1) {
|
nuclear@27
|
68 free(n);
|
nuclear@27
|
69 return 0;
|
nuclear@27
|
70 }
|
nuclear@27
|
71 }
|
nuclear@27
|
72 return n;
|
nuclear@27
|
73 }
|
nuclear@27
|
74
|
nuclear@27
|
75 void anm_free_node(struct anm_node *node)
|
nuclear@27
|
76 {
|
nuclear@27
|
77 anm_destroy_node(node);
|
nuclear@27
|
78 free(node);
|
nuclear@27
|
79 }
|
nuclear@27
|
80
|
nuclear@27
|
81 void anm_free_node_tree(struct anm_node *tree)
|
nuclear@27
|
82 {
|
nuclear@27
|
83 struct anm_node *c, *tmp;
|
nuclear@27
|
84
|
nuclear@27
|
85 if(!tree) return;
|
nuclear@27
|
86
|
nuclear@27
|
87 c = tree->child;
|
nuclear@27
|
88 while(c) {
|
nuclear@27
|
89 tmp = c;
|
nuclear@27
|
90 c = c->next;
|
nuclear@27
|
91
|
nuclear@27
|
92 anm_free_node_tree(tmp);
|
nuclear@27
|
93 }
|
nuclear@27
|
94
|
nuclear@27
|
95 anm_free_node(tree);
|
nuclear@27
|
96 }
|
nuclear@27
|
97
|
nuclear@27
|
98 int anm_set_node_name(struct anm_node *node, const char *name)
|
nuclear@27
|
99 {
|
nuclear@27
|
100 char *str;
|
nuclear@27
|
101
|
nuclear@27
|
102 if(!(str = malloc(strlen(name) + 1))) {
|
nuclear@27
|
103 return -1;
|
nuclear@27
|
104 }
|
nuclear@27
|
105 strcpy(str, name);
|
nuclear@27
|
106 free(node->name);
|
nuclear@27
|
107 node->name = str;
|
nuclear@27
|
108 return 0;
|
nuclear@27
|
109 }
|
nuclear@27
|
110
|
nuclear@27
|
111 const char *anm_get_node_name(struct anm_node *node)
|
nuclear@27
|
112 {
|
nuclear@27
|
113 return node->name ? node->name : "";
|
nuclear@27
|
114 }
|
nuclear@27
|
115
|
nuclear@27
|
116 void anm_set_interpolator(struct anm_node *node, enum anm_interpolator in)
|
nuclear@27
|
117 {
|
nuclear@27
|
118 int i;
|
nuclear@27
|
119
|
nuclear@27
|
120 for(i=0; i<ANM_NUM_TRACKS; i++) {
|
nuclear@27
|
121 anm_set_track_interpolator(node->tracks + i, in);
|
nuclear@27
|
122 }
|
nuclear@27
|
123 invalidate_cache(node);
|
nuclear@27
|
124 }
|
nuclear@27
|
125
|
nuclear@27
|
126 void anm_set_extrapolator(struct anm_node *node, enum anm_extrapolator ex)
|
nuclear@27
|
127 {
|
nuclear@27
|
128 int i;
|
nuclear@27
|
129
|
nuclear@27
|
130 for(i=0; i<ANM_NUM_TRACKS; i++) {
|
nuclear@27
|
131 anm_set_track_extrapolator(node->tracks + i, ex);
|
nuclear@27
|
132 }
|
nuclear@27
|
133 invalidate_cache(node);
|
nuclear@27
|
134 }
|
nuclear@27
|
135
|
nuclear@27
|
136 void anm_link_node(struct anm_node *p, struct anm_node *c)
|
nuclear@27
|
137 {
|
nuclear@27
|
138 c->next = p->child;
|
nuclear@27
|
139 p->child = c;
|
nuclear@27
|
140
|
nuclear@27
|
141 c->parent = p;
|
nuclear@27
|
142 invalidate_cache(c);
|
nuclear@27
|
143 }
|
nuclear@27
|
144
|
nuclear@27
|
145 int anm_unlink_node(struct anm_node *p, struct anm_node *c)
|
nuclear@27
|
146 {
|
nuclear@27
|
147 struct anm_node *iter;
|
nuclear@27
|
148
|
nuclear@27
|
149 if(p->child == c) {
|
nuclear@27
|
150 p->child = c->next;
|
nuclear@27
|
151 c->next = 0;
|
nuclear@27
|
152 invalidate_cache(c);
|
nuclear@27
|
153 return 0;
|
nuclear@27
|
154 }
|
nuclear@27
|
155
|
nuclear@27
|
156 iter = p->child;
|
nuclear@27
|
157 while(iter->next) {
|
nuclear@27
|
158 if(iter->next == c) {
|
nuclear@27
|
159 iter->next = c->next;
|
nuclear@27
|
160 c->next = 0;
|
nuclear@27
|
161 invalidate_cache(c);
|
nuclear@27
|
162 return 0;
|
nuclear@27
|
163 }
|
nuclear@27
|
164 }
|
nuclear@27
|
165 return -1;
|
nuclear@27
|
166 }
|
nuclear@27
|
167
|
nuclear@27
|
168 void anm_set_position(struct anm_node *node, vec3_t pos, anm_time_t tm)
|
nuclear@27
|
169 {
|
nuclear@27
|
170 anm_set_value(node->tracks + ANM_TRACK_POS_X, tm, pos.x);
|
nuclear@27
|
171 anm_set_value(node->tracks + ANM_TRACK_POS_Y, tm, pos.y);
|
nuclear@27
|
172 anm_set_value(node->tracks + ANM_TRACK_POS_Z, tm, pos.z);
|
nuclear@27
|
173 invalidate_cache(node);
|
nuclear@27
|
174 }
|
nuclear@27
|
175
|
nuclear@27
|
176 vec3_t anm_get_node_position(struct anm_node *node, anm_time_t tm)
|
nuclear@27
|
177 {
|
nuclear@27
|
178 vec3_t v;
|
nuclear@27
|
179 v.x = anm_get_value(node->tracks + ANM_TRACK_POS_X, tm);
|
nuclear@27
|
180 v.y = anm_get_value(node->tracks + ANM_TRACK_POS_Y, tm);
|
nuclear@27
|
181 v.z = anm_get_value(node->tracks + ANM_TRACK_POS_Z, tm);
|
nuclear@27
|
182 return v;
|
nuclear@27
|
183 }
|
nuclear@27
|
184
|
nuclear@27
|
185 void anm_set_rotation(struct anm_node *node, quat_t rot, anm_time_t tm)
|
nuclear@27
|
186 {
|
nuclear@27
|
187 anm_set_value(node->tracks + ANM_TRACK_ROT_X, tm, rot.x);
|
nuclear@27
|
188 anm_set_value(node->tracks + ANM_TRACK_ROT_Y, tm, rot.y);
|
nuclear@27
|
189 anm_set_value(node->tracks + ANM_TRACK_ROT_Z, tm, rot.z);
|
nuclear@27
|
190 anm_set_value(node->tracks + ANM_TRACK_ROT_W, tm, rot.w);
|
nuclear@27
|
191 invalidate_cache(node);
|
nuclear@27
|
192 }
|
nuclear@27
|
193
|
nuclear@27
|
194 quat_t anm_get_node_rotation(struct anm_node *node, anm_time_t tm)
|
nuclear@27
|
195 {
|
nuclear@27
|
196 #ifndef ROT_USE_SLERP
|
nuclear@27
|
197 quat_t q;
|
nuclear@27
|
198 q.x = anm_get_value(node->tracks + ANM_TRACK_ROT_X, tm);
|
nuclear@27
|
199 q.y = anm_get_value(node->tracks + ANM_TRACK_ROT_Y, tm);
|
nuclear@27
|
200 q.z = anm_get_value(node->tracks + ANM_TRACK_ROT_Z, tm);
|
nuclear@27
|
201 q.w = anm_get_value(node->tracks + ANM_TRACK_ROT_W, tm);
|
nuclear@27
|
202 return q;
|
nuclear@27
|
203 #else
|
nuclear@27
|
204 int idx0, idx1, last_idx;
|
nuclear@27
|
205 anm_time_t tstart, tend;
|
nuclear@27
|
206 float t, dt;
|
nuclear@27
|
207 struct anm_track *track_x, *track_y, *track_z, *track_w;
|
nuclear@27
|
208 quat_t q, q1, q2;
|
nuclear@27
|
209
|
nuclear@27
|
210 track_x = node->tracks + ANM_TRACK_ROT_X;
|
nuclear@27
|
211 track_y = node->tracks + ANM_TRACK_ROT_Y;
|
nuclear@27
|
212 track_z = node->tracks + ANM_TRACK_ROT_Z;
|
nuclear@27
|
213 track_w = node->tracks + ANM_TRACK_ROT_W;
|
nuclear@27
|
214
|
nuclear@27
|
215 if(!track_x->count) {
|
nuclear@27
|
216 q.x = track_x->def_val;
|
nuclear@27
|
217 q.y = track_y->def_val;
|
nuclear@27
|
218 q.z = track_z->def_val;
|
nuclear@27
|
219 q.w = track_w->def_val;
|
nuclear@27
|
220 return q;
|
nuclear@27
|
221 }
|
nuclear@27
|
222
|
nuclear@27
|
223 last_idx = track_x->count - 1;
|
nuclear@27
|
224
|
nuclear@27
|
225 tstart = track_x->keys[0].time;
|
nuclear@27
|
226 tend = track_x->keys[last_idx].time;
|
nuclear@27
|
227
|
nuclear@27
|
228 if(tstart == tend) {
|
nuclear@27
|
229 q.x = track_x->keys[0].val;
|
nuclear@27
|
230 q.y = track_y->keys[0].val;
|
nuclear@27
|
231 q.z = track_z->keys[0].val;
|
nuclear@27
|
232 q.w = track_w->keys[0].val;
|
nuclear@27
|
233 return q;
|
nuclear@27
|
234 }
|
nuclear@27
|
235
|
nuclear@27
|
236 tm = anm_remap_time(track_x, tm, tstart, tend);
|
nuclear@27
|
237
|
nuclear@27
|
238 idx0 = anm_get_key_interval(track_x, tm);
|
nuclear@27
|
239 assert(idx0 >= 0 && idx0 < track_x->count);
|
nuclear@27
|
240 idx1 = idx0 + 1;
|
nuclear@27
|
241
|
nuclear@27
|
242 if(idx0 == last_idx) {
|
nuclear@27
|
243 q.x = track_x->keys[idx0].val;
|
nuclear@27
|
244 q.y = track_y->keys[idx0].val;
|
nuclear@27
|
245 q.z = track_z->keys[idx0].val;
|
nuclear@27
|
246 q.w = track_w->keys[idx0].val;
|
nuclear@27
|
247 return q;
|
nuclear@27
|
248 }
|
nuclear@27
|
249
|
nuclear@27
|
250 dt = (float)(track_x->keys[idx1].time - track_x->keys[idx0].time);
|
nuclear@27
|
251 t = (float)(tm - track_x->keys[idx0].time) / dt;
|
nuclear@27
|
252
|
nuclear@27
|
253 q1.x = track_x->keys[idx0].val;
|
nuclear@27
|
254 q1.y = track_y->keys[idx0].val;
|
nuclear@27
|
255 q1.z = track_z->keys[idx0].val;
|
nuclear@27
|
256 q1.w = track_w->keys[idx0].val;
|
nuclear@27
|
257
|
nuclear@27
|
258 q2.x = track_x->keys[idx1].val;
|
nuclear@27
|
259 q2.y = track_y->keys[idx1].val;
|
nuclear@27
|
260 q2.z = track_z->keys[idx1].val;
|
nuclear@27
|
261 q2.w = track_w->keys[idx1].val;
|
nuclear@27
|
262
|
nuclear@27
|
263 /*q1 = quat_normalize(q1);
|
nuclear@27
|
264 q2 = quat_normalize(q2);*/
|
nuclear@27
|
265
|
nuclear@27
|
266 return quat_slerp(q1, q2, t);
|
nuclear@27
|
267 #endif
|
nuclear@27
|
268 }
|
nuclear@27
|
269
|
nuclear@27
|
270 void anm_set_scaling(struct anm_node *node, vec3_t scl, anm_time_t tm)
|
nuclear@27
|
271 {
|
nuclear@27
|
272 anm_set_value(node->tracks + ANM_TRACK_SCL_X, tm, scl.x);
|
nuclear@27
|
273 anm_set_value(node->tracks + ANM_TRACK_SCL_Y, tm, scl.y);
|
nuclear@27
|
274 anm_set_value(node->tracks + ANM_TRACK_SCL_Z, tm, scl.z);
|
nuclear@27
|
275 invalidate_cache(node);
|
nuclear@27
|
276 }
|
nuclear@27
|
277
|
nuclear@27
|
278 vec3_t anm_get_node_scaling(struct anm_node *node, anm_time_t tm)
|
nuclear@27
|
279 {
|
nuclear@27
|
280 vec3_t v;
|
nuclear@27
|
281 v.x = anm_get_value(node->tracks + ANM_TRACK_SCL_X, tm);
|
nuclear@27
|
282 v.y = anm_get_value(node->tracks + ANM_TRACK_SCL_Y, tm);
|
nuclear@27
|
283 v.z = anm_get_value(node->tracks + ANM_TRACK_SCL_Z, tm);
|
nuclear@27
|
284 return v;
|
nuclear@27
|
285 }
|
nuclear@27
|
286
|
nuclear@27
|
287
|
nuclear@27
|
288 vec3_t anm_get_position(struct anm_node *node, anm_time_t tm)
|
nuclear@27
|
289 {
|
nuclear@27
|
290 mat4_t xform;
|
nuclear@27
|
291 vec3_t pos = {0.0, 0.0, 0.0};
|
nuclear@27
|
292
|
nuclear@27
|
293 if(!node->parent) {
|
nuclear@27
|
294 return anm_get_node_position(node, tm);
|
nuclear@27
|
295 }
|
nuclear@27
|
296
|
nuclear@27
|
297 anm_get_matrix(node, xform, tm);
|
nuclear@27
|
298 return v3_transform(pos, xform);
|
nuclear@27
|
299 }
|
nuclear@27
|
300
|
nuclear@27
|
301 quat_t anm_get_rotation(struct anm_node *node, anm_time_t tm)
|
nuclear@27
|
302 {
|
nuclear@27
|
303 quat_t rot, prot;
|
nuclear@27
|
304 rot = anm_get_node_rotation(node, tm);
|
nuclear@27
|
305
|
nuclear@27
|
306 if(!node->parent) {
|
nuclear@27
|
307 return rot;
|
nuclear@27
|
308 }
|
nuclear@27
|
309
|
nuclear@27
|
310 prot = anm_get_rotation(node->parent, tm);
|
nuclear@27
|
311 return quat_mul(prot, rot);
|
nuclear@27
|
312 }
|
nuclear@27
|
313
|
nuclear@27
|
314 vec3_t anm_get_scaling(struct anm_node *node, anm_time_t tm)
|
nuclear@27
|
315 {
|
nuclear@27
|
316 vec3_t s, ps;
|
nuclear@27
|
317 s = anm_get_node_scaling(node, tm);
|
nuclear@27
|
318
|
nuclear@27
|
319 if(!node->parent) {
|
nuclear@27
|
320 return s;
|
nuclear@27
|
321 }
|
nuclear@27
|
322
|
nuclear@27
|
323 ps = anm_get_scaling(node->parent, tm);
|
nuclear@27
|
324 return v3_mul(s, ps);
|
nuclear@27
|
325 }
|
nuclear@27
|
326
|
nuclear@27
|
327 void anm_set_pivot(struct anm_node *node, vec3_t piv)
|
nuclear@27
|
328 {
|
nuclear@27
|
329 node->pivot = piv;
|
nuclear@27
|
330 }
|
nuclear@27
|
331
|
nuclear@27
|
332 vec3_t anm_get_pivot(struct anm_node *node)
|
nuclear@27
|
333 {
|
nuclear@27
|
334 return node->pivot;
|
nuclear@27
|
335 }
|
nuclear@27
|
336
|
nuclear@27
|
337 void anm_get_node_matrix(struct anm_node *node, mat4_t mat, anm_time_t tm)
|
nuclear@27
|
338 {
|
nuclear@27
|
339 int i;
|
nuclear@27
|
340 mat4_t rmat;
|
nuclear@27
|
341 vec3_t pos, scale;
|
nuclear@27
|
342 quat_t rot;
|
nuclear@27
|
343
|
nuclear@27
|
344 pos = anm_get_node_position(node, tm);
|
nuclear@27
|
345 rot = anm_get_node_rotation(node, tm);
|
nuclear@27
|
346 scale = anm_get_node_scaling(node, tm);
|
nuclear@27
|
347
|
nuclear@27
|
348 m4_set_translation(mat, node->pivot.x, node->pivot.y, node->pivot.z);
|
nuclear@27
|
349
|
nuclear@27
|
350 quat_to_mat4(rmat, rot);
|
nuclear@27
|
351 for(i=0; i<3; i++) {
|
nuclear@27
|
352 mat[i][0] = rmat[i][0];
|
nuclear@27
|
353 mat[i][1] = rmat[i][1];
|
nuclear@27
|
354 mat[i][2] = rmat[i][2];
|
nuclear@27
|
355 }
|
nuclear@27
|
356 /* this loop is equivalent to: m4_mult(mat, mat, rmat); */
|
nuclear@27
|
357
|
nuclear@27
|
358 mat[0][0] *= scale.x; mat[0][1] *= scale.y; mat[0][2] *= scale.z; mat[0][3] += pos.x;
|
nuclear@27
|
359 mat[1][0] *= scale.x; mat[1][1] *= scale.y; mat[1][2] *= scale.z; mat[1][3] += pos.y;
|
nuclear@27
|
360 mat[2][0] *= scale.x; mat[2][1] *= scale.y; mat[2][2] *= scale.z; mat[2][3] += pos.z;
|
nuclear@27
|
361
|
nuclear@27
|
362 m4_translate(mat, -node->pivot.x, -node->pivot.y, -node->pivot.z);
|
nuclear@27
|
363
|
nuclear@27
|
364 /* that's basically: pivot * rotation * translation * scaling * -pivot */
|
nuclear@27
|
365 }
|
nuclear@27
|
366
|
nuclear@27
|
367 void anm_get_node_inv_matrix(struct anm_node *node, mat4_t mat, anm_time_t tm)
|
nuclear@27
|
368 {
|
nuclear@27
|
369 mat4_t tmp;
|
nuclear@27
|
370 anm_get_node_matrix(node, tmp, tm);
|
nuclear@27
|
371 m4_inverse(mat, tmp);
|
nuclear@27
|
372 }
|
nuclear@27
|
373
|
nuclear@27
|
374 void anm_get_matrix(struct anm_node *node, mat4_t mat, anm_time_t tm)
|
nuclear@27
|
375 {
|
nuclear@27
|
376 if(node->cache.time != tm) {
|
nuclear@27
|
377 anm_get_node_matrix(node, node->cache.matrix, tm);
|
nuclear@27
|
378
|
nuclear@27
|
379 if(node->parent) {
|
nuclear@27
|
380 mat4_t parent_mat;
|
nuclear@27
|
381
|
nuclear@27
|
382 anm_get_matrix(node->parent, parent_mat, tm);
|
nuclear@27
|
383 m4_mult(node->cache.matrix, parent_mat, node->cache.matrix);
|
nuclear@27
|
384 }
|
nuclear@27
|
385 node->cache.time = tm;
|
nuclear@27
|
386 }
|
nuclear@27
|
387 m4_copy(mat, node->cache.matrix);
|
nuclear@27
|
388 }
|
nuclear@27
|
389
|
nuclear@27
|
390 void anm_get_inv_matrix(struct anm_node *node, mat4_t mat, anm_time_t tm)
|
nuclear@27
|
391 {
|
nuclear@27
|
392 if(node->cache.inv_time != tm) {
|
nuclear@27
|
393 anm_get_matrix(node, mat, tm);
|
nuclear@27
|
394 m4_inverse(node->cache.inv_matrix, mat);
|
nuclear@27
|
395 node->cache.inv_time = tm;
|
nuclear@27
|
396 }
|
nuclear@27
|
397 m4_copy(mat, node->cache.inv_matrix);
|
nuclear@27
|
398 }
|
nuclear@27
|
399
|
nuclear@27
|
400 anm_time_t anm_get_start_time(struct anm_node *node)
|
nuclear@27
|
401 {
|
nuclear@27
|
402 int i;
|
nuclear@27
|
403 struct anm_node *c;
|
nuclear@27
|
404 anm_time_t res = LONG_MAX;
|
nuclear@27
|
405
|
nuclear@27
|
406 for(i=0; i<ANM_NUM_TRACKS; i++) {
|
nuclear@27
|
407 if(node->tracks[i].count) {
|
nuclear@27
|
408 anm_time_t tm = node->tracks[i].keys[0].time;
|
nuclear@27
|
409 if(tm < res) {
|
nuclear@27
|
410 res = tm;
|
nuclear@27
|
411 }
|
nuclear@27
|
412 }
|
nuclear@27
|
413 }
|
nuclear@27
|
414
|
nuclear@27
|
415 c = node->child;
|
nuclear@27
|
416 while(c) {
|
nuclear@27
|
417 anm_time_t tm = anm_get_start_time(c);
|
nuclear@27
|
418 if(tm < res) {
|
nuclear@27
|
419 res = tm;
|
nuclear@27
|
420 }
|
nuclear@27
|
421 c = c->next;
|
nuclear@27
|
422 }
|
nuclear@27
|
423 return res;
|
nuclear@27
|
424 }
|
nuclear@27
|
425
|
nuclear@27
|
426 anm_time_t anm_get_end_time(struct anm_node *node)
|
nuclear@27
|
427 {
|
nuclear@27
|
428 int i;
|
nuclear@27
|
429 struct anm_node *c;
|
nuclear@27
|
430 anm_time_t res = LONG_MIN;
|
nuclear@27
|
431
|
nuclear@27
|
432 for(i=0; i<ANM_NUM_TRACKS; i++) {
|
nuclear@27
|
433 if(node->tracks[i].count) {
|
nuclear@27
|
434 anm_time_t tm = node->tracks[i].keys[node->tracks[i].count - 1].time;
|
nuclear@27
|
435 if(tm > res) {
|
nuclear@27
|
436 res = tm;
|
nuclear@27
|
437 }
|
nuclear@27
|
438 }
|
nuclear@27
|
439 }
|
nuclear@27
|
440
|
nuclear@27
|
441 c = node->child;
|
nuclear@27
|
442 while(c) {
|
nuclear@27
|
443 anm_time_t tm = anm_get_end_time(c);
|
nuclear@27
|
444 if(tm > res) {
|
nuclear@27
|
445 res = tm;
|
nuclear@27
|
446 }
|
nuclear@27
|
447 c = c->next;
|
nuclear@27
|
448 }
|
nuclear@27
|
449 return res;
|
nuclear@27
|
450 }
|
nuclear@27
|
451
|
nuclear@27
|
452 static void invalidate_cache(struct anm_node *node)
|
nuclear@27
|
453 {
|
nuclear@27
|
454 node->cache.time = node->cache.inv_time = ANM_TIME_INVAL;
|
nuclear@27
|
455 }
|