rev |
line source |
nuclear@1
|
1 #include <stdlib.h>
|
nuclear@0
|
2 #include <limits.h>
|
nuclear@0
|
3 #include <assert.h>
|
nuclear@0
|
4 #include "anim.h"
|
nuclear@0
|
5 #include "dynarr.h"
|
nuclear@0
|
6
|
nuclear@7
|
7 #define ROT_USE_SLERP
|
nuclear@7
|
8
|
nuclear@0
|
9 static void invalidate_cache(struct anm_node *node);
|
nuclear@0
|
10
|
nuclear@21
|
11 int anm_init_animation(struct anm_animation *anim)
|
nuclear@0
|
12 {
|
nuclear@0
|
13 int i, j;
|
nuclear@0
|
14 static const float defaults[] = {
|
nuclear@0
|
15 0.0f, 0.0f, 0.0f, /* default position */
|
nuclear@0
|
16 0.0f, 0.0f, 0.0f, 1.0f, /* default rotation quat */
|
nuclear@0
|
17 1.0f, 1.0f, 1.0f /* default scale factor */
|
nuclear@0
|
18 };
|
nuclear@0
|
19
|
nuclear@21
|
20 anim->name = 0;
|
nuclear@21
|
21
|
nuclear@21
|
22 for(i=0; i<ANM_NUM_TRACKS; i++) {
|
nuclear@21
|
23 if(anm_init_track(anim->tracks + i) == -1) {
|
nuclear@21
|
24 for(j=0; j<i; j++) {
|
nuclear@21
|
25 anm_destroy_track(anim->tracks + i);
|
nuclear@21
|
26 }
|
nuclear@21
|
27 }
|
nuclear@21
|
28 anm_set_track_default(anim->tracks + i, defaults[i]);
|
nuclear@21
|
29 }
|
nuclear@21
|
30 return 0;
|
nuclear@21
|
31 }
|
nuclear@21
|
32
|
nuclear@21
|
33 void anm_destroy_animation(struct anm_animation *anim)
|
nuclear@21
|
34 {
|
nuclear@21
|
35 int i;
|
nuclear@21
|
36 for(i=0; i<ANM_NUM_TRACKS; i++) {
|
nuclear@21
|
37 anm_destroy_track(anim->tracks + i);
|
nuclear@21
|
38 }
|
nuclear@21
|
39 free(anim->name);
|
nuclear@21
|
40 }
|
nuclear@21
|
41
|
nuclear@22
|
42 void anm_set_animation_name(struct anm_animation *anim, const char *name)
|
nuclear@22
|
43 {
|
nuclear@22
|
44 char *newname = malloc(strlen(name) + 1);
|
nuclear@22
|
45 if(!newname) return;
|
nuclear@22
|
46
|
nuclear@23
|
47 strcpy(newname, name);
|
nuclear@23
|
48
|
nuclear@22
|
49 free(anim->name);
|
nuclear@22
|
50 anim->name = newname;
|
nuclear@22
|
51 }
|
nuclear@22
|
52
|
nuclear@21
|
53 /* ---- node implementation ----- */
|
nuclear@21
|
54
|
nuclear@21
|
55 int anm_init_node(struct anm_node *node)
|
nuclear@21
|
56 {
|
nuclear@0
|
57 memset(node, 0, sizeof *node);
|
nuclear@0
|
58
|
nuclear@21
|
59 node->cur_anim[1] = -1;
|
nuclear@21
|
60
|
nuclear@21
|
61 if(!(node->animations = dynarr_alloc(1, sizeof *node->animations))) {
|
nuclear@21
|
62 return -1;
|
nuclear@21
|
63 }
|
nuclear@21
|
64 if(anm_init_animation(node->animations) == -1) {
|
nuclear@21
|
65 dynarr_free(node->animations);
|
nuclear@21
|
66 return -1;
|
nuclear@21
|
67 }
|
nuclear@21
|
68
|
nuclear@0
|
69 /* initialize thread-local matrix cache */
|
nuclear@0
|
70 pthread_key_create(&node->cache_key, 0);
|
nuclear@10
|
71 pthread_mutex_init(&node->cache_list_lock, 0);
|
nuclear@0
|
72
|
nuclear@0
|
73 return 0;
|
nuclear@0
|
74 }
|
nuclear@0
|
75
|
nuclear@0
|
76 void anm_destroy_node(struct anm_node *node)
|
nuclear@0
|
77 {
|
nuclear@26
|
78 int i, num_anim;
|
nuclear@0
|
79 free(node->name);
|
nuclear@0
|
80
|
nuclear@26
|
81 num_anim = anm_get_animation_count(node);
|
nuclear@26
|
82 for(i=0; i<num_anim; i++) {
|
nuclear@21
|
83 anm_destroy_animation(node->animations + i);
|
nuclear@0
|
84 }
|
nuclear@21
|
85 dynarr_free(node->animations);
|
nuclear@0
|
86
|
nuclear@0
|
87 /* destroy thread-specific cache */
|
nuclear@0
|
88 pthread_key_delete(node->cache_key);
|
nuclear@0
|
89
|
nuclear@0
|
90 while(node->cache_list) {
|
nuclear@0
|
91 struct mat_cache *tmp = node->cache_list;
|
nuclear@0
|
92 node->cache_list = tmp->next;
|
nuclear@0
|
93 free(tmp);
|
nuclear@0
|
94 }
|
nuclear@0
|
95 }
|
nuclear@0
|
96
|
nuclear@0
|
97 void anm_destroy_node_tree(struct anm_node *tree)
|
nuclear@0
|
98 {
|
nuclear@0
|
99 struct anm_node *c, *tmp;
|
nuclear@0
|
100
|
nuclear@0
|
101 if(!tree) return;
|
nuclear@0
|
102
|
nuclear@0
|
103 c = tree->child;
|
nuclear@0
|
104 while(c) {
|
nuclear@0
|
105 tmp = c;
|
nuclear@0
|
106 c = c->next;
|
nuclear@0
|
107
|
nuclear@0
|
108 anm_destroy_node_tree(tmp);
|
nuclear@0
|
109 }
|
nuclear@0
|
110 anm_destroy_node(tree);
|
nuclear@0
|
111 }
|
nuclear@0
|
112
|
nuclear@0
|
113 struct anm_node *anm_create_node(void)
|
nuclear@0
|
114 {
|
nuclear@0
|
115 struct anm_node *n;
|
nuclear@0
|
116
|
nuclear@0
|
117 if((n = malloc(sizeof *n))) {
|
nuclear@0
|
118 if(anm_init_node(n) == -1) {
|
nuclear@0
|
119 free(n);
|
nuclear@0
|
120 return 0;
|
nuclear@0
|
121 }
|
nuclear@0
|
122 }
|
nuclear@0
|
123 return n;
|
nuclear@0
|
124 }
|
nuclear@0
|
125
|
nuclear@0
|
126 void anm_free_node(struct anm_node *node)
|
nuclear@0
|
127 {
|
nuclear@0
|
128 anm_destroy_node(node);
|
nuclear@0
|
129 free(node);
|
nuclear@0
|
130 }
|
nuclear@0
|
131
|
nuclear@0
|
132 void anm_free_node_tree(struct anm_node *tree)
|
nuclear@0
|
133 {
|
nuclear@0
|
134 struct anm_node *c, *tmp;
|
nuclear@0
|
135
|
nuclear@0
|
136 if(!tree) return;
|
nuclear@0
|
137
|
nuclear@0
|
138 c = tree->child;
|
nuclear@0
|
139 while(c) {
|
nuclear@0
|
140 tmp = c;
|
nuclear@0
|
141 c = c->next;
|
nuclear@0
|
142
|
nuclear@0
|
143 anm_free_node_tree(tmp);
|
nuclear@0
|
144 }
|
nuclear@0
|
145
|
nuclear@0
|
146 anm_free_node(tree);
|
nuclear@0
|
147 }
|
nuclear@0
|
148
|
nuclear@0
|
149 int anm_set_node_name(struct anm_node *node, const char *name)
|
nuclear@0
|
150 {
|
nuclear@0
|
151 char *str;
|
nuclear@0
|
152
|
nuclear@0
|
153 if(!(str = malloc(strlen(name) + 1))) {
|
nuclear@0
|
154 return -1;
|
nuclear@0
|
155 }
|
nuclear@0
|
156 strcpy(str, name);
|
nuclear@0
|
157 free(node->name);
|
nuclear@0
|
158 node->name = str;
|
nuclear@0
|
159 return 0;
|
nuclear@0
|
160 }
|
nuclear@0
|
161
|
nuclear@0
|
162 const char *anm_get_node_name(struct anm_node *node)
|
nuclear@0
|
163 {
|
nuclear@0
|
164 return node->name ? node->name : "";
|
nuclear@0
|
165 }
|
nuclear@0
|
166
|
nuclear@0
|
167 void anm_link_node(struct anm_node *p, struct anm_node *c)
|
nuclear@0
|
168 {
|
nuclear@0
|
169 c->next = p->child;
|
nuclear@0
|
170 p->child = c;
|
nuclear@0
|
171
|
nuclear@0
|
172 c->parent = p;
|
nuclear@0
|
173 invalidate_cache(c);
|
nuclear@0
|
174 }
|
nuclear@0
|
175
|
nuclear@0
|
176 int anm_unlink_node(struct anm_node *p, struct anm_node *c)
|
nuclear@0
|
177 {
|
nuclear@0
|
178 struct anm_node *iter;
|
nuclear@0
|
179
|
nuclear@0
|
180 if(p->child == c) {
|
nuclear@0
|
181 p->child = c->next;
|
nuclear@0
|
182 c->next = 0;
|
nuclear@0
|
183 invalidate_cache(c);
|
nuclear@0
|
184 return 0;
|
nuclear@0
|
185 }
|
nuclear@0
|
186
|
nuclear@0
|
187 iter = p->child;
|
nuclear@0
|
188 while(iter->next) {
|
nuclear@0
|
189 if(iter->next == c) {
|
nuclear@0
|
190 iter->next = c->next;
|
nuclear@0
|
191 c->next = 0;
|
nuclear@0
|
192 invalidate_cache(c);
|
nuclear@0
|
193 return 0;
|
nuclear@0
|
194 }
|
nuclear@0
|
195 }
|
nuclear@0
|
196 return -1;
|
nuclear@0
|
197 }
|
nuclear@0
|
198
|
nuclear@21
|
199 void anm_set_pivot(struct anm_node *node, vec3_t piv)
|
nuclear@21
|
200 {
|
nuclear@21
|
201 node->pivot = piv;
|
nuclear@21
|
202 }
|
nuclear@21
|
203
|
nuclear@21
|
204 vec3_t anm_get_pivot(struct anm_node *node)
|
nuclear@21
|
205 {
|
nuclear@21
|
206 return node->pivot;
|
nuclear@21
|
207 }
|
nuclear@21
|
208
|
nuclear@21
|
209
|
nuclear@21
|
210 /* animation management */
|
nuclear@21
|
211
|
nuclear@21
|
212 int anm_use_node_animation(struct anm_node *node, int aidx)
|
nuclear@21
|
213 {
|
nuclear@21
|
214 if(aidx == node->cur_anim[0] && node->cur_anim[1] == -1) {
|
nuclear@21
|
215 return 0; /* no change, no invalidation */
|
nuclear@21
|
216 }
|
nuclear@21
|
217
|
nuclear@21
|
218 if(aidx < 0 || aidx >= anm_get_animation_count(node)) {
|
nuclear@21
|
219 return -1;
|
nuclear@21
|
220 }
|
nuclear@21
|
221
|
nuclear@21
|
222 node->cur_anim[0] = aidx;
|
nuclear@21
|
223 node->cur_anim[1] = -1;
|
nuclear@21
|
224 node->cur_mix = 0;
|
nuclear@24
|
225 node->blend_dur = -1;
|
nuclear@21
|
226
|
nuclear@21
|
227 invalidate_cache(node);
|
nuclear@21
|
228 return 0;
|
nuclear@21
|
229 }
|
nuclear@21
|
230
|
nuclear@21
|
231 int anm_use_node_animations(struct anm_node *node, int aidx, int bidx, float t)
|
nuclear@21
|
232 {
|
nuclear@21
|
233 int num_anim;
|
nuclear@21
|
234
|
nuclear@21
|
235 if(node->cur_anim[0] == aidx && node->cur_anim[1] == bidx &&
|
nuclear@21
|
236 fabs(t - node->cur_mix) < 1e-6) {
|
nuclear@21
|
237 return 0; /* no change, no invalidation */
|
nuclear@21
|
238 }
|
nuclear@21
|
239
|
nuclear@21
|
240 num_anim = anm_get_animation_count(node);
|
nuclear@21
|
241 if(aidx < 0 || aidx >= num_anim) {
|
nuclear@21
|
242 return anm_use_animation(node, bidx);
|
nuclear@21
|
243 }
|
nuclear@21
|
244 if(bidx < 0 || bidx >= num_anim) {
|
nuclear@21
|
245 return anm_use_animation(node, aidx);
|
nuclear@21
|
246 }
|
nuclear@21
|
247 node->cur_anim[0] = aidx;
|
nuclear@21
|
248 node->cur_anim[1] = bidx;
|
nuclear@21
|
249 node->cur_mix = t;
|
nuclear@21
|
250
|
nuclear@21
|
251 invalidate_cache(node);
|
nuclear@21
|
252 return 0;
|
nuclear@21
|
253 }
|
nuclear@21
|
254
|
nuclear@21
|
255 int anm_use_animation(struct anm_node *node, int aidx)
|
nuclear@21
|
256 {
|
nuclear@21
|
257 struct anm_node *child;
|
nuclear@21
|
258
|
nuclear@21
|
259 if(anm_use_node_animation(node, aidx) == -1) {
|
nuclear@21
|
260 return -1;
|
nuclear@21
|
261 }
|
nuclear@21
|
262
|
nuclear@21
|
263 child = node->child;
|
nuclear@21
|
264 while(child) {
|
nuclear@21
|
265 if(anm_use_animation(child, aidx) == -1) {
|
nuclear@21
|
266 return -1;
|
nuclear@21
|
267 }
|
nuclear@21
|
268 child = child->next;
|
nuclear@21
|
269 }
|
nuclear@21
|
270 return 0;
|
nuclear@21
|
271 }
|
nuclear@21
|
272
|
nuclear@21
|
273 int anm_use_animations(struct anm_node *node, int aidx, int bidx, float t)
|
nuclear@21
|
274 {
|
nuclear@21
|
275 struct anm_node *child;
|
nuclear@21
|
276
|
nuclear@21
|
277 if(anm_use_node_animations(node, aidx, bidx, t) == -1) {
|
nuclear@21
|
278 return -1;
|
nuclear@21
|
279 }
|
nuclear@21
|
280
|
nuclear@21
|
281 child = node->child;
|
nuclear@21
|
282 while(child) {
|
nuclear@21
|
283 if(anm_use_animations(child, aidx, bidx, t) == -1) {
|
nuclear@21
|
284 return -1;
|
nuclear@21
|
285 }
|
nuclear@21
|
286 child = child->next;
|
nuclear@21
|
287 }
|
nuclear@21
|
288 return 0;
|
nuclear@21
|
289
|
nuclear@21
|
290 }
|
nuclear@21
|
291
|
nuclear@24
|
292 void anm_set_node_animation_offset(struct anm_node *node, anm_time_t offs, int which)
|
nuclear@24
|
293 {
|
nuclear@24
|
294 if(which < 0 || which >= 2) {
|
nuclear@24
|
295 return;
|
nuclear@24
|
296 }
|
nuclear@24
|
297 node->cur_anim_offset[which] = offs;
|
nuclear@24
|
298 }
|
nuclear@24
|
299
|
nuclear@24
|
300 anm_time_t anm_get_animation_offset(const struct anm_node *node, int which)
|
nuclear@24
|
301 {
|
nuclear@24
|
302 if(which < 0 || which >= 2) {
|
nuclear@24
|
303 return 0;
|
nuclear@24
|
304 }
|
nuclear@24
|
305 return node->cur_anim_offset[which];
|
nuclear@24
|
306 }
|
nuclear@24
|
307
|
nuclear@24
|
308 void anm_set_animation_offset(struct anm_node *node, anm_time_t offs, int which)
|
nuclear@24
|
309 {
|
nuclear@24
|
310 struct anm_node *c = node->child;
|
nuclear@24
|
311 while(c) {
|
nuclear@24
|
312 anm_set_animation_offset(c, offs, which);
|
nuclear@24
|
313 c = c->next;
|
nuclear@24
|
314 }
|
nuclear@24
|
315
|
nuclear@24
|
316 anm_set_node_animation_offset(node, offs, which);
|
nuclear@24
|
317 }
|
nuclear@24
|
318
|
nuclear@24
|
319 int anm_get_active_animation_index(const struct anm_node *node, int which)
|
nuclear@21
|
320 {
|
nuclear@21
|
321 if(which < 0 || which >= 2) return -1;
|
nuclear@21
|
322 return node->cur_anim[which];
|
nuclear@21
|
323 }
|
nuclear@21
|
324
|
nuclear@24
|
325 struct anm_animation *anm_get_active_animation(const struct anm_node *node, int which)
|
nuclear@21
|
326 {
|
nuclear@21
|
327 int idx = anm_get_active_animation_index(node, which);
|
nuclear@21
|
328 if(idx < 0 || idx >= anm_get_animation_count(node)) {
|
nuclear@21
|
329 return 0;
|
nuclear@21
|
330 }
|
nuclear@21
|
331 return node->animations + idx;
|
nuclear@21
|
332 }
|
nuclear@21
|
333
|
nuclear@24
|
334 float anm_get_active_animation_mix(const struct anm_node *node)
|
nuclear@21
|
335 {
|
nuclear@21
|
336 return node->cur_mix;
|
nuclear@21
|
337 }
|
nuclear@21
|
338
|
nuclear@24
|
339 int anm_get_animation_count(const struct anm_node *node)
|
nuclear@21
|
340 {
|
nuclear@21
|
341 return dynarr_size(node->animations);
|
nuclear@21
|
342 }
|
nuclear@21
|
343
|
nuclear@21
|
344 int anm_add_node_animation(struct anm_node *node)
|
nuclear@21
|
345 {
|
nuclear@21
|
346 struct anm_animation newanim;
|
nuclear@21
|
347 anm_init_animation(&newanim);
|
nuclear@21
|
348
|
nuclear@21
|
349 node->animations = dynarr_push(node->animations, &newanim);
|
nuclear@21
|
350 return 0;
|
nuclear@21
|
351 }
|
nuclear@21
|
352
|
nuclear@21
|
353 int anm_remove_node_animation(struct anm_node *node, int idx)
|
nuclear@21
|
354 {
|
nuclear@21
|
355 fprintf(stderr, "anm_remove_animation: unimplemented!");
|
nuclear@21
|
356 abort();
|
nuclear@21
|
357 return 0;
|
nuclear@21
|
358 }
|
nuclear@21
|
359
|
nuclear@21
|
360 int anm_add_animation(struct anm_node *node)
|
nuclear@21
|
361 {
|
nuclear@21
|
362 struct anm_node *child;
|
nuclear@21
|
363
|
nuclear@21
|
364 if(anm_add_node_animation(node) == -1) {
|
nuclear@21
|
365 return -1;
|
nuclear@21
|
366 }
|
nuclear@21
|
367
|
nuclear@21
|
368 child = node->child;
|
nuclear@21
|
369 while(child) {
|
nuclear@21
|
370 if(anm_add_animation(child)) {
|
nuclear@21
|
371 return -1;
|
nuclear@21
|
372 }
|
nuclear@21
|
373 child = child->next;
|
nuclear@21
|
374 }
|
nuclear@21
|
375 return 0;
|
nuclear@21
|
376 }
|
nuclear@21
|
377
|
nuclear@21
|
378 int anm_remove_animation(struct anm_node *node, int idx)
|
nuclear@21
|
379 {
|
nuclear@21
|
380 struct anm_node *child;
|
nuclear@21
|
381
|
nuclear@21
|
382 if(anm_remove_node_animation(node, idx) == -1) {
|
nuclear@21
|
383 return -1;
|
nuclear@21
|
384 }
|
nuclear@21
|
385
|
nuclear@21
|
386 child = node->child;
|
nuclear@21
|
387 while(child) {
|
nuclear@21
|
388 if(anm_remove_animation(child, idx) == -1) {
|
nuclear@21
|
389 return -1;
|
nuclear@21
|
390 }
|
nuclear@21
|
391 child = child->next;
|
nuclear@21
|
392 }
|
nuclear@21
|
393 return 0;
|
nuclear@21
|
394 }
|
nuclear@21
|
395
|
nuclear@21
|
396 struct anm_animation *anm_get_animation(struct anm_node *node, int idx)
|
nuclear@21
|
397 {
|
nuclear@21
|
398 if(idx < 0 || idx > anm_get_animation_count(node)) {
|
nuclear@21
|
399 return 0;
|
nuclear@21
|
400 }
|
nuclear@21
|
401 return node->animations + idx;
|
nuclear@21
|
402 }
|
nuclear@21
|
403
|
nuclear@21
|
404 struct anm_animation *anm_get_animation_by_name(struct anm_node *node, const char *name)
|
nuclear@21
|
405 {
|
nuclear@21
|
406 return anm_get_animation(node, anm_find_animation(node, name));
|
nuclear@21
|
407 }
|
nuclear@21
|
408
|
nuclear@21
|
409 int anm_find_animation(struct anm_node *node, const char *name)
|
nuclear@21
|
410 {
|
nuclear@21
|
411 int i, count = anm_get_animation_count(node);
|
nuclear@21
|
412 for(i=0; i<count; i++) {
|
nuclear@21
|
413 if(strcmp(node->animations[i].name, name) == 0) {
|
nuclear@21
|
414 return i;
|
nuclear@21
|
415 }
|
nuclear@21
|
416 }
|
nuclear@21
|
417 return -1;
|
nuclear@21
|
418 }
|
nuclear@21
|
419
|
nuclear@21
|
420 /* all the rest act on the current animation(s) */
|
nuclear@21
|
421
|
nuclear@21
|
422 void anm_set_interpolator(struct anm_node *node, enum anm_interpolator in)
|
nuclear@21
|
423 {
|
nuclear@21
|
424 int i;
|
nuclear@21
|
425 struct anm_animation *anim = anm_get_active_animation(node, 0);
|
nuclear@21
|
426 if(!anim) return;
|
nuclear@21
|
427
|
nuclear@21
|
428 for(i=0; i<ANM_NUM_TRACKS; i++) {
|
nuclear@21
|
429 anm_set_track_interpolator(anim->tracks + i, in);
|
nuclear@21
|
430 }
|
nuclear@21
|
431 invalidate_cache(node);
|
nuclear@21
|
432 }
|
nuclear@21
|
433
|
nuclear@21
|
434 void anm_set_extrapolator(struct anm_node *node, enum anm_extrapolator ex)
|
nuclear@21
|
435 {
|
nuclear@21
|
436 int i;
|
nuclear@21
|
437 struct anm_animation *anim = anm_get_active_animation(node, 0);
|
nuclear@21
|
438 if(!anim) return;
|
nuclear@21
|
439
|
nuclear@21
|
440 for(i=0; i<ANM_NUM_TRACKS; i++) {
|
nuclear@21
|
441 anm_set_track_extrapolator(anim->tracks + i, ex);
|
nuclear@21
|
442 }
|
nuclear@21
|
443 invalidate_cache(node);
|
nuclear@21
|
444 }
|
nuclear@21
|
445
|
nuclear@23
|
446 void anm_set_node_active_animation_name(struct anm_node *node, const char *name)
|
nuclear@23
|
447 {
|
nuclear@23
|
448 struct anm_animation *anim = anm_get_active_animation(node, 0);
|
nuclear@23
|
449 if(!anim) return;
|
nuclear@23
|
450
|
nuclear@23
|
451 anm_set_animation_name(anim, name);
|
nuclear@23
|
452 }
|
nuclear@23
|
453
|
nuclear@23
|
454 void anm_set_active_animation_name(struct anm_node *node, const char *name)
|
nuclear@23
|
455 {
|
nuclear@23
|
456 struct anm_node *child;
|
nuclear@23
|
457
|
nuclear@23
|
458 anm_set_node_active_animation_name(node, name);
|
nuclear@23
|
459
|
nuclear@23
|
460 child = node->child;
|
nuclear@23
|
461 while(child) {
|
nuclear@23
|
462 anm_set_active_animation_name(child, name);
|
nuclear@23
|
463 child = child->next;
|
nuclear@23
|
464 }
|
nuclear@23
|
465 }
|
nuclear@23
|
466
|
nuclear@23
|
467 const char *anm_get_active_animation_name(struct anm_node *node)
|
nuclear@23
|
468 {
|
nuclear@23
|
469 struct anm_animation *anim = anm_get_active_animation(node, 0);
|
nuclear@23
|
470 if(anim) {
|
nuclear@23
|
471 return anim->name;
|
nuclear@23
|
472 }
|
nuclear@23
|
473 return 0;
|
nuclear@23
|
474 }
|
nuclear@23
|
475
|
nuclear@24
|
476 /* ---- high level animation blending ---- */
|
nuclear@24
|
477 void anm_transition(struct anm_node *node, int anmidx, anm_time_t start, anm_time_t dur)
|
nuclear@24
|
478 {
|
nuclear@24
|
479 struct anm_node *c = node->child;
|
nuclear@25
|
480
|
nuclear@25
|
481 if(anmidx == node->cur_anim[0]) {
|
nuclear@25
|
482 return;
|
nuclear@25
|
483 }
|
nuclear@25
|
484
|
nuclear@24
|
485 while(c) {
|
nuclear@24
|
486 anm_transition(c, anmidx, start, dur);
|
nuclear@24
|
487 c = c->next;
|
nuclear@24
|
488 }
|
nuclear@24
|
489
|
nuclear@24
|
490 anm_node_transition(node, anmidx, start, dur);
|
nuclear@24
|
491 }
|
nuclear@24
|
492
|
nuclear@24
|
493 void anm_node_transition(struct anm_node *node, int anmidx, anm_time_t start, anm_time_t dur)
|
nuclear@24
|
494 {
|
nuclear@25
|
495 if(anmidx == node->cur_anim[0]) {
|
nuclear@25
|
496 return;
|
nuclear@25
|
497 }
|
nuclear@25
|
498
|
nuclear@24
|
499 node->cur_anim[1] = anmidx;
|
nuclear@24
|
500 node->cur_anim_offset[1] = start;
|
nuclear@24
|
501 node->blend_dur = dur;
|
nuclear@24
|
502 }
|
nuclear@24
|
503
|
nuclear@24
|
504
|
nuclear@24
|
505 #define BLEND_START_TM node->cur_anim_offset[1]
|
nuclear@24
|
506
|
nuclear@24
|
507 static anm_time_t animation_time(struct anm_node *node, anm_time_t tm, int which)
|
nuclear@24
|
508 {
|
nuclear@24
|
509 float t;
|
nuclear@24
|
510
|
nuclear@24
|
511 if(node->blend_dur >= 0) {
|
nuclear@24
|
512 /* we're in transition... */
|
nuclear@24
|
513 t = (float)(tm - BLEND_START_TM) / (float)node->blend_dur;
|
nuclear@24
|
514 if(t < 0.0) t = 0.0;
|
nuclear@24
|
515
|
nuclear@24
|
516 node->cur_mix = t;
|
nuclear@24
|
517
|
nuclear@24
|
518 if(t > 1.0) {
|
nuclear@24
|
519 /* switch completely over to the target animation and stop blending */
|
nuclear@24
|
520 anm_use_node_animation(node, node->cur_anim[1]);
|
nuclear@24
|
521 node->cur_anim_offset[0] = node->cur_anim_offset[1];
|
nuclear@24
|
522 }
|
nuclear@24
|
523 }
|
nuclear@24
|
524
|
nuclear@24
|
525 return tm - node->cur_anim_offset[which];
|
nuclear@24
|
526 }
|
nuclear@24
|
527
|
nuclear@24
|
528
|
nuclear@0
|
529 void anm_set_position(struct anm_node *node, vec3_t pos, anm_time_t tm)
|
nuclear@0
|
530 {
|
nuclear@21
|
531 struct anm_animation *anim = anm_get_active_animation(node, 0);
|
nuclear@21
|
532 if(!anim) return;
|
nuclear@21
|
533
|
nuclear@21
|
534 anm_set_value(anim->tracks + ANM_TRACK_POS_X, tm, pos.x);
|
nuclear@21
|
535 anm_set_value(anim->tracks + ANM_TRACK_POS_Y, tm, pos.y);
|
nuclear@21
|
536 anm_set_value(anim->tracks + ANM_TRACK_POS_Z, tm, pos.z);
|
nuclear@0
|
537 invalidate_cache(node);
|
nuclear@0
|
538 }
|
nuclear@0
|
539
|
nuclear@24
|
540
|
nuclear@0
|
541 vec3_t anm_get_node_position(struct anm_node *node, anm_time_t tm)
|
nuclear@0
|
542 {
|
nuclear@0
|
543 vec3_t v;
|
nuclear@24
|
544 anm_time_t tm0 = animation_time(node, tm, 0);
|
nuclear@21
|
545 struct anm_animation *anim0 = anm_get_active_animation(node, 0);
|
nuclear@21
|
546 struct anm_animation *anim1 = anm_get_active_animation(node, 1);
|
nuclear@21
|
547
|
nuclear@21
|
548 if(!anim0) {
|
nuclear@21
|
549 return v3_cons(0, 0, 0);
|
nuclear@21
|
550 }
|
nuclear@21
|
551
|
nuclear@24
|
552 v.x = anm_get_value(anim0->tracks + ANM_TRACK_POS_X, tm0);
|
nuclear@24
|
553 v.y = anm_get_value(anim0->tracks + ANM_TRACK_POS_Y, tm0);
|
nuclear@24
|
554 v.z = anm_get_value(anim0->tracks + ANM_TRACK_POS_Z, tm0);
|
nuclear@21
|
555
|
nuclear@21
|
556 if(anim1) {
|
nuclear@21
|
557 vec3_t v1;
|
nuclear@24
|
558 anm_time_t tm1 = animation_time(node, tm, 1);
|
nuclear@24
|
559 v1.x = anm_get_value(anim1->tracks + ANM_TRACK_POS_X, tm1);
|
nuclear@24
|
560 v1.y = anm_get_value(anim1->tracks + ANM_TRACK_POS_Y, tm1);
|
nuclear@24
|
561 v1.z = anm_get_value(anim1->tracks + ANM_TRACK_POS_Z, tm1);
|
nuclear@21
|
562
|
nuclear@21
|
563 v.x = v.x + (v1.x - v.x) * node->cur_mix;
|
nuclear@21
|
564 v.y = v.y + (v1.y - v.y) * node->cur_mix;
|
nuclear@21
|
565 v.z = v.z + (v1.z - v.z) * node->cur_mix;
|
nuclear@21
|
566 }
|
nuclear@21
|
567
|
nuclear@0
|
568 return v;
|
nuclear@0
|
569 }
|
nuclear@0
|
570
|
nuclear@0
|
571 void anm_set_rotation(struct anm_node *node, quat_t rot, anm_time_t tm)
|
nuclear@0
|
572 {
|
nuclear@21
|
573 struct anm_animation *anim = anm_get_active_animation(node, 0);
|
nuclear@21
|
574 if(!anim) return;
|
nuclear@21
|
575
|
nuclear@21
|
576 anm_set_value(anim->tracks + ANM_TRACK_ROT_X, tm, rot.x);
|
nuclear@21
|
577 anm_set_value(anim->tracks + ANM_TRACK_ROT_Y, tm, rot.y);
|
nuclear@21
|
578 anm_set_value(anim->tracks + ANM_TRACK_ROT_Z, tm, rot.z);
|
nuclear@21
|
579 anm_set_value(anim->tracks + ANM_TRACK_ROT_W, tm, rot.w);
|
nuclear@0
|
580 invalidate_cache(node);
|
nuclear@0
|
581 }
|
nuclear@0
|
582
|
nuclear@21
|
583 static quat_t get_node_rotation(struct anm_node *node, anm_time_t tm, struct anm_animation *anim)
|
nuclear@0
|
584 {
|
nuclear@7
|
585 #ifndef ROT_USE_SLERP
|
nuclear@7
|
586 quat_t q;
|
nuclear@21
|
587 q.x = anm_get_value(anim->tracks + ANM_TRACK_ROT_X, tm);
|
nuclear@21
|
588 q.y = anm_get_value(anim->tracks + ANM_TRACK_ROT_Y, tm);
|
nuclear@21
|
589 q.z = anm_get_value(anim->tracks + ANM_TRACK_ROT_Z, tm);
|
nuclear@21
|
590 q.w = anm_get_value(anim->tracks + ANM_TRACK_ROT_W, tm);
|
nuclear@7
|
591 return q;
|
nuclear@7
|
592 #else
|
nuclear@0
|
593 int idx0, idx1, last_idx;
|
nuclear@0
|
594 anm_time_t tstart, tend;
|
nuclear@0
|
595 float t, dt;
|
nuclear@0
|
596 struct anm_track *track_x, *track_y, *track_z, *track_w;
|
nuclear@0
|
597 quat_t q, q1, q2;
|
nuclear@0
|
598
|
nuclear@21
|
599 track_x = anim->tracks + ANM_TRACK_ROT_X;
|
nuclear@21
|
600 track_y = anim->tracks + ANM_TRACK_ROT_Y;
|
nuclear@21
|
601 track_z = anim->tracks + ANM_TRACK_ROT_Z;
|
nuclear@21
|
602 track_w = anim->tracks + ANM_TRACK_ROT_W;
|
nuclear@0
|
603
|
nuclear@0
|
604 if(!track_x->count) {
|
nuclear@0
|
605 q.x = track_x->def_val;
|
nuclear@0
|
606 q.y = track_y->def_val;
|
nuclear@0
|
607 q.z = track_z->def_val;
|
nuclear@0
|
608 q.w = track_w->def_val;
|
nuclear@0
|
609 return q;
|
nuclear@0
|
610 }
|
nuclear@0
|
611
|
nuclear@0
|
612 last_idx = track_x->count - 1;
|
nuclear@0
|
613
|
nuclear@0
|
614 tstart = track_x->keys[0].time;
|
nuclear@0
|
615 tend = track_x->keys[last_idx].time;
|
nuclear@6
|
616
|
nuclear@6
|
617 if(tstart == tend) {
|
nuclear@6
|
618 q.x = track_x->keys[0].val;
|
nuclear@6
|
619 q.y = track_y->keys[0].val;
|
nuclear@6
|
620 q.z = track_z->keys[0].val;
|
nuclear@6
|
621 q.w = track_w->keys[0].val;
|
nuclear@6
|
622 return q;
|
nuclear@6
|
623 }
|
nuclear@6
|
624
|
nuclear@0
|
625 tm = anm_remap_time(track_x, tm, tstart, tend);
|
nuclear@0
|
626
|
nuclear@0
|
627 idx0 = anm_get_key_interval(track_x, tm);
|
nuclear@0
|
628 assert(idx0 >= 0 && idx0 < track_x->count);
|
nuclear@0
|
629 idx1 = idx0 + 1;
|
nuclear@0
|
630
|
nuclear@6
|
631 if(idx0 == last_idx) {
|
nuclear@6
|
632 q.x = track_x->keys[idx0].val;
|
nuclear@6
|
633 q.y = track_y->keys[idx0].val;
|
nuclear@6
|
634 q.z = track_z->keys[idx0].val;
|
nuclear@6
|
635 q.w = track_w->keys[idx0].val;
|
nuclear@6
|
636 return q;
|
nuclear@6
|
637 }
|
nuclear@6
|
638
|
nuclear@0
|
639 dt = (float)(track_x->keys[idx1].time - track_x->keys[idx0].time);
|
nuclear@0
|
640 t = (float)(tm - track_x->keys[idx0].time) / dt;
|
nuclear@0
|
641
|
nuclear@0
|
642 q1.x = track_x->keys[idx0].val;
|
nuclear@0
|
643 q1.y = track_y->keys[idx0].val;
|
nuclear@0
|
644 q1.z = track_z->keys[idx0].val;
|
nuclear@0
|
645 q1.w = track_w->keys[idx0].val;
|
nuclear@0
|
646
|
nuclear@0
|
647 q2.x = track_x->keys[idx1].val;
|
nuclear@0
|
648 q2.y = track_y->keys[idx1].val;
|
nuclear@0
|
649 q2.z = track_z->keys[idx1].val;
|
nuclear@0
|
650 q2.w = track_w->keys[idx1].val;
|
nuclear@0
|
651
|
nuclear@9
|
652 /*q1 = quat_normalize(q1);
|
nuclear@9
|
653 q2 = quat_normalize(q2);*/
|
nuclear@9
|
654
|
nuclear@0
|
655 return quat_slerp(q1, q2, t);
|
nuclear@7
|
656 #endif
|
nuclear@0
|
657 }
|
nuclear@0
|
658
|
nuclear@21
|
659 quat_t anm_get_node_rotation(struct anm_node *node, anm_time_t tm)
|
nuclear@21
|
660 {
|
nuclear@21
|
661 quat_t q;
|
nuclear@24
|
662 anm_time_t tm0 = animation_time(node, tm, 0);
|
nuclear@21
|
663 struct anm_animation *anim0 = anm_get_active_animation(node, 0);
|
nuclear@21
|
664 struct anm_animation *anim1 = anm_get_active_animation(node, 1);
|
nuclear@21
|
665
|
nuclear@21
|
666 if(!anim0) {
|
nuclear@21
|
667 return quat_identity();
|
nuclear@21
|
668 }
|
nuclear@21
|
669
|
nuclear@24
|
670 q = get_node_rotation(node, tm0, anim0);
|
nuclear@21
|
671
|
nuclear@21
|
672 if(anim1) {
|
nuclear@24
|
673 anm_time_t tm1 = animation_time(node, tm, 1);
|
nuclear@24
|
674 quat_t q1 = get_node_rotation(node, tm1, anim1);
|
nuclear@21
|
675
|
nuclear@21
|
676 q = quat_slerp(q, q1, node->cur_mix);
|
nuclear@21
|
677 }
|
nuclear@21
|
678 return q;
|
nuclear@21
|
679 }
|
nuclear@21
|
680
|
nuclear@0
|
681 void anm_set_scaling(struct anm_node *node, vec3_t scl, anm_time_t tm)
|
nuclear@0
|
682 {
|
nuclear@21
|
683 struct anm_animation *anim = anm_get_active_animation(node, 0);
|
nuclear@21
|
684 if(!anim) return;
|
nuclear@21
|
685
|
nuclear@21
|
686 anm_set_value(anim->tracks + ANM_TRACK_SCL_X, tm, scl.x);
|
nuclear@21
|
687 anm_set_value(anim->tracks + ANM_TRACK_SCL_Y, tm, scl.y);
|
nuclear@21
|
688 anm_set_value(anim->tracks + ANM_TRACK_SCL_Z, tm, scl.z);
|
nuclear@0
|
689 invalidate_cache(node);
|
nuclear@0
|
690 }
|
nuclear@0
|
691
|
nuclear@0
|
692 vec3_t anm_get_node_scaling(struct anm_node *node, anm_time_t tm)
|
nuclear@0
|
693 {
|
nuclear@0
|
694 vec3_t v;
|
nuclear@24
|
695 anm_time_t tm0 = animation_time(node, tm, 0);
|
nuclear@21
|
696 struct anm_animation *anim0 = anm_get_active_animation(node, 0);
|
nuclear@21
|
697 struct anm_animation *anim1 = anm_get_active_animation(node, 1);
|
nuclear@21
|
698
|
nuclear@21
|
699 if(!anim0) {
|
nuclear@21
|
700 return v3_cons(1, 1, 1);
|
nuclear@21
|
701 }
|
nuclear@21
|
702
|
nuclear@24
|
703 v.x = anm_get_value(anim0->tracks + ANM_TRACK_SCL_X, tm0);
|
nuclear@24
|
704 v.y = anm_get_value(anim0->tracks + ANM_TRACK_SCL_Y, tm0);
|
nuclear@24
|
705 v.z = anm_get_value(anim0->tracks + ANM_TRACK_SCL_Z, tm0);
|
nuclear@21
|
706
|
nuclear@21
|
707 if(anim1) {
|
nuclear@21
|
708 vec3_t v1;
|
nuclear@24
|
709 anm_time_t tm1 = animation_time(node, tm, 1);
|
nuclear@24
|
710 v1.x = anm_get_value(anim1->tracks + ANM_TRACK_SCL_X, tm1);
|
nuclear@24
|
711 v1.y = anm_get_value(anim1->tracks + ANM_TRACK_SCL_Y, tm1);
|
nuclear@24
|
712 v1.z = anm_get_value(anim1->tracks + ANM_TRACK_SCL_Z, tm1);
|
nuclear@21
|
713
|
nuclear@21
|
714 v.x = v.x + (v1.x - v.x) * node->cur_mix;
|
nuclear@21
|
715 v.y = v.y + (v1.y - v.y) * node->cur_mix;
|
nuclear@21
|
716 v.z = v.z + (v1.z - v.z) * node->cur_mix;
|
nuclear@21
|
717 }
|
nuclear@21
|
718
|
nuclear@0
|
719 return v;
|
nuclear@0
|
720 }
|
nuclear@0
|
721
|
nuclear@0
|
722
|
nuclear@0
|
723 vec3_t anm_get_position(struct anm_node *node, anm_time_t tm)
|
nuclear@0
|
724 {
|
nuclear@0
|
725 mat4_t xform;
|
nuclear@0
|
726 vec3_t pos = {0.0, 0.0, 0.0};
|
nuclear@0
|
727
|
nuclear@0
|
728 if(!node->parent) {
|
nuclear@0
|
729 return anm_get_node_position(node, tm);
|
nuclear@0
|
730 }
|
nuclear@0
|
731
|
nuclear@0
|
732 anm_get_matrix(node, xform, tm);
|
nuclear@0
|
733 return v3_transform(pos, xform);
|
nuclear@0
|
734 }
|
nuclear@0
|
735
|
nuclear@0
|
736 quat_t anm_get_rotation(struct anm_node *node, anm_time_t tm)
|
nuclear@0
|
737 {
|
nuclear@0
|
738 quat_t rot, prot;
|
nuclear@0
|
739 rot = anm_get_node_rotation(node, tm);
|
nuclear@0
|
740
|
nuclear@0
|
741 if(!node->parent) {
|
nuclear@0
|
742 return rot;
|
nuclear@0
|
743 }
|
nuclear@0
|
744
|
nuclear@0
|
745 prot = anm_get_rotation(node->parent, tm);
|
nuclear@0
|
746 return quat_mul(prot, rot);
|
nuclear@0
|
747 }
|
nuclear@0
|
748
|
nuclear@0
|
749 vec3_t anm_get_scaling(struct anm_node *node, anm_time_t tm)
|
nuclear@0
|
750 {
|
nuclear@0
|
751 vec3_t s, ps;
|
nuclear@0
|
752 s = anm_get_node_scaling(node, tm);
|
nuclear@0
|
753
|
nuclear@0
|
754 if(!node->parent) {
|
nuclear@0
|
755 return s;
|
nuclear@0
|
756 }
|
nuclear@0
|
757
|
nuclear@0
|
758 ps = anm_get_scaling(node->parent, tm);
|
nuclear@0
|
759 return v3_mul(s, ps);
|
nuclear@0
|
760 }
|
nuclear@0
|
761
|
nuclear@5
|
762 void anm_get_node_matrix(struct anm_node *node, mat4_t mat, anm_time_t tm)
|
nuclear@5
|
763 {
|
nuclear@9
|
764 int i;
|
nuclear@9
|
765 mat4_t rmat;
|
nuclear@5
|
766 vec3_t pos, scale;
|
nuclear@5
|
767 quat_t rot;
|
nuclear@5
|
768
|
nuclear@5
|
769 pos = anm_get_node_position(node, tm);
|
nuclear@5
|
770 rot = anm_get_node_rotation(node, tm);
|
nuclear@5
|
771 scale = anm_get_node_scaling(node, tm);
|
nuclear@5
|
772
|
nuclear@9
|
773 m4_set_translation(mat, node->pivot.x, node->pivot.y, node->pivot.z);
|
nuclear@5
|
774
|
nuclear@5
|
775 quat_to_mat4(rmat, rot);
|
nuclear@9
|
776 for(i=0; i<3; i++) {
|
nuclear@9
|
777 mat[i][0] = rmat[i][0];
|
nuclear@9
|
778 mat[i][1] = rmat[i][1];
|
nuclear@9
|
779 mat[i][2] = rmat[i][2];
|
nuclear@9
|
780 }
|
nuclear@9
|
781 /* this loop is equivalent to: m4_mult(mat, mat, rmat); */
|
nuclear@5
|
782
|
nuclear@9
|
783 mat[0][0] *= scale.x; mat[0][1] *= scale.y; mat[0][2] *= scale.z; mat[0][3] += pos.x;
|
nuclear@9
|
784 mat[1][0] *= scale.x; mat[1][1] *= scale.y; mat[1][2] *= scale.z; mat[1][3] += pos.y;
|
nuclear@9
|
785 mat[2][0] *= scale.x; mat[2][1] *= scale.y; mat[2][2] *= scale.z; mat[2][3] += pos.z;
|
nuclear@9
|
786
|
nuclear@9
|
787 m4_translate(mat, -node->pivot.x, -node->pivot.y, -node->pivot.z);
|
nuclear@9
|
788
|
nuclear@9
|
789 /* that's basically: pivot * rotation * translation * scaling * -pivot */
|
nuclear@5
|
790 }
|
nuclear@5
|
791
|
nuclear@5
|
792 void anm_get_node_inv_matrix(struct anm_node *node, mat4_t mat, anm_time_t tm)
|
nuclear@5
|
793 {
|
nuclear@5
|
794 mat4_t tmp;
|
nuclear@5
|
795 anm_get_node_matrix(node, tmp, tm);
|
nuclear@5
|
796 m4_inverse(mat, tmp);
|
nuclear@5
|
797 }
|
nuclear@5
|
798
|
nuclear@20
|
799 void anm_eval_node(struct anm_node *node, anm_time_t tm)
|
nuclear@20
|
800 {
|
nuclear@20
|
801 anm_get_node_matrix(node, node->matrix, tm);
|
nuclear@20
|
802 }
|
nuclear@20
|
803
|
nuclear@20
|
804 void anm_eval(struct anm_node *node, anm_time_t tm)
|
nuclear@20
|
805 {
|
nuclear@20
|
806 struct anm_node *c;
|
nuclear@20
|
807
|
nuclear@20
|
808 anm_eval_node(node, tm);
|
nuclear@20
|
809
|
nuclear@20
|
810 if(node->parent) {
|
nuclear@20
|
811 /* due to post-order traversal, the parent matrix is already evaluated */
|
nuclear@20
|
812 m4_mult(node->matrix, node->parent->matrix, node->matrix);
|
nuclear@20
|
813 }
|
nuclear@20
|
814
|
nuclear@20
|
815 /* recersively evaluate all children */
|
nuclear@20
|
816 c = node->child;
|
nuclear@20
|
817 while(c) {
|
nuclear@20
|
818 anm_eval(c, tm);
|
nuclear@20
|
819 c = c->next;
|
nuclear@20
|
820 }
|
nuclear@20
|
821 }
|
nuclear@20
|
822
|
nuclear@0
|
823 void anm_get_matrix(struct anm_node *node, mat4_t mat, anm_time_t tm)
|
nuclear@0
|
824 {
|
nuclear@0
|
825 struct mat_cache *cache = pthread_getspecific(node->cache_key);
|
nuclear@0
|
826 if(!cache) {
|
nuclear@0
|
827 cache = malloc(sizeof *cache);
|
nuclear@0
|
828 assert(cache);
|
nuclear@0
|
829
|
nuclear@0
|
830 pthread_mutex_lock(&node->cache_list_lock);
|
nuclear@0
|
831 cache->next = node->cache_list;
|
nuclear@0
|
832 node->cache_list = cache;
|
nuclear@0
|
833 pthread_mutex_unlock(&node->cache_list_lock);
|
nuclear@0
|
834
|
nuclear@0
|
835 cache->time = ANM_TIME_INVAL;
|
nuclear@2
|
836 cache->inv_time = ANM_TIME_INVAL;
|
nuclear@0
|
837 pthread_setspecific(node->cache_key, cache);
|
nuclear@0
|
838 }
|
nuclear@0
|
839
|
nuclear@0
|
840 if(cache->time != tm) {
|
nuclear@5
|
841 anm_get_node_matrix(node, cache->matrix, tm);
|
nuclear@0
|
842
|
nuclear@0
|
843 if(node->parent) {
|
nuclear@0
|
844 mat4_t parent_mat;
|
nuclear@0
|
845
|
nuclear@4
|
846 anm_get_matrix(node->parent, parent_mat, tm);
|
nuclear@0
|
847 m4_mult(cache->matrix, parent_mat, cache->matrix);
|
nuclear@0
|
848 }
|
nuclear@0
|
849 cache->time = tm;
|
nuclear@0
|
850 }
|
nuclear@0
|
851 m4_copy(mat, cache->matrix);
|
nuclear@0
|
852 }
|
nuclear@0
|
853
|
nuclear@0
|
854 void anm_get_inv_matrix(struct anm_node *node, mat4_t mat, anm_time_t tm)
|
nuclear@0
|
855 {
|
nuclear@0
|
856 struct mat_cache *cache = pthread_getspecific(node->cache_key);
|
nuclear@0
|
857 if(!cache) {
|
nuclear@0
|
858 cache = malloc(sizeof *cache);
|
nuclear@0
|
859 assert(cache);
|
nuclear@0
|
860
|
nuclear@0
|
861 pthread_mutex_lock(&node->cache_list_lock);
|
nuclear@0
|
862 cache->next = node->cache_list;
|
nuclear@0
|
863 node->cache_list = cache;
|
nuclear@0
|
864 pthread_mutex_unlock(&node->cache_list_lock);
|
nuclear@0
|
865
|
nuclear@0
|
866 cache->inv_time = ANM_TIME_INVAL;
|
nuclear@2
|
867 cache->inv_time = ANM_TIME_INVAL;
|
nuclear@0
|
868 pthread_setspecific(node->cache_key, cache);
|
nuclear@0
|
869 }
|
nuclear@0
|
870
|
nuclear@0
|
871 if(cache->inv_time != tm) {
|
nuclear@0
|
872 anm_get_matrix(node, mat, tm);
|
nuclear@0
|
873 m4_inverse(cache->inv_matrix, mat);
|
nuclear@0
|
874 cache->inv_time = tm;
|
nuclear@0
|
875 }
|
nuclear@0
|
876 m4_copy(mat, cache->inv_matrix);
|
nuclear@0
|
877 }
|
nuclear@0
|
878
|
nuclear@0
|
879 anm_time_t anm_get_start_time(struct anm_node *node)
|
nuclear@0
|
880 {
|
nuclear@21
|
881 int i, j;
|
nuclear@0
|
882 struct anm_node *c;
|
nuclear@0
|
883 anm_time_t res = LONG_MAX;
|
nuclear@0
|
884
|
nuclear@21
|
885 for(j=0; j<2; j++) {
|
nuclear@21
|
886 struct anm_animation *anim = anm_get_active_animation(node, j);
|
nuclear@21
|
887 if(!anim) break;
|
nuclear@21
|
888
|
nuclear@21
|
889 for(i=0; i<ANM_NUM_TRACKS; i++) {
|
nuclear@21
|
890 if(anim->tracks[i].count) {
|
nuclear@21
|
891 anm_time_t tm = anim->tracks[i].keys[0].time;
|
nuclear@21
|
892 if(tm < res) {
|
nuclear@21
|
893 res = tm;
|
nuclear@21
|
894 }
|
nuclear@0
|
895 }
|
nuclear@0
|
896 }
|
nuclear@0
|
897 }
|
nuclear@0
|
898
|
nuclear@0
|
899 c = node->child;
|
nuclear@0
|
900 while(c) {
|
nuclear@0
|
901 anm_time_t tm = anm_get_start_time(c);
|
nuclear@0
|
902 if(tm < res) {
|
nuclear@0
|
903 res = tm;
|
nuclear@0
|
904 }
|
nuclear@0
|
905 c = c->next;
|
nuclear@0
|
906 }
|
nuclear@0
|
907 return res;
|
nuclear@0
|
908 }
|
nuclear@0
|
909
|
nuclear@0
|
910 anm_time_t anm_get_end_time(struct anm_node *node)
|
nuclear@0
|
911 {
|
nuclear@21
|
912 int i, j;
|
nuclear@0
|
913 struct anm_node *c;
|
nuclear@0
|
914 anm_time_t res = LONG_MIN;
|
nuclear@0
|
915
|
nuclear@21
|
916 for(j=0; j<2; j++) {
|
nuclear@21
|
917 struct anm_animation *anim = anm_get_active_animation(node, j);
|
nuclear@21
|
918 if(!anim) break;
|
nuclear@21
|
919
|
nuclear@21
|
920 for(i=0; i<ANM_NUM_TRACKS; i++) {
|
nuclear@21
|
921 if(anim->tracks[i].count) {
|
nuclear@21
|
922 anm_time_t tm = anim->tracks[i].keys[anim->tracks[i].count - 1].time;
|
nuclear@21
|
923 if(tm > res) {
|
nuclear@21
|
924 res = tm;
|
nuclear@21
|
925 }
|
nuclear@0
|
926 }
|
nuclear@0
|
927 }
|
nuclear@0
|
928 }
|
nuclear@0
|
929
|
nuclear@0
|
930 c = node->child;
|
nuclear@0
|
931 while(c) {
|
nuclear@0
|
932 anm_time_t tm = anm_get_end_time(c);
|
nuclear@0
|
933 if(tm > res) {
|
nuclear@0
|
934 res = tm;
|
nuclear@0
|
935 }
|
nuclear@0
|
936 c = c->next;
|
nuclear@0
|
937 }
|
nuclear@0
|
938 return res;
|
nuclear@0
|
939 }
|
nuclear@0
|
940
|
nuclear@0
|
941 static void invalidate_cache(struct anm_node *node)
|
nuclear@0
|
942 {
|
nuclear@0
|
943 struct mat_cache *cache = pthread_getspecific(node->cache_key);
|
nuclear@0
|
944 if(cache) {
|
nuclear@13
|
945 cache->time = cache->inv_time = ANM_TIME_INVAL;
|
nuclear@0
|
946 }
|
nuclear@0
|
947 }
|