goat3d
diff libs/anim/anim.c @ 27:4deb0b12fe14
wtf... corrupted heap?
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Sun, 29 Sep 2013 08:20:19 +0300 |
parents | |
children | 0ecb788a87f7 |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/libs/anim/anim.c Sun Sep 29 08:20:19 2013 +0300 1.3 @@ -0,0 +1,455 @@ 1.4 +#include <stdlib.h> 1.5 +#include <limits.h> 1.6 +#include <assert.h> 1.7 +#include "anim.h" 1.8 +#include "dynarr.h" 1.9 + 1.10 +#define ROT_USE_SLERP 1.11 + 1.12 +static void invalidate_cache(struct anm_node *node); 1.13 + 1.14 +int anm_init_node(struct anm_node *node) 1.15 +{ 1.16 + int i, j; 1.17 + static const float defaults[] = { 1.18 + 0.0f, 0.0f, 0.0f, /* default position */ 1.19 + 0.0f, 0.0f, 0.0f, 1.0f, /* default rotation quat */ 1.20 + 1.0f, 1.0f, 1.0f /* default scale factor */ 1.21 + }; 1.22 + 1.23 + memset(node, 0, sizeof *node); 1.24 + 1.25 + for(i=0; i<ANM_NUM_TRACKS; i++) { 1.26 + if(anm_init_track(node->tracks + i) == -1) { 1.27 + for(j=0; j<i; j++) { 1.28 + anm_destroy_track(node->tracks + i); 1.29 + } 1.30 + } 1.31 + anm_set_track_default(node->tracks + i, defaults[i]); 1.32 + } 1.33 + 1.34 + node->cache.time = ANM_TIME_INVAL; 1.35 + node->cache.inv_time = ANM_TIME_INVAL; 1.36 + return 0; 1.37 +} 1.38 + 1.39 +void anm_destroy_node(struct anm_node *node) 1.40 +{ 1.41 + int i; 1.42 + free(node->name); 1.43 + 1.44 + for(i=0; i<ANM_NUM_TRACKS; i++) { 1.45 + anm_destroy_track(node->tracks + i); 1.46 + } 1.47 +} 1.48 + 1.49 +void anm_destroy_node_tree(struct anm_node *tree) 1.50 +{ 1.51 + struct anm_node *c, *tmp; 1.52 + 1.53 + if(!tree) return; 1.54 + 1.55 + c = tree->child; 1.56 + while(c) { 1.57 + tmp = c; 1.58 + c = c->next; 1.59 + 1.60 + anm_destroy_node_tree(tmp); 1.61 + } 1.62 + anm_destroy_node(tree); 1.63 +} 1.64 + 1.65 +struct anm_node *anm_create_node(void) 1.66 +{ 1.67 + struct anm_node *n; 1.68 + 1.69 + if((n = malloc(sizeof *n))) { 1.70 + if(anm_init_node(n) == -1) { 1.71 + free(n); 1.72 + return 0; 1.73 + } 1.74 + } 1.75 + return n; 1.76 +} 1.77 + 1.78 +void anm_free_node(struct anm_node *node) 1.79 +{ 1.80 + anm_destroy_node(node); 1.81 + free(node); 1.82 +} 1.83 + 1.84 +void anm_free_node_tree(struct anm_node *tree) 1.85 +{ 1.86 + struct anm_node *c, *tmp; 1.87 + 1.88 + if(!tree) return; 1.89 + 1.90 + c = tree->child; 1.91 + while(c) { 1.92 + tmp = c; 1.93 + c = c->next; 1.94 + 1.95 + anm_free_node_tree(tmp); 1.96 + } 1.97 + 1.98 + anm_free_node(tree); 1.99 +} 1.100 + 1.101 +int anm_set_node_name(struct anm_node *node, const char *name) 1.102 +{ 1.103 + char *str; 1.104 + 1.105 + if(!(str = malloc(strlen(name) + 1))) { 1.106 + return -1; 1.107 + } 1.108 + strcpy(str, name); 1.109 + free(node->name); 1.110 + node->name = str; 1.111 + return 0; 1.112 +} 1.113 + 1.114 +const char *anm_get_node_name(struct anm_node *node) 1.115 +{ 1.116 + return node->name ? node->name : ""; 1.117 +} 1.118 + 1.119 +void anm_set_interpolator(struct anm_node *node, enum anm_interpolator in) 1.120 +{ 1.121 + int i; 1.122 + 1.123 + for(i=0; i<ANM_NUM_TRACKS; i++) { 1.124 + anm_set_track_interpolator(node->tracks + i, in); 1.125 + } 1.126 + invalidate_cache(node); 1.127 +} 1.128 + 1.129 +void anm_set_extrapolator(struct anm_node *node, enum anm_extrapolator ex) 1.130 +{ 1.131 + int i; 1.132 + 1.133 + for(i=0; i<ANM_NUM_TRACKS; i++) { 1.134 + anm_set_track_extrapolator(node->tracks + i, ex); 1.135 + } 1.136 + invalidate_cache(node); 1.137 +} 1.138 + 1.139 +void anm_link_node(struct anm_node *p, struct anm_node *c) 1.140 +{ 1.141 + c->next = p->child; 1.142 + p->child = c; 1.143 + 1.144 + c->parent = p; 1.145 + invalidate_cache(c); 1.146 +} 1.147 + 1.148 +int anm_unlink_node(struct anm_node *p, struct anm_node *c) 1.149 +{ 1.150 + struct anm_node *iter; 1.151 + 1.152 + if(p->child == c) { 1.153 + p->child = c->next; 1.154 + c->next = 0; 1.155 + invalidate_cache(c); 1.156 + return 0; 1.157 + } 1.158 + 1.159 + iter = p->child; 1.160 + while(iter->next) { 1.161 + if(iter->next == c) { 1.162 + iter->next = c->next; 1.163 + c->next = 0; 1.164 + invalidate_cache(c); 1.165 + return 0; 1.166 + } 1.167 + } 1.168 + return -1; 1.169 +} 1.170 + 1.171 +void anm_set_position(struct anm_node *node, vec3_t pos, anm_time_t tm) 1.172 +{ 1.173 + anm_set_value(node->tracks + ANM_TRACK_POS_X, tm, pos.x); 1.174 + anm_set_value(node->tracks + ANM_TRACK_POS_Y, tm, pos.y); 1.175 + anm_set_value(node->tracks + ANM_TRACK_POS_Z, tm, pos.z); 1.176 + invalidate_cache(node); 1.177 +} 1.178 + 1.179 +vec3_t anm_get_node_position(struct anm_node *node, anm_time_t tm) 1.180 +{ 1.181 + vec3_t v; 1.182 + v.x = anm_get_value(node->tracks + ANM_TRACK_POS_X, tm); 1.183 + v.y = anm_get_value(node->tracks + ANM_TRACK_POS_Y, tm); 1.184 + v.z = anm_get_value(node->tracks + ANM_TRACK_POS_Z, tm); 1.185 + return v; 1.186 +} 1.187 + 1.188 +void anm_set_rotation(struct anm_node *node, quat_t rot, anm_time_t tm) 1.189 +{ 1.190 + anm_set_value(node->tracks + ANM_TRACK_ROT_X, tm, rot.x); 1.191 + anm_set_value(node->tracks + ANM_TRACK_ROT_Y, tm, rot.y); 1.192 + anm_set_value(node->tracks + ANM_TRACK_ROT_Z, tm, rot.z); 1.193 + anm_set_value(node->tracks + ANM_TRACK_ROT_W, tm, rot.w); 1.194 + invalidate_cache(node); 1.195 +} 1.196 + 1.197 +quat_t anm_get_node_rotation(struct anm_node *node, anm_time_t tm) 1.198 +{ 1.199 +#ifndef ROT_USE_SLERP 1.200 + quat_t q; 1.201 + q.x = anm_get_value(node->tracks + ANM_TRACK_ROT_X, tm); 1.202 + q.y = anm_get_value(node->tracks + ANM_TRACK_ROT_Y, tm); 1.203 + q.z = anm_get_value(node->tracks + ANM_TRACK_ROT_Z, tm); 1.204 + q.w = anm_get_value(node->tracks + ANM_TRACK_ROT_W, tm); 1.205 + return q; 1.206 +#else 1.207 + int idx0, idx1, last_idx; 1.208 + anm_time_t tstart, tend; 1.209 + float t, dt; 1.210 + struct anm_track *track_x, *track_y, *track_z, *track_w; 1.211 + quat_t q, q1, q2; 1.212 + 1.213 + track_x = node->tracks + ANM_TRACK_ROT_X; 1.214 + track_y = node->tracks + ANM_TRACK_ROT_Y; 1.215 + track_z = node->tracks + ANM_TRACK_ROT_Z; 1.216 + track_w = node->tracks + ANM_TRACK_ROT_W; 1.217 + 1.218 + if(!track_x->count) { 1.219 + q.x = track_x->def_val; 1.220 + q.y = track_y->def_val; 1.221 + q.z = track_z->def_val; 1.222 + q.w = track_w->def_val; 1.223 + return q; 1.224 + } 1.225 + 1.226 + last_idx = track_x->count - 1; 1.227 + 1.228 + tstart = track_x->keys[0].time; 1.229 + tend = track_x->keys[last_idx].time; 1.230 + 1.231 + if(tstart == tend) { 1.232 + q.x = track_x->keys[0].val; 1.233 + q.y = track_y->keys[0].val; 1.234 + q.z = track_z->keys[0].val; 1.235 + q.w = track_w->keys[0].val; 1.236 + return q; 1.237 + } 1.238 + 1.239 + tm = anm_remap_time(track_x, tm, tstart, tend); 1.240 + 1.241 + idx0 = anm_get_key_interval(track_x, tm); 1.242 + assert(idx0 >= 0 && idx0 < track_x->count); 1.243 + idx1 = idx0 + 1; 1.244 + 1.245 + if(idx0 == last_idx) { 1.246 + q.x = track_x->keys[idx0].val; 1.247 + q.y = track_y->keys[idx0].val; 1.248 + q.z = track_z->keys[idx0].val; 1.249 + q.w = track_w->keys[idx0].val; 1.250 + return q; 1.251 + } 1.252 + 1.253 + dt = (float)(track_x->keys[idx1].time - track_x->keys[idx0].time); 1.254 + t = (float)(tm - track_x->keys[idx0].time) / dt; 1.255 + 1.256 + q1.x = track_x->keys[idx0].val; 1.257 + q1.y = track_y->keys[idx0].val; 1.258 + q1.z = track_z->keys[idx0].val; 1.259 + q1.w = track_w->keys[idx0].val; 1.260 + 1.261 + q2.x = track_x->keys[idx1].val; 1.262 + q2.y = track_y->keys[idx1].val; 1.263 + q2.z = track_z->keys[idx1].val; 1.264 + q2.w = track_w->keys[idx1].val; 1.265 + 1.266 + /*q1 = quat_normalize(q1); 1.267 + q2 = quat_normalize(q2);*/ 1.268 + 1.269 + return quat_slerp(q1, q2, t); 1.270 +#endif 1.271 +} 1.272 + 1.273 +void anm_set_scaling(struct anm_node *node, vec3_t scl, anm_time_t tm) 1.274 +{ 1.275 + anm_set_value(node->tracks + ANM_TRACK_SCL_X, tm, scl.x); 1.276 + anm_set_value(node->tracks + ANM_TRACK_SCL_Y, tm, scl.y); 1.277 + anm_set_value(node->tracks + ANM_TRACK_SCL_Z, tm, scl.z); 1.278 + invalidate_cache(node); 1.279 +} 1.280 + 1.281 +vec3_t anm_get_node_scaling(struct anm_node *node, anm_time_t tm) 1.282 +{ 1.283 + vec3_t v; 1.284 + v.x = anm_get_value(node->tracks + ANM_TRACK_SCL_X, tm); 1.285 + v.y = anm_get_value(node->tracks + ANM_TRACK_SCL_Y, tm); 1.286 + v.z = anm_get_value(node->tracks + ANM_TRACK_SCL_Z, tm); 1.287 + return v; 1.288 +} 1.289 + 1.290 + 1.291 +vec3_t anm_get_position(struct anm_node *node, anm_time_t tm) 1.292 +{ 1.293 + mat4_t xform; 1.294 + vec3_t pos = {0.0, 0.0, 0.0}; 1.295 + 1.296 + if(!node->parent) { 1.297 + return anm_get_node_position(node, tm); 1.298 + } 1.299 + 1.300 + anm_get_matrix(node, xform, tm); 1.301 + return v3_transform(pos, xform); 1.302 +} 1.303 + 1.304 +quat_t anm_get_rotation(struct anm_node *node, anm_time_t tm) 1.305 +{ 1.306 + quat_t rot, prot; 1.307 + rot = anm_get_node_rotation(node, tm); 1.308 + 1.309 + if(!node->parent) { 1.310 + return rot; 1.311 + } 1.312 + 1.313 + prot = anm_get_rotation(node->parent, tm); 1.314 + return quat_mul(prot, rot); 1.315 +} 1.316 + 1.317 +vec3_t anm_get_scaling(struct anm_node *node, anm_time_t tm) 1.318 +{ 1.319 + vec3_t s, ps; 1.320 + s = anm_get_node_scaling(node, tm); 1.321 + 1.322 + if(!node->parent) { 1.323 + return s; 1.324 + } 1.325 + 1.326 + ps = anm_get_scaling(node->parent, tm); 1.327 + return v3_mul(s, ps); 1.328 +} 1.329 + 1.330 +void anm_set_pivot(struct anm_node *node, vec3_t piv) 1.331 +{ 1.332 + node->pivot = piv; 1.333 +} 1.334 + 1.335 +vec3_t anm_get_pivot(struct anm_node *node) 1.336 +{ 1.337 + return node->pivot; 1.338 +} 1.339 + 1.340 +void anm_get_node_matrix(struct anm_node *node, mat4_t mat, anm_time_t tm) 1.341 +{ 1.342 + int i; 1.343 + mat4_t rmat; 1.344 + vec3_t pos, scale; 1.345 + quat_t rot; 1.346 + 1.347 + pos = anm_get_node_position(node, tm); 1.348 + rot = anm_get_node_rotation(node, tm); 1.349 + scale = anm_get_node_scaling(node, tm); 1.350 + 1.351 + m4_set_translation(mat, node->pivot.x, node->pivot.y, node->pivot.z); 1.352 + 1.353 + quat_to_mat4(rmat, rot); 1.354 + for(i=0; i<3; i++) { 1.355 + mat[i][0] = rmat[i][0]; 1.356 + mat[i][1] = rmat[i][1]; 1.357 + mat[i][2] = rmat[i][2]; 1.358 + } 1.359 + /* this loop is equivalent to: m4_mult(mat, mat, rmat); */ 1.360 + 1.361 + mat[0][0] *= scale.x; mat[0][1] *= scale.y; mat[0][2] *= scale.z; mat[0][3] += pos.x; 1.362 + mat[1][0] *= scale.x; mat[1][1] *= scale.y; mat[1][2] *= scale.z; mat[1][3] += pos.y; 1.363 + mat[2][0] *= scale.x; mat[2][1] *= scale.y; mat[2][2] *= scale.z; mat[2][3] += pos.z; 1.364 + 1.365 + m4_translate(mat, -node->pivot.x, -node->pivot.y, -node->pivot.z); 1.366 + 1.367 + /* that's basically: pivot * rotation * translation * scaling * -pivot */ 1.368 +} 1.369 + 1.370 +void anm_get_node_inv_matrix(struct anm_node *node, mat4_t mat, anm_time_t tm) 1.371 +{ 1.372 + mat4_t tmp; 1.373 + anm_get_node_matrix(node, tmp, tm); 1.374 + m4_inverse(mat, tmp); 1.375 +} 1.376 + 1.377 +void anm_get_matrix(struct anm_node *node, mat4_t mat, anm_time_t tm) 1.378 +{ 1.379 + if(node->cache.time != tm) { 1.380 + anm_get_node_matrix(node, node->cache.matrix, tm); 1.381 + 1.382 + if(node->parent) { 1.383 + mat4_t parent_mat; 1.384 + 1.385 + anm_get_matrix(node->parent, parent_mat, tm); 1.386 + m4_mult(node->cache.matrix, parent_mat, node->cache.matrix); 1.387 + } 1.388 + node->cache.time = tm; 1.389 + } 1.390 + m4_copy(mat, node->cache.matrix); 1.391 +} 1.392 + 1.393 +void anm_get_inv_matrix(struct anm_node *node, mat4_t mat, anm_time_t tm) 1.394 +{ 1.395 + if(node->cache.inv_time != tm) { 1.396 + anm_get_matrix(node, mat, tm); 1.397 + m4_inverse(node->cache.inv_matrix, mat); 1.398 + node->cache.inv_time = tm; 1.399 + } 1.400 + m4_copy(mat, node->cache.inv_matrix); 1.401 +} 1.402 + 1.403 +anm_time_t anm_get_start_time(struct anm_node *node) 1.404 +{ 1.405 + int i; 1.406 + struct anm_node *c; 1.407 + anm_time_t res = LONG_MAX; 1.408 + 1.409 + for(i=0; i<ANM_NUM_TRACKS; i++) { 1.410 + if(node->tracks[i].count) { 1.411 + anm_time_t tm = node->tracks[i].keys[0].time; 1.412 + if(tm < res) { 1.413 + res = tm; 1.414 + } 1.415 + } 1.416 + } 1.417 + 1.418 + c = node->child; 1.419 + while(c) { 1.420 + anm_time_t tm = anm_get_start_time(c); 1.421 + if(tm < res) { 1.422 + res = tm; 1.423 + } 1.424 + c = c->next; 1.425 + } 1.426 + return res; 1.427 +} 1.428 + 1.429 +anm_time_t anm_get_end_time(struct anm_node *node) 1.430 +{ 1.431 + int i; 1.432 + struct anm_node *c; 1.433 + anm_time_t res = LONG_MIN; 1.434 + 1.435 + for(i=0; i<ANM_NUM_TRACKS; i++) { 1.436 + if(node->tracks[i].count) { 1.437 + anm_time_t tm = node->tracks[i].keys[node->tracks[i].count - 1].time; 1.438 + if(tm > res) { 1.439 + res = tm; 1.440 + } 1.441 + } 1.442 + } 1.443 + 1.444 + c = node->child; 1.445 + while(c) { 1.446 + anm_time_t tm = anm_get_end_time(c); 1.447 + if(tm > res) { 1.448 + res = tm; 1.449 + } 1.450 + c = c->next; 1.451 + } 1.452 + return res; 1.453 +} 1.454 + 1.455 +static void invalidate_cache(struct anm_node *node) 1.456 +{ 1.457 + node->cache.time = node->cache.inv_time = ANM_TIME_INVAL; 1.458 +}