migrated r_lerpsprites cvar check to r_lerpanim, r_lerpmodels no longer affects sprites
[divverent/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 sub1, sub2, numframes, f, i, dolerp;
10         double sublerp, lerp, d;
11         animscene_t *scene;
12         frameblend_t *blend;
13         model_t *model = r->model;
14
15         blend = r->frameblend;
16         blend[0].frame = blend[1].frame = blend[2].frame = blend[3].frame = 0;
17         blend[0].lerp = blend[1].lerp = blend[2].lerp = blend[3].lerp = 0;
18
19         if (!model || !model->type)
20                 return;
21
22         numframes = model->numframes;
23
24         if (r->frame1 >= numframes)
25         {
26                 Con_DPrintf("CL_LerpAnimation: no such frame %d\n", r->frame1);
27                 r->frame1 = 0;
28         }
29
30         if (r->frame2 >= numframes)
31         {
32                 Con_DPrintf("CL_LerpAnimation: no such frame %d\n", r->frame2);
33                 r->frame2 = 0;
34         }
35
36         // note: this could be removed, if the rendering code allows an empty blend array
37         if (r->frame1 < 0)
38         {
39                 Con_Printf ("CL_LerpAnimation: frame1 is NULL\n");
40                 r->frame1 = 0;
41         }
42
43         // check r_lerpmodels and round off very close blend percentages
44         dolerp = (model->type == mod_sprite) ? r_lerpsprites.integer : r_lerpmodels.integer;
45
46         if (!dolerp || r->framelerp >= (65535.0f / 65536.0f))
47                 r->framelerp = 1;
48         else if (r->framelerp < (1.0f / 65536.0f))
49                 r->framelerp = 0;
50
51         if (model->animscenes)
52         {
53                 if (r->framelerp < 1 && r->frame1 >= 0)
54                 {
55                         scene = model->animscenes + r->frame1;
56                         lerp = 1 - r->framelerp;
57
58                         if (scene->framecount > 1)
59                         {
60                                 sublerp = scene->framerate * (cl.time - r->frame1time);
61                                 sub1 = (int) (sublerp);
62                                 sub2 = sub1 + 1;
63                                 sublerp -= sub1;
64                                 if (!dolerp)
65                                         sublerp = 0;
66                                 else if (sublerp >= (65535.0f / 65536.0f))
67                                         sublerp = 1;
68                                 else if (sublerp < (1.0f / 65536.0f))
69                                         sublerp = 0;
70                                 if (scene->loop)
71                                 {
72                                         sub1 = (sub1 % scene->framecount);
73                                         sub2 = (sub2 % scene->framecount);
74                                 }
75                                 sub1 = bound(0, sub1, (scene->framecount - 1)) + scene->firstframe;
76                                 sub2 = bound(0, sub2, (scene->framecount - 1)) + scene->firstframe;
77                                 f = sub1;
78                                 d = (1 - sublerp) * lerp;
79 #define FRAMEBLENDINSERT\
80                                 if (d > 0)\
81                                 {\
82                                         for (i = 0;i < 4;i++)\
83                                         {\
84                                                 if (blend[i].frame == f)\
85                                                 {\
86                                                         blend[i].lerp += d;\
87                                                         break;\
88                                                 }\
89                                                 if (blend[i].lerp <= 0)\
90                                                 {\
91                                                         blend[i].frame = f;\
92                                                         blend[i].lerp = d;\
93                                                         break;\
94                                                 }\
95                                         }\
96                                 }
97                                 FRAMEBLENDINSERT
98                                 f = sub2;
99                                 d = sublerp * lerp;
100                         }
101                         else
102                         {
103                                 f = scene->firstframe;
104                                 d = lerp;
105                         }
106                         FRAMEBLENDINSERT
107                 }
108                 if (r->framelerp > 0 && r->frame2 >= 0)
109                 {
110                         scene = model->animscenes + r->frame2;
111                         lerp = r->framelerp;
112
113                         if (scene->framecount > 1)
114                         {
115                                 sublerp = scene->framerate * (cl.time - r->frame1time);
116                                 sub1 = (int) (sublerp);
117                                 sub2 = sub1 + 1;
118                                 sublerp -= sub1;
119                                 if (!dolerp)
120                                         sublerp = 0;
121                                 else if (sublerp >= (65535.0f / 65536.0f))
122                                         sublerp = 1;
123                                 else if (sublerp < (1.0f / 65536.0f))
124                                         sublerp = 0;
125                                 if (scene->loop)
126                                 {
127                                         sub1 = (sub1 % scene->framecount);
128                                         sub2 = (sub2 % scene->framecount);
129                                 }
130                                 sub1 = bound(0, sub1, (scene->framecount - 1)) + scene->firstframe;
131                                 sub2 = bound(0, sub2, (scene->framecount - 1)) + scene->firstframe;
132                                 f = sub1;
133                                 d = (1 - sublerp) * lerp;
134                                 FRAMEBLENDINSERT
135                                 f = sub2;
136                                 d = sublerp * lerp;
137                         }
138                         else
139                         {
140                                 f = scene->firstframe;
141                                 d = lerp;
142                         }
143                         FRAMEBLENDINSERT
144                 }
145         }
146         else
147         {
148                 // if there are no scenes, assume it is all single-frame groups
149                 if (r->framelerp < 1 && r->frame1 >= 0)
150                 {
151                         f = r->frame1;
152                         d = 1 - r->framelerp;
153                         FRAMEBLENDINSERT
154                 }
155                 if (r->framelerp > 0 && r->frame2 >= 0)
156                 {
157                         f = r->frame2;
158                         d = r->framelerp;
159                         FRAMEBLENDINSERT
160                 }
161         }
162 }
163