]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - r_lerpanim.c
reworked animation interpolation code - entity_render_t now has
[xonotic/darkplaces.git] / r_lerpanim.c
index fe8f2495f90a21b03e3e1cc69cb7b1ec5afde077..f384d81af0eb39c67af64157fb3c565e70e413ed 100644 (file)
 // LordHavoc: later note: made FRAMEBLENDINSERT macro
 void R_LerpAnimation(entity_render_t *r)
 {
-       int sub1, sub2, numframes, f, i;
+       int sub2, numframes, f, i, k;
+       int isfirstframegroup = true;
+       int nolerp;
        double sublerp, lerp, d;
        animscene_t *scene;
+       framegroupblend_t *g;
        frameblend_t *blend;
-       blend = r->frameblend;
+       dp_model_t *model = r->model;
 
-       numframes = r->model->numframes;
+       memset(r->frameblend, 0, sizeof(r->frameblend));
 
-       if (r->frame1 >= numframes)
+       if (!model || !model->surfmesh.isanimated)
        {
-               Con_DPrintf ("CL_LerpAnimation: no such frame %d\n", r->frame1);
-               r->frame1 = 0;
+               r->frameblend[0].lerp = 1;
+               return;
        }
 
-       if (r->frame2 >= numframes)
-       {
-               Con_DPrintf ("CL_LerpAnimation: no such frame %d\n", r->frame2);
-               r->frame2 = 0;
-       }
-
-       // note: this could be removed, if the rendering code allows an empty blend array
-       if (r->frame1 < 0)
-               Host_Error ("CL_LerpAnimation: frame1 is NULL\n");
-
-       // round off very close blend percentages
-       if (r->framelerp < (1.0f / 65536.0f))
-               r->framelerp = 0;
-       if (r->framelerp >= (65535.0f / 65536.0f))
-               r->framelerp = 1;
-
-       blend[0].frame = blend[1].frame = blend[2].frame = blend[3].frame = 0;
-       blend[0].lerp = blend[1].lerp = blend[2].lerp = blend[3].lerp = 0;
-       if (r->model->animscenes)
+       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++)
        {
-               if (r->framelerp < 1 && r->frame1 >= 0)
+               if ((unsigned int)g->frame >= (unsigned int)numframes)
                {
-                       scene = r->model->animscenes + r->frame1;
-                       lerp = 1 - r->framelerp;
-
-                       if (scene->framecount > 1)
+                       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)
+               {
+                       if (isfirstframegroup)
                        {
-                               sublerp = scene->framerate * (cl.time - r->frame1time);
-                               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);
-                                       sub2 = (sub2 % scene->framecount);
-                               }
-                               else
-                               {
-                                       sub1 = bound(0, sub1, (scene->framecount - 1));
-                                       sub2 = bound(0, sub2, (scene->framecount - 1));
-                               }
-                               sub1 += scene->firstframe;
-                               sub2 += scene->firstframe;
-                               f = sub1;
-                               d = (1 - sublerp) * lerp;
-#define FRAMEBLENDINSERT\
-                               if (d > 0)\
-                               {\
-                                       for (i = 0;i < 4;i++)\
-                                       {\
-                                               if (blend[i].frame == f)\
-                                               {\
-                                                       blend[i].lerp += d;\
-                                                       break;\
-                                               }\
-                                               if (blend[i].lerp <= 0)\
-                                               {\
-                                                       blend[i].frame = f;\
-                                                       blend[i].lerp = d;\
-                                                       break;\
-                                               }\
-                                       }\
-                               }
-                               FRAMEBLENDINSERT
-                               f = sub2;
-                               d = sublerp * lerp;
+                               d = lerp = 1;
+                               isfirstframegroup = false;
                        }
                        else
-                       {
-                               f = scene->firstframe;
-                               d = lerp;
-                       }
-                       FRAMEBLENDINSERT
+                               continue;
                }
-               if (r->framelerp > 0 && r->frame2 >= 0)
+               if (model->animscenes)
                {
-                       scene = r->model->animscenes + r->frame2;
-                       lerp = r->framelerp;
-
+                       scene = model->animscenes + f;
+                       f = scene->firstframe;
                        if (scene->framecount > 1)
                        {
-                               sublerp = scene->framerate * (cl.time - r->frame1time);
-                               sub1 = (int) (sublerp);
-                               sub2 = sub1 + 1;
-                               sublerp -= sub1;
-                               if (sublerp < (1.0f / 65536.0f))
+                               // 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 (nolerp)
                                        sublerp = 0;
-                               if (sublerp >= (65535.0f / 65536.0f))
-                                       sublerp = 1;
                                if (scene->loop)
                                {
-                                       sub1 = (sub1 % scene->framecount);
+                                       f = (f % scene->framecount);
                                        sub2 = (sub2 % scene->framecount);
                                }
-                               else
+                               f = bound(0, f, (scene->framecount - 1)) + scene->firstframe;
+                               sub2 = bound(0, sub2, (scene->framecount - 1)) + scene->firstframe;
+                               d = sublerp * lerp;
+                               // two framelerps produced from one animation
+                               if (f != sub2 && d > 0)
                                {
-                                       sub1 = bound(0, sub1, (scene->framecount - 1));
-                                       sub2 = bound(0, sub2, (scene->framecount - 1));
+                                       for (i = 0;i < MAX_FRAMEBLENDS;i++)
+                                       {
+                                               if (blend[i].lerp <= 0 || blend[i].subframe == sub2)
+                                               {
+                                                       blend[i].subframe = sub2;
+                                                       blend[i].lerp += d;
+                                                       break;
+                                               }
+                                       }
                                }
-                               sub1 += scene->firstframe;
-                               sub2 += scene->firstframe;
-                               f = sub1;
                                d = (1 - sublerp) * lerp;
-                               FRAMEBLENDINSERT
-                               f = sub2;
-                               d = sublerp * lerp;
-                       }
-                       else
-                       {
-                               f = scene->firstframe;
-                               d = lerp;
                        }
-                       FRAMEBLENDINSERT
-               }
-       }
-       else
-       {
-               // if there are no scenes, assume it is all single-frame groups
-               if (r->framelerp < 1 && r->frame1 >= 0)
-               {
-                       f = r->frame1;
-                       d = 1 - r->framelerp;
-                       FRAMEBLENDINSERT
                }
-               if (r->framelerp > 0 && r->frame2 >= 0)
+               if (d > 0)
                {
-                       f = r->frame2;
-                       d = r->framelerp;
-                       FRAMEBLENDINSERT
+                       for (i = 0;i < MAX_FRAMEBLENDS;i++)
+                       {
+                               if (blend[i].lerp <= 0 || blend[i].subframe == f)
+                               {
+                                       blend[i].subframe = f;
+                                       blend[i].lerp += d;
+                                       break;
+                               }
+                       }
                }
        }
 }