libanim
diff src/anim.c @ 24:09e267e7ed4a
implemented high-level animation blending interface
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Mon, 30 Dec 2013 15:20:31 +0200 |
parents | 203c11299586 |
children | ebead35c9eb1 |
line diff
1.1 --- a/src/anim.c Fri Dec 27 11:29:42 2013 +0200 1.2 +++ b/src/anim.c Mon Dec 30 15:20:31 2013 +0200 1.3 @@ -57,7 +57,6 @@ 1.4 memset(node, 0, sizeof *node); 1.5 1.6 node->cur_anim[1] = -1; 1.7 - node->cur_mix = 0; 1.8 1.9 if(!(node->animations = dynarr_alloc(1, sizeof *node->animations))) { 1.10 return -1; 1.11 @@ -222,6 +221,7 @@ 1.12 node->cur_anim[0] = aidx; 1.13 node->cur_anim[1] = -1; 1.14 node->cur_mix = 0; 1.15 + node->blend_dur = -1; 1.16 1.17 invalidate_cache(node); 1.18 return 0; 1.19 @@ -288,13 +288,40 @@ 1.20 1.21 } 1.22 1.23 -int anm_get_active_animation_index(struct anm_node *node, int which) 1.24 +void anm_set_node_animation_offset(struct anm_node *node, anm_time_t offs, int which) 1.25 +{ 1.26 + if(which < 0 || which >= 2) { 1.27 + return; 1.28 + } 1.29 + node->cur_anim_offset[which] = offs; 1.30 +} 1.31 + 1.32 +anm_time_t anm_get_animation_offset(const struct anm_node *node, int which) 1.33 +{ 1.34 + if(which < 0 || which >= 2) { 1.35 + return 0; 1.36 + } 1.37 + return node->cur_anim_offset[which]; 1.38 +} 1.39 + 1.40 +void anm_set_animation_offset(struct anm_node *node, anm_time_t offs, int which) 1.41 +{ 1.42 + struct anm_node *c = node->child; 1.43 + while(c) { 1.44 + anm_set_animation_offset(c, offs, which); 1.45 + c = c->next; 1.46 + } 1.47 + 1.48 + anm_set_node_animation_offset(node, offs, which); 1.49 +} 1.50 + 1.51 +int anm_get_active_animation_index(const struct anm_node *node, int which) 1.52 { 1.53 if(which < 0 || which >= 2) return -1; 1.54 return node->cur_anim[which]; 1.55 } 1.56 1.57 -struct anm_animation *anm_get_active_animation(struct anm_node *node, int which) 1.58 +struct anm_animation *anm_get_active_animation(const struct anm_node *node, int which) 1.59 { 1.60 int idx = anm_get_active_animation_index(node, which); 1.61 if(idx < 0 || idx >= anm_get_animation_count(node)) { 1.62 @@ -303,12 +330,12 @@ 1.63 return node->animations + idx; 1.64 } 1.65 1.66 -float anm_get_active_animation_mix(struct anm_node *node) 1.67 +float anm_get_active_animation_mix(const struct anm_node *node) 1.68 { 1.69 return node->cur_mix; 1.70 } 1.71 1.72 -int anm_get_animation_count(struct anm_node *node) 1.73 +int anm_get_animation_count(const struct anm_node *node) 1.74 { 1.75 return dynarr_size(node->animations); 1.76 } 1.77 @@ -445,6 +472,50 @@ 1.78 return 0; 1.79 } 1.80 1.81 +/* ---- high level animation blending ---- */ 1.82 +void anm_transition(struct anm_node *node, int anmidx, anm_time_t start, anm_time_t dur) 1.83 +{ 1.84 + struct anm_node *c = node->child; 1.85 + while(c) { 1.86 + anm_transition(c, anmidx, start, dur); 1.87 + c = c->next; 1.88 + } 1.89 + 1.90 + anm_node_transition(node, anmidx, start, dur); 1.91 +} 1.92 + 1.93 +void anm_node_transition(struct anm_node *node, int anmidx, anm_time_t start, anm_time_t dur) 1.94 +{ 1.95 + node->cur_anim[1] = anmidx; 1.96 + node->cur_anim_offset[1] = start; 1.97 + node->blend_dur = dur; 1.98 +} 1.99 + 1.100 + 1.101 +#define BLEND_START_TM node->cur_anim_offset[1] 1.102 + 1.103 +static anm_time_t animation_time(struct anm_node *node, anm_time_t tm, int which) 1.104 +{ 1.105 + float t; 1.106 + 1.107 + if(node->blend_dur >= 0) { 1.108 + /* we're in transition... */ 1.109 + t = (float)(tm - BLEND_START_TM) / (float)node->blend_dur; 1.110 + if(t < 0.0) t = 0.0; 1.111 + 1.112 + node->cur_mix = t; 1.113 + 1.114 + if(t > 1.0) { 1.115 + /* switch completely over to the target animation and stop blending */ 1.116 + anm_use_node_animation(node, node->cur_anim[1]); 1.117 + node->cur_anim_offset[0] = node->cur_anim_offset[1]; 1.118 + } 1.119 + } 1.120 + 1.121 + return tm - node->cur_anim_offset[which]; 1.122 +} 1.123 + 1.124 + 1.125 void anm_set_position(struct anm_node *node, vec3_t pos, anm_time_t tm) 1.126 { 1.127 struct anm_animation *anim = anm_get_active_animation(node, 0); 1.128 @@ -456,9 +527,11 @@ 1.129 invalidate_cache(node); 1.130 } 1.131 1.132 + 1.133 vec3_t anm_get_node_position(struct anm_node *node, anm_time_t tm) 1.134 { 1.135 vec3_t v; 1.136 + anm_time_t tm0 = animation_time(node, tm, 0); 1.137 struct anm_animation *anim0 = anm_get_active_animation(node, 0); 1.138 struct anm_animation *anim1 = anm_get_active_animation(node, 1); 1.139 1.140 @@ -466,15 +539,16 @@ 1.141 return v3_cons(0, 0, 0); 1.142 } 1.143 1.144 - v.x = anm_get_value(anim0->tracks + ANM_TRACK_POS_X, tm); 1.145 - v.y = anm_get_value(anim0->tracks + ANM_TRACK_POS_Y, tm); 1.146 - v.z = anm_get_value(anim0->tracks + ANM_TRACK_POS_Z, tm); 1.147 + v.x = anm_get_value(anim0->tracks + ANM_TRACK_POS_X, tm0); 1.148 + v.y = anm_get_value(anim0->tracks + ANM_TRACK_POS_Y, tm0); 1.149 + v.z = anm_get_value(anim0->tracks + ANM_TRACK_POS_Z, tm0); 1.150 1.151 if(anim1) { 1.152 vec3_t v1; 1.153 - v1.x = anm_get_value(anim1->tracks + ANM_TRACK_POS_X, tm); 1.154 - v1.y = anm_get_value(anim1->tracks + ANM_TRACK_POS_Y, tm); 1.155 - v1.z = anm_get_value(anim1->tracks + ANM_TRACK_POS_Z, tm); 1.156 + anm_time_t tm1 = animation_time(node, tm, 1); 1.157 + v1.x = anm_get_value(anim1->tracks + ANM_TRACK_POS_X, tm1); 1.158 + v1.y = anm_get_value(anim1->tracks + ANM_TRACK_POS_Y, tm1); 1.159 + v1.z = anm_get_value(anim1->tracks + ANM_TRACK_POS_Z, tm1); 1.160 1.161 v.x = v.x + (v1.x - v.x) * node->cur_mix; 1.162 v.y = v.y + (v1.y - v.y) * node->cur_mix; 1.163 @@ -575,6 +649,7 @@ 1.164 quat_t anm_get_node_rotation(struct anm_node *node, anm_time_t tm) 1.165 { 1.166 quat_t q; 1.167 + anm_time_t tm0 = animation_time(node, tm, 0); 1.168 struct anm_animation *anim0 = anm_get_active_animation(node, 0); 1.169 struct anm_animation *anim1 = anm_get_active_animation(node, 1); 1.170 1.171 @@ -582,10 +657,11 @@ 1.172 return quat_identity(); 1.173 } 1.174 1.175 - q = get_node_rotation(node, tm, anim0); 1.176 + q = get_node_rotation(node, tm0, anim0); 1.177 1.178 if(anim1) { 1.179 - quat_t q1 = get_node_rotation(node, tm, anim1); 1.180 + anm_time_t tm1 = animation_time(node, tm, 1); 1.181 + quat_t q1 = get_node_rotation(node, tm1, anim1); 1.182 1.183 q = quat_slerp(q, q1, node->cur_mix); 1.184 } 1.185 @@ -606,6 +682,7 @@ 1.186 vec3_t anm_get_node_scaling(struct anm_node *node, anm_time_t tm) 1.187 { 1.188 vec3_t v; 1.189 + anm_time_t tm0 = animation_time(node, tm, 0); 1.190 struct anm_animation *anim0 = anm_get_active_animation(node, 0); 1.191 struct anm_animation *anim1 = anm_get_active_animation(node, 1); 1.192 1.193 @@ -613,15 +690,16 @@ 1.194 return v3_cons(1, 1, 1); 1.195 } 1.196 1.197 - v.x = anm_get_value(anim0->tracks + ANM_TRACK_SCL_X, tm); 1.198 - v.y = anm_get_value(anim0->tracks + ANM_TRACK_SCL_Y, tm); 1.199 - v.z = anm_get_value(anim0->tracks + ANM_TRACK_SCL_Z, tm); 1.200 + v.x = anm_get_value(anim0->tracks + ANM_TRACK_SCL_X, tm0); 1.201 + v.y = anm_get_value(anim0->tracks + ANM_TRACK_SCL_Y, tm0); 1.202 + v.z = anm_get_value(anim0->tracks + ANM_TRACK_SCL_Z, tm0); 1.203 1.204 if(anim1) { 1.205 vec3_t v1; 1.206 - v1.x = anm_get_value(anim1->tracks + ANM_TRACK_SCL_X, tm); 1.207 - v1.y = anm_get_value(anim1->tracks + ANM_TRACK_SCL_Y, tm); 1.208 - v1.z = anm_get_value(anim1->tracks + ANM_TRACK_SCL_Z, tm); 1.209 + anm_time_t tm1 = animation_time(node, tm, 1); 1.210 + v1.x = anm_get_value(anim1->tracks + ANM_TRACK_SCL_X, tm1); 1.211 + v1.y = anm_get_value(anim1->tracks + ANM_TRACK_SCL_Y, tm1); 1.212 + v1.z = anm_get_value(anim1->tracks + ANM_TRACK_SCL_Z, tm1); 1.213 1.214 v.x = v.x + (v1.x - v.x) * node->cur_mix; 1.215 v.y = v.y + (v1.y - v.y) * node->cur_mix;