reworked animation interpolation code - entity_render_t now has
[xonotic/darkplaces.git] / r_lerpanim.c
1 #include "quakedef.h"
2
3 // LordHavoc: quite tempting to break apart this function to reuse the
4 //            duplicated code, but I suspect it is better for performance
5 //            this way
6 // LordHavoc: later note: made FRAMEBLENDINSERT macro
7 void R_LerpAnimation(entity_render_t *r)
8 {
9         int sub2, numframes, f, i, k;
10         int isfirstframegroup = true;
11         int nolerp;
12         double sublerp, lerp, d;
13         animscene_t *scene;
14         framegroupblend_t *g;
15         frameblend_t *blend;
16         dp_model_t *model = r->model;
17
18         memset(r->frameblend, 0, sizeof(r->frameblend));
19
20         if (!model || !model->surfmesh.isanimated)
21         {
22                 r->frameblend[0].lerp = 1;
23                 return;
24         }
25
26         blend = r->frameblend;
27         nolerp = (model->type == mod_sprite) ? !r_lerpsprites.integer : !r_lerpmodels.integer;
28         numframes = model->numframes;
29         for (k = 0, g = r->framegroupblend;k < MAX_FRAMEGROUPBLENDS;k++, g++)
30         {
31                 if ((unsigned int)g->frame >= (unsigned int)numframes)
32                 {
33                         Con_DPrintf("CL_LerpAnimation: no such frame %d\n", g->frame);
34                         g->frame = 0;
35                 }
36                 f = g->frame;
37                 d = lerp = g->lerp;
38                 if (lerp <= 0)
39                         continue;
40                 if (nolerp)
41                 {
42                         if (isfirstframegroup)
43                         {
44                                 d = lerp = 1;
45                                 isfirstframegroup = false;
46                         }
47                         else
48                                 continue;
49                 }
50                 if (model->animscenes)
51                 {
52                         scene = model->animscenes + f;
53                         f = scene->firstframe;
54                         if (scene->framecount > 1)
55                         {
56                                 // this code path is only used on .zym models and torches
57                                 sublerp = scene->framerate * (cl.time - g->start);
58                                 f = (int) floor(sublerp);
59                                 sublerp -= f;
60                                 sub2 = f + 1;
61                                 if (nolerp)
62                                         sublerp = 0;
63                                 if (scene->loop)
64                                 {
65                                         f = (f % scene->framecount);
66                                         sub2 = (sub2 % scene->framecount);
67                                 }
68                                 f = bound(0, f, (scene->framecount - 1)) + scene->firstframe;
69                                 sub2 = bound(0, sub2, (scene->framecount - 1)) + scene->firstframe;
70                                 d = sublerp * lerp;
71                                 // two framelerps produced from one animation
72                                 if (f != sub2 && d > 0)
73                                 {
74                                         for (i = 0;i < MAX_FRAMEBLENDS;i++)
75                                         {
76                                                 if (blend[i].lerp <= 0 || blend[i].subframe == sub2)
77                                                 {
78                                                         blend[i].subframe = sub2;
79                                                         blend[i].lerp += d;
80                                                         break;
81                                                 }
82                                         }
83                                 }
84                                 d = (1 - sublerp) * lerp;
85                         }
86                 }
87                 if (d > 0)
88                 {
89                         for (i = 0;i < MAX_FRAMEBLENDS;i++)
90                         {
91                                 if (blend[i].lerp <= 0 || blend[i].subframe == f)
92                                 {
93                                         blend[i].subframe = f;
94                                         blend[i].lerp += d;
95                                         break;
96                                 }
97                         }
98                 }
99         }
100 }
101