-
#include "quakedef.h"
// LordHavoc: quite tempting to break apart this function to reuse the
// duplicated code, but I suspect it is better for performance
// this way
-void R_LerpAnimation(model_t *mod, int frame1, int frame2, double frame1start, double frame2start, double framelerp, frameblend_t *blend)
+// LordHavoc: later note: made FRAMEBLENDINSERT macro
+void R_LerpAnimation(entity_render_t *r)
{
- int sub1, sub2, numframes, f, i, data;
- double sublerp, lerp, l;
- animscene_t *scene, *scenes;
-
- data = (int) Mod_Extradata(mod);
- if (!data)
- Host_Error("R_LerpAnimation: model not loaded\n");
- scenes = (animscene_t *) (mod->ofs_scenes + data);
-
- numframes = mod->numframes;
+ int sub2, numframes, f, i, k;
+ int isfirstframegroup = true;
+ int nolerp;
+ double sublerp, lerp, d;
+ animscene_t *scene;
+ framegroupblend_t *g;
+ frameblend_t *blend;
+ dp_model_t *model = r->model;
- if ((frame1 >= numframes))
- {
- Con_Printf ("R_LerpAnimation: no such frame %d\n", frame1);
- frame1 = 0;
- }
+ memset(r->frameblend, 0, sizeof(r->frameblend));
- if ((frame2 >= numframes))
+ if (!model || !model->surfmesh.isanimated)
{
- Con_Printf ("R_LerpAnimation: no such frame %d\n", frame2);
- frame2 = 0;
+ r->frameblend[0].lerp = 1;
+ return;
}
- if (frame1 < 0)
- Host_Error ("R_LerpAnimation: frame1 is NULL\n");
-
- // round off very close blend percentages
- if (framelerp < (1.0f / 65536.0f))
- framelerp = 0;
- if (framelerp >= (65535.0f / 65536.0f))
- framelerp = 1;
-
- blend[0].frame = blend[1].frame = blend[2].frame = blend[3].frame = -1;
- blend[0].lerp = blend[1].lerp = blend[2].lerp = blend[3].lerp = 0;
- if (framelerp < 1)
+ blend = r->frameblend;
+ nolerp = (model->type == mod_sprite) ? !r_lerpsprites.integer : !r_lerpmodels.integer;
+ numframes = model->numframes;
+ for (k = 0, g = r->framegroupblend;k < MAX_FRAMEGROUPBLENDS;k++, g++)
{
- scene = scenes + frame1;
- lerp = 1 - framelerp;
-
- if (scene->framecount > 1)
+ if ((unsigned int)g->frame >= (unsigned int)numframes)
+ {
+ Con_DPrintf("CL_LerpAnimation: no such frame %d\n", g->frame);
+ g->frame = 0;
+ }
+ f = g->frame;
+ d = lerp = g->lerp;
+ if (lerp <= 0)
+ continue;
+ if (nolerp)
{
- sublerp = scene->framerate * (cl.time - frame1start);
- sub1 = (int) (sublerp);
- sub2 = sub1 + 1;
- sublerp -= sub1;
- if (sublerp < (1.0f / 65536.0f))
- sublerp = 0;
- if (sublerp >= (65535.0f / 65536.0f))
- sublerp = 1;
- if (scene->loop)
+ if (isfirstframegroup)
{
- sub1 = (sub1 % scene->framecount) + scene->firstframe;
- sub2 = (sub2 % scene->framecount) + scene->firstframe;
+ d = lerp = 1;
+ isfirstframegroup = false;
}
else
- {
- sub1 = bound(0, sub1, (scene->framecount - 1)) + scene->firstframe;
- sub2 = bound(0, sub2, (scene->framecount - 1)) + scene->firstframe;
- }
- f = sub1;
- l = (1 - sublerp) * lerp;
- if (l > 0)
- {
- for (i = 0;i < 4;i++)
- {
- if (blend[i].frame == f)
- {
- blend[i].lerp += l;
- break;
- }
- if (blend[i].lerp <= 0)
- {
- blend[i].frame = f;
- blend[i].lerp = l;
- break;
- }
- }
- }
- f = sub2;
- l = sublerp * lerp;
+ continue;
}
- else
+ if (model->animscenes)
{
+ scene = model->animscenes + f;
f = scene->firstframe;
- l = lerp;
- }
- if (l > 0)
- {
- for (i = 0;i < 4;i++)
+ if (scene->framecount > 1)
{
- if (blend[i].frame == f)
- {
- blend[i].lerp += l;
- break;
- }
- if (blend[i].lerp <= 0)
+ // this code path is only used on .zym models and torches
+ sublerp = scene->framerate * (cl.time - g->start);
+ f = (int) floor(sublerp);
+ sublerp -= f;
+ sub2 = f + 1;
+ if (sublerp < (1.0 / 65536.0f))
+ sublerp = 0;
+ if (sublerp > (65535.0f / 65536.0f))
+ sublerp = 1;
+ if (nolerp)
+ sublerp = 0;
+ if (scene->loop)
{
- blend[i].frame = f;
- blend[i].lerp = l;
- break;
+ f = (f % scene->framecount);
+ sub2 = (sub2 % scene->framecount);
}
- }
- }
- }
- if (framelerp > 0 && frame2 >= 0)
- {
- scene = scenes + frame2;
- lerp = framelerp;
-
- if (scene->framecount > 1)
- {
- sublerp = scene->framerate * (cl.time - frame1start);
- sub1 = (int) (sublerp);
- sub2 = sub1 + 1;
- sublerp -= sub1;
- if (sublerp < (1.0f / 65536.0f))
- sublerp = 0;
- if (sublerp >= (65535.0f / 65536.0f))
- sublerp = 1;
- if (scene->loop)
- {
- sub1 = (sub1 % scene->framecount) + scene->firstframe;
- sub2 = (sub2 % scene->framecount) + scene->firstframe;
- }
- else
- {
- sub1 = bound(0, sub1, (scene->framecount - 1)) + scene->firstframe;
+ f = bound(0, f, (scene->framecount - 1)) + scene->firstframe;
sub2 = bound(0, sub2, (scene->framecount - 1)) + scene->firstframe;
- }
- f = sub1;
- l = (1 - sublerp) * lerp;
- if (l > 0)
- {
- for (i = 0;i < 4;i++)
+ d = sublerp * lerp;
+ // two framelerps produced from one animation
+ if (d > 0)
{
- if (blend[i].frame == f)
+ for (i = 0;i < MAX_FRAMEBLENDS;i++)
{
- blend[i].lerp += l;
- break;
- }
- if (blend[i].lerp <= 0)
- {
- blend[i].frame = f;
- blend[i].lerp = l;
- break;
+ if (blend[i].lerp <= 0 || blend[i].subframe == sub2)
+ {
+ blend[i].subframe = sub2;
+ blend[i].lerp += d;
+ break;
+ }
}
}
+ d = (1 - sublerp) * lerp;
}
- f = sub2;
- l = sublerp * lerp;
- }
- else
- {
- f = scene->firstframe;
- l = lerp;
}
- if (l > 0)
+ if (d > 0)
{
- for (i = 0;i < 4;i++)
+ for (i = 0;i < MAX_FRAMEBLENDS;i++)
{
- if (blend[i].frame == f)
- {
- blend[i].lerp += l;
- break;
- }
- if (blend[i].lerp <= 0)
+ if (blend[i].lerp <= 0 || blend[i].subframe == f)
{
- blend[i].frame = f;
- blend[i].lerp = l;
+ blend[i].subframe = f;
+ blend[i].lerp += d;
break;
}
}
}
}
}
+