r_mesh_anim.c
Go to the documentation of this file.00001
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "r_local.h"
00027 #include "r_mesh_anim.h"
00028
00029 #define LNEXT(x) ((x + 1 < MAX_ANIMLIST) ? x + 1 : 0)
00030
00041 static const mAliasAnim_t *R_AnimGet (const model_t * mod, const char *name)
00042 {
00043 mAliasAnim_t *anim;
00044 int i;
00045
00046 if (!mod || !mod->alias.num_anims)
00047 return NULL;
00048
00049 for (i = 0, anim = mod->alias.animdata; i < mod->alias.num_anims; i++, anim++)
00050 if (!strcmp(name, anim->name))
00051 return anim;
00052
00053 Com_Printf("model \"%s\" doesn't have animation \"%s\"\n", mod->name, name);
00054 return NULL;
00055 }
00056
00057
00068 void R_AnimAppend (animState_t * as, const model_t * mod, const char *name)
00069 {
00070 const mAliasAnim_t *anim;
00071
00072 assert(as->ladd < MAX_ANIMLIST);
00073
00074 if (!mod || !mod->alias.num_anims)
00075 return;
00076
00077
00078 anim = R_AnimGet(mod, name);
00079 if (!anim)
00080 return;
00081
00082 if (as->lcur == as->ladd) {
00083
00084 as->oldframe = anim->from;
00085 if (anim->to > anim->from)
00086 as->frame = anim->from + 1;
00087 else
00088 as->frame = anim->from;
00089
00090 as->backlerp = 0.0;
00091 as->time = anim->time;
00092 as->dt = 0;
00093
00094 as->list[as->ladd] = anim - mod->alias.animdata;
00095 } else {
00096
00097 as->list[as->ladd] = anim - mod->alias.animdata;
00098 }
00099
00100
00101 as->ladd = LNEXT(as->ladd);
00102 }
00103
00104
00115 void R_AnimChange (animState_t * as, const model_t * mod, const char *name)
00116 {
00117 const mAliasAnim_t *anim;
00118
00119 assert(as->ladd < MAX_ANIMLIST);
00120
00121 if (!mod || !mod->alias.num_anims)
00122 return;
00123
00124
00125 anim = R_AnimGet(mod, name);
00126 if (!anim) {
00127 Com_Printf("R_AnimChange: No such animation: %s (model: %s)\n", name, mod->name);
00128 return;
00129 }
00130
00131 if (as->lcur == as->ladd) {
00132
00133 as->oldframe = anim->from;
00134 if (anim->to > anim->from)
00135 as->frame = anim->from + 1;
00136 else
00137 as->frame = anim->from;
00138
00139 as->backlerp = 1.0;
00140 as->time = anim->time;
00141 as->dt = 0;
00142
00143 as->list[as->ladd] = anim - mod->alias.animdata;
00144 as->change = qtrue;
00145 } else {
00146
00147 as->ladd = LNEXT(as->lcur);
00148 as->list[as->ladd] = anim - mod->alias.animdata;
00149
00150 if (anim->time < as->time)
00151 as->time = anim->time;
00152
00153 if (anim != mod->alias.animdata + as->list[as->lcur])
00154 as->change = qtrue;
00155 }
00156
00157
00158 as->ladd = LNEXT(as->ladd);
00159 }
00160
00161
00172 void R_AnimRun (animState_t * as, const model_t * mod, int msec)
00173 {
00174 assert(as->lcur < MAX_ANIMLIST);
00175
00176 if (!mod || !mod->alias.num_anims)
00177 return;
00178
00179 if (as->lcur == as->ladd)
00180 return;
00181
00182 as->dt += msec;
00183
00184 while (as->dt > as->time) {
00185 const mAliasAnim_t *anim = mod->alias.animdata + as->list[as->lcur];
00186 as->dt -= as->time;
00187
00188 if (as->change || as->frame >= anim->to) {
00189
00190 if (LNEXT(as->lcur) != as->ladd)
00191 as->lcur = LNEXT(as->lcur);
00192
00193 anim = mod->alias.animdata + as->list[as->lcur];
00194
00195
00196 as->dt = 0;
00197 as->time = anim->time;
00198 as->oldframe = as->frame;
00199 as->frame = anim->from;
00200 as->change = qfalse;
00201 } else {
00202
00203 as->time = anim->time;
00204 as->oldframe = as->frame;
00205 as->frame++;
00206 }
00207 }
00208
00209 as->backlerp = 1.0 - (float) as->dt / as->time;
00210 }
00211
00212
00223 const char *R_AnimGetName (const animState_t * as, const model_t * mod)
00224 {
00225 const mAliasAnim_t *anim;
00226
00227 assert(as->lcur < MAX_ANIMLIST);
00228
00229 if (!mod || !mod->alias.num_anims)
00230 return NULL;
00231
00232 if (as->lcur == as->ladd)
00233 return NULL;
00234
00235 anim = mod->alias.animdata + as->list[as->lcur];
00236 return anim->name;
00237 }
00238
00243 void R_InterpolateTransform (animState_t * as, int numframes, const float *tag, float *interpolated)
00244 {
00245 const float *current, *old;
00246 float bl, fl;
00247 int i;
00248
00249
00250 if (as->frame >= numframes || as->frame < 0)
00251 as->frame = 0;
00252 if (as->oldframe >= numframes || as->oldframe < 0)
00253 as->oldframe = 0;
00254
00255
00256 current = tag + as->frame * 16;
00257 old = tag + as->oldframe * 16;
00258 bl = as->backlerp;
00259 fl = 1.0 - as->backlerp;
00260
00261
00262 if (bl == 0.0) {
00263 memcpy(interpolated, current, sizeof(float) * 16);
00264 return;
00265 }
00266 if (bl == 1.0) {
00267 memcpy(interpolated, old, sizeof(float) * 16);
00268 return;
00269 }
00270
00271
00272 for (i = 0; i < 16; i++)
00273 interpolated[i] = fl * current[i] + bl * old[i];
00274
00275
00276 for (i = 0; i < 3; i++)
00277 VectorNormalize(interpolated + i * 4);
00278 }