bmodel rotation physics now work
[divverent/darkplaces.git] / r_sprites.c
1 #include "quakedef.h"
2
3 /*
4 ================
5 R_GetSpriteFrame
6 ================
7 */
8 void R_GetSpriteFrame (entity_t *currententity, mspriteframe_t **oldframe, mspriteframe_t **newframe, float *framelerp)
9 {
10         msprite_t               *psprite;
11         mspritegroup_t  *pspritegroup;
12         int                             i, j, numframes, frame;
13         float                   *pintervals, fullinterval, targettime, time, jtime, jinterval;
14
15         psprite = currententity->model->cache.data;
16         frame = currententity->frame;
17
18         if ((frame >= psprite->numframes) || (frame < 0))
19         {
20                 Con_Printf ("R_DrawSprite: no such frame %d\n", frame);
21                 frame = 0;
22         }
23
24         if (psprite->frames[frame].type == SPR_SINGLE)
25         {
26                 if (currententity->draw_lastmodel == currententity->model && currententity->draw_lerpstart < cl.time)
27                 {
28                         if (frame != currententity->draw_pose)
29                         {
30                                 currententity->draw_lastpose = currententity->draw_pose;
31                                 currententity->draw_pose = frame;
32                                 currententity->draw_lerpstart = cl.time;
33                                 *framelerp = 0;
34                         }
35                         else
36                                 *framelerp = (cl.time - currententity->draw_lerpstart) * 10.0;
37                 }
38                 else // uninitialized
39                 {
40                         currententity->draw_lastmodel = currententity->model;
41                         currententity->draw_lastpose = currententity->draw_pose = frame;
42                         currententity->draw_lerpstart = cl.time;
43                         *framelerp = 0;
44                 }
45                 *oldframe = psprite->frames[currententity->draw_lastpose].frameptr;
46                 *newframe = psprite->frames[frame].frameptr;
47         }
48         else
49         {
50                 pspritegroup = (mspritegroup_t *)psprite->frames[frame].frameptr;
51                 pintervals = pspritegroup->intervals;
52                 numframes = pspritegroup->numframes;
53                 fullinterval = pintervals[numframes-1];
54
55                 time = cl.time + currententity->syncbase;
56
57         // when loading in Mod_LoadSpriteGroup, we guaranteed all interval values
58         // are positive, so we don't have to worry about division by 0
59                 targettime = time - ((int)(time / fullinterval)) * fullinterval;
60
61                 // LordHavoc: since I can't measure the time properly when it loops from numframes-1 to 0,
62                 //            I instead measure the time of the first frame, hoping it is consistent
63                 j = numframes-1;jtime = 0;jinterval = pintervals[1] - pintervals[0];
64                 for (i=0 ; i<(numframes-1) ; i++)
65                 {
66                         if (pintervals[i] > targettime)
67                                 break;
68                         j = i;jinterval = pintervals[i] - jtime;jtime = pintervals[i];
69                 }
70                 *framelerp = (targettime - jtime) / jinterval;
71
72                 *oldframe = pspritegroup->frames[j];
73                 *newframe = pspritegroup->frames[i];
74         }
75 }
76
77 void GL_DrawSpriteImage (mspriteframe_t *frame, vec3_t origin, vec3_t up, vec3_t right, int red, int green, int blue, int alpha)
78 {
79         // LordHavoc: rewrote this to use the transparent poly system
80         transpolybegin(frame->gl_texturenum, 0, frame->gl_fogtexturenum, currententity->effects & EF_ADDITIVE ? TPOLYTYPE_ADD : TPOLYTYPE_ALPHA);
81         transpolyvert(origin[0] + frame->down * up[0] + frame->left * right[0], origin[1] + frame->down * up[1] + frame->left * right[1], origin[2] + frame->down * up[2] + frame->left * right[2], 0, 1, red, green, blue, alpha);
82         transpolyvert(origin[0] + frame->up * up[0] + frame->left * right[0], origin[1] + frame->up * up[1] + frame->left * right[1], origin[2] + frame->up * up[2] + frame->left * right[2], 0, 0, red, green, blue, alpha);
83         transpolyvert(origin[0] + frame->up * up[0] + frame->right * right[0], origin[1] + frame->up * up[1] + frame->right * right[1], origin[2] + frame->up * up[2] + frame->right * right[2], 1, 0, red, green, blue, alpha);
84         transpolyvert(origin[0] + frame->down * up[0] + frame->right * right[0], origin[1] + frame->down * up[1] + frame->right * right[1], origin[2] + frame->down * up[2] + frame->right * right[2], 1, 1, red, green, blue, alpha);
85         transpolyend();
86 }
87
88 /*
89 =================
90 R_DrawSpriteModel
91
92 =================
93 */
94 void R_DrawSpriteModel (entity_t *e)
95 {
96         mspriteframe_t  *oldframe, *newframe;
97         float                   lerp, ilerp;
98         vec3_t                  forward, right, up, org, color;
99         msprite_t               *psprite;
100
101         // don't even bother culling, because it's just a single
102         // polygon without a surface cache
103         R_GetSpriteFrame (e, &oldframe, &newframe, &lerp);
104         if (lerp < 0) lerp = 0;
105         if (lerp > 1) lerp = 1;
106         if (isRagePro) // LordHavoc: no alpha scaling supported on per pixel alpha images on ATI Rage Pro... ACK!
107                 lerp = 1;
108         ilerp = 1.0 - lerp;
109         psprite = e->model->cache.data;
110
111         if (psprite->type == SPR_ORIENTED)
112         {       // bullet marks on walls
113                 AngleVectors (e->angles, forward, right, up);
114                 VectorSubtract(e->origin, vpn, org);
115         }
116         else
117         {       // normal sprite
118                 VectorCopy(vup, up);
119                 VectorCopy(vright, right);
120                 VectorCopy(e->origin, org);
121         }
122         if (e->scale != 1)
123         {
124                 VectorScale(up, e->scale, up);
125                 VectorScale(right, e->scale, right);
126         }
127
128         if (e->model->flags & EF_FULLBRIGHT || e->effects & EF_FULLBRIGHT)
129         {
130                 color[0] = e->colormod[0] * 255;
131                 color[1] = e->colormod[1] * 255;
132                 color[2] = e->colormod[2] * 255;
133         }
134         else
135         {
136                 R_LightPoint (color, e->origin);
137                 R_DynamicLightPointNoMask(color, e->origin);
138         }
139
140         // LordHavoc: interpolated sprite rendering
141         if (ilerp != 0)
142                 GL_DrawSpriteImage(oldframe, org, up, right, color[0],color[1],color[2],e->alpha*255*ilerp);
143         if (lerp != 0)
144                 GL_DrawSpriteImage(newframe, org, up, right, color[0],color[1],color[2],e->alpha*255*lerp);
145 }
146