]> icculus.org git repositories - divverent/darkplaces.git/blob - gl_rmain.c
explosions push away particles
[divverent/darkplaces.git] / gl_rmain.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 */
20 // r_main.c
21
22 #include "quakedef.h"
23
24 entity_t        r_worldentity;
25
26 qboolean        r_cache_thrash;         // compatability
27
28 vec3_t          modelorg, r_entorigin;
29 entity_t        *currententity;
30
31 int                     r_visframecount;        // bumped when going to a new PVS
32 int                     r_framecount;           // used for dlight push checking
33
34 mplane_t        frustum[4];
35
36 int                     c_brush_polys, c_alias_polys;
37
38 qboolean        envmap;                         // true during envmap command capture 
39
40 // LordHavoc: moved all code related to particles into r_part.c
41 //int                   particletexture;        // little dot for particles
42 int                     playertextures;         // up to 16 color translated skins
43
44 extern qboolean isG200, isRagePro; // LordHavoc: special card hacks
45
46 //
47 // view origin
48 //
49 vec3_t  vup;
50 vec3_t  vpn;
51 vec3_t  vright;
52 vec3_t  r_origin;
53
54 float   r_world_matrix[16];
55 float   r_base_world_matrix[16];
56
57 //
58 // screen size info
59 //
60 refdef_t        r_refdef;
61
62 mleaf_t         *r_viewleaf, *r_oldviewleaf;
63
64 texture_t       *r_notexture_mip;
65
66 int             d_lightstylevalue[256]; // 8.8 fraction of base light value
67
68
69 void R_MarkLeaves (void);
70
71 //cvar_t        r_norefresh = {"r_norefresh","0"};
72 cvar_t  r_drawentities = {"r_drawentities","1"};
73 cvar_t  r_drawviewmodel = {"r_drawviewmodel","1"};
74 cvar_t  r_speeds = {"r_speeds","0"};
75 cvar_t  r_speeds2 = {"r_speeds2","0"};
76 cvar_t  r_fullbright = {"r_fullbright","0"};
77 //cvar_t        r_lightmap = {"r_lightmap","0"};
78 cvar_t  r_shadows = {"r_shadows","0"};
79 cvar_t  r_wateralpha = {"r_wateralpha","1"};
80 cvar_t  r_dynamic = {"r_dynamic","1"};
81 cvar_t  r_novis = {"r_novis","0"};
82 cvar_t  r_waterripple = {"r_waterripple","0"};
83 cvar_t  r_fullbrights = {"r_fullbrights", "1"};
84
85 //cvar_t        gl_cull = {"gl_cull","1"};
86 //cvar_t        gl_affinemodels = {"gl_affinemodels","0"};
87 //cvar_t        gl_polyblend = {"gl_polyblend","1"};
88 //cvar_t        gl_flashblend = {"gl_flashblend","0"};
89 cvar_t  gl_playermip = {"gl_playermip","0"};
90 //cvar_t        gl_nocolors = {"gl_nocolors","0"};
91 //cvar_t        gl_keeptjunctions = {"gl_keeptjunctions","1"};
92 //cvar_t        gl_reporttjunctions = {"gl_reporttjunctions","0"};
93 cvar_t  contrast = {"contrast", "1.0", TRUE}; // LordHavoc: a method of operating system independent color correction
94 cvar_t  brightness = {"brightness", "1.0", TRUE}; // LordHavoc: a method of operating system independent color correction
95 cvar_t  gl_lightmode = {"gl_lightmode", "1", TRUE}; // LordHavoc: overbright lighting
96 //cvar_t        r_dynamicwater = {"r_dynamicwater", "1"};
97 //cvar_t        r_dynamicbothsides = {"r_dynamicbothsides", "1"}; // LordHavoc: can disable dynamic lighting of backfaces, but quake maps are weird so it doesn't always work right...
98 cvar_t  r_farclip = {"r_farclip", "6144"};
99
100 cvar_t  gl_fogenable = {"gl_fogenable", "0"};
101 cvar_t  gl_fogdensity = {"gl_fogdensity", "0.25"};
102 cvar_t  gl_fogred = {"gl_fogred","0.3"};
103 cvar_t  gl_foggreen = {"gl_foggreen","0.3"};
104 cvar_t  gl_fogblue = {"gl_fogblue","0.3"};
105 cvar_t  gl_fogstart = {"gl_fogstart", "0"};
106 cvar_t  gl_fogend = {"gl_fogend","0"};
107 cvar_t  glfog = {"glfog", "0"};
108
109 int chrometexture;
110
111 void makechrometextures()
112 {
113         int x, y, g, g2, amplitude, noise[64][64], min, max;
114         byte data[64][64][4];
115         //
116         // particle texture
117         //
118         chrometexture = texture_extension_number++;
119     glBindTexture(GL_TEXTURE_2D, chrometexture);
120
121 #define n(x,y) noise[(y)&63][(x)&63]
122
123         amplitude = 16777215;
124         g2 = 64;
125         noise[0][0] = 0;
126         for (;(g = g2 >> 1) >= 1;g2 >>= 1)
127         {
128                 // subdivide, diamond-square algorythm (really this has little to do with squares)
129                 // diamond
130                 for (y = 0;y < 64;y += g2)
131                         for (x = 0;x < 64;x += g2)
132                                 n(x+g,y+g) = (n(x,y) + n(x+g2,y) + n(x,y+g2) + n(x+g2,y+g2)) >> 2;
133                 // square
134                 for (y = 0;y < 64;y += g2)
135                         for (x = 0;x < 64;x += g2)
136                         {
137                                 n(x+g,y) = (n(x,y) + n(x+g2,y) + n(x+g,y-g) + n(x+g,y+g)) >> 2;
138                                 n(x,y+g) = (n(x,y) + n(x,y+g2) + n(x-g,y+g) + n(x+g,y+g)) >> 2;
139                         }
140                 // brownian motion theory
141                 amplitude >>= 1;
142                 for (y = 0;y < 64;y += g)
143                         for (x = 0;x < 64;x += g)
144                                 noise[y][x] += rand()&amplitude;
145         }
146         // normalize the noise range
147         min = max = 0;
148         for (y = 0;y < 64;y++)
149                 for (x = 0;x < 64;x++)
150                 {
151                         if (n(x,y) < min) min = n(x,y);
152                         if (n(x,y) > max) max = n(x,y);
153                 }
154         max -= min;
155         for (y = 0;y < 64;y++)
156                 for (x = 0;x < 64;x++)
157                         n(x,y) = (n(x,y) - min) * 255 / max;
158
159 #undef n
160
161         // convert to RGBA data
162         for (y = 0;y < 64;y++)
163                 for (x = 0;x < 64;x++)
164                 {
165                         data[y][x][0] = data[y][x][1] = data[y][x][2] = (byte) noise[y][x];
166                         data[y][x][3] = 255;
167                 }
168
169         glTexImage2D (GL_TEXTURE_2D, 0, 4, 64, 64, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
170
171         glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
172
173         glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
174         glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
175 }
176
177 extern qboolean isRagePro;
178
179 qboolean lighthalf;
180
181 vec3_t fogcolor;
182 vec_t fogdensity;
183 float fog_density, fog_red, fog_green, fog_blue;
184 qboolean fogenabled;
185 qboolean oldgl_fogenable;
186 void FOG_framebegin()
187 {
188         if (nehahra)
189         {
190 //              if (!Nehahrademcompatibility)
191 //                      gl_fogenable.value = 0;
192                 if (gl_fogenable.value)
193                 {
194                         oldgl_fogenable = true;
195                         fog_density = gl_fogdensity.value;
196                         fog_red = gl_fogred.value;
197                         fog_green = gl_foggreen.value;
198                         fog_blue = gl_fogblue.value;
199                 }
200                 else if (oldgl_fogenable)
201                 {
202                         oldgl_fogenable = false;
203                         fog_density = 0;
204                         fog_red = 0;
205                         fog_green = 0;
206                         fog_blue = 0;
207                 }
208         }
209         if (glfog.value)
210         {
211                 if(fog_density)
212                 {
213                         // LordHavoc: Borland C++ 5.0 was choking on this line, stupid compiler...
214                         //GLfloat colors[4] = {(GLfloat) gl_fogred.value, (GLfloat) gl_foggreen.value, (GLfloat) gl_fogblue.value, (GLfloat) 1};
215                         GLfloat colors[4];
216                         colors[0] = fog_red;
217                         colors[1] = fog_green;
218                         colors[2] = fog_blue;
219                         colors[3] = 1;
220                         if (lighthalf)
221                         {
222                                 colors[0] *= 0.5f;
223                                 colors[1] *= 0.5f;
224                                 colors[2] *= 0.5f;
225                         }
226
227                         glFogi (GL_FOG_MODE, GL_EXP2);
228                         glFogf (GL_FOG_DENSITY, (GLfloat) fog_density / 100); 
229                         glFogfv (GL_FOG_COLOR, colors);
230                         glEnable (GL_FOG);
231                 }
232                 else
233                         glDisable(GL_FOG);
234         }
235         else
236         {
237                 if (fog_density)
238                 {
239                         fogenabled = true;
240                         fogdensity = -4000.0f / (fog_density * fog_density);
241                         fogcolor[0] = fog_red   = bound(0.0f, fog_red  , 1.0f);
242                         fogcolor[1] = fog_green = bound(0.0f, fog_green, 1.0f);
243                         fogcolor[2] = fog_blue  = bound(0.0f, fog_blue , 1.0f);
244                         if (lighthalf)
245                         {
246                                 fogcolor[0] *= 0.5f;
247                                 fogcolor[1] *= 0.5f;
248                                 fogcolor[2] *= 0.5f;
249                         }
250                 }
251                 else
252                         fogenabled = false;
253         }
254 }
255
256 void FOG_frameend()
257 {
258         if (glfog.value)
259                 glDisable(GL_FOG);
260 }
261
262 void FOG_clear()
263 {
264         if (nehahra)
265         {
266                 Cvar_Set("gl_fogenable", "0");
267                 Cvar_Set("gl_fogdensity", "0.2");
268                 Cvar_Set("gl_fogred", "0.3");
269                 Cvar_Set("gl_foggreen", "0.3");
270                 Cvar_Set("gl_fogblue", "0.3");
271         }
272         fog_density = fog_red = fog_green = fog_blue = 0.0f;
273 }
274
275 void FOG_registercvars()
276 {
277         Cvar_RegisterVariable (&glfog);
278         if (nehahra)
279         {
280                 Cvar_RegisterVariable (&gl_fogenable);
281                 Cvar_RegisterVariable (&gl_fogdensity);
282                 Cvar_RegisterVariable (&gl_fogred);
283                 Cvar_RegisterVariable (&gl_foggreen); 
284                 Cvar_RegisterVariable (&gl_fogblue);
285                 Cvar_RegisterVariable (&gl_fogstart);
286                 Cvar_RegisterVariable (&gl_fogend);
287         }
288 }
289
290 void glpoly_init();
291 void glrsurf_init();
292 void rlight_init();
293
294 // LordHavoc: vertex array
295 float *aliasvert;
296 float *aliasvertnorm;
297 byte *aliasvertcolor;
298
299 void rmain_registercvars()
300 {
301         // allocate vertex processing arrays
302         aliasvert = malloc(sizeof(float[MD2MAX_VERTS][3]));
303         aliasvertnorm = malloc(sizeof(float[MD2MAX_VERTS][3]));
304         aliasvertcolor = malloc(sizeof(byte[MD2MAX_VERTS][4]));
305
306         FOG_registercvars();
307         Cvar_RegisterVariable (&r_speeds2);
308         Cvar_RegisterVariable (&contrast);
309         Cvar_RegisterVariable (&brightness);
310         Cvar_RegisterVariable (&gl_lightmode);
311 //      Cvar_RegisterVariable (&r_dynamicwater);
312 //      Cvar_RegisterVariable (&r_dynamicbothsides);
313         Cvar_RegisterVariable (&r_fullbrights);
314         if (nehahra)
315                 Cvar_SetValue("r_fullbrights", 0);
316 //      if (gl_vendor && strstr(gl_vendor, "3Dfx"))
317 //              gl_lightmode.value = 0;
318         Cvar_RegisterVariable (&r_fullbright);
319         makechrometextures();
320         glpoly_init();
321         glrsurf_init();
322         rlight_init();
323 }
324
325 /*
326 void R_RotateForEntity (entity_t *e)
327 {
328         glTranslatef (e->origin[0],  e->origin[1],  e->origin[2]);
329
330         glRotatef (e->angles[1],  0, 0, 1);
331         glRotatef (-e->angles[0],  0, 1, 0);
332         glRotatef (e->angles[2],  1, 0, 0);
333
334         glScalef (e->scale, e->scale, e->scale); // LordHavoc: model scale
335 }
336 */
337
338 // LordHavoc: if not for the fact BRIGHTFIELD particles require this, it would be removed...
339 #define NUMVERTEXNORMALS        162
340
341 float   r_avertexnormals[NUMVERTEXNORMALS][3] = {
342 #include "anorms.h"
343 };
344
345 // LordHavoc: moved this shading stuff up because the sprites need shading stuff
346 vec3_t  shadevector;
347 vec3_t  shadecolor;
348
349 float   modelalpha;
350
351 void R_LightPoint (vec3_t color, vec3_t p);
352 void R_DynamicLightPoint(vec3_t color, vec3_t org, int *dlightbits);
353 void R_DynamicLightPointNoMask(vec3_t color, vec3_t org);
354
355 float R_CalcAnimLerp(int pose, float lerpscale)
356 {
357         if (currententity->draw_lastmodel == currententity->model && currententity->draw_lerpstart <= cl.time)
358         {
359                 if (pose != currententity->draw_pose)
360                 {
361                         currententity->draw_lastpose = currententity->draw_pose;
362                         currententity->draw_pose = pose;
363                         currententity->draw_lerpstart = cl.time;
364                         return 0;
365                 }
366                 else
367                         return ((cl.time - currententity->draw_lerpstart) * lerpscale);
368         }
369         else // uninitialized
370         {
371                 currententity->draw_lastmodel = currententity->model;
372                 currententity->draw_lastpose = currententity->draw_pose = pose;
373                 currententity->draw_lerpstart = cl.time;
374                 return 0;
375         }
376 }
377
378 /*
379 =============================================================
380
381   SPRITE MODELS
382
383 =============================================================
384 */
385
386 /*
387 ================
388 R_GetSpriteFrame
389 ================
390 */
391 void R_GetSpriteFrame (entity_t *currententity, mspriteframe_t **oldframe, mspriteframe_t **newframe, float *framelerp)
392 {
393         msprite_t               *psprite;
394         mspritegroup_t  *pspritegroup;
395         int                             i, j, numframes, frame;
396         float                   *pintervals, fullinterval, targettime, time, jtime, jinterval;
397
398         psprite = currententity->model->cache.data;
399         frame = currententity->frame;
400
401         if ((frame >= psprite->numframes) || (frame < 0))
402         {
403                 Con_Printf ("R_DrawSprite: no such frame %d\n", frame);
404                 frame = 0;
405         }
406
407         if (psprite->frames[frame].type == SPR_SINGLE)
408         {
409                 if (currententity->draw_lastmodel == currententity->model && currententity->draw_lerpstart < cl.time)
410                 {
411                         if (frame != currententity->draw_pose)
412                         {
413                                 currententity->draw_lastpose = currententity->draw_pose;
414                                 currententity->draw_pose = frame;
415                                 currententity->draw_lerpstart = cl.time;
416                                 *framelerp = 0;
417                         }
418                         else
419                                 *framelerp = (cl.time - currententity->draw_lerpstart) * 10.0;
420                 }
421                 else // uninitialized
422                 {
423                         currententity->draw_lastmodel = currententity->model;
424                         currententity->draw_lastpose = currententity->draw_pose = frame;
425                         currententity->draw_lerpstart = cl.time;
426                         *framelerp = 0;
427                 }
428                 *oldframe = psprite->frames[currententity->draw_lastpose].frameptr;
429                 *newframe = psprite->frames[frame].frameptr;
430         }
431         else
432         {
433                 pspritegroup = (mspritegroup_t *)psprite->frames[frame].frameptr;
434                 pintervals = pspritegroup->intervals;
435                 numframes = pspritegroup->numframes;
436                 fullinterval = pintervals[numframes-1];
437
438                 time = cl.time + currententity->syncbase;
439
440         // when loading in Mod_LoadSpriteGroup, we guaranteed all interval values
441         // are positive, so we don't have to worry about division by 0
442                 targettime = time - ((int)(time / fullinterval)) * fullinterval;
443
444                 // LordHavoc: since I can't measure the time properly when it loops from numframes-1 to 0,
445                 //            I instead measure the time of the first frame, hoping it is consistent
446                 j = numframes-1;jtime = 0;jinterval = pintervals[1] - pintervals[0];
447                 for (i=0 ; i<(numframes-1) ; i++)
448                 {
449                         if (pintervals[i] > targettime)
450                                 break;
451                         j = i;jinterval = pintervals[i] - jtime;jtime = pintervals[i];
452                 }
453                 *framelerp = (targettime - jtime) / jinterval;
454
455                 *oldframe = pspritegroup->frames[j];
456                 *newframe = pspritegroup->frames[i];
457         }
458 }
459
460 void GL_DrawSpriteImage (mspriteframe_t *frame, vec3_t origin, vec3_t up, vec3_t right, int red, int green, int blue, int alpha)
461 {
462         // LordHavoc: rewrote this to use the transparent poly system
463         transpolybegin(frame->gl_texturenum, 0, frame->gl_fogtexturenum, currententity->effects & EF_ADDITIVE ? TPOLYTYPE_ADD : TPOLYTYPE_ALPHA);
464         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);
465         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);
466         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);
467         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);
468         transpolyend();
469 }
470
471 extern qboolean isG200, isRagePro, lighthalf;
472
473 /*
474 =================
475 R_DrawSpriteModel
476
477 =================
478 */
479 void R_DrawSpriteModel (entity_t *e)
480 {
481         mspriteframe_t  *oldframe, *newframe;
482         float           *up, *right, lerp, ilerp;
483         vec3_t          v_forward, v_right, v_up, org;
484         msprite_t               *psprite;
485
486         // don't even bother culling, because it's just a single
487         // polygon without a surface cache
488         R_GetSpriteFrame (e, &oldframe, &newframe, &lerp);
489         if (lerp < 0) lerp = 0;
490         if (lerp > 1) lerp = 1;
491         if (isRagePro) // LordHavoc: no alpha scaling supported on per pixel alpha images on ATI Rage Pro... ACK!
492                 lerp = 1;
493         ilerp = 1.0 - lerp;
494         psprite = e->model->cache.data;
495
496         if (psprite->type == SPR_ORIENTED)
497         {       // bullet marks on walls
498                 AngleVectors (e->angles, v_forward, v_right, v_up);
499                 up = v_up;
500                 right = v_right;
501                 VectorSubtract(e->origin, vpn, org);
502         }
503         else
504         {       // normal sprite
505                 up = vup;
506                 right = vright;
507                 VectorCopy(e->origin, org);
508         }
509         if (e->scale != 1)
510         {
511                 VectorScale(up, e->scale, up);
512                 VectorScale(right, e->scale, right);
513         }
514
515         if (e->model->flags & EF_FULLBRIGHT || e->effects & EF_FULLBRIGHT)
516         {
517                 if (lighthalf)
518                 {
519                         shadecolor[0] = e->colormod[0] * 128;
520                         shadecolor[1] = e->colormod[1] * 128;
521                         shadecolor[2] = e->colormod[2] * 128;
522                 }
523                 else
524                 {
525                         shadecolor[0] = e->colormod[0] * 255;
526                         shadecolor[1] = e->colormod[1] * 255;
527                         shadecolor[2] = e->colormod[2] * 255;
528                 }
529         }
530         else
531         {
532                 R_LightPoint (shadecolor, e->origin);
533                 R_DynamicLightPointNoMask(shadecolor, e->origin);
534                 if (lighthalf)
535                 {
536                         shadecolor[0] *= e->colormod[0] * 0.5;
537                         shadecolor[1] *= e->colormod[1] * 0.5;
538                         shadecolor[2] *= e->colormod[2] * 0.5;
539                 }
540         }
541
542         // LordHavoc: interpolated sprite rendering
543         if (ilerp != 0)
544                 GL_DrawSpriteImage(oldframe, org, up, right, shadecolor[0],shadecolor[1],shadecolor[2],e->alpha*255*ilerp);
545         if (lerp != 0)
546                 GL_DrawSpriteImage(newframe, org, up, right, shadecolor[0],shadecolor[1],shadecolor[2],e->alpha*255*lerp);
547 }
548
549 /*
550 =============================================================
551
552   ALIAS MODELS
553
554 =============================================================
555 */
556
557 extern vec3_t softwaretransform_x;
558 extern vec3_t softwaretransform_y;
559 extern vec3_t softwaretransform_z;
560 extern vec_t softwaretransform_scale;
561 extern vec3_t softwaretransform_offset;
562 void R_AliasLerpVerts(int vertcount, float lerp, trivert2 *verts1, vec3_t scale1, vec3_t translate1, trivert2 *verts2, vec3_t scale2, vec3_t translate2)
563 {
564         int i;
565         vec3_t point, matrix_x, matrix_y, matrix_z;
566         float *av, *avn;
567         av = aliasvert;
568         avn = aliasvertnorm;
569         if (lerp < 0) lerp = 0;
570         if (lerp > 1) lerp = 1;
571         if (lerp != 0)
572         {
573                 float ilerp, ilerp127, lerp127, scalex1, scalex2, translatex, scaley1, scaley2, translatey, scalez1, scalez2, translatez;
574                 if (lerp < 0) lerp = 0;
575                 if (lerp > 1) lerp = 1;
576                 ilerp = 1 - lerp;
577                 ilerp127 = ilerp * (1.0 / 127.0);
578                 lerp127 = lerp * (1.0 / 127.0);
579                 VectorScale(softwaretransform_x, softwaretransform_scale, matrix_x);
580                 VectorScale(softwaretransform_y, softwaretransform_scale, matrix_y);
581                 VectorScale(softwaretransform_z, softwaretransform_scale, matrix_z);
582                 // calculate combined interpolation variables
583                 scalex1 = scale1[0] * ilerp;scalex2 = scale2[0] *  lerp;translatex = translate1[0] * ilerp + translate2[0] *  lerp;
584                 scaley1 = scale1[1] * ilerp;scaley2 = scale2[1] *  lerp;translatey = translate1[1] * ilerp + translate2[1] *  lerp;
585                 scalez1 = scale1[2] * ilerp;scalez2 = scale2[2] *  lerp;translatez = translate1[2] * ilerp + translate2[2] *  lerp;
586                 // generate vertices
587                 for (i = 0;i < vertcount;i++)
588                 {
589                         // rotate, scale, and translate the vertex locations
590                         point[0] = verts1->v[0] * scalex1 + verts2->v[0] * scalex2 + translatex;
591                         point[1] = verts1->v[1] * scaley1 + verts2->v[1] * scaley2 + translatey;
592                         point[2] = verts1->v[2] * scalez1 + verts2->v[2] * scalez2 + translatez;
593                         *av++ = point[0] * matrix_x[0] + point[1] * matrix_y[0] + point[2] * matrix_z[0] + softwaretransform_offset[0];
594                         *av++ = point[0] * matrix_x[1] + point[1] * matrix_y[1] + point[2] * matrix_z[1] + softwaretransform_offset[1];
595                         *av++ = point[0] * matrix_x[2] + point[1] * matrix_y[2] + point[2] * matrix_z[2] + softwaretransform_offset[2];
596                         // rotate the normals
597                         point[0] = verts1->n[0] * ilerp127 + verts2->n[0] * lerp127;
598                         point[1] = verts1->n[1] * ilerp127 + verts2->n[1] * lerp127;
599                         point[2] = verts1->n[2] * ilerp127 + verts2->n[2] * lerp127;
600                         *avn++ = point[0] * softwaretransform_x[0] + point[1] * softwaretransform_y[0] + point[2] * softwaretransform_z[0];
601                         *avn++ = point[0] * softwaretransform_x[1] + point[1] * softwaretransform_y[1] + point[2] * softwaretransform_z[1];
602                         *avn++ = point[0] * softwaretransform_x[2] + point[1] * softwaretransform_y[2] + point[2] * softwaretransform_z[2];
603                         verts1++;verts2++;
604                 }
605         }
606         else
607         {
608                 float i127;
609                 i127 = 1.0f / 127.0f;
610                 VectorScale(softwaretransform_x, softwaretransform_scale, matrix_x);
611                 VectorScale(softwaretransform_y, softwaretransform_scale, matrix_y);
612                 VectorScale(softwaretransform_z, softwaretransform_scale, matrix_z);
613                 // generate vertices
614                 for (i = 0;i < vertcount;i++)
615                 {
616                         // rotate, scale, and translate the vertex locations
617                         point[0] = verts1->v[0] * scale1[0] + translate1[0];
618                         point[1] = verts1->v[1] * scale1[1] + translate1[1];
619                         point[2] = verts1->v[2] * scale1[2] + translate1[2];
620                         *av++ = point[0] * matrix_x[0] + point[1] * matrix_y[0] + point[2] * matrix_z[0] + softwaretransform_offset[0];
621                         *av++ = point[0] * matrix_x[1] + point[1] * matrix_y[1] + point[2] * matrix_z[1] + softwaretransform_offset[1];
622                         *av++ = point[0] * matrix_x[2] + point[1] * matrix_y[2] + point[2] * matrix_z[2] + softwaretransform_offset[2];
623                         // rotate the normals
624                         point[0] = verts1->n[0] * i127;
625                         point[1] = verts1->n[1] * i127;
626                         point[2] = verts1->n[2] * i127;
627                         *avn++ = point[0] * softwaretransform_x[0] + point[1] * softwaretransform_y[0] + point[2] * softwaretransform_z[0];
628                         *avn++ = point[0] * softwaretransform_x[1] + point[1] * softwaretransform_y[1] + point[2] * softwaretransform_z[1];
629                         *avn++ = point[0] * softwaretransform_x[2] + point[1] * softwaretransform_y[2] + point[2] * softwaretransform_z[2];
630                         verts1++;
631                 }
632         }
633 }
634
635 /*
636 =================
637 R_DrawAliasFrame
638
639 =================
640 */
641 extern vec3_t lightspot;
642 void R_LightModel(int numverts, vec3_t center);
643 extern cvar_t gl_vertexarrays;
644 void R_DrawAliasFrame (aliashdr_t *paliashdr)
645 {
646         int                             i, pose, frame = currententity->frame;
647         float                   lerpscale, lerp;
648
649         softwaretransformforentity(currententity);
650
651         if ((frame >= paliashdr->numframes) || (frame < 0))
652         {
653                 Con_DPrintf ("R_AliasSetupFrame: no such frame %d\n", frame);
654                 frame = 0;
655         }
656
657         pose = paliashdr->frames[frame].firstpose;
658
659         if (paliashdr->frames[frame].numposes > 1)
660         {
661                 lerpscale = 1.0 / paliashdr->frames[frame].interval;
662                 pose += (int)(cl.time * lerpscale) % paliashdr->frames[frame].numposes;
663         }
664         else
665                 lerpscale = 10.0;
666
667         lerp = R_CalcAnimLerp(pose, lerpscale);
668
669         R_AliasLerpVerts(paliashdr->numverts, lerp, (trivert2 *)((byte *)paliashdr + paliashdr->posedata) + currententity->draw_lastpose * paliashdr->numverts, paliashdr->scale, paliashdr->scale_origin, (trivert2 *)((byte *)paliashdr + paliashdr->posedata) + currententity->draw_pose * paliashdr->numverts, paliashdr->scale, paliashdr->scale_origin);
670
671         R_LightModel(paliashdr->numverts, currententity->origin);
672
673         glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
674         glShadeModel(GL_SMOOTH);
675         if (currententity->effects & EF_ADDITIVE)
676         {
677                 glBlendFunc(GL_SRC_ALPHA, GL_ONE); // additive rendering
678                 glEnable(GL_BLEND);
679                 glDepthMask(0);
680         }
681         else if (modelalpha != 1.0)
682         {
683                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
684                 glEnable(GL_BLEND);
685                 glDepthMask(0);
686         }
687         else
688         {
689                 glDisable(GL_BLEND);
690                 glDepthMask(1);
691         }
692
693         if (gl_vertexarrays.value)
694         {
695                 // LordHavoc: I would use InterleavedArrays here,
696                 // but the texture coordinates are a seperate array,
697                 // and it would be wasteful to copy them into the main array...
698         //      glColor4f(shadecolor[0], shadecolor[1], shadecolor[2], modelalpha);
699                 qglVertexPointer(3, GL_FLOAT, 0, aliasvert);
700                 qglColorPointer(4, GL_UNSIGNED_BYTE, 0, aliasvertcolor);
701                 glEnableClientState(GL_VERTEX_ARRAY);
702                 glEnableClientState(GL_COLOR_ARRAY);
703
704                 // draw the front faces
705                 qglTexCoordPointer(2, GL_FLOAT, 0, (void *)((int) paliashdr->texcoords + (int) paliashdr));
706                 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
707                 qglDrawElements(GL_TRIANGLES, paliashdr->frontfaces * 3, GL_UNSIGNED_SHORT, (void *)((int) paliashdr->vertindices + (int) paliashdr));
708                 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
709
710                 // draw the back faces
711                 qglTexCoordPointer(2, GL_FLOAT, 0, (void *)((int) paliashdr->texcoords + sizeof(float[2]) * paliashdr->numverts + (int) paliashdr));
712                 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
713                 qglDrawElements(GL_TRIANGLES, paliashdr->backfaces * 3, GL_UNSIGNED_SHORT, (void *)((int) paliashdr->vertindices + sizeof(unsigned short[3]) * paliashdr->frontfaces + (int) paliashdr));
714                 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
715
716                 glDisableClientState(GL_COLOR_ARRAY);
717                 glDisableClientState(GL_VERTEX_ARRAY);
718         }
719         else
720         {
721                 unsigned short *in, index;
722                 float *tex;
723                 in = (void *)((int) paliashdr->vertindices + (int) paliashdr);
724                 glBegin(GL_TRIANGLES);
725                 // draw the front faces
726                 tex = (void *)((int) paliashdr->texcoords + (int) paliashdr);
727                 //if (isG200)
728                 //{
729                         for (i = 0;i < paliashdr->frontfaces * 3;i++)
730                         {
731                                 index = *in++;
732                                 glTexCoord2f(tex[index*2], tex[index*2+1]);
733                                 glColor4f(aliasvertcolor[index*4] * (1.0f / 255.0f), aliasvertcolor[index*4+1] * (1.0f / 255.0f), aliasvertcolor[index*4+2] * (1.0f / 255.0f), aliasvertcolor[index*4+3] * (1.0f / 255.0f));
734                                 glVertex3fv(&aliasvert[index*3]);
735                         }
736                 /*
737                 }
738                 else
739                 {
740                         for (i = 0;i < paliashdr->frontfaces * 3;i++)
741                         {
742                                 index = *in++;
743                                 glTexCoord2f(tex[index*2], tex[index*2+1]);
744                                 glColor4ub(aliasvertcolor[index*4], aliasvertcolor[index*4+1], aliasvertcolor[index*4+2], aliasvertcolor[index*4+3]);
745                                 glVertex3fv(&aliasvert[index*3]);
746                         }
747                 }
748                 */
749                 // draw the back faces
750                 tex += 2 * paliashdr->numverts;
751                 //if (isG200)
752                 //{
753                         for (i = 0;i < paliashdr->backfaces * 3;i++)
754                         {
755                                 index = *in++;
756                                 glTexCoord2f(tex[index*2], tex[index*2+1]);
757                                 glColor4f(aliasvertcolor[index*4] * (1.0f / 255.0f), aliasvertcolor[index*4+1] * (1.0f / 255.0f), aliasvertcolor[index*4+2] * (1.0f / 255.0f), aliasvertcolor[index*4+3] * (1.0f / 255.0f));
758                                 glVertex3fv(&aliasvert[index*3]);
759                         }
760                 /*
761                 }
762                 else
763                 {
764                         for (i = 0;i < paliashdr->backfaces * 3;i++)
765                         {
766                                 index = *in++;
767                                 glTexCoord2f(tex[index*2], tex[index*2+1]);
768                                 glColor4ub(aliasvertcolor[index*4], aliasvertcolor[index*4+1], aliasvertcolor[index*4+2], aliasvertcolor[index*4+3]);
769                                 glVertex3fv(&aliasvert[index*3]);
770                         }
771                 }
772                 */
773                 glEnd();
774         }
775
776         if (fogenabled)
777         {
778                 vec3_t diff;
779                 glDisable (GL_TEXTURE_2D);
780                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
781                 glEnable (GL_BLEND);
782                 glDepthMask(0); // disable zbuffer updates
783
784                 VectorSubtract(currententity->origin, r_refdef.vieworg, diff);
785                 glColor4f(fogcolor[0], fogcolor[1], fogcolor[2], exp(fogdensity/DotProduct(diff,diff)));
786
787                 if (gl_vertexarrays.value)
788                 {
789                         qglVertexPointer(3, GL_FLOAT, 0, aliasvert);
790                         glEnableClientState(GL_VERTEX_ARRAY);
791                         qglDrawElements(GL_TRIANGLES, paliashdr->numtris * 3, GL_UNSIGNED_SHORT, (void *)((int) paliashdr->vertindices + (int) paliashdr));
792                         glDisableClientState(GL_VERTEX_ARRAY);
793                 }
794                 else
795                 {
796                         unsigned short *in;
797                         in = (void *)((int) paliashdr->vertindices + (int) paliashdr);
798                         glBegin(GL_TRIANGLES);
799                         for (i = 0;i < paliashdr->numtris * 3;i++)
800                                 glVertex3fv(&aliasvert[*in++ * 3]);
801                         glEnd();
802                 }
803
804                 glEnable (GL_TEXTURE_2D);
805                 glColor3f (1,1,1);
806         }
807
808         if (!fogenabled && r_shadows.value && !(currententity->effects & EF_ADDITIVE) && currententity != &cl.viewent)
809         {
810                 // flatten it to make a shadow
811                 float *av = aliasvert + 2, l = lightspot[2] + 0.125;
812                 av = aliasvert + 2;
813                 for (i = 0;i < paliashdr->numverts;i++, av+=3)
814                         if (*av > l)
815                                 *av = l;
816                 glDisable (GL_TEXTURE_2D);
817                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
818                 glEnable (GL_BLEND);
819                 glDepthMask(0); // disable zbuffer updates
820                 glColor4f (0,0,0,0.5 * modelalpha);
821
822                 if (gl_vertexarrays.value)
823                 {
824                         qglVertexPointer(3, GL_FLOAT, 0, aliasvert);
825                         glEnableClientState(GL_VERTEX_ARRAY);
826                         qglDrawElements(GL_TRIANGLES, paliashdr->numtris * 3, GL_UNSIGNED_SHORT, (void *)((int) paliashdr->vertindices + (int) paliashdr));
827                         glDisableClientState(GL_VERTEX_ARRAY);
828                 }
829                 else
830                 {
831                         unsigned short *in;
832                         in = (void *)((int) paliashdr->vertindices + (int) paliashdr);
833                         glBegin(GL_TRIANGLES);
834                         for (i = 0;i < paliashdr->numtris * 3;i++)
835                                 glVertex3fv(&aliasvert[*in++ * 3]);
836                         glEnd();
837                 }
838
839                 glEnable (GL_TEXTURE_2D);
840                 glColor3f (1,1,1);
841         }
842
843         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
844         glEnable (GL_BLEND);
845         glDepthMask(1);
846 }
847
848 /*
849 =================
850 R_DrawQ2AliasFrame
851
852 =================
853 */
854 void R_DrawQ2AliasFrame (md2mem_t *pheader)
855 {
856         int *order, count, frame = currententity->frame;
857         float lerp;
858         md2memframe_t *frame1, *frame2;
859
860         softwaretransformforentity(currententity);
861
862         if ((frame >= pheader->num_frames) || (frame < 0))
863         {
864                 Con_DPrintf ("R_SetupQ2AliasFrame: no such frame %d\n", frame);
865                 frame = 0;
866         }
867
868         lerp = R_CalcAnimLerp(frame, 10);
869
870         frame1 = (void *)((int) pheader + pheader->ofs_frames + (pheader->framesize * currententity->draw_lastpose));
871         frame2 = (void *)((int) pheader + pheader->ofs_frames + (pheader->framesize * currententity->draw_pose));
872         R_AliasLerpVerts(pheader->num_xyz, lerp, frame1->verts, frame1->scale, frame1->translate, frame2->verts, frame2->scale, frame2->translate);
873
874         R_LightModel(pheader->num_xyz, currententity->origin);
875
876         if (gl_vertexarrays.value)
877         {
878                 // LordHavoc: big mess...
879                 // using arrays only slightly, although it is enough to prevent duplicates
880                 // (saving half the transforms)
881                 //glColor4f(shadecolor[0], shadecolor[1], shadecolor[2], modelalpha);
882                 qglVertexPointer(3, GL_FLOAT, 0, aliasvert);
883                 qglColorPointer(4, GL_UNSIGNED_BYTE, 0, aliasvertcolor);
884                 glEnableClientState(GL_VERTEX_ARRAY);
885                 glEnableClientState(GL_COLOR_ARRAY);
886
887                 order = (int *)((int)pheader + pheader->ofs_glcmds);
888                 while(1)
889                 {
890                         if (!(count = *order++))
891                                 break;
892                         if (count > 0)
893                                 glBegin(GL_TRIANGLE_STRIP);
894                         else
895                         {
896                                 glBegin(GL_TRIANGLE_FAN);
897                                 count = -count;
898                         }
899                         do
900                         {
901                                 glTexCoord2f(((float *)order)[0], ((float *)order)[1]);
902                                 qglArrayElement(order[2]);
903                                 order += 3;
904                         }
905                         while (count--);
906                 }
907
908                 glDisableClientState(GL_COLOR_ARRAY);
909                 glDisableClientState(GL_VERTEX_ARRAY);
910         }
911         else
912         {
913                 order = (int *)((int)pheader + pheader->ofs_glcmds);
914                 while(1)
915                 {
916                         if (!(count = *order++))
917                                 break;
918                         if (count > 0)
919                                 glBegin(GL_TRIANGLE_STRIP);
920                         else
921                         {
922                                 glBegin(GL_TRIANGLE_FAN);
923                                 count = -count;
924                         }
925                         //if (isG200)
926                         //{
927                                 do
928                                 {
929                                         glTexCoord2f(((float *)order)[0], ((float *)order)[1]);
930                                         glColor4f(aliasvertcolor[order[2] * 4] * (1.0f / 255.0f), aliasvertcolor[order[2] * 4 + 1] * (1.0f / 255.0f), aliasvertcolor[order[2] * 4 + 2] * (1.0f / 255.0f), aliasvertcolor[order[2] * 4 + 3] * (1.0f / 255.0f));
931                                         glVertex3fv(&aliasvert[order[2] * 3]);
932                                         order += 3;
933                                 }
934                                 while (count--);
935                         /*
936                         }
937                         else
938                         {
939                                 do
940                                 {
941                                         glTexCoord2f(((float *)order)[0], ((float *)order)[1]);
942                                         glColor4ub(aliasvertcolor[order[2] * 4], aliasvertcolor[order[2] * 4 + 1], aliasvertcolor[order[2] * 4 + 2], aliasvertcolor[order[2] * 4 + 3]);
943                                         glVertex3fv(&aliasvert[order[2] * 3]);
944                                         order += 3;
945                                 }
946                                 while (count--);
947                         }
948                         */
949                 }
950         }
951
952         if (fogenabled)
953         {
954                 glDisable (GL_TEXTURE_2D);
955                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
956                 glEnable (GL_BLEND);
957                 glDepthMask(0); // disable zbuffer updates
958                 {
959                         vec3_t diff;
960                         VectorSubtract(currententity->origin, r_refdef.vieworg, diff);
961                         glColor4f(fogcolor[0], fogcolor[1], fogcolor[2], exp(fogdensity/DotProduct(diff,diff)));
962                 }
963
964                 if (gl_vertexarrays.value)
965                 {
966                         // LordHavoc: big mess...
967                         // using arrays only slightly, although it is enough to prevent duplicates
968                         // (saving half the transforms)
969                         //glColor4f(shadecolor[0], shadecolor[1], shadecolor[2], modelalpha);
970                         qglVertexPointer(3, GL_FLOAT, 0, aliasvert);
971                         glEnableClientState(GL_VERTEX_ARRAY);
972
973                         order = (int *)((int)pheader + pheader->ofs_glcmds);
974                         while(1)
975                         {
976                                 if (!(count = *order++))
977                                         break;
978                                 if (count > 0)
979                                         glBegin(GL_TRIANGLE_STRIP);
980                                 else
981                                 {
982                                         glBegin(GL_TRIANGLE_FAN);
983                                         count = -count;
984                                 }
985                                 do
986                                 {
987                                         qglArrayElement(order[2]);
988                                         order += 3;
989                                 }
990                                 while (count--);
991                         }
992
993                         glDisableClientState(GL_VERTEX_ARRAY);
994                 }
995                 else
996                 {
997                         order = (int *)((int)pheader + pheader->ofs_glcmds);
998                         while(1)
999                         {
1000                                 if (!(count = *order++))
1001                                         break;
1002                                 if (count > 0)
1003                                         glBegin(GL_TRIANGLE_STRIP);
1004                                 else
1005                                 {
1006                                         glBegin(GL_TRIANGLE_FAN);
1007                                         count = -count;
1008                                 }
1009                                 do
1010                                 {
1011                                         glVertex3fv(&aliasvert[order[2] * 3]);
1012                                         order += 3;
1013                                 }
1014                                 while (count--);
1015                         }
1016                 }
1017
1018                 glEnable (GL_TEXTURE_2D);
1019                 glColor3f (1,1,1);
1020         }
1021
1022         if (!fogenabled && r_shadows.value && !(currententity->effects & EF_ADDITIVE) && currententity != &cl.viewent)
1023         {
1024                 int i;
1025                 float *av = aliasvert + 2, l = lightspot[2] + 0.125;
1026                 av = aliasvert + 2;
1027                 for (i = 0;i < pheader->num_xyz;i++, av+=3)
1028                         if (*av > l)
1029                                 *av = l;
1030                 glDisable (GL_TEXTURE_2D);
1031                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1032                 glEnable (GL_BLEND);
1033                 glDepthMask(0); // disable zbuffer updates
1034                 glColor4f (0,0,0,0.5 * modelalpha);
1035
1036                 if (gl_vertexarrays.value)
1037                 {
1038                         qglVertexPointer(3, GL_FLOAT, 0, aliasvert);
1039                         glEnableClientState(GL_VERTEX_ARRAY);
1040                                                 
1041                         while(1)
1042                         {
1043                                 if (!(count = *order++))
1044                                         break;
1045                                 if (count > 0)
1046                                         glBegin(GL_TRIANGLE_STRIP);
1047                                 else
1048                                 {
1049                                         glBegin(GL_TRIANGLE_FAN);
1050                                         count = -count;
1051                                 }
1052                                 do
1053                                 {
1054                                         qglArrayElement(order[2]);
1055                                         order += 3;
1056                                 }
1057                                 while (count--);
1058                         }
1059
1060                         glDisableClientState(GL_VERTEX_ARRAY);
1061                 }
1062                 else
1063                 {
1064                         while(1)
1065                         {
1066                                 if (!(count = *order++))
1067                                         break;
1068                                 if (count > 0)
1069                                         glBegin(GL_TRIANGLE_STRIP);
1070                                 else
1071                                 {
1072                                         glBegin(GL_TRIANGLE_FAN);
1073                                         count = -count;
1074                                 }
1075                                 do
1076                                 {
1077                                         glVertex3fv(&aliasvert[order[2] * 3]);
1078                                         order += 3;
1079                                 }
1080                                 while (count--);
1081                         }
1082                 }
1083
1084                 glEnable (GL_TEXTURE_2D);
1085                 glColor3f (1,1,1);
1086         }
1087
1088         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1089         glEnable (GL_BLEND);
1090         glDepthMask(1);
1091 }
1092
1093 /*
1094 =================
1095 R_DrawAliasModel
1096
1097 =================
1098 */
1099 void R_DrawAliasModel (entity_t *e, int cull)
1100 {
1101         int                     i;
1102         model_t         *clmodel;
1103         vec3_t          mins, maxs;
1104         aliashdr_t      *paliashdr = NULL;
1105         md2mem_t                *pheader = NULL;
1106         int                     anim;
1107
1108         if (modelalpha < (1.0 / 64.0))
1109                 return; // basically completely transparent
1110
1111         clmodel = currententity->model;
1112
1113         VectorAdd (currententity->origin, clmodel->mins, mins);
1114         VectorAdd (currententity->origin, clmodel->maxs, maxs);
1115
1116         if (cull && R_CullBox (mins, maxs))
1117                 return;
1118
1119         VectorCopy (currententity->origin, r_entorigin);
1120         VectorSubtract (r_origin, r_entorigin, modelorg);
1121
1122         // get lighting information
1123
1124         if (currententity->model->flags & EF_FULLBRIGHT || currententity->effects & EF_FULLBRIGHT)
1125         {
1126                 shadecolor[0] = currententity->colormod[0] * 256;
1127                 shadecolor[1] = currententity->colormod[1] * 256;
1128                 shadecolor[2] = currententity->colormod[2] * 256;
1129         }
1130         else
1131         {
1132                 R_LightPoint (shadecolor, currententity->origin);
1133
1134                 // HACK HACK HACK -- no fullbright colors, so make torches full light
1135                 if (!strcmp (currententity->model->name, "progs/flame2.mdl") || !strcmp (currententity->model->name, "progs/flame.mdl") )
1136                         shadecolor[0] = shadecolor[1] = shadecolor[2] = 128;
1137
1138                 shadecolor[0] *= currententity->colormod[0];
1139                 shadecolor[1] *= currententity->colormod[1];
1140                 shadecolor[2] *= currententity->colormod[2];
1141         }
1142
1143         // locate the proper data
1144         if (clmodel->aliastype == ALIASTYPE_MD2)
1145         {
1146                 pheader = (void *)Mod_Extradata (currententity->model);
1147                 c_alias_polys += pheader->num_tris;
1148         }
1149         else
1150         {
1151                 paliashdr = (void *)Mod_Extradata (currententity->model);
1152                 c_alias_polys += paliashdr->numtris;
1153         }
1154
1155         // draw all the triangles
1156
1157         if (clmodel->aliastype == ALIASTYPE_MD2)
1158         {
1159                 if (currententity->skinnum < 0 || currententity->skinnum >= pheader->num_skins)
1160                 {
1161                         currententity->skinnum = 0;
1162                         Con_DPrintf("invalid skin number %d for model %s\n", currententity->skinnum, clmodel->name);
1163                 }
1164                 glBindTexture(GL_TEXTURE_2D, pheader->gl_texturenum[currententity->skinnum]);
1165         }
1166         else
1167         {
1168                 if (currententity->skinnum < 0 || currententity->skinnum >= paliashdr->numskins)
1169                 {
1170                         currententity->skinnum = 0;
1171                         Con_DPrintf("invalid skin number %d for model %s\n", currententity->skinnum, clmodel->name);
1172                 }
1173                 anim = (int)(cl.time*10) & 3;
1174             glBindTexture(GL_TEXTURE_2D, paliashdr->gl_texturenum[currententity->skinnum][anim]);
1175         }
1176         glDisable(GL_ALPHA_TEST);
1177         glEnable (GL_TEXTURE_2D);
1178
1179         // we can't dynamically colormap textures, so they are cached
1180         // seperately for the players.  Heads are just uncolored.
1181         if (currententity->colormap != 0 /*vid.colormap*/ /* && !gl_nocolors.value*/)
1182         {
1183                 i = currententity - cl_entities;
1184                 if (i >= 1 && i<=cl.maxclients /* && !strcmp (currententity->model->name, "progs/player.mdl") */)
1185                         glBindTexture(GL_TEXTURE_2D, playertextures - 1 + i);
1186         }
1187
1188 //      if (gl_affinemodels.value)
1189 //              glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
1190         if (clmodel->aliastype == ALIASTYPE_MD2)
1191                 R_DrawQ2AliasFrame (pheader);
1192         else
1193                 R_DrawAliasFrame (paliashdr);
1194
1195         glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
1196 }
1197
1198 //==================================================================================
1199
1200 void R_DrawBrushModel (entity_t *e);
1201
1202 /*
1203 =============
1204 R_DrawEntitiesOnList
1205 =============
1206 */
1207 // LordHavoc: split so bmodels are rendered before any other objects
1208 void R_DrawEntitiesOnList1 (void)
1209 {
1210         int             i;
1211
1212         if (!r_drawentities.value)
1213                 return;
1214
1215         for (i=0 ; i<cl_numvisedicts ; i++)
1216         {
1217                 if (cl_visedicts[i]->model->type != mod_brush)
1218                         continue;
1219                 currententity = cl_visedicts[i];
1220                 modelalpha = currententity->alpha;
1221
1222                 R_DrawBrushModel (currententity);
1223         }
1224 }
1225
1226 void R_DrawEntitiesOnList2 (void)
1227 {
1228         int             i;
1229
1230         if (!r_drawentities.value)
1231                 return;
1232
1233         for (i=0 ; i<cl_numvisedicts ; i++)
1234         {
1235                 currententity = cl_visedicts[i];
1236                 modelalpha = currententity->alpha;
1237
1238                 switch (currententity->model->type)
1239                 {
1240                 case mod_alias:
1241                         R_DrawAliasModel (currententity, true);
1242                         break;
1243
1244                 case mod_sprite:
1245                         R_DrawSpriteModel (currententity);
1246                         break;
1247
1248                 default:
1249                         break;
1250                 }
1251         }
1252 }
1253
1254 /*
1255 =============
1256 R_DrawViewModel
1257 =============
1258 */
1259 void R_DrawViewModel (void)
1260 {
1261         if (!r_drawviewmodel.value || chase_active.value || envmap || !r_drawentities.value || cl.items & IT_INVISIBILITY || cl.stats[STAT_HEALTH] <= 0 || !cl.viewent.model)
1262                 return;
1263
1264         currententity = &cl.viewent;
1265         currententity->alpha = modelalpha = cl_entities[cl.viewentity].alpha; // LordHavoc: if the player is transparent, so is his gun
1266         currententity->effects = cl_entities[cl.viewentity].effects;
1267         currententity->scale = 1;
1268         VectorCopy(cl_entities[cl.viewentity].colormod, currententity->colormod);
1269
1270         // hack the depth range to prevent view model from poking into walls
1271         glDepthRange (gldepthmin, gldepthmin + 0.3*(gldepthmax-gldepthmin));
1272         R_DrawAliasModel (currententity, FALSE);
1273         glDepthRange (gldepthmin, gldepthmax);
1274 }
1275
1276 void R_DrawBrushModel (entity_t *e);
1277
1278 void RotatePointAroundVector( vec3_t dst, const vec3_t dir, const vec3_t point, float degrees );
1279
1280 void R_SetFrustum (void)
1281 {
1282         int             i;
1283
1284         if (r_refdef.fov_x == 90) 
1285         {
1286                 // front side is visible
1287
1288                 VectorAdd (vpn, vright, frustum[0].normal);
1289                 VectorSubtract (vpn, vright, frustum[1].normal);
1290
1291                 VectorAdd (vpn, vup, frustum[2].normal);
1292                 VectorSubtract (vpn, vup, frustum[3].normal);
1293         }
1294         else
1295         {
1296                 // rotate VPN right by FOV_X/2 degrees
1297                 RotatePointAroundVector( frustum[0].normal, vup, vpn, -(90-r_refdef.fov_x / 2 ) );
1298                 // rotate VPN left by FOV_X/2 degrees
1299                 RotatePointAroundVector( frustum[1].normal, vup, vpn, 90-r_refdef.fov_x / 2 );
1300                 // rotate VPN up by FOV_X/2 degrees
1301                 RotatePointAroundVector( frustum[2].normal, vright, vpn, 90-r_refdef.fov_y / 2 );
1302                 // rotate VPN down by FOV_X/2 degrees
1303                 RotatePointAroundVector( frustum[3].normal, vright, vpn, -( 90 - r_refdef.fov_y / 2 ) );
1304         }
1305
1306         for (i=0 ; i<4 ; i++)
1307         {
1308                 frustum[i].type = PLANE_ANYZ;
1309                 frustum[i].dist = DotProduct (r_origin, frustum[i].normal);
1310 //              frustum[i].signbits = SignbitsForPlane (&frustum[i]);
1311                 BoxOnPlaneSideClassify(&frustum[i]);
1312         }
1313 }
1314
1315 void R_AnimateLight (void);
1316 void V_CalcBlend (void);
1317
1318 /*
1319 ===============
1320 R_SetupFrame
1321 ===============
1322 */
1323 void R_SetupFrame (void)
1324 {
1325 // don't allow cheats in multiplayer
1326         if (cl.maxclients > 1)
1327         {
1328                 Cvar_Set ("r_fullbright", "0");
1329                 Cvar_Set ("r_ambient", "0");
1330         }
1331
1332         R_AnimateLight ();
1333
1334         r_framecount++;
1335
1336 // build the transformation matrix for the given view angles
1337         VectorCopy (r_refdef.vieworg, r_origin);
1338
1339         AngleVectors (r_refdef.viewangles, vpn, vright, vup);
1340
1341 // current viewleaf
1342         r_oldviewleaf = r_viewleaf;
1343         r_viewleaf = Mod_PointInLeaf (r_origin, cl.worldmodel);
1344
1345         V_SetContentsColor (r_viewleaf->contents);
1346         V_CalcBlend ();
1347
1348         r_cache_thrash = false;
1349
1350         c_brush_polys = 0;
1351         c_alias_polys = 0;
1352
1353 }
1354
1355
1356 void MYgluPerspective( GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar )
1357 {
1358    GLdouble xmin, xmax, ymin, ymax;
1359
1360    ymax = zNear * tan( fovy * M_PI / 360.0 );
1361    ymin = -ymax;
1362
1363    xmin = ymin * aspect;
1364    xmax = ymax * aspect;
1365
1366    glFrustum( xmin, xmax, ymin, ymax, zNear, zFar );
1367 }
1368
1369
1370 extern char skyname[];
1371
1372 /*
1373 =============
1374 R_SetupGL
1375 =============
1376 */
1377 void R_SetupGL (void)
1378 {
1379         float   screenaspect;
1380         extern  int glwidth, glheight;
1381         int             x, x2, y2, y, w, h;
1382
1383         //
1384         // set up viewpoint
1385         //
1386         glMatrixMode(GL_PROJECTION);
1387     glLoadIdentity ();
1388         x = r_refdef.vrect.x * glwidth/vid.width;
1389         x2 = (r_refdef.vrect.x + r_refdef.vrect.width) * glwidth/vid.width;
1390         y = (vid.height-r_refdef.vrect.y) * glheight/vid.height;
1391         y2 = (vid.height - (r_refdef.vrect.y + r_refdef.vrect.height)) * glheight/vid.height;
1392
1393         // fudge around because of frac screen scale
1394         if (x > 0)
1395                 x--;
1396         if (x2 < glwidth)
1397                 x2++;
1398         if (y2 < 0)
1399                 y2--;
1400         if (y < glheight)
1401                 y++;
1402
1403         w = x2 - x;
1404         h = y - y2;
1405
1406         if (envmap)
1407         {
1408                 x = y2 = 0;
1409                 w = h = 256;
1410         }
1411
1412         glViewport (glx + x, gly + y2, w, h);
1413     screenaspect = (float)r_refdef.vrect.width/r_refdef.vrect.height;
1414 //      yfov = 2*atan((float)r_refdef.vrect.height/r_refdef.vrect.width)*180/M_PI;
1415 //      if (skyname[0]) // skybox enabled?
1416 //              MYgluPerspective (r_refdef.fov_y,  screenaspect,  4,  r_skyboxsize.value*1.732050807569 + 256); // this is size*sqrt(3) + 256
1417 //      else
1418                 MYgluPerspective (r_refdef.fov_y,  screenaspect,  4,  r_farclip.value);
1419
1420         glCullFace(GL_FRONT);
1421
1422         glMatrixMode(GL_MODELVIEW);
1423     glLoadIdentity ();
1424
1425     glRotatef (-90,  1, 0, 0);      // put Z going up
1426     glRotatef (90,  0, 0, 1);       // put Z going up
1427     glRotatef (-r_refdef.viewangles[2],  1, 0, 0);
1428     glRotatef (-r_refdef.viewangles[0],  0, 1, 0);
1429     glRotatef (-r_refdef.viewangles[1],  0, 0, 1);
1430     glTranslatef (-r_refdef.vieworg[0],  -r_refdef.vieworg[1],  -r_refdef.vieworg[2]);
1431
1432         glGetFloatv (GL_MODELVIEW_MATRIX, r_world_matrix);
1433
1434         //
1435         // set drawing parms
1436         //
1437 //      if (gl_cull.value)
1438                 glEnable(GL_CULL_FACE);
1439 //      else
1440 //              glDisable(GL_CULL_FACE);
1441
1442         glEnable(GL_BLEND); // was Disable
1443         glDisable(GL_ALPHA_TEST);
1444         glAlphaFunc(GL_GREATER, 0.5);
1445         glEnable(GL_DEPTH_TEST);
1446         glDepthMask(1);
1447         glShadeModel(GL_SMOOTH);
1448 }
1449
1450 void R_DrawWorld (void);
1451 //void R_RenderDlights (void);
1452 void R_DrawParticles (void);
1453
1454 /*
1455 =============
1456 R_Clear
1457 =============
1458 */
1459 void R_Clear (void)
1460 {
1461 //      glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // LordHavoc: moved to SCR_UpdateScreen
1462         gldepthmin = 0;
1463         gldepthmax = 1;
1464         glDepthFunc (GL_LEQUAL);
1465
1466         glDepthRange (gldepthmin, gldepthmax);
1467 }
1468
1469 // LordHavoc: my trick to *FIX* GLQuake lighting once and for all :)
1470 void GL_Brighten()
1471 {
1472         glMatrixMode(GL_PROJECTION);
1473     glLoadIdentity ();
1474         glOrtho  (0, vid.width, vid.height, 0, -99999, 99999);
1475         glMatrixMode(GL_MODELVIEW);
1476     glLoadIdentity ();
1477         glDisable (GL_DEPTH_TEST);
1478         glDisable (GL_CULL_FACE);
1479         glDisable(GL_TEXTURE_2D);
1480         glEnable(GL_BLEND);
1481         glBlendFunc (GL_DST_COLOR, GL_ONE);
1482         glBegin (GL_TRIANGLES);
1483         glColor3f (1, 1, 1);
1484         glVertex2f (-5000, -5000);
1485         glVertex2f (10000, -5000);
1486         glVertex2f (-5000, 10000);
1487         glEnd ();
1488         glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1489         glDisable(GL_BLEND);
1490         glEnable(GL_TEXTURE_2D);
1491         glEnable (GL_DEPTH_TEST);
1492         glEnable (GL_CULL_FACE);
1493 }
1494
1495 extern cvar_t contrast;
1496 extern cvar_t brightness;
1497 extern cvar_t gl_lightmode;
1498
1499 void GL_BlendView()
1500 {
1501         glMatrixMode(GL_PROJECTION);
1502     glLoadIdentity ();
1503         glOrtho  (0, vid.width, vid.height, 0, -99999, 99999);
1504         glMatrixMode(GL_MODELVIEW);
1505     glLoadIdentity ();
1506         glDisable (GL_DEPTH_TEST);
1507         glDisable (GL_CULL_FACE);
1508         glDisable(GL_TEXTURE_2D);
1509         glEnable(GL_BLEND);
1510         if (lighthalf)
1511         {
1512                 glBlendFunc (GL_DST_COLOR, GL_ONE);
1513                 glBegin (GL_TRIANGLES);
1514                 glColor3f (1, 1, 1);
1515                 glVertex2f (-5000, -5000);
1516                 glVertex2f (10000, -5000);
1517                 glVertex2f (-5000, 10000);
1518                 glEnd ();
1519         }
1520         glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1521         contrast.value = bound(0.2, contrast.value, 1.0);
1522         if (/*gl_polyblend.value && */v_blend[3])
1523         {
1524                 glBegin (GL_TRIANGLES);
1525                 glColor4fv (v_blend);
1526                 glVertex2f (-5000, -5000);
1527                 glVertex2f (10000, -5000);
1528                 glVertex2f (-5000, 10000);
1529                 glEnd ();
1530         }
1531
1532         glEnable (GL_CULL_FACE);
1533         glEnable (GL_DEPTH_TEST);
1534         glDisable(GL_BLEND);
1535         glEnable(GL_TEXTURE_2D);
1536 }
1537
1538 #define TIMEREPORT(DESC) \
1539         if (r_speeds2.value)\
1540         {\
1541                 temptime = -currtime;\
1542                 currtime = Sys_FloatTime();\
1543                 temptime += currtime;\
1544                 Con_Printf(DESC " %.4fms ", temptime * 1000.0);\
1545         }
1546
1547 /*
1548 ================
1549 R_RenderView
1550
1551 r_refdef must be set before the first call
1552 ================
1553 */
1554 void R_RenderView (void)
1555 {
1556 //      double currtime, temptime;
1557 //      if (r_norefresh.value)
1558 //              return;
1559
1560         if (!r_worldentity.model || !cl.worldmodel)
1561                 Sys_Error ("R_RenderView: NULL worldmodel");
1562
1563         lighthalf = gl_lightmode.value;
1564
1565         FOG_framebegin();
1566         transpolyclear();
1567
1568 //      if (r_speeds2.value)
1569 //      {
1570 //              currtime = Sys_FloatTime();
1571 //              Con_Printf("render time: ");
1572 //      }
1573         R_Clear();
1574 //      TIMEREPORT("R_Clear")
1575
1576         // render normal view
1577
1578         R_SetupFrame ();
1579         R_SetFrustum ();
1580         R_SetupGL ();
1581         R_MarkLeaves ();        // done here so we know if we're in water
1582         R_DrawWorld ();         // adds static entities to the list
1583         S_ExtraUpdate ();       // don't let sound get messed up if going slow
1584         wallpolyclear();
1585         R_DrawEntitiesOnList1 (); // BSP models
1586         wallpolyrender();
1587         R_DrawEntitiesOnList2 (); // other models
1588 //      R_RenderDlights ();
1589         R_DrawViewModel ();
1590         R_DrawParticles ();
1591         transpolyrender();
1592
1593         FOG_frameend();
1594         GL_BlendView();
1595 //      if (r_speeds2.value)
1596 //              Con_Printf("\n");
1597 }