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