libanim
changeset 21:5993f405a1cb
implemented multiple animations per node, and blending between two animations
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Fri, 27 Dec 2013 06:28:43 +0200 |
parents | 3c2428cb38f7 |
children | 9758004136f8 |
files | example/test.c src/anim.c src/anim.h |
diffstat | 3 files changed, 511 insertions(+), 90 deletions(-) [+] |
line diff
1.1 --- a/example/test.c Mon Dec 09 04:06:30 2013 +0200 1.2 +++ b/example/test.c Fri Dec 27 06:28:43 2013 +0200 1.3 @@ -48,6 +48,8 @@ 1.4 }; 1.5 1.6 int init(void); 1.7 +static void set_walk_animation(int idx); 1.8 +static void set_jump_animation(int idx); 1.9 void disp(void); 1.10 void idle(void); 1.11 void reshape(int x, int y); 1.12 @@ -60,6 +62,9 @@ 1.13 1.14 struct anm_node *nodes[NUM_NODES]; 1.15 1.16 +int cur_anim = 0, next_anim = 0; 1.17 +unsigned int trans_start_tm; 1.18 + 1.19 int main(int argc, char **argv) 1.20 { 1.21 glutInitWindowSize(800, 600); 1.22 @@ -92,15 +97,11 @@ 1.23 glEnable(GL_LIGHTING); 1.24 glEnable(GL_LIGHT0); 1.25 1.26 - root = nodes[0]; 1.27 - 1.28 for(i=0; i<NUM_NODES; i++) { 1.29 nodes[i] = anm_create_node(); 1.30 - 1.31 anm_set_pivot(nodes[i], parts[i].pivot); 1.32 - anm_set_position(nodes[i], parts[i].pos, 0); 1.33 - anm_set_extrapolator(nodes[i], ANM_EXTRAP_REPEAT); 1.34 } 1.35 + root = nodes[0]; 1.36 1.37 anm_link_node(nodes[NODE_TORSO], nodes[NODE_HEAD]); 1.38 anm_link_node(nodes[NODE_TORSO], nodes[NODE_LEFT_UPPER_LEG]); 1.39 @@ -112,6 +113,27 @@ 1.40 anm_link_node(nodes[NODE_LEFT_UPPER_ARM], nodes[NODE_LEFT_LOWER_ARM]); 1.41 anm_link_node(nodes[NODE_RIGHT_UPPER_ARM], nodes[NODE_RIGHT_LOWER_ARM]); 1.42 1.43 + set_walk_animation(0); 1.44 + 1.45 + anm_add_animation(root); /* recursively add another animation slot to all nodes */ 1.46 + set_jump_animation(1); 1.47 + 1.48 + anm_use_animation(root, cur_anim); 1.49 + 1.50 + return 0; 1.51 +} 1.52 + 1.53 +static void set_walk_animation(int idx) 1.54 +{ 1.55 + int i; 1.56 + 1.57 + anm_use_animation(root, idx); 1.58 + 1.59 + for(i=0; i<NUM_NODES; i++) { 1.60 + anm_set_position(nodes[i], parts[i].pos, 0); 1.61 + anm_set_extrapolator(nodes[i], ANM_EXTRAP_REPEAT); 1.62 + } 1.63 + 1.64 /* upper leg animation */ 1.65 anm_set_rotation(nodes[NODE_LEFT_UPPER_LEG], quat_rotate(quat_identity(), DEG_TO_RAD(-15), 1, 0, 0), 0); 1.66 anm_set_rotation(nodes[NODE_LEFT_UPPER_LEG], quat_rotate(quat_identity(), DEG_TO_RAD(45), 1, 0, 0), 1000); 1.67 @@ -163,8 +185,53 @@ 1.68 anm_set_rotation(nodes[NODE_RIGHT_LOWER_ARM], quat_rotate(quat_identity(), DEG_TO_RAD(0), 1, 0, 0), 500); 1.69 anm_set_rotation(nodes[NODE_RIGHT_LOWER_ARM], quat_rotate(quat_identity(), DEG_TO_RAD(40), 1, 0, 0), 1000); 1.70 anm_set_rotation(nodes[NODE_RIGHT_LOWER_ARM], quat_rotate(quat_identity(), DEG_TO_RAD(0), 1, 0, 0), 2000); 1.71 +} 1.72 1.73 - return 0; 1.74 +static void set_jump_animation(int idx) 1.75 +{ 1.76 + int i; 1.77 + 1.78 + anm_use_animation(root, idx); 1.79 + 1.80 + for(i=0; i<NUM_NODES; i++) { 1.81 + anm_set_position(nodes[i], parts[i].pos, 0); 1.82 + anm_set_extrapolator(nodes[i], ANM_EXTRAP_REPEAT); 1.83 + } 1.84 + 1.85 + anm_set_rotation(nodes[NODE_LEFT_UPPER_LEG], quat_rotate(quat_identity(), DEG_TO_RAD(0), 1, 0, 0), 0); 1.86 + anm_set_rotation(nodes[NODE_LEFT_UPPER_LEG], quat_rotate(quat_identity(), DEG_TO_RAD(40), 1, 0, 0), 1000); 1.87 + anm_set_rotation(nodes[NODE_LEFT_UPPER_LEG], quat_rotate(quat_identity(), DEG_TO_RAD(0), 1, 0, 0), 1500); 1.88 + anm_set_rotation(nodes[NODE_LEFT_UPPER_LEG], quat_rotate(quat_identity(), DEG_TO_RAD(0), 1, 0, 0), 2000); 1.89 + anm_set_rotation(nodes[NODE_RIGHT_UPPER_LEG], quat_rotate(quat_identity(), DEG_TO_RAD(0), 1, 0, 0), 0); 1.90 + anm_set_rotation(nodes[NODE_RIGHT_UPPER_LEG], quat_rotate(quat_identity(), DEG_TO_RAD(40), 1, 0, 0), 1000); 1.91 + anm_set_rotation(nodes[NODE_RIGHT_UPPER_LEG], quat_rotate(quat_identity(), DEG_TO_RAD(0), 1, 0, 0), 1500); 1.92 + anm_set_rotation(nodes[NODE_RIGHT_UPPER_LEG], quat_rotate(quat_identity(), DEG_TO_RAD(0), 1, 0, 0), 2000); 1.93 + 1.94 + anm_set_rotation(nodes[NODE_LEFT_LOWER_LEG], quat_rotate(quat_identity(), DEG_TO_RAD(0), 1, 0, 0), 0); 1.95 + anm_set_rotation(nodes[NODE_LEFT_LOWER_LEG], quat_rotate(quat_identity(), DEG_TO_RAD(-80), 1, 0, 0), 1000); 1.96 + anm_set_rotation(nodes[NODE_LEFT_LOWER_LEG], quat_rotate(quat_identity(), DEG_TO_RAD(0), 1, 0, 0), 1500); 1.97 + anm_set_rotation(nodes[NODE_LEFT_LOWER_LEG], quat_rotate(quat_identity(), DEG_TO_RAD(0), 1, 0, 0), 2000); 1.98 + anm_set_rotation(nodes[NODE_RIGHT_LOWER_LEG], quat_rotate(quat_identity(), DEG_TO_RAD(0), 1, 0, 0), 0); 1.99 + anm_set_rotation(nodes[NODE_RIGHT_LOWER_LEG], quat_rotate(quat_identity(), DEG_TO_RAD(-80), 1, 0, 0), 1000); 1.100 + anm_set_rotation(nodes[NODE_RIGHT_LOWER_LEG], quat_rotate(quat_identity(), DEG_TO_RAD(0), 1, 0, 0), 1500); 1.101 + anm_set_rotation(nodes[NODE_RIGHT_LOWER_LEG], quat_rotate(quat_identity(), DEG_TO_RAD(0), 1, 0, 0), 2000); 1.102 + 1.103 + anm_set_position(nodes[NODE_TORSO], parts[NODE_TORSO].pos, 0); 1.104 + anm_set_position(nodes[NODE_TORSO], v3_add(parts[NODE_TORSO].pos, v3_cons(0, -1, 0)), 1000); 1.105 + anm_set_position(nodes[NODE_TORSO], v3_add(parts[NODE_TORSO].pos, v3_cons(0, 2, 0)), 1500); 1.106 + anm_set_position(nodes[NODE_TORSO], parts[NODE_TORSO].pos, 2000); 1.107 + 1.108 + anm_set_rotation(nodes[NODE_LEFT_UPPER_ARM], quat_rotate(quat_identity(), DEG_TO_RAD(0), 1, 0, 0), 0); 1.109 + anm_set_rotation(nodes[NODE_LEFT_UPPER_ARM], quat_rotate(quat_identity(), DEG_TO_RAD(-20), 1, 0, 0), 1000); 1.110 + anm_set_rotation(nodes[NODE_LEFT_UPPER_ARM], quat_rotate(quat_identity(), DEG_TO_RAD(20), 1, 0, 0), 1200); 1.111 + anm_set_rotation(nodes[NODE_LEFT_UPPER_ARM], quat_rotate(quat_identity(), DEG_TO_RAD(170), 1, 0, 0), 1500); 1.112 + anm_set_rotation(nodes[NODE_LEFT_UPPER_ARM], quat_rotate(quat_identity(), DEG_TO_RAD(0), 1, 0, 0), 2000); 1.113 + 1.114 + anm_set_rotation(nodes[NODE_RIGHT_UPPER_ARM], quat_rotate(quat_identity(), DEG_TO_RAD(0), 1, 0, 0), 0); 1.115 + anm_set_rotation(nodes[NODE_RIGHT_UPPER_ARM], quat_rotate(quat_identity(), DEG_TO_RAD(-20), 1, 0, 0), 1000); 1.116 + anm_set_rotation(nodes[NODE_RIGHT_UPPER_ARM], quat_rotate(quat_identity(), DEG_TO_RAD(20), 1, 0, 0), 1200); 1.117 + anm_set_rotation(nodes[NODE_RIGHT_UPPER_ARM], quat_rotate(quat_identity(), DEG_TO_RAD(170), 1, 0, 0), 1500); 1.118 + anm_set_rotation(nodes[NODE_RIGHT_UPPER_ARM], quat_rotate(quat_identity(), DEG_TO_RAD(0), 1, 0, 0), 2000); 1.119 } 1.120 1.121 void disp(void) 1.122 @@ -184,6 +251,18 @@ 1.123 glRotatef(cam_phi, 1, 0, 0); 1.124 glRotatef(cam_theta, 0, 1, 0); 1.125 1.126 + if(cur_anim != next_anim) { 1.127 + float t = (msec - trans_start_tm) / 1000.0; 1.128 + 1.129 + if(t >= 1.0) { 1.130 + t = 1.0; 1.131 + cur_anim = next_anim; 1.132 + anm_use_animation(root, cur_anim); 1.133 + } else { 1.134 + anm_use_animations(root, cur_anim, next_anim, t); 1.135 + } 1.136 + } 1.137 + 1.138 /* first render a character with bottom-up lazy matrix calculation */ 1.139 glPushMatrix(); 1.140 glTranslatef(-2.5, 0, 0); 1.141 @@ -264,6 +343,11 @@ 1.142 switch(key) { 1.143 case 27: 1.144 exit(0); 1.145 + 1.146 + case ' ': 1.147 + next_anim = (cur_anim + 1) % 2; 1.148 + trans_start_tm = glutGet(GLUT_ELAPSED_TIME); 1.149 + break; 1.150 } 1.151 } 1.152
2.1 --- a/src/anim.c Mon Dec 09 04:06:30 2013 +0200 2.2 +++ b/src/anim.c Fri Dec 27 06:28:43 2013 +0200 2.3 @@ -8,7 +8,7 @@ 2.4 2.5 static void invalidate_cache(struct anm_node *node); 2.6 2.7 -int anm_init_node(struct anm_node *node) 2.8 +int anm_init_animation(struct anm_animation *anim) 2.9 { 2.10 int i, j; 2.11 static const float defaults[] = { 2.12 @@ -17,20 +17,49 @@ 2.13 1.0f, 1.0f, 1.0f /* default scale factor */ 2.14 }; 2.15 2.16 + anim->name = 0; 2.17 + 2.18 + for(i=0; i<ANM_NUM_TRACKS; i++) { 2.19 + if(anm_init_track(anim->tracks + i) == -1) { 2.20 + for(j=0; j<i; j++) { 2.21 + anm_destroy_track(anim->tracks + i); 2.22 + } 2.23 + } 2.24 + anm_set_track_default(anim->tracks + i, defaults[i]); 2.25 + } 2.26 + return 0; 2.27 +} 2.28 + 2.29 +void anm_destroy_animation(struct anm_animation *anim) 2.30 +{ 2.31 + int i; 2.32 + for(i=0; i<ANM_NUM_TRACKS; i++) { 2.33 + anm_destroy_track(anim->tracks + i); 2.34 + } 2.35 + free(anim->name); 2.36 +} 2.37 + 2.38 +/* ---- node implementation ----- */ 2.39 + 2.40 +int anm_init_node(struct anm_node *node) 2.41 +{ 2.42 memset(node, 0, sizeof *node); 2.43 2.44 + node->cur_anim[1] = -1; 2.45 + node->cur_mix = 0; 2.46 + 2.47 + if(!(node->animations = dynarr_alloc(1, sizeof *node->animations))) { 2.48 + return -1; 2.49 + } 2.50 + if(anm_init_animation(node->animations) == -1) { 2.51 + dynarr_free(node->animations); 2.52 + return -1; 2.53 + } 2.54 + 2.55 /* initialize thread-local matrix cache */ 2.56 pthread_key_create(&node->cache_key, 0); 2.57 pthread_mutex_init(&node->cache_list_lock, 0); 2.58 2.59 - for(i=0; i<ANM_NUM_TRACKS; i++) { 2.60 - if(anm_init_track(node->tracks + i) == -1) { 2.61 - for(j=0; j<i; j++) { 2.62 - anm_destroy_track(node->tracks + i); 2.63 - } 2.64 - } 2.65 - anm_set_track_default(node->tracks + i, defaults[i]); 2.66 - } 2.67 return 0; 2.68 } 2.69 2.70 @@ -40,8 +69,9 @@ 2.71 free(node->name); 2.72 2.73 for(i=0; i<ANM_NUM_TRACKS; i++) { 2.74 - anm_destroy_track(node->tracks + i); 2.75 + anm_destroy_animation(node->animations + i); 2.76 } 2.77 + dynarr_free(node->animations); 2.78 2.79 /* destroy thread-specific cache */ 2.80 pthread_key_delete(node->cache_key); 2.81 @@ -123,26 +153,6 @@ 2.82 return node->name ? node->name : ""; 2.83 } 2.84 2.85 -void anm_set_interpolator(struct anm_node *node, enum anm_interpolator in) 2.86 -{ 2.87 - int i; 2.88 - 2.89 - for(i=0; i<ANM_NUM_TRACKS; i++) { 2.90 - anm_set_track_interpolator(node->tracks + i, in); 2.91 - } 2.92 - invalidate_cache(node); 2.93 -} 2.94 - 2.95 -void anm_set_extrapolator(struct anm_node *node, enum anm_extrapolator ex) 2.96 -{ 2.97 - int i; 2.98 - 2.99 - for(i=0; i<ANM_NUM_TRACKS; i++) { 2.100 - anm_set_track_extrapolator(node->tracks + i, ex); 2.101 - } 2.102 - invalidate_cache(node); 2.103 -} 2.104 - 2.105 void anm_link_node(struct anm_node *p, struct anm_node *c) 2.106 { 2.107 c->next = p->child; 2.108 @@ -175,40 +185,284 @@ 2.109 return -1; 2.110 } 2.111 2.112 +void anm_set_pivot(struct anm_node *node, vec3_t piv) 2.113 +{ 2.114 + node->pivot = piv; 2.115 +} 2.116 + 2.117 +vec3_t anm_get_pivot(struct anm_node *node) 2.118 +{ 2.119 + return node->pivot; 2.120 +} 2.121 + 2.122 + 2.123 +/* animation management */ 2.124 + 2.125 +int anm_use_node_animation(struct anm_node *node, int aidx) 2.126 +{ 2.127 + if(aidx == node->cur_anim[0] && node->cur_anim[1] == -1) { 2.128 + return 0; /* no change, no invalidation */ 2.129 + } 2.130 + 2.131 + if(aidx < 0 || aidx >= anm_get_animation_count(node)) { 2.132 + return -1; 2.133 + } 2.134 + 2.135 + node->cur_anim[0] = aidx; 2.136 + node->cur_anim[1] = -1; 2.137 + node->cur_mix = 0; 2.138 + 2.139 + invalidate_cache(node); 2.140 + return 0; 2.141 +} 2.142 + 2.143 +int anm_use_node_animations(struct anm_node *node, int aidx, int bidx, float t) 2.144 +{ 2.145 + int num_anim; 2.146 + 2.147 + if(node->cur_anim[0] == aidx && node->cur_anim[1] == bidx && 2.148 + fabs(t - node->cur_mix) < 1e-6) { 2.149 + return 0; /* no change, no invalidation */ 2.150 + } 2.151 + 2.152 + num_anim = anm_get_animation_count(node); 2.153 + if(aidx < 0 || aidx >= num_anim) { 2.154 + return anm_use_animation(node, bidx); 2.155 + } 2.156 + if(bidx < 0 || bidx >= num_anim) { 2.157 + return anm_use_animation(node, aidx); 2.158 + } 2.159 + node->cur_anim[0] = aidx; 2.160 + node->cur_anim[1] = bidx; 2.161 + node->cur_mix = t; 2.162 + 2.163 + invalidate_cache(node); 2.164 + return 0; 2.165 +} 2.166 + 2.167 +int anm_use_animation(struct anm_node *node, int aidx) 2.168 +{ 2.169 + struct anm_node *child; 2.170 + 2.171 + if(anm_use_node_animation(node, aidx) == -1) { 2.172 + return -1; 2.173 + } 2.174 + 2.175 + child = node->child; 2.176 + while(child) { 2.177 + if(anm_use_animation(child, aidx) == -1) { 2.178 + return -1; 2.179 + } 2.180 + child = child->next; 2.181 + } 2.182 + return 0; 2.183 +} 2.184 + 2.185 +int anm_use_animations(struct anm_node *node, int aidx, int bidx, float t) 2.186 +{ 2.187 + struct anm_node *child; 2.188 + 2.189 + if(anm_use_node_animations(node, aidx, bidx, t) == -1) { 2.190 + return -1; 2.191 + } 2.192 + 2.193 + child = node->child; 2.194 + while(child) { 2.195 + if(anm_use_animations(child, aidx, bidx, t) == -1) { 2.196 + return -1; 2.197 + } 2.198 + child = child->next; 2.199 + } 2.200 + return 0; 2.201 + 2.202 +} 2.203 + 2.204 +int anm_get_active_animation_index(struct anm_node *node, int which) 2.205 +{ 2.206 + if(which < 0 || which >= 2) return -1; 2.207 + return node->cur_anim[which]; 2.208 +} 2.209 + 2.210 +struct anm_animation *anm_get_active_animation(struct anm_node *node, int which) 2.211 +{ 2.212 + int idx = anm_get_active_animation_index(node, which); 2.213 + if(idx < 0 || idx >= anm_get_animation_count(node)) { 2.214 + return 0; 2.215 + } 2.216 + return node->animations + idx; 2.217 +} 2.218 + 2.219 +float anm_get_active_animation_mix(struct anm_node *node) 2.220 +{ 2.221 + return node->cur_mix; 2.222 +} 2.223 + 2.224 +int anm_get_animation_count(struct anm_node *node) 2.225 +{ 2.226 + return dynarr_size(node->animations); 2.227 +} 2.228 + 2.229 +int anm_add_node_animation(struct anm_node *node) 2.230 +{ 2.231 + struct anm_animation newanim; 2.232 + anm_init_animation(&newanim); 2.233 + 2.234 + node->animations = dynarr_push(node->animations, &newanim); 2.235 + return 0; 2.236 +} 2.237 + 2.238 +int anm_remove_node_animation(struct anm_node *node, int idx) 2.239 +{ 2.240 + fprintf(stderr, "anm_remove_animation: unimplemented!"); 2.241 + abort(); 2.242 + return 0; 2.243 +} 2.244 + 2.245 +int anm_add_animation(struct anm_node *node) 2.246 +{ 2.247 + struct anm_node *child; 2.248 + 2.249 + if(anm_add_node_animation(node) == -1) { 2.250 + return -1; 2.251 + } 2.252 + 2.253 + child = node->child; 2.254 + while(child) { 2.255 + if(anm_add_animation(child)) { 2.256 + return -1; 2.257 + } 2.258 + child = child->next; 2.259 + } 2.260 + return 0; 2.261 +} 2.262 + 2.263 +int anm_remove_animation(struct anm_node *node, int idx) 2.264 +{ 2.265 + struct anm_node *child; 2.266 + 2.267 + if(anm_remove_node_animation(node, idx) == -1) { 2.268 + return -1; 2.269 + } 2.270 + 2.271 + child = node->child; 2.272 + while(child) { 2.273 + if(anm_remove_animation(child, idx) == -1) { 2.274 + return -1; 2.275 + } 2.276 + child = child->next; 2.277 + } 2.278 + return 0; 2.279 +} 2.280 + 2.281 +struct anm_animation *anm_get_animation(struct anm_node *node, int idx) 2.282 +{ 2.283 + if(idx < 0 || idx > anm_get_animation_count(node)) { 2.284 + return 0; 2.285 + } 2.286 + return node->animations + idx; 2.287 +} 2.288 + 2.289 +struct anm_animation *anm_get_animation_by_name(struct anm_node *node, const char *name) 2.290 +{ 2.291 + return anm_get_animation(node, anm_find_animation(node, name)); 2.292 +} 2.293 + 2.294 +int anm_find_animation(struct anm_node *node, const char *name) 2.295 +{ 2.296 + int i, count = anm_get_animation_count(node); 2.297 + for(i=0; i<count; i++) { 2.298 + if(strcmp(node->animations[i].name, name) == 0) { 2.299 + return i; 2.300 + } 2.301 + } 2.302 + return -1; 2.303 +} 2.304 + 2.305 +/* all the rest act on the current animation(s) */ 2.306 + 2.307 +void anm_set_interpolator(struct anm_node *node, enum anm_interpolator in) 2.308 +{ 2.309 + int i; 2.310 + struct anm_animation *anim = anm_get_active_animation(node, 0); 2.311 + if(!anim) return; 2.312 + 2.313 + for(i=0; i<ANM_NUM_TRACKS; i++) { 2.314 + anm_set_track_interpolator(anim->tracks + i, in); 2.315 + } 2.316 + invalidate_cache(node); 2.317 +} 2.318 + 2.319 +void anm_set_extrapolator(struct anm_node *node, enum anm_extrapolator ex) 2.320 +{ 2.321 + int i; 2.322 + struct anm_animation *anim = anm_get_active_animation(node, 0); 2.323 + if(!anim) return; 2.324 + 2.325 + for(i=0; i<ANM_NUM_TRACKS; i++) { 2.326 + anm_set_track_extrapolator(anim->tracks + i, ex); 2.327 + } 2.328 + invalidate_cache(node); 2.329 +} 2.330 + 2.331 void anm_set_position(struct anm_node *node, vec3_t pos, anm_time_t tm) 2.332 { 2.333 - anm_set_value(node->tracks + ANM_TRACK_POS_X, tm, pos.x); 2.334 - anm_set_value(node->tracks + ANM_TRACK_POS_Y, tm, pos.y); 2.335 - anm_set_value(node->tracks + ANM_TRACK_POS_Z, tm, pos.z); 2.336 + struct anm_animation *anim = anm_get_active_animation(node, 0); 2.337 + if(!anim) return; 2.338 + 2.339 + anm_set_value(anim->tracks + ANM_TRACK_POS_X, tm, pos.x); 2.340 + anm_set_value(anim->tracks + ANM_TRACK_POS_Y, tm, pos.y); 2.341 + anm_set_value(anim->tracks + ANM_TRACK_POS_Z, tm, pos.z); 2.342 invalidate_cache(node); 2.343 } 2.344 2.345 vec3_t anm_get_node_position(struct anm_node *node, anm_time_t tm) 2.346 { 2.347 vec3_t v; 2.348 - v.x = anm_get_value(node->tracks + ANM_TRACK_POS_X, tm); 2.349 - v.y = anm_get_value(node->tracks + ANM_TRACK_POS_Y, tm); 2.350 - v.z = anm_get_value(node->tracks + ANM_TRACK_POS_Z, tm); 2.351 + struct anm_animation *anim0 = anm_get_active_animation(node, 0); 2.352 + struct anm_animation *anim1 = anm_get_active_animation(node, 1); 2.353 + 2.354 + if(!anim0) { 2.355 + return v3_cons(0, 0, 0); 2.356 + } 2.357 + 2.358 + v.x = anm_get_value(anim0->tracks + ANM_TRACK_POS_X, tm); 2.359 + v.y = anm_get_value(anim0->tracks + ANM_TRACK_POS_Y, tm); 2.360 + v.z = anm_get_value(anim0->tracks + ANM_TRACK_POS_Z, tm); 2.361 + 2.362 + if(anim1) { 2.363 + vec3_t v1; 2.364 + v1.x = anm_get_value(anim1->tracks + ANM_TRACK_POS_X, tm); 2.365 + v1.y = anm_get_value(anim1->tracks + ANM_TRACK_POS_Y, tm); 2.366 + v1.z = anm_get_value(anim1->tracks + ANM_TRACK_POS_Z, tm); 2.367 + 2.368 + v.x = v.x + (v1.x - v.x) * node->cur_mix; 2.369 + v.y = v.y + (v1.y - v.y) * node->cur_mix; 2.370 + v.z = v.z + (v1.z - v.z) * node->cur_mix; 2.371 + } 2.372 + 2.373 return v; 2.374 } 2.375 2.376 void anm_set_rotation(struct anm_node *node, quat_t rot, anm_time_t tm) 2.377 { 2.378 - anm_set_value(node->tracks + ANM_TRACK_ROT_X, tm, rot.x); 2.379 - anm_set_value(node->tracks + ANM_TRACK_ROT_Y, tm, rot.y); 2.380 - anm_set_value(node->tracks + ANM_TRACK_ROT_Z, tm, rot.z); 2.381 - anm_set_value(node->tracks + ANM_TRACK_ROT_W, tm, rot.w); 2.382 + struct anm_animation *anim = anm_get_active_animation(node, 0); 2.383 + if(!anim) return; 2.384 + 2.385 + anm_set_value(anim->tracks + ANM_TRACK_ROT_X, tm, rot.x); 2.386 + anm_set_value(anim->tracks + ANM_TRACK_ROT_Y, tm, rot.y); 2.387 + anm_set_value(anim->tracks + ANM_TRACK_ROT_Z, tm, rot.z); 2.388 + anm_set_value(anim->tracks + ANM_TRACK_ROT_W, tm, rot.w); 2.389 invalidate_cache(node); 2.390 } 2.391 2.392 -quat_t anm_get_node_rotation(struct anm_node *node, anm_time_t tm) 2.393 +static quat_t get_node_rotation(struct anm_node *node, anm_time_t tm, struct anm_animation *anim) 2.394 { 2.395 #ifndef ROT_USE_SLERP 2.396 quat_t q; 2.397 - q.x = anm_get_value(node->tracks + ANM_TRACK_ROT_X, tm); 2.398 - q.y = anm_get_value(node->tracks + ANM_TRACK_ROT_Y, tm); 2.399 - q.z = anm_get_value(node->tracks + ANM_TRACK_ROT_Z, tm); 2.400 - q.w = anm_get_value(node->tracks + ANM_TRACK_ROT_W, tm); 2.401 + q.x = anm_get_value(anim->tracks + ANM_TRACK_ROT_X, tm); 2.402 + q.y = anm_get_value(anim->tracks + ANM_TRACK_ROT_Y, tm); 2.403 + q.z = anm_get_value(anim->tracks + ANM_TRACK_ROT_Z, tm); 2.404 + q.w = anm_get_value(anim->tracks + ANM_TRACK_ROT_W, tm); 2.405 return q; 2.406 #else 2.407 int idx0, idx1, last_idx; 2.408 @@ -217,10 +471,10 @@ 2.409 struct anm_track *track_x, *track_y, *track_z, *track_w; 2.410 quat_t q, q1, q2; 2.411 2.412 - track_x = node->tracks + ANM_TRACK_ROT_X; 2.413 - track_y = node->tracks + ANM_TRACK_ROT_Y; 2.414 - track_z = node->tracks + ANM_TRACK_ROT_Z; 2.415 - track_w = node->tracks + ANM_TRACK_ROT_W; 2.416 + track_x = anim->tracks + ANM_TRACK_ROT_X; 2.417 + track_y = anim->tracks + ANM_TRACK_ROT_Y; 2.418 + track_z = anim->tracks + ANM_TRACK_ROT_Z; 2.419 + track_w = anim->tracks + ANM_TRACK_ROT_W; 2.420 2.421 if(!track_x->count) { 2.422 q.x = track_x->def_val; 2.423 @@ -277,20 +531,62 @@ 2.424 #endif 2.425 } 2.426 2.427 +quat_t anm_get_node_rotation(struct anm_node *node, anm_time_t tm) 2.428 +{ 2.429 + quat_t q; 2.430 + struct anm_animation *anim0 = anm_get_active_animation(node, 0); 2.431 + struct anm_animation *anim1 = anm_get_active_animation(node, 1); 2.432 + 2.433 + if(!anim0) { 2.434 + return quat_identity(); 2.435 + } 2.436 + 2.437 + q = get_node_rotation(node, tm, anim0); 2.438 + 2.439 + if(anim1) { 2.440 + quat_t q1 = get_node_rotation(node, tm, anim1); 2.441 + 2.442 + q = quat_slerp(q, q1, node->cur_mix); 2.443 + } 2.444 + return q; 2.445 +} 2.446 + 2.447 void anm_set_scaling(struct anm_node *node, vec3_t scl, anm_time_t tm) 2.448 { 2.449 - anm_set_value(node->tracks + ANM_TRACK_SCL_X, tm, scl.x); 2.450 - anm_set_value(node->tracks + ANM_TRACK_SCL_Y, tm, scl.y); 2.451 - anm_set_value(node->tracks + ANM_TRACK_SCL_Z, tm, scl.z); 2.452 + struct anm_animation *anim = anm_get_active_animation(node, 0); 2.453 + if(!anim) return; 2.454 + 2.455 + anm_set_value(anim->tracks + ANM_TRACK_SCL_X, tm, scl.x); 2.456 + anm_set_value(anim->tracks + ANM_TRACK_SCL_Y, tm, scl.y); 2.457 + anm_set_value(anim->tracks + ANM_TRACK_SCL_Z, tm, scl.z); 2.458 invalidate_cache(node); 2.459 } 2.460 2.461 vec3_t anm_get_node_scaling(struct anm_node *node, anm_time_t tm) 2.462 { 2.463 vec3_t v; 2.464 - v.x = anm_get_value(node->tracks + ANM_TRACK_SCL_X, tm); 2.465 - v.y = anm_get_value(node->tracks + ANM_TRACK_SCL_Y, tm); 2.466 - v.z = anm_get_value(node->tracks + ANM_TRACK_SCL_Z, tm); 2.467 + struct anm_animation *anim0 = anm_get_active_animation(node, 0); 2.468 + struct anm_animation *anim1 = anm_get_active_animation(node, 1); 2.469 + 2.470 + if(!anim0) { 2.471 + return v3_cons(1, 1, 1); 2.472 + } 2.473 + 2.474 + v.x = anm_get_value(anim0->tracks + ANM_TRACK_SCL_X, tm); 2.475 + v.y = anm_get_value(anim0->tracks + ANM_TRACK_SCL_Y, tm); 2.476 + v.z = anm_get_value(anim0->tracks + ANM_TRACK_SCL_Z, tm); 2.477 + 2.478 + if(anim1) { 2.479 + vec3_t v1; 2.480 + v1.x = anm_get_value(anim1->tracks + ANM_TRACK_SCL_X, tm); 2.481 + v1.y = anm_get_value(anim1->tracks + ANM_TRACK_SCL_Y, tm); 2.482 + v1.z = anm_get_value(anim1->tracks + ANM_TRACK_SCL_Z, tm); 2.483 + 2.484 + v.x = v.x + (v1.x - v.x) * node->cur_mix; 2.485 + v.y = v.y + (v1.y - v.y) * node->cur_mix; 2.486 + v.z = v.z + (v1.z - v.z) * node->cur_mix; 2.487 + } 2.488 + 2.489 return v; 2.490 } 2.491 2.492 @@ -334,16 +630,6 @@ 2.493 return v3_mul(s, ps); 2.494 } 2.495 2.496 -void anm_set_pivot(struct anm_node *node, vec3_t piv) 2.497 -{ 2.498 - node->pivot = piv; 2.499 -} 2.500 - 2.501 -vec3_t anm_get_pivot(struct anm_node *node) 2.502 -{ 2.503 - return node->pivot; 2.504 -} 2.505 - 2.506 void anm_get_node_matrix(struct anm_node *node, mat4_t mat, anm_time_t tm) 2.507 { 2.508 int i; 2.509 @@ -463,15 +749,20 @@ 2.510 2.511 anm_time_t anm_get_start_time(struct anm_node *node) 2.512 { 2.513 - int i; 2.514 + int i, j; 2.515 struct anm_node *c; 2.516 anm_time_t res = LONG_MAX; 2.517 2.518 - for(i=0; i<ANM_NUM_TRACKS; i++) { 2.519 - if(node->tracks[i].count) { 2.520 - anm_time_t tm = node->tracks[i].keys[0].time; 2.521 - if(tm < res) { 2.522 - res = tm; 2.523 + for(j=0; j<2; j++) { 2.524 + struct anm_animation *anim = anm_get_active_animation(node, j); 2.525 + if(!anim) break; 2.526 + 2.527 + for(i=0; i<ANM_NUM_TRACKS; i++) { 2.528 + if(anim->tracks[i].count) { 2.529 + anm_time_t tm = anim->tracks[i].keys[0].time; 2.530 + if(tm < res) { 2.531 + res = tm; 2.532 + } 2.533 } 2.534 } 2.535 } 2.536 @@ -489,15 +780,20 @@ 2.537 2.538 anm_time_t anm_get_end_time(struct anm_node *node) 2.539 { 2.540 - int i; 2.541 + int i, j; 2.542 struct anm_node *c; 2.543 anm_time_t res = LONG_MIN; 2.544 2.545 - for(i=0; i<ANM_NUM_TRACKS; i++) { 2.546 - if(node->tracks[i].count) { 2.547 - anm_time_t tm = node->tracks[i].keys[node->tracks[i].count - 1].time; 2.548 - if(tm > res) { 2.549 - res = tm; 2.550 + for(j=0; j<2; j++) { 2.551 + struct anm_animation *anim = anm_get_active_animation(node, j); 2.552 + if(!anim) break; 2.553 + 2.554 + for(i=0; i<ANM_NUM_TRACKS; i++) { 2.555 + if(anim->tracks[i].count) { 2.556 + anm_time_t tm = anim->tracks[i].keys[anim->tracks[i].count - 1].time; 2.557 + if(tm > res) { 2.558 + res = tm; 2.559 + } 2.560 } 2.561 } 2.562 }
3.1 --- a/src/anim.h Mon Dec 09 04:06:30 2013 +0200 3.2 +++ b/src/anim.h Fri Dec 27 06:28:43 2013 +0200 3.3 @@ -27,10 +27,18 @@ 3.4 ANM_NUM_TRACKS 3.5 }; 3.6 3.7 +struct anm_animation { 3.8 + char *name; 3.9 + struct anm_track tracks[ANM_NUM_TRACKS]; 3.10 +}; 3.11 + 3.12 struct anm_node { 3.13 char *name; 3.14 3.15 - struct anm_track tracks[ANM_NUM_TRACKS]; 3.16 + int cur_anim[2]; 3.17 + float cur_mix; 3.18 + 3.19 + struct anm_animation *animations; 3.20 vec3_t pivot; 3.21 3.22 /* matrix cache */ 3.23 @@ -54,6 +62,9 @@ 3.24 extern "C" { 3.25 #endif 3.26 3.27 +int anm_init_animation(struct anm_animation *anim); 3.28 +void anm_destroy_animation(struct anm_animation *anim); 3.29 + 3.30 /* node constructor and destructor */ 3.31 int anm_init_node(struct anm_node *node); 3.32 void anm_destroy_node(struct anm_node *node); 3.33 @@ -74,13 +85,46 @@ 3.34 int anm_set_node_name(struct anm_node *node, const char *name); 3.35 const char *anm_get_node_name(struct anm_node *node); 3.36 3.37 -void anm_set_interpolator(struct anm_node *node, enum anm_interpolator in); 3.38 -void anm_set_extrapolator(struct anm_node *node, enum anm_extrapolator ex); 3.39 - 3.40 /* link and unlink nodes with parent/child relations */ 3.41 void anm_link_node(struct anm_node *parent, struct anm_node *child); 3.42 int anm_unlink_node(struct anm_node *parent, struct anm_node *child); 3.43 3.44 +void anm_set_pivot(struct anm_node *node, vec3_t pivot); 3.45 +vec3_t anm_get_pivot(struct anm_node *node); 3.46 + 3.47 +/* set active animation(s) */ 3.48 +int anm_use_node_animation(struct anm_node *node, int aidx); 3.49 +int anm_use_node_animations(struct anm_node *node, int aidx, int bidx, float t); 3.50 +/* recursive variants */ 3.51 +int anm_use_animation(struct anm_node *node, int aidx); 3.52 +int anm_use_animations(struct anm_node *node, int aidx, int bidx, float t); 3.53 + 3.54 +/* returns the requested current animation index, which can be 0 or 1 */ 3.55 +int anm_get_active_animation_index(struct anm_node *node, int which); 3.56 +/* returns the requested current animation, which can be 0 or 1 */ 3.57 +struct anm_animation *anm_get_active_animation(struct anm_node *node, int which); 3.58 +float anm_get_active_animation_mix(struct anm_node *node); 3.59 + 3.60 +int anm_get_animation_count(struct anm_node *node); 3.61 + 3.62 +/* add/remove an animation to the specified node */ 3.63 +int anm_add_node_animation(struct anm_node *node); 3.64 +int anm_remove_node_animation(struct anm_node *node, int idx); 3.65 + 3.66 +/* add/remove an animation to the specified node and all it's descendants */ 3.67 +int anm_add_animation(struct anm_node *node); 3.68 +int anm_remove_animation(struct anm_node *node, int idx); 3.69 + 3.70 +struct anm_animation *anm_get_animation(struct anm_node *node, int idx); 3.71 +struct anm_animation *anm_get_animation_by_name(struct anm_node *node, const char *name); 3.72 + 3.73 +int anm_find_animation(struct anm_node *node, const char *name); 3.74 + 3.75 +/* set the interpolator for the (first) currently active animation */ 3.76 +void anm_set_interpolator(struct anm_node *node, enum anm_interpolator in); 3.77 +/* set the extrapolator for the (first) currently active animation */ 3.78 +void anm_set_extrapolator(struct anm_node *node, enum anm_extrapolator ex); 3.79 + 3.80 void anm_set_position(struct anm_node *node, vec3_t pos, anm_time_t tm); 3.81 vec3_t anm_get_node_position(struct anm_node *node, anm_time_t tm); 3.82 3.83 @@ -95,9 +139,6 @@ 3.84 quat_t anm_get_rotation(struct anm_node *node, anm_time_t tm); 3.85 vec3_t anm_get_scaling(struct anm_node *node, anm_time_t tm); 3.86 3.87 -void anm_set_pivot(struct anm_node *node, vec3_t pivot); 3.88 -vec3_t anm_get_pivot(struct anm_node *node); 3.89 - 3.90 /* those return the start and end times of the whole tree */ 3.91 anm_time_t anm_get_start_time(struct anm_node *node); 3.92 anm_time_t anm_get_end_time(struct anm_node *node);