dungeon_crawler
diff prototype/anim/anim.c @ 67:2560a7ab0243
internalized libanim, libimago2, and libpsys
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Sun, 07 Oct 2012 02:04:00 +0300 |
parents | |
children |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/prototype/anim/anim.c Sun Oct 07 02:04:00 2012 +0300 1.3 @@ -0,0 +1,394 @@ 1.4 +#include <limits.h> 1.5 +#include <assert.h> 1.6 +#include "anim.h" 1.7 +#include "dynarr.h" 1.8 + 1.9 +int anm_init_node(struct anm_node *node) 1.10 +{ 1.11 + int i, j; 1.12 + static const float defaults[] = { 1.13 + 0.0f, 0.0f, 0.0f, /* default position */ 1.14 + 0.0f, 0.0f, 0.0f, 1.0f, /* default rotation quat */ 1.15 + 1.0f, 1.0f, 1.0f /* default scale factor */ 1.16 + }; 1.17 + 1.18 + memset(node, 0, sizeof *node); 1.19 + 1.20 + for(i=0; i<ANM_NUM_TRACKS; i++) { 1.21 + if(anm_init_track(node->tracks + i) == -1) { 1.22 + for(j=0; j<i; j++) { 1.23 + anm_destroy_track(node->tracks + i); 1.24 + } 1.25 + } 1.26 + anm_set_track_default(node->tracks + i, defaults[i]); 1.27 + } 1.28 + return 0; 1.29 +} 1.30 + 1.31 +void anm_destroy_node(struct anm_node *node) 1.32 +{ 1.33 + int i; 1.34 + free(node->name); 1.35 + 1.36 + for(i=0; i<ANM_NUM_TRACKS; i++) { 1.37 + anm_destroy_track(node->tracks + i); 1.38 + } 1.39 +} 1.40 + 1.41 +void anm_destroy_node_tree(struct anm_node *tree) 1.42 +{ 1.43 + struct anm_node *c, *tmp; 1.44 + 1.45 + if(!tree) return; 1.46 + 1.47 + c = tree->child; 1.48 + while(c) { 1.49 + tmp = c; 1.50 + c = c->next; 1.51 + 1.52 + anm_destroy_node_tree(tmp); 1.53 + } 1.54 + anm_destroy_node(tree); 1.55 +} 1.56 + 1.57 +struct anm_node *anm_create_node(void) 1.58 +{ 1.59 + struct anm_node *n; 1.60 + 1.61 + if((n = malloc(sizeof *n))) { 1.62 + if(anm_init_node(n) == -1) { 1.63 + free(n); 1.64 + return 0; 1.65 + } 1.66 + } 1.67 + return n; 1.68 +} 1.69 + 1.70 +void anm_free_node(struct anm_node *node) 1.71 +{ 1.72 + anm_destroy_node(node); 1.73 + free(node); 1.74 +} 1.75 + 1.76 +void anm_free_node_tree(struct anm_node *tree) 1.77 +{ 1.78 + struct anm_node *c, *tmp; 1.79 + 1.80 + if(!tree) return; 1.81 + 1.82 + c = tree->child; 1.83 + while(c) { 1.84 + tmp = c; 1.85 + c = c->next; 1.86 + 1.87 + anm_free_node_tree(tmp); 1.88 + } 1.89 + 1.90 + anm_free_node(tree); 1.91 +} 1.92 + 1.93 +int anm_set_node_name(struct anm_node *node, const char *name) 1.94 +{ 1.95 + char *str; 1.96 + 1.97 + if(!(str = malloc(strlen(name) + 1))) { 1.98 + return -1; 1.99 + } 1.100 + strcpy(str, name); 1.101 + free(node->name); 1.102 + node->name = str; 1.103 + return 0; 1.104 +} 1.105 + 1.106 +const char *anm_get_node_name(struct anm_node *node) 1.107 +{ 1.108 + return node->name ? node->name : ""; 1.109 +} 1.110 + 1.111 +void anm_set_interpolator(struct anm_node *node, enum anm_interpolator in) 1.112 +{ 1.113 + int i; 1.114 + 1.115 + for(i=0; i<ANM_NUM_TRACKS; i++) { 1.116 + anm_set_track_interpolator(node->tracks + i, in); 1.117 + } 1.118 +} 1.119 + 1.120 +void anm_set_extrapolator(struct anm_node *node, enum anm_extrapolator ex) 1.121 +{ 1.122 + int i; 1.123 + 1.124 + for(i=0; i<ANM_NUM_TRACKS; i++) { 1.125 + anm_set_track_extrapolator(node->tracks + i, ex); 1.126 + } 1.127 +} 1.128 + 1.129 +void anm_link_node(struct anm_node *p, struct anm_node *c) 1.130 +{ 1.131 + c->next = p->child; 1.132 + p->child = c; 1.133 + 1.134 + c->parent = p; 1.135 +} 1.136 + 1.137 +int anm_unlink_node(struct anm_node *p, struct anm_node *c) 1.138 +{ 1.139 + struct anm_node *iter; 1.140 + 1.141 + if(p->child == c) { 1.142 + p->child = c->next; 1.143 + c->next = 0; 1.144 + return 0; 1.145 + } 1.146 + 1.147 + iter = p->child; 1.148 + while(iter->next) { 1.149 + if(iter->next == c) { 1.150 + iter->next = c->next; 1.151 + c->next = 0; 1.152 + return 0; 1.153 + } 1.154 + } 1.155 + return -1; 1.156 +} 1.157 + 1.158 +void anm_set_position(struct anm_node *node, vec3_t pos, anm_time_t tm) 1.159 +{ 1.160 + anm_set_value(node->tracks + ANM_TRACK_POS_X, tm, pos.x); 1.161 + anm_set_value(node->tracks + ANM_TRACK_POS_Y, tm, pos.y); 1.162 + anm_set_value(node->tracks + ANM_TRACK_POS_Z, tm, pos.z); 1.163 +} 1.164 + 1.165 +vec3_t anm_get_node_position(struct anm_node *node, anm_time_t tm) 1.166 +{ 1.167 + vec3_t v; 1.168 + v.x = anm_get_value(node->tracks + ANM_TRACK_POS_X, tm); 1.169 + v.y = anm_get_value(node->tracks + ANM_TRACK_POS_Y, tm); 1.170 + v.z = anm_get_value(node->tracks + ANM_TRACK_POS_Z, tm); 1.171 + return v; 1.172 +} 1.173 + 1.174 +void anm_set_rotation(struct anm_node *node, quat_t rot, anm_time_t tm) 1.175 +{ 1.176 + anm_set_value(node->tracks + ANM_TRACK_ROT_X, tm, rot.x); 1.177 + anm_set_value(node->tracks + ANM_TRACK_ROT_Y, tm, rot.y); 1.178 + anm_set_value(node->tracks + ANM_TRACK_ROT_Z, tm, rot.z); 1.179 + anm_set_value(node->tracks + ANM_TRACK_ROT_W, tm, rot.w); 1.180 +} 1.181 + 1.182 +quat_t anm_get_node_rotation(struct anm_node *node, anm_time_t tm) 1.183 +{ 1.184 + int idx0, idx1, last_idx; 1.185 + anm_time_t tstart, tend; 1.186 + float t, dt; 1.187 + struct anm_track *track_x, *track_y, *track_z, *track_w; 1.188 + quat_t q, q1, q2; 1.189 + 1.190 + track_x = node->tracks + ANM_TRACK_ROT_X; 1.191 + track_y = node->tracks + ANM_TRACK_ROT_Y; 1.192 + track_z = node->tracks + ANM_TRACK_ROT_Z; 1.193 + track_w = node->tracks + ANM_TRACK_ROT_W; 1.194 + 1.195 + if(!track_x->count) { 1.196 + q.x = track_x->def_val; 1.197 + q.y = track_y->def_val; 1.198 + q.z = track_z->def_val; 1.199 + q.w = track_w->def_val; 1.200 + return q; 1.201 + } 1.202 + 1.203 + last_idx = track_x->count - 1; 1.204 + 1.205 + tstart = track_x->keys[0].time; 1.206 + tend = track_x->keys[last_idx].time; 1.207 + tm = anm_remap_time(track_x, tm, tstart, tend); 1.208 + 1.209 + idx0 = anm_get_key_interval(track_x, tm); 1.210 + assert(idx0 >= 0 && idx0 < track_x->count); 1.211 + idx1 = idx0 + 1; 1.212 + 1.213 + dt = (float)(track_x->keys[idx1].time - track_x->keys[idx0].time); 1.214 + t = (float)(tm - track_x->keys[idx0].time) / dt; 1.215 + 1.216 + q1.x = track_x->keys[idx0].val; 1.217 + q1.y = track_y->keys[idx0].val; 1.218 + q1.z = track_z->keys[idx0].val; 1.219 + q1.w = track_w->keys[idx0].val; 1.220 + 1.221 + q2.x = track_x->keys[idx1].val; 1.222 + q2.y = track_y->keys[idx1].val; 1.223 + q2.z = track_z->keys[idx1].val; 1.224 + q2.w = track_w->keys[idx1].val; 1.225 + 1.226 + return quat_slerp(q1, q2, t); 1.227 +} 1.228 + 1.229 +void anm_set_scaling(struct anm_node *node, vec3_t scl, anm_time_t tm) 1.230 +{ 1.231 + anm_set_value(node->tracks + ANM_TRACK_SCL_X, tm, scl.x); 1.232 + anm_set_value(node->tracks + ANM_TRACK_SCL_Y, tm, scl.y); 1.233 + anm_set_value(node->tracks + ANM_TRACK_SCL_Z, tm, scl.z); 1.234 +} 1.235 + 1.236 +vec3_t anm_get_node_scaling(struct anm_node *node, anm_time_t tm) 1.237 +{ 1.238 + vec3_t v; 1.239 + v.x = anm_get_value(node->tracks + ANM_TRACK_SCL_X, tm); 1.240 + v.y = anm_get_value(node->tracks + ANM_TRACK_SCL_Y, tm); 1.241 + v.z = anm_get_value(node->tracks + ANM_TRACK_SCL_Z, tm); 1.242 + return v; 1.243 +} 1.244 + 1.245 + 1.246 +vec3_t anm_get_position(struct anm_node *node, anm_time_t tm) 1.247 +{ 1.248 + mat4_t xform; 1.249 + vec3_t pos = {0.0, 0.0, 0.0}; 1.250 + 1.251 + if(!node->parent) { 1.252 + return anm_get_node_position(node, tm); 1.253 + } 1.254 + 1.255 + anm_get_matrix(node, xform, tm); 1.256 + return v3_transform(pos, xform); 1.257 +} 1.258 + 1.259 +quat_t anm_get_rotation(struct anm_node *node, anm_time_t tm) 1.260 +{ 1.261 + quat_t rot, prot; 1.262 + rot = anm_get_node_rotation(node, tm); 1.263 + 1.264 + if(!node->parent) { 1.265 + return rot; 1.266 + } 1.267 + 1.268 + prot = anm_get_rotation(node->parent, tm); 1.269 + return quat_mul(prot, rot); 1.270 +} 1.271 + 1.272 +vec3_t anm_get_scaling(struct anm_node *node, anm_time_t tm) 1.273 +{ 1.274 + vec3_t s, ps; 1.275 + s = anm_get_node_scaling(node, tm); 1.276 + 1.277 + if(!node->parent) { 1.278 + return s; 1.279 + } 1.280 + 1.281 + ps = anm_get_scaling(node->parent, tm); 1.282 + return v3_mul(s, ps); 1.283 +} 1.284 + 1.285 +void anm_set_pivot(struct anm_node *node, vec3_t piv) 1.286 +{ 1.287 + node->pivot = piv; 1.288 +} 1.289 + 1.290 +vec3_t anm_get_pivot(struct anm_node *node) 1.291 +{ 1.292 + return node->pivot; 1.293 +} 1.294 + 1.295 +void anm_get_matrix(struct anm_node *node, mat4_t mat, anm_time_t tm) 1.296 +{ 1.297 +#ifdef ANIM_THREAD_SAFE 1.298 + /* XXX we're holding the mutex for way too anm_time_t... but it looks like the 1.299 + * alternative would be to lock/unlock twice which might be worse. 1.300 + */ 1.301 + pthread_mutex_lock(node->cache_mutex); 1.302 +#endif 1.303 + 1.304 + if(node->cache_time != tm) { 1.305 + mat4_t tmat, rmat, smat, pivmat, neg_pivmat; 1.306 + vec3_t pos, scale; 1.307 + quat_t rot; 1.308 + 1.309 + m4_identity(tmat); 1.310 + /*no need to m4_identity(rmat); quat_to_mat4 sets this properly */ 1.311 + m4_identity(smat); 1.312 + m4_identity(pivmat); 1.313 + m4_identity(neg_pivmat); 1.314 + 1.315 + pos = anm_get_node_position(node, tm); 1.316 + rot = anm_get_node_rotation(node, tm); 1.317 + scale = anm_get_node_scaling(node, tm); 1.318 + 1.319 + m4_translate(pivmat, node->pivot.x, node->pivot.y, node->pivot.z); 1.320 + m4_translate(neg_pivmat, -node->pivot.x, -node->pivot.y, -node->pivot.z); 1.321 + 1.322 + m4_translate(tmat, pos.x, pos.y, pos.z); 1.323 + quat_to_mat4(rmat, rot); 1.324 + m4_translate(smat, scale.x, scale.y, scale.z); 1.325 + 1.326 + /* ok this would look nicer in C++ */ 1.327 + m4_mult(node->cache_matrix, pivmat, tmat); 1.328 + m4_mult(node->cache_matrix, node->cache_matrix, rmat); 1.329 + m4_mult(node->cache_matrix, node->cache_matrix, smat); 1.330 + m4_mult(node->cache_matrix, node->cache_matrix, neg_pivmat); 1.331 + 1.332 + if(node->parent) { 1.333 + mat4_t parent_mat; 1.334 + 1.335 + anm_get_matrix(node->parent, mat, tm); 1.336 + m4_mult(node->cache_matrix, parent_mat, node->cache_matrix); 1.337 + } 1.338 + node->cache_time = tm; 1.339 + } 1.340 + m4_copy(mat, node->cache_matrix); 1.341 + 1.342 +#ifdef ANIM_THREAD_SAFE 1.343 + pthread_mutex_unlock(node->cache_mutex); 1.344 +#endif 1.345 +} 1.346 + 1.347 +anm_time_t anm_get_start_time(struct anm_node *node) 1.348 +{ 1.349 + int i; 1.350 + struct anm_node *c; 1.351 + anm_time_t res = LONG_MAX; 1.352 + 1.353 + for(i=0; i<ANM_NUM_TRACKS; i++) { 1.354 + if(node->tracks[i].count) { 1.355 + anm_time_t tm = node->tracks[i].keys[0].time; 1.356 + if(tm < res) { 1.357 + res = tm; 1.358 + } 1.359 + } 1.360 + } 1.361 + 1.362 + c = node->child; 1.363 + while(c) { 1.364 + anm_time_t tm = anm_get_start_time(c); 1.365 + if(tm < res) { 1.366 + res = tm; 1.367 + } 1.368 + c = c->next; 1.369 + } 1.370 + return res; 1.371 +} 1.372 + 1.373 +anm_time_t anm_get_end_time(struct anm_node *node) 1.374 +{ 1.375 + int i; 1.376 + struct anm_node *c; 1.377 + anm_time_t res = LONG_MIN; 1.378 + 1.379 + for(i=0; i<ANM_NUM_TRACKS; i++) { 1.380 + if(node->tracks[i].count) { 1.381 + anm_time_t tm = node->tracks[i].keys[node->tracks[i].count - 1].time; 1.382 + if(tm > res) { 1.383 + res = tm; 1.384 + } 1.385 + } 1.386 + } 1.387 + 1.388 + c = node->child; 1.389 + while(c) { 1.390 + anm_time_t tm = anm_get_end_time(c); 1.391 + if(tm > res) { 1.392 + res = tm; 1.393 + } 1.394 + c = c->next; 1.395 + } 1.396 + return res; 1.397 +}