]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rsurf.c
9f09d2ab6af75e33f4c6b3f465919eb49913ac27
[xonotic/darkplaces.git] / gl_rsurf.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_surf.c: surface-related refresh code
21
22 #include "quakedef.h"
23
24 extern int                     skytexturenum;
25
26 int             lightmap_textures;
27
28 signed blocklights[18*18*3]; // LordHavoc: *3 for colored lighting
29
30 // LordHavoc: skinny but tall lightmaps for quicker subimage uploads
31 #define BLOCK_WIDTH             128
32 #define BLOCK_HEIGHT    128
33 // LordHavoc: increased lightmap limit from 64 to 1024
34 #define MAX_LIGHTMAPS   1024
35 #define LIGHTMAPSIZE    (BLOCK_WIDTH*BLOCK_HEIGHT*3)
36
37 int                     active_lightmaps;
38
39 short allocated[MAX_LIGHTMAPS][BLOCK_WIDTH];
40
41 byte *lightmaps[MAX_LIGHTMAPS];
42 short lightmapupdate[MAX_LIGHTMAPS][2];
43
44 int lightmapalign, lightmapalignmask; // LordHavoc: NVIDIA's broken subimage fix, see BuildLightmaps for notes
45 cvar_t gl_lightmapalign = {"gl_lightmapalign", "4"};
46 cvar_t gl_lightmaprgba = {"gl_lightmaprgba", "1"};
47 cvar_t gl_nosubimagefragments = {"gl_nosubimagefragments", "0"};
48 cvar_t gl_nosubimage = {"gl_nosubimage", "0"};
49 cvar_t r_ambient = {"r_ambient", "0"};
50
51 qboolean lightmaprgba, nosubimagefragments, nosubimage;
52 int lightmapbytes;
53
54 qboolean skyisvisible;
55 extern qboolean gl_arrays;
56
57 void glrsurf_init()
58 {
59         int i;
60         for (i = 0;i < MAX_LIGHTMAPS;i++)
61                 lightmaps[i] = NULL;
62         Cvar_RegisterVariable(&gl_lightmapalign);
63         Cvar_RegisterVariable(&gl_lightmaprgba);
64         Cvar_RegisterVariable(&gl_nosubimagefragments);
65         Cvar_RegisterVariable(&gl_nosubimage);
66         Cvar_RegisterVariable(&r_ambient);
67         // check if it's the glquake minigl driver
68         if (strncasecmp(gl_vendor,"3Dfx",4)==0)
69         if (!gl_arrays)
70         {
71 //              Cvar_SetValue("gl_nosubimagefragments", 1);
72 //              Cvar_SetValue("gl_nosubimage", 1);
73                 Cvar_SetValue("gl_lightmode", 0);
74         }
75 }
76
77 int dlightdivtable[8192];
78 int dlightdivtableinitialized = 0;
79
80 /*
81 ===============
82 R_AddDynamicLights
83 ===============
84 */
85 void R_AddDynamicLights (msurface_t *surf)
86 {
87         int                     sdtable[18], lnum, td, maxdist, maxdist2, maxdist3, i, s, t, smax, tmax, red, green, blue, j;
88         unsigned        *bl;
89         float           dist, f;
90         vec3_t          impact, local;
91         // use 64bit integer...  shame it's not very standardized...
92 #if _MSC_VER || __BORLANDC__
93         __int64         k; // MSVC
94 #else
95         long long       k; // GCC
96 #endif
97
98         if (!dlightdivtableinitialized)
99         {
100                 dlightdivtable[0] = 1048576 >> 7;
101                 for (s = 1;s < 8192;s++)
102                         dlightdivtable[s] = 1048576 / (s << 7);
103                 dlightdivtableinitialized = 1;
104         }
105
106         smax = (surf->extents[0]>>4)+1;
107         tmax = (surf->extents[1]>>4)+1;
108
109         for (lnum=0 ; lnum<MAX_DLIGHTS ; lnum++)
110         {
111                 if ( !(surf->dlightbits[lnum >> 5] & (1<<(lnum&31)) ) )
112                         continue;               // not lit by this light
113
114                 VectorSubtract(cl_dlights[lnum].origin, currententity->origin, local);
115                 dist = DotProduct (local, surf->plane->normal) - surf->plane->dist;
116                 for (i=0 ; i<3 ; i++)
117                         impact[i] = cl_dlights[lnum].origin[i] - surf->plane->normal[i]*dist;
118
119                 f = DotProduct (impact, surf->texinfo->vecs[0]) + surf->texinfo->vecs[0][3] - surf->texturemins[0];
120                 i = f;
121
122                 // reduce calculations
123                 t = dist*dist;
124                 for (s = 0;s < smax;s++, i -= 16)
125                         sdtable[s] = i*i + t;
126
127                 f = DotProduct (impact, surf->texinfo->vecs[1]) + surf->texinfo->vecs[1][3] - surf->texturemins[1];
128                 i = f;
129
130                 maxdist = (int) (cl_dlights[lnum].radius*cl_dlights[lnum].radius); // for comparisons to minimum acceptable light
131                 // clamp radius to avoid exceeding 8192 entry division table
132                 if (maxdist > 1048576)
133                         maxdist = 1048576;
134                 maxdist3 = maxdist - (int) (dist*dist);
135                 // convert to 8.8 blocklights format
136                 if (!cl_dlights[lnum].dark)
137                 {
138                         f = cl_dlights[lnum].color[0] * maxdist;red = f;
139                         f = cl_dlights[lnum].color[1] * maxdist;green = f;
140                         f = cl_dlights[lnum].color[2] * maxdist;blue = f;
141                 }
142                 else // negate for darklight
143                 {
144                         f = cl_dlights[lnum].color[0] * -maxdist;red = f;
145                         f = cl_dlights[lnum].color[1] * -maxdist;green = f;
146                         f = cl_dlights[lnum].color[2] * -maxdist;blue = f;
147                 }
148                 bl = blocklights;
149                 for (t = 0;t < tmax;t++,i -= 16)
150                 {
151                         td = i*i;
152                         if (td < maxdist3) // make sure some part of it is visible on this line
153                         {
154                                 maxdist2 = maxdist - td;
155                                 for (s = 0;s < smax;s++)
156                                 {
157                                         if (sdtable[s] < maxdist2)
158                                         {
159                                                 j = dlightdivtable[(sdtable[s]+td) >> 7];
160                                                 k = (red   * j) >> 8;bl[0] += k;
161                                                 k = (green * j) >> 8;bl[1] += k;
162                                                 k = (blue  * j) >> 8;bl[2] += k;
163                                         }
164                                         bl += 3;
165                                 }
166                         }
167                         else
168                                 bl+=smax*3; // skip line
169                 }
170         }
171 }
172
173 extern qboolean lighthalf;
174 /*
175 ===============
176 R_BuildLightMap
177
178 Combine and scale multiple lightmaps into the 8.8 format in blocklights
179 ===============
180 */
181 void R_BuildLightMap (msurface_t *surf, byte *dest, int stride)
182 {
183         int                     smax, tmax;
184         int                     t;
185         int                     i, j, size;
186         byte            *lightmap;
187         int                     scale;
188         int                     maps;
189         int                     *bl;
190
191         surf->cached_dlight = (surf->dlightframe == r_framecount);
192         surf->cached_lighthalf = lighthalf;
193         surf->cached_ambient = r_ambient.value;
194
195         smax = (surf->extents[0]>>4)+1;
196         tmax = (surf->extents[1]>>4)+1;
197         size = smax*tmax;
198         lightmap = surf->samples;
199
200 // set to full bright if no light data
201         if (currententity->effects & EF_FULLBRIGHT || !cl.worldmodel->lightdata)
202         {
203                 bl = blocklights;
204                 for (i=0 ; i<size ; i++)
205                 {
206                         *bl++ = 255*256;
207                         *bl++ = 255*256;
208                         *bl++ = 255*256;
209                 }
210         }
211         else
212         {
213 // clear to no light
214                 bl = blocklights;
215                 j = r_ambient.value * 512.0f; // would be 256.0f logically, but using 512.0f to match winquake style
216                 for (i=0 ; i<size ; i++)
217                 {
218                         *bl++ = j;
219                         *bl++ = j;
220                         *bl++ = j;
221                 }
222
223 // add all the lightmaps
224                 if (lightmap)
225                         for (maps = 0;maps < MAXLIGHTMAPS && surf->styles[maps] != 255;maps++)
226                         {
227                                 scale = d_lightstylevalue[surf->styles[maps]];
228                                 surf->cached_light[maps] = scale;       // 8.8 fraction
229                                 bl = blocklights;
230                                 for (i=0 ; i<size ; i++)
231                                 {
232                                         *bl++ += *lightmap++ * scale;
233                                         *bl++ += *lightmap++ * scale;
234                                         *bl++ += *lightmap++ * scale;
235                                 }
236                         }
237
238 // add all the dynamic lights
239                 if (surf->dlightframe == r_framecount)
240                         R_AddDynamicLights (surf);
241         }
242         stride -= (smax*lightmapbytes);
243         bl = blocklights;
244         if (lighthalf)
245         {
246                 // LordHavoc: I shift down by 8 unlike GLQuake's 7,
247                 // the image is brightened as a processing pass
248                 if (lightmaprgba)
249                 {
250                         for (i=0 ; i<tmax ; i++, dest += stride)
251                         {
252                                 for (j=0 ; j<smax ; j++)
253                                 {
254                                         t = *bl++ >> 8;if (t > 255) t = 255;else if (t < 0) t = 0;*dest++ = t;
255                                         t = *bl++ >> 8;if (t > 255) t = 255;else if (t < 0) t = 0;*dest++ = t;
256                                         t = *bl++ >> 8;if (t > 255) t = 255;else if (t < 0) t = 0;*dest++ = t;
257                                         *dest++ = 255;
258                                 }
259                         }
260                 }
261                 else
262                 {
263                         for (i=0 ; i<tmax ; i++, dest += stride)
264                         {
265                                 for (j=0 ; j<smax ; j++)
266                                 {
267                                         t = *bl++ >> 8;if (t > 255) t = 255;else if (t < 0) t = 0;*dest++ = t;
268                                         t = *bl++ >> 8;if (t > 255) t = 255;else if (t < 0) t = 0;*dest++ = t;
269                                         t = *bl++ >> 8;if (t > 255) t = 255;else if (t < 0) t = 0;*dest++ = t;
270                                 }
271                         }
272                 }
273         }
274         else
275         {
276                 if (lightmaprgba)
277                 {
278                         for (i=0 ; i<tmax ; i++, dest += stride)
279                         {
280                                 for (j=0 ; j<smax ; j++)
281                                 {
282                                         t = *bl++ >> 7;if (t > 255) t = 255;else if (t < 0) t = 0;*dest++ = t;
283                                         t = *bl++ >> 7;if (t > 255) t = 255;else if (t < 0) t = 0;*dest++ = t;
284                                         t = *bl++ >> 7;if (t > 255) t = 255;else if (t < 0) t = 0;*dest++ = t;
285                                         *dest++ = 255;
286                                 }
287                         }
288                 }
289                 else
290                 {
291                         for (i=0 ; i<tmax ; i++, dest += stride)
292                         {
293                                 for (j=0 ; j<smax ; j++)
294                                 {
295                                         t = *bl++ >> 7;if (t > 255) t = 255;else if (t < 0) t = 0;*dest++ = t;
296                                         t = *bl++ >> 7;if (t > 255) t = 255;else if (t < 0) t = 0;*dest++ = t;
297                                         t = *bl++ >> 7;if (t > 255) t = 255;else if (t < 0) t = 0;*dest++ = t;
298                                 }
299                         }
300                 }
301         }
302 }
303
304 byte templight[32*32*4];
305
306 void R_UpdateLightmap(msurface_t *s, int lnum)
307 {
308         int smax, tmax;
309         // upload the new lightmap texture fragment
310         glBindTexture(GL_TEXTURE_2D, lightmap_textures + lnum);
311         if (nosubimage || nosubimagefragments)
312         {
313                 if (lightmapupdate[lnum][0] > s->light_t)
314                         lightmapupdate[lnum][0] = s->light_t;
315                 if (lightmapupdate[lnum][1] < (s->light_t + ((s->extents[1]>>4)+1)))
316                         lightmapupdate[lnum][1] = (s->light_t + ((s->extents[1]>>4)+1));
317                 if (lightmaprgba)
318                         R_BuildLightMap (s, lightmaps[s->lightmaptexturenum] + (s->light_t * BLOCK_WIDTH + s->light_s) * 4, BLOCK_WIDTH * 4);
319                 else
320                         R_BuildLightMap (s, lightmaps[s->lightmaptexturenum] + (s->light_t * BLOCK_WIDTH + s->light_s) * 3, BLOCK_WIDTH * 3);
321         }
322         else
323         {
324                 smax = ((s->extents[0]>>4)+lightmapalign) & lightmapalignmask;
325                 tmax = (s->extents[1]>>4)+1;
326                 if (lightmaprgba)
327                 {
328                         R_BuildLightMap (s, templight, smax * 4);
329                         glTexSubImage2D(GL_TEXTURE_2D, 0, s->light_s, s->light_t, smax, tmax, GL_RGBA, GL_UNSIGNED_BYTE, templight);
330                 }
331                 else
332                 {
333                         R_BuildLightMap (s, templight, smax * 3);
334                         glTexSubImage2D(GL_TEXTURE_2D, 0, s->light_s, s->light_t, smax, tmax, GL_RGB , GL_UNSIGNED_BYTE, templight);
335                 }
336         }
337 }
338
339
340 /*
341 ===============
342 R_TextureAnimation
343
344 Returns the proper texture for a given time and base texture
345 ===============
346 */
347 texture_t *R_TextureAnimation (texture_t *base)
348 {
349         texture_t *original;
350         int             relative;
351         int             count;
352
353         if (currententity->frame)
354         {
355                 if (base->alternate_anims)
356                         base = base->alternate_anims;
357         }
358         
359         if (!base->anim_total)
360                 return base;
361
362         original = base;
363
364         relative = (int)(cl.time*10) % base->anim_total;
365
366         count = 0;      
367         while (base->anim_min > relative || base->anim_max <= relative)
368         {
369                 base = base->anim_next;
370                 if (!base)
371                 {
372                         Con_Printf("R_TextureAnimation: broken cycle");
373                         return original;
374                 }
375                 if (++count > 100)
376                 {
377                         Con_Printf("R_TextureAnimation: infinite cycle");
378                         return original;
379                 }
380         }
381
382         return base;
383 }
384
385
386 /*
387 =============================================================
388
389         BRUSH MODELS
390
391 =============================================================
392 */
393
394
395 extern  int             solidskytexture;
396 extern  int             alphaskytexture;
397 extern  float   speedscale;             // for top sky and bottom sky
398
399 qboolean mtexenabled = false;
400
401 extern char skyname[];
402
403 void R_DynamicLightPoint(vec3_t color, vec3_t org, int *dlightbits);
404 //extern cvar_t r_dynamicwater;
405 extern int r_dlightframecount;
406 float   turbsin[256] =
407 {
408         #include "gl_warp_sin.h"
409 };
410 #define TURBSCALE (256.0 / (2 * M_PI))
411
412
413 void UploadLightmaps()
414 {
415         int i;
416         if (nosubimage || nosubimagefragments)
417         {
418                 for (i = 0;i < MAX_LIGHTMAPS;i++)
419                 {
420                         if (lightmapupdate[i][0] < lightmapupdate[i][1])
421                         {
422                                 glBindTexture(GL_TEXTURE_2D, lightmap_textures + i);
423                                 if (nosubimage)
424                                 {
425                                         if (lightmaprgba)
426                                                 glTexImage2D(GL_TEXTURE_2D, 0, 3, BLOCK_WIDTH, BLOCK_HEIGHT, 0, GL_RGBA, GL_UNSIGNED_BYTE, lightmaps[i]);
427                                         else
428                                                 glTexImage2D(GL_TEXTURE_2D, 0, 3, BLOCK_WIDTH, BLOCK_HEIGHT, 0, GL_RGB, GL_UNSIGNED_BYTE, lightmaps[i]);
429                                 }
430                                 else
431                                 {
432                                         if (lightmaprgba)
433                                                 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, lightmapupdate[i][0], BLOCK_WIDTH, lightmapupdate[i][1] - lightmapupdate[i][0], GL_RGBA, GL_UNSIGNED_BYTE, lightmaps[i] + (BLOCK_WIDTH * 4 * lightmapupdate[i][0]));
434                                         else
435                                                 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, lightmapupdate[i][0], BLOCK_WIDTH, lightmapupdate[i][1] - lightmapupdate[i][0], GL_RGB, GL_UNSIGNED_BYTE, lightmaps[i] + (BLOCK_WIDTH * 3 * lightmapupdate[i][0]));
436                                 }
437                         }
438                         lightmapupdate[i][0] = BLOCK_HEIGHT;
439                         lightmapupdate[i][1] = 0;
440                 }
441         }
442 }
443
444 /*
445 ================
446 DrawTextureChains
447 ================
448 */
449 extern qboolean hlbsp;
450 extern void R_Sky();
451 extern char skyname[];
452 void DrawTextureChains (void)
453 {
454         int             i, j, maps;
455         msurface_t      *s;
456         texture_t       *t;
457         glpoly_t        *p;
458         float           *v;
459         float           os = turbsin[(int)(realtime * TURBSCALE) & 255], ot = turbsin[(int)(realtime * TURBSCALE + 96.0) & 255];
460
461         // first the sky
462         skypolyclear();
463         for (j = 0;j < cl.worldmodel->numtextures;j++)
464         {
465                 if (!cl.worldmodel->textures[j] || !(s = cl.worldmodel->textures[j]->texturechain))
466                         continue;
467                 // LordHavoc: decide the render type only once, because the surface properties were determined by texture anyway
468                 // subdivided water surface warp
469                 if (s->flags & SURF_DRAWSKY)
470                 {
471                         cl.worldmodel->textures[j]->texturechain = NULL;
472                         t = R_TextureAnimation (cl.worldmodel->textures[j]);
473                         skyisvisible = true;
474                         if (!hlbsp) // LordHavoc: HalfLife maps have freaky skypolys...
475                         {
476                                 for (;s;s = s->texturechain)
477                                 {
478                                         for (p=s->polys ; p ; p=p->next)
479                                         {
480                                                 if (currentskypoly < MAX_SKYPOLYS && currentskyvert + p->numverts <= MAX_SKYVERTS)
481                                                 {
482                                                         skypoly[currentskypoly].firstvert = currentskyvert;
483                                                         skypoly[currentskypoly++].verts = p->numverts;
484                                                         for (i = 0,v = p->verts[0];i < p->numverts;i++, v += VERTEXSIZE)
485                                                         {
486                                                                 skyvert[currentskyvert].v[0] = v[0];
487                                                                 skyvert[currentskyvert].v[1] = v[1];
488                                                                 skyvert[currentskyvert++].v[2] = v[2];
489                                                         }
490                                                 }
491                                         }
492                                 }
493                         }
494                 }
495         }
496         skypolyrender(); // fogged sky polys, affects depth
497
498         if (skyname[0] && skyisvisible && !fogenabled)
499                 R_Sky(); // does not affect depth, draws over the sky polys
500
501         // then walls
502         wallpolyclear();
503         for (j = 0;j < cl.worldmodel->numtextures;j++)
504         {
505                 if (!cl.worldmodel->textures[j] || !(s = cl.worldmodel->textures[j]->texturechain))
506                         continue;
507                 if (!(s->flags & SURF_DRAWTURB))
508                 {
509                         cl.worldmodel->textures[j]->texturechain = NULL;
510                         t = R_TextureAnimation (cl.worldmodel->textures[j]);
511                         for (;s;s = s->texturechain)
512                         {
513                                 if (currentwallpoly < MAX_WALLPOLYS && currentwallvert < MAX_WALLVERTS && (currentwallvert + s->polys->numverts) <= MAX_WALLVERTS)
514                                 {
515                                         // check for lightmap modification
516                                         if (r_dynamic.value)
517                                         {
518                                                 if (s->dlightframe == r_framecount || s->cached_dlight || r_ambient.value != s->cached_ambient || lighthalf != s->cached_lighthalf) // dynamic this frame or previously, or lighthalf changed, or r_ambient changed
519                                                         R_UpdateLightmap(s, s->lightmaptexturenum);
520                                                 else
521                                                         for (maps = 0 ; maps < MAXLIGHTMAPS && s->styles[maps] != 255 ; maps++)
522                                                                 if (d_lightstylevalue[s->styles[maps]] != s->cached_light[maps])
523                                                                 {
524                                                                         R_UpdateLightmap(s, s->lightmaptexturenum);
525                                                                         break;
526                                                                 }
527                                         }
528                                         wallpoly[currentwallpoly].texnum = (unsigned short) t->gl_texturenum;
529                                         wallpoly[currentwallpoly].lighttexnum = (unsigned short) lightmap_textures + s->lightmaptexturenum;
530                                         wallpoly[currentwallpoly].glowtexnum = (unsigned short) t->gl_glowtexturenum;
531                                         wallpoly[currentwallpoly].firstvert = currentwallvert;
532                                         wallpoly[currentwallpoly++].verts = s->polys->numverts;
533                                         for (i = 0,v = s->polys->verts[0];i<s->polys->numverts;i++, v += VERTEXSIZE)
534                                         {
535                                                 wallvert[currentwallvert].vert[0] = v[0];
536                                                 wallvert[currentwallvert].vert[1] = v[1];
537                                                 wallvert[currentwallvert].vert[2] = v[2];
538                                                 wallvert[currentwallvert].s = v[3];
539                                                 wallvert[currentwallvert].t = v[4];
540                                                 wallvert[currentwallvert].u = v[5];
541                                                 wallvert[currentwallvert++].v = v[6];
542                                         }
543                                 }
544                         }
545                 }
546         }
547         UploadLightmaps();
548         wallpolyrender();
549
550         // then water (water gets diverted to transpoly list)
551         for (j = 0;j < cl.worldmodel->numtextures;j++)
552         {
553                 if (!cl.worldmodel->textures[j] || !(s = cl.worldmodel->textures[j]->texturechain))
554                         continue;
555                 cl.worldmodel->textures[j]->texturechain = NULL;
556                 t = R_TextureAnimation (cl.worldmodel->textures[j]);
557                 // LordHavoc: decide the render type only once, because the surface properties were determined by texture anyway
558                 // subdivided water surface warp
559                 if (s->flags & SURF_DRAWTURB)
560                 {
561                         int light, alpha, r = 0, g = 0, b = 0;
562                         vec3_t nv, shadecolor;
563                         alpha = s->flags & SURF_DRAWNOALPHA ? 255 : r_wateralpha.value*255.0f;
564                         light = false;
565                         if (s->flags & SURF_DRAWFULLBRIGHT)
566                                 r = g = b = lighthalf ? 128 : 255;
567                         else if (s->dlightframe == r_dlightframecount && r_dynamic.value)
568                                 light = true;
569                         else
570                                 r = g = b = (lighthalf ? 64 : 128) + (int) (r_ambient.value * 2.0f);
571                         if (r_waterripple.value)
572                         {
573                                 if (lighthalf)
574                                 {
575                                         if (light)
576                                         {
577                                                 for (;s;s = s->texturechain)
578                                                 {
579                                                         for (p=s->polys ; p ; p=p->next)
580                                                         {
581                                                                 // FIXME: could be a transparent water texture
582                                                                 transpolybegin(s->texinfo->texture->gl_texturenum, s->texinfo->texture->gl_glowtexturenum, 0, TPOLYTYPE_ALPHA);
583                                                                 for (i = 0,v = p->verts[0];i < p->numverts;i++, v += VERTEXSIZE)
584                                                                 {
585                                                                         nv[0] = v[0];
586                                                                         nv[1] = v[1];
587                                                                         nv[2] = v[2] + r_waterripple.value * turbsin[(int)((v[3]*0.125f+realtime) * TURBSCALE) & 255] * turbsin[(int)((v[4]*0.125f+realtime) * TURBSCALE) & 255] * (1.0f / 64.0f);
588                                                                         shadecolor[0] = shadecolor[1] = shadecolor[2] = 128 + (int) (r_ambient.value * 2.0f);
589                                                                         R_DynamicLightPoint(shadecolor, nv, s->dlightbits);
590                                                                         transpolyvert(nv[0], nv[1], nv[2], (v[3] + os) * (1.0f/64.0f), (v[4] + ot) * (1.0f/64.0f), (int) shadecolor[0] >> 1,(int) shadecolor[1] >> 1,(int) shadecolor[2] >> 1,alpha);
591                                                                 }
592                                                                 transpolyend();
593                                                         }
594                                                 }
595                                         }
596                                         else
597                                         {
598                                                 for (;s;s = s->texturechain)
599                                                 {
600                                                         for (p=s->polys ; p ; p=p->next)
601                                                         {
602                                                                 // FIXME: could be a transparent water texture
603                                                                 transpolybegin(s->texinfo->texture->gl_texturenum, s->texinfo->texture->gl_glowtexturenum, 0, TPOLYTYPE_ALPHA);
604                                                                 for (i = 0,v = p->verts[0];i < p->numverts;i++, v += VERTEXSIZE)
605                                                                 {
606                                                                         nv[0] = v[0];
607                                                                         nv[1] = v[1];
608                                                                         nv[2] = v[2] + r_waterripple.value * turbsin[(int)((v[3]*0.125f+realtime) * TURBSCALE) & 255] * turbsin[(int)((v[4]*0.125f+realtime) * TURBSCALE) & 255] * (1.0f / 64.0f);
609                                                                         transpolyvert(nv[0], nv[1], nv[2], (v[3] + os) * (1.0f/64.0f), (v[4] + ot) * (1.0f/64.0f), r,g,b,alpha);
610                                                                 }
611                                                                 transpolyend();
612                                                         }
613                                                 }
614                                         }
615                                 }
616                                 else
617                                 {
618                                         if (light)
619                                         {
620                                                 for (;s;s = s->texturechain)
621                                                 {
622                                                         for (p=s->polys ; p ; p=p->next)
623                                                         {
624                                                                 // FIXME: could be a transparent water texture
625                                                                 transpolybegin(s->texinfo->texture->gl_texturenum, s->texinfo->texture->gl_glowtexturenum, 0, TPOLYTYPE_ALPHA);
626                                                                 for (i = 0,v = p->verts[0];i < p->numverts;i++, v += VERTEXSIZE)
627                                                                 {
628                                                                         nv[0] = v[0];
629                                                                         nv[1] = v[1];
630                                                                         nv[2] = v[2] + r_waterripple.value * turbsin[(int)((v[3]*0.125f+realtime) * TURBSCALE) & 255] * turbsin[(int)((v[4]*0.125f+realtime) * TURBSCALE) & 255] * (1.0f / 64.0f);
631                                                                         shadecolor[0] = shadecolor[1] = shadecolor[2] = 128 + (int) (r_ambient.value * 2.0f);
632                                                                         R_DynamicLightPoint(shadecolor, nv, s->dlightbits);
633                                                                         transpolyvert(nv[0], nv[1], nv[2], (v[3] + os) * (1.0f/64.0f), (v[4] + ot) * (1.0f/64.0f), shadecolor[0],shadecolor[1],shadecolor[2],alpha);
634                                                                 }
635                                                                 transpolyend();
636                                                         }
637                                                 }
638                                         }
639                                         else
640                                         {
641                                                 for (;s;s = s->texturechain)
642                                                 {
643                                                         for (p=s->polys ; p ; p=p->next)
644                                                         {
645                                                                 // FIXME: could be a transparent water texture
646                                                                 transpolybegin(s->texinfo->texture->gl_texturenum, s->texinfo->texture->gl_glowtexturenum, 0, TPOLYTYPE_ALPHA);
647                                                                 for (i = 0,v = p->verts[0];i < p->numverts;i++, v += VERTEXSIZE)
648                                                                 {
649                                                                         nv[0] = v[0];
650                                                                         nv[1] = v[1];
651                                                                         nv[2] = v[2] + r_waterripple.value * turbsin[(int)((v[3]*0.125f+realtime) * TURBSCALE) & 255] * turbsin[(int)((v[4]*0.125f+realtime) * TURBSCALE) & 255] * (1.0f / 64.0f);
652                                                                         transpolyvert(nv[0], nv[1], nv[2], (v[3] + os) * (1.0f/64.0f), (v[4] + ot) * (1.0f/64.0f), r,g,b,alpha);
653                                                                 }
654                                                                 transpolyend();
655                                                         }
656                                                 }
657                                         }
658                                 }
659                         }
660                         else
661                         {
662                                 if (lighthalf)
663                                 {
664                                         if (light)
665                                         {
666                                                 for (;s;s = s->texturechain)
667                                                 {
668                                                         for (p=s->polys ; p ; p=p->next)
669                                                         {
670                                                                 // FIXME: could be a transparent water texture
671                                                                 transpolybegin(s->texinfo->texture->gl_texturenum, s->texinfo->texture->gl_glowtexturenum, 0, TPOLYTYPE_ALPHA);
672                                                                 for (i = 0,v = p->verts[0];i < p->numverts;i++, v += VERTEXSIZE)
673                                                                 {
674                                                                         shadecolor[0] = shadecolor[1] = shadecolor[2] = 128 + (int) (r_ambient.value * 2.0f);
675                                                                         R_DynamicLightPoint(shadecolor, v, s->dlightbits);
676                                                                         transpolyvert(v[0], v[1], v[2], (v[3] + os) * (1.0f/64.0f), (v[4] + ot) * (1.0f/64.0f), (int) shadecolor[0] >> 1,(int) shadecolor[1] >> 1,(int) shadecolor[2] >> 1,alpha);
677                                                                 }
678                                                                 transpolyend();
679                                                         }
680                                                 }
681                                         }
682                                         else
683                                         {
684                                                 for (;s;s = s->texturechain)
685                                                 {
686                                                         for (p=s->polys ; p ; p=p->next)
687                                                         {
688                                                                 // FIXME: could be a transparent water texture
689                                                                 transpolybegin(s->texinfo->texture->gl_texturenum, s->texinfo->texture->gl_glowtexturenum, 0, TPOLYTYPE_ALPHA);
690                                                                 for (i = 0,v = p->verts[0];i < p->numverts;i++, v += VERTEXSIZE)
691                                                                 {
692                                                                         transpolyvert(v[0], v[1], v[2], (v[3] + os) * (1.0f/64.0f), (v[4] + ot) * (1.0f/64.0f), r,g,b,alpha);
693                                                                 }
694                                                                 transpolyend();
695                                                         }
696                                                 }
697                                         }
698                                 }
699                                 else
700                                 {
701                                         if (light)
702                                         {
703                                                 for (;s;s = s->texturechain)
704                                                 {
705                                                         for (p=s->polys ; p ; p=p->next)
706                                                         {
707                                                                 // FIXME: could be a transparent water texture
708                                                                 transpolybegin(s->texinfo->texture->gl_texturenum, s->texinfo->texture->gl_glowtexturenum, 0, TPOLYTYPE_ALPHA);
709                                                                 for (i = 0,v = p->verts[0];i < p->numverts;i++, v += VERTEXSIZE)
710                                                                 {
711                                                                         shadecolor[0] = shadecolor[1] = shadecolor[2] = 128 + (int) (r_ambient.value * 2.0f);
712                                                                         R_DynamicLightPoint(shadecolor, v, s->dlightbits);
713                                                                         transpolyvert(v[0], v[1], v[2], (v[3] + os) * (1.0f/64.0f), (v[4] + ot) * (1.0f/64.0f), shadecolor[0],shadecolor[1],shadecolor[2],alpha);
714                                                                 }
715                                                                 transpolyend();
716                                                         }
717                                                 }
718                                         }
719                                         else
720                                         {
721                                                 for (;s;s = s->texturechain)
722                                                 {
723                                                         for (p=s->polys ; p ; p=p->next)
724                                                         {
725                                                                 // FIXME: could be a transparent water texture
726                                                                 transpolybegin(s->texinfo->texture->gl_texturenum, s->texinfo->texture->gl_glowtexturenum, 0, TPOLYTYPE_ALPHA);
727                                                                 for (i = 0,v = p->verts[0];i < p->numverts;i++, v += VERTEXSIZE)
728                                                                 {
729                                                                         transpolyvert(v[0], v[1], v[2], (v[3] + os) * (1.0f/64.0f), (v[4] + ot) * (1.0f/64.0f), r,g,b,alpha);
730                                                                 }
731                                                                 transpolyend();
732                                                         }
733                                                 }
734                                         }
735                                 }
736                         }
737                 }
738         }
739 }
740
741 // LordHavoc: transparent brush models
742 extern int r_dlightframecount;
743 extern float modelalpha;
744 extern vec3_t shadecolor;
745 //qboolean R_CullBox (vec3_t mins, vec3_t maxs);
746 void R_DynamicLightPoint(vec3_t color, vec3_t org, int *dlightbits);
747 void R_DynamicLightPointNoMask(vec3_t color, vec3_t org);
748 void EmitWaterPolys (msurface_t *fa);
749 void R_MarkLights (vec3_t lightorigin, dlight_t *light, int bit, int bitindex, mnode_t *node);
750
751 /*
752 =================
753 R_DrawBrushModel
754 =================
755 */
756 void R_DrawBrushModel (entity_t *e)
757 {
758         int                     i, j, k, smax, tmax, size3, maps;
759         vec3_t          mins, maxs, nv;
760         msurface_t      *s;
761         mplane_t        *pplane;
762         model_t         *clmodel;
763         qboolean        rotated, vertexlit = false;
764         float           dot, *v, scale;
765         texture_t       *t;
766         byte            *lm;
767         float           os = turbsin[(int)(realtime * TURBSCALE) & 255], ot = turbsin[(int)(realtime * TURBSCALE + 96.0) & 255];
768
769         currententity = e;
770
771         clmodel = e->model;
772
773         if (e->angles[0] || e->angles[1] || e->angles[2])
774         {
775                 rotated = true;
776                 for (i=0 ; i<3 ; i++)
777                 {
778                         mins[i] = e->origin[i] - clmodel->radius;
779                         maxs[i] = e->origin[i] + clmodel->radius;
780                 }
781         }
782         else
783         {
784                 rotated = false;
785                 VectorAdd (e->origin, clmodel->mins, mins);
786                 VectorAdd (e->origin, clmodel->maxs, maxs);
787         }
788
789         if (R_CullBox (mins, maxs))
790                 return;
791
792         VectorSubtract (r_refdef.vieworg, e->origin, modelorg);
793         if (rotated)
794         {
795                 vec3_t  temp;
796                 vec3_t  forward, right, up;
797
798                 VectorCopy (modelorg, temp);
799                 AngleVectors (e->angles, forward, right, up);
800                 modelorg[0] = DotProduct (temp, forward);
801                 modelorg[1] = -DotProduct (temp, right);
802                 modelorg[2] = DotProduct (temp, up);
803         }
804
805         s = &clmodel->surfaces[clmodel->firstmodelsurface];
806
807 // calculate dynamic lighting for bmodel if it's not an
808 // instanced model
809         if (modelalpha == 1 && clmodel->firstmodelsurface != 0 && !(currententity->effects & EF_FULLBRIGHT) && currententity->colormod[0] == 1 && currententity->colormod[2] == 1 && currententity->colormod[2] == 1)
810         {
811 //              if (!gl_flashblend.value)
812 //              {
813                         vec3_t org;
814                         for (k=0 ; k<MAX_DLIGHTS ; k++)
815                         {
816                                 if ((cl_dlights[k].die < cl.time) || (!cl_dlights[k].radius))
817                                         continue;
818
819                                 VectorSubtract(cl_dlights[k].origin, currententity->origin, org);
820                                 R_MarkLights (org, &cl_dlights[k], 1<<(k&31), k >> 5, clmodel->nodes + clmodel->hulls[0].firstclipnode);
821                         }
822 //              }
823         }
824         else
825                 vertexlit = true;
826
827 e->angles[0] = -e->angles[0];   // stupid quake bug
828         softwaretransformforentity (e);
829 e->angles[0] = -e->angles[0];   // stupid quake bug
830
831         // draw texture
832         for (j = 0;j < clmodel->nummodelsurfaces;j++, s++)
833         {
834         // find which side of the node we are on
835                 pplane = s->plane;
836
837                 dot = DotProduct (modelorg, pplane->normal) - pplane->dist;
838
839         // draw the polygon
840                 if (((s->flags & SURF_PLANEBACK) && (dot < -BACKFACE_EPSILON)) ||
841                         (!(s->flags & SURF_PLANEBACK) && (dot > BACKFACE_EPSILON)))
842                 {
843                         if (s->flags & SURF_DRAWSKY)
844                                 continue;
845                         if (s->flags & SURF_DRAWTURB)
846                         {
847                                 glpoly_t        *p;
848                                 int                     light, alpha, r = 0, g = 0, b = 0;
849                                 vec3_t          shadecolor;
850
851                                 if (s->flags & SURF_DRAWNOALPHA)
852                                         alpha = modelalpha*255.0f;
853                                 else
854                                         alpha = r_wateralpha.value*modelalpha*255.0f;
855                                 light = false;
856                                 if (s->flags & SURF_DRAWFULLBRIGHT || currententity->effects & EF_FULLBRIGHT)
857                                 {
858                                         if (lighthalf)
859                                         {
860                                                 r = 128.0f * currententity->colormod[0];
861                                                 g = 128.0f * currententity->colormod[1];
862                                                 b = 128.0f * currententity->colormod[2];
863                                         }
864                                         else
865                                         {
866                                                 r = 255.0f * currententity->colormod[0];
867                                                 g = 255.0f * currententity->colormod[1];
868                                                 b = 255.0f * currententity->colormod[2];
869                                         }
870                                 }
871                                 else if (s->dlightframe == r_dlightframecount && r_dynamic.value)
872                                         light = true;
873                                 else
874                                 {
875                                         if (lighthalf)
876                                         {
877                                                 r = 64.0f * currententity->colormod[0] + (int) r_ambient.value;
878                                                 g = 64.0f * currententity->colormod[1] + (int) r_ambient.value;
879                                                 b = 64.0f * currententity->colormod[2] + (int) r_ambient.value;
880                                         }
881                                         else
882                                         {
883                                                 r = 128.0f * currententity->colormod[0] + (int) (r_ambient.value * 2.0f);
884                                                 g = 128.0f * currententity->colormod[1] + (int) (r_ambient.value * 2.0f);
885                                                 b = 128.0f * currententity->colormod[2] + (int) (r_ambient.value * 2.0f);
886                                         }
887                                 }
888                                 for (p=s->polys ; p ; p=p->next)
889                                 {
890                                         // FIXME: could be a transparent water texture
891                                         transpolybegin(s->texinfo->texture->gl_texturenum, s->texinfo->texture->gl_glowtexturenum, 0, currententity->effects & EF_ADDITIVE ? TPOLYTYPE_ADD : TPOLYTYPE_ALPHA);
892                                         for (i = 0,v = p->verts[0];i < p->numverts;i++, v += VERTEXSIZE)
893                                         {
894                                                 softwaretransform(v, nv);
895                                                 if (r_waterripple.value)
896                                                         nv[2] += r_waterripple.value * turbsin[(int)((v[3]*0.125f+realtime) * TURBSCALE) & 255] * turbsin[(int)((v[4]*0.125f+realtime) * TURBSCALE) & 255] * (1.0f / 64.0f);
897                                                 if (light)
898                                                 {
899                                                         shadecolor[0] = shadecolor[1] = shadecolor[2] = 128 + (int) (r_ambient.value * 2.0f);
900                                                         R_DynamicLightPoint(shadecolor, nv, s->dlightbits);
901                                                         if (lighthalf)
902                                                         {
903                                                                 r = (int) ((float) (shadecolor[0] * currententity->colormod[0])) >> 1;
904                                                                 g = (int) ((float) (shadecolor[1] * currententity->colormod[1])) >> 1;
905                                                                 b = (int) ((float) (shadecolor[2] * currententity->colormod[2])) >> 1;
906                                                         }
907                                                         else
908                                                         {
909                                                                 r = (int) ((float) (shadecolor[0] * currententity->colormod[0]));
910                                                                 g = (int) ((float) (shadecolor[1] * currententity->colormod[1]));
911                                                                 b = (int) ((float) (shadecolor[2] * currententity->colormod[2]));
912                                                         }
913                                                 }
914                                                 transpolyvert(nv[0], nv[1], nv[2], (v[3] + os) * (1.0f/64.0f), (v[4] + ot) * (1.0f/64.0f), r,g,b,alpha);
915                                         }
916                                         transpolyend();
917                                 }
918                                 continue;
919                         }
920                         t = R_TextureAnimation (s->texinfo->texture);
921                         v = s->polys->verts[0];
922                         if (vertexlit || s->texinfo->texture->transparent)
923                         {
924                                 // FIXME: could be a transparent water texture
925                                 transpolybegin(t->gl_texturenum, t->gl_glowtexturenum, 0, currententity->effects & EF_ADDITIVE ? TPOLYTYPE_ADD : TPOLYTYPE_ALPHA);
926                                 if ((currententity->effects & EF_FULLBRIGHT) || !s->samples)
927                                 {
928                                         for (i = 0;i < s->polys->numverts;i++, v += VERTEXSIZE)
929                                         {
930                                                 softwaretransform(v, nv);
931                                                 transpolyvert(nv[0], nv[1], nv[2], v[3], v[4], 255,255,255,modelalpha*255.0f);
932                                         }
933                                 }
934                                 else
935                                 {
936                                         smax = (s->extents[0]>>4)+1;
937                                         tmax = (s->extents[1]>>4)+1;
938                                         size3 = smax*tmax*3; // *3 for colored lighting
939                                         for (i = 0;i < s->polys->numverts;i++, v += VERTEXSIZE)
940                                         {
941                                                 shadecolor[0] = shadecolor[1] = shadecolor[2] = r_ambient.value * 2.0f;
942                                                 lm = (byte *)((long) s->samples + ((int) v[8] * smax + (int) v[7]) * 3); // LordHavoc: *3 for colored lighting
943                                                 for (maps = 0;maps < MAXLIGHTMAPS && s->styles[maps] != 255;maps++)
944                                                 {
945                                                         scale = d_lightstylevalue[s->styles[maps]] * (1.0 / 128.0);
946                                                         shadecolor[0] += lm[0] * scale;
947                                                         shadecolor[1] += lm[1] * scale;
948                                                         shadecolor[2] += lm[2] * scale;
949                                                         lm += size3; // LordHavoc: *3 for colored lighting
950                                                 }
951                                                 softwaretransform(v, nv);
952                                                 R_DynamicLightPointNoMask(shadecolor, nv); // LordHavoc: dynamic lighting
953                                                 if (lighthalf)
954                                                 {
955                                                         transpolyvert(nv[0], nv[1], nv[2], v[3], v[4], (int) shadecolor[0] >> 1, (int) shadecolor[1] >> 1, (int) shadecolor[2] >> 1, modelalpha*255.0f);
956                                                 }
957                                                 else
958                                                 {
959                                                         transpolyvert(nv[0], nv[1], nv[2], v[3], v[4], shadecolor[0], shadecolor[1], shadecolor[2], modelalpha*255.0f);
960                                                 }
961                                         }
962                                 }
963                                 transpolyend();
964                         }
965                         else
966                         {
967                                 // check for lightmap modification
968                                 if (r_dynamic.value)
969                                 {
970                                         if (s->dlightframe == r_framecount || s->cached_dlight || r_ambient.value != s->cached_ambient || lighthalf != s->cached_lighthalf) // dynamic this frame or previously, or lighthalf changed
971                                                 R_UpdateLightmap(s, s->lightmaptexturenum);
972                                         else
973                                                 for (maps = 0 ; maps < MAXLIGHTMAPS && s->styles[maps] != 255 ; maps++)
974                                                         if (d_lightstylevalue[s->styles[maps]] != s->cached_light[maps])
975                                                         {
976                                                                 R_UpdateLightmap(s, s->lightmaptexturenum);
977                                                                 break;
978                                                         }
979                                 }
980                                 if (currentwallpoly < MAX_WALLPOLYS && (currentwallvert + s->polys->numverts) <= MAX_WALLVERTS)
981                                 {
982                                         wallpoly[currentwallpoly].texnum = (unsigned short) t->gl_texturenum;
983                                         wallpoly[currentwallpoly].lighttexnum = (unsigned short) lightmap_textures + s->lightmaptexturenum;
984                                         wallpoly[currentwallpoly].glowtexnum = (unsigned short) t->gl_glowtexturenum;
985                                         wallpoly[currentwallpoly].firstvert = currentwallvert;
986                                         wallpoly[currentwallpoly++].verts = s->polys->numverts;
987                                         for (i = 0;i<s->polys->numverts;i++, v += VERTEXSIZE)
988                                         {
989                                                 softwaretransform(v, wallvert[currentwallvert].vert);
990                                                 wallvert[currentwallvert].s = v[3];
991                                                 wallvert[currentwallvert].t = v[4];
992                                                 wallvert[currentwallvert].u = v[5];
993                                                 wallvert[currentwallvert++].v = v[6];
994                                         }
995                                 }
996                         }
997                 }
998         }
999         UploadLightmaps();
1000 }
1001
1002 /*
1003 =============================================================
1004
1005         WORLD MODEL
1006
1007 =============================================================
1008 */
1009
1010 void R_StoreEfrags (efrag_t **ppefrag);
1011
1012 /*
1013 ================
1014 R_RecursiveWorldNode
1015 ================
1016 */
1017 //extern qboolean R_CullBox (vec3_t mins, vec3_t maxs);
1018 /*
1019 void R_RecursiveWorldNode (mnode_t *node)
1020 {
1021         int                     c, side;
1022         double          dot;
1023
1024 loc0:
1025 // if a leaf node, draw stuff
1026         if (node->contents < 0)
1027         {
1028                 mleaf_t         *pleaf;
1029                 pleaf = (mleaf_t *)node;
1030
1031                 if (c = pleaf->nummarksurfaces)
1032                 {
1033                         msurface_t      **mark;
1034                         mark = pleaf->firstmarksurface;
1035                         do
1036                         {
1037                                 (*mark)->visframe = r_framecount;
1038                                 mark++;
1039                         } while (--c);
1040                 }
1041
1042         // deal with model fragments in this leaf
1043                 if (pleaf->efrags)
1044                         R_StoreEfrags (&pleaf->efrags);
1045
1046                 return;
1047         }
1048
1049 // node is just a decision point, so go down the apropriate sides
1050
1051 // find which side of the node we are on
1052         dot = (node->plane->type < 3 ? modelorg[node->plane->type] : DotProduct (modelorg, node->plane->normal)) - node->plane->dist;
1053
1054 // recurse down the children, front side first
1055         side = dot < 0;
1056         // LordHavoc: save a stack frame by avoiding a call
1057 //      if (node->children[side]->contents != CONTENTS_SOLID && node->children[side]->visframe == r_visframecount && !R_CullBox (node->children[side]->minmaxs, node->children[side]->minmaxs+3))
1058         // LordHavoc: inlined further to reduce conditions
1059         if (node->children[side]->contents != CONTENTS_SOLID
1060          && node->children[side]->visframe == r_visframecount
1061          && frustum[0].BoxOnPlaneSideFunc(node->children[side]->minmaxs, node->children[side]->minmaxs+3, &frustum[0]) != 2
1062          && frustum[1].BoxOnPlaneSideFunc(node->children[side]->minmaxs, node->children[side]->minmaxs+3, &frustum[1]) != 2
1063          && frustum[2].BoxOnPlaneSideFunc(node->children[side]->minmaxs, node->children[side]->minmaxs+3, &frustum[2]) != 2
1064          && frustum[3].BoxOnPlaneSideFunc(node->children[side]->minmaxs, node->children[side]->minmaxs+3, &frustum[3]) != 2)
1065                 R_RecursiveWorldNode (node->children[side]);
1066
1067         // backside
1068         side = dot >= 0;
1069 // draw stuff
1070         if (c = node->numsurfaces)
1071         {
1072                 msurface_t      *surf;
1073                 surf = cl.worldmodel->surfaces + node->firstsurface;
1074
1075                 // LordHavoc: caused a crash due to texsort (it could render twice...)
1076                 // back side
1077                 //side = dot >= -BACKFACE_EPSILON;
1078                 if (dot < 0)
1079                 {
1080                         for (;c;c--, surf++)
1081                         {
1082                                 if (surf->visframe == r_framecount && (surf->flags & SURF_PLANEBACK))
1083                                 {
1084                                         surf->texturechain = surf->texinfo->texture->texturechain;
1085                                         surf->texinfo->texture->texturechain = surf;
1086                                 }
1087                         }
1088                 }
1089                 else
1090                 {
1091                         for (;c;c--, surf++)
1092                         {
1093                                 if (surf->visframe == r_framecount && (!(surf->flags & SURF_PLANEBACK)))
1094                                 {
1095                                         surf->texturechain = surf->texinfo->texture->texturechain;
1096                                         surf->texinfo->texture->texturechain = surf;
1097                                 }
1098                         }
1099                 }
1100         }
1101
1102 // recurse down the back side
1103         // LordHavoc: save a stack frame by avoiding a call
1104 //      if (node->children[side]->contents != CONTENTS_SOLID && node->children[side]->visframe == r_visframecount && !R_CullBox (node->children[side]->minmaxs, node->children[side]->minmaxs+3))
1105         // LordHavoc: inlined further to reduce conditions
1106         if (node->children[side]->contents != CONTENTS_SOLID
1107          && node->children[side]->visframe == r_visframecount
1108          && frustum[0].BoxOnPlaneSideFunc(node->children[side]->minmaxs, node->children[side]->minmaxs+3, &frustum[0]) != 2
1109          && frustum[1].BoxOnPlaneSideFunc(node->children[side]->minmaxs, node->children[side]->minmaxs+3, &frustum[1]) != 2
1110          && frustum[2].BoxOnPlaneSideFunc(node->children[side]->minmaxs, node->children[side]->minmaxs+3, &frustum[2]) != 2
1111          && frustum[3].BoxOnPlaneSideFunc(node->children[side]->minmaxs, node->children[side]->minmaxs+3, &frustum[3]) != 2)
1112         {
1113                 node = node->children[side];
1114                 goto loc0;
1115         }
1116 //              R_RecursiveWorldNode (node->children[side]);
1117 }
1118 */
1119
1120 extern int c_nodes;
1121 void R_WorldNode ()
1122 {
1123         int             c, side;
1124         double  dot;
1125         struct
1126         {
1127                 double dot;
1128                 mnode_t *node;
1129         } nodestack[1024];
1130         int             s = 0;
1131         mnode_t *node;
1132
1133         if (!(node = cl.worldmodel->nodes))
1134                 return;
1135
1136         while(1)
1137         {
1138         // if a leaf node, draw stuff
1139                 c_nodes++;
1140                 if (node->contents < 0)
1141                 {
1142                         if (node->contents != CONTENTS_SOLID)
1143                         {
1144                                 mleaf_t         *pleaf;
1145                                 pleaf = (mleaf_t *)node;
1146
1147                                 if ((c = pleaf->nummarksurfaces))
1148                                 {
1149                                         msurface_t      **mark;
1150                                         mark = pleaf->firstmarksurface;
1151                                         do
1152                                         {
1153                                                 (*mark)->visframe = r_framecount;
1154                                                 mark++;
1155                                         } while (--c);
1156                                 }
1157
1158                                 // deal with model fragments in this leaf
1159                                 if (pleaf->efrags)
1160                                         R_StoreEfrags (&pleaf->efrags);
1161                         }
1162
1163                         if (!s)
1164                                 break;
1165                         node = nodestack[--s].node;
1166                         dot = nodestack[s].dot;
1167                         goto loc0;
1168                 }
1169
1170         // node is just a decision point, so go down the apropriate sides
1171
1172         // find which side of the node we are on
1173                 dot = (node->plane->type < 3 ? modelorg[node->plane->type] : DotProduct (modelorg, node->plane->normal)) - node->plane->dist;
1174
1175         // recurse down the children, front side first
1176                 side = dot < 0;
1177                 if (node->children[side]->visframe == r_visframecount
1178                  && frustum[0].BoxOnPlaneSideFunc(node->children[side]->minmaxs, node->children[side]->minmaxs+3, &frustum[0]) != 2
1179                  && frustum[1].BoxOnPlaneSideFunc(node->children[side]->minmaxs, node->children[side]->minmaxs+3, &frustum[1]) != 2
1180                  && frustum[2].BoxOnPlaneSideFunc(node->children[side]->minmaxs, node->children[side]->minmaxs+3, &frustum[2]) != 2
1181                  && frustum[3].BoxOnPlaneSideFunc(node->children[side]->minmaxs, node->children[side]->minmaxs+3, &frustum[3]) != 2)
1182                 {
1183                         nodestack[s].node = node;
1184                         nodestack[s++].dot = dot;
1185                         node = node->children[side];
1186                         continue;
1187                 }
1188 loc0:
1189
1190                 // backside
1191                 side = dot >= 0;
1192         // draw stuff
1193                 if ((c = node->numsurfaces))
1194                 {
1195                         msurface_t      *surf;
1196                         surf = cl.worldmodel->surfaces + node->firstsurface;
1197
1198                         if (side)
1199                         {
1200                                 for (;c;c--, surf++)
1201                                 {
1202                                         if (surf->visframe == r_framecount && !(surf->flags & SURF_PLANEBACK))
1203                                         {
1204                                                 surf->texturechain = surf->texinfo->texture->texturechain;
1205                                                 surf->texinfo->texture->texturechain = surf;
1206                                         }
1207                                 }
1208                         }
1209                         else
1210                         {
1211                                 for (;c;c--, surf++)
1212                                 {
1213                                         if (surf->visframe == r_framecount && (surf->flags & SURF_PLANEBACK))
1214                                         {
1215                                                 surf->texturechain = surf->texinfo->texture->texturechain;
1216                                                 surf->texinfo->texture->texturechain = surf;
1217                                         }
1218                                 }
1219                         }
1220                 }
1221
1222         // recurse down the back side
1223                 if (node->children[side]->visframe == r_visframecount
1224                  && frustum[0].BoxOnPlaneSideFunc(node->children[side]->minmaxs, node->children[side]->minmaxs+3, &frustum[0]) != 2
1225                  && frustum[1].BoxOnPlaneSideFunc(node->children[side]->minmaxs, node->children[side]->minmaxs+3, &frustum[1]) != 2
1226                  && frustum[2].BoxOnPlaneSideFunc(node->children[side]->minmaxs, node->children[side]->minmaxs+3, &frustum[2]) != 2
1227                  && frustum[3].BoxOnPlaneSideFunc(node->children[side]->minmaxs, node->children[side]->minmaxs+3, &frustum[3]) != 2)
1228                 {
1229                         node = node->children[side];
1230                         continue;
1231                 }
1232
1233                 if (!s)
1234                         break;
1235                 node = nodestack[--s].node;
1236                 dot = nodestack[s].dot;
1237                 goto loc0;
1238         }
1239 }
1240
1241
1242 /*
1243 =============
1244 R_DrawWorld
1245 =============
1246 */
1247 void R_DrawWorld (void)
1248 {
1249         entity_t        ent;
1250
1251         memset (&ent, 0, sizeof(ent));
1252         ent.model = cl.worldmodel;
1253         ent.colormod[0] = ent.colormod[1] = ent.colormod[2] = 1;
1254         modelalpha = ent.alpha = 1;
1255         ent.scale = 1;
1256
1257         VectorCopy (r_refdef.vieworg, modelorg);
1258
1259         currententity = &ent;
1260
1261         softwaretransformidentity(); // LordHavoc: clear transform
1262         skyisvisible = false;
1263
1264         if (cl.worldmodel)
1265                 R_WorldNode ();
1266
1267         glClear (GL_DEPTH_BUFFER_BIT);
1268
1269         DrawTextureChains ();
1270
1271         glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
1272         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1273 }
1274
1275
1276 /*
1277 ===============
1278 R_MarkLeaves
1279 ===============
1280 */
1281 void R_MarkLeaves (void)
1282 {
1283         byte    *vis;
1284         mnode_t *node;
1285         int             i;
1286
1287         if (r_oldviewleaf == r_viewleaf && !r_novis.value)
1288                 return;
1289         
1290         r_visframecount++;
1291         r_oldviewleaf = r_viewleaf;
1292
1293         if (r_novis.value)
1294         {
1295                 for (i=0 ; i<cl.worldmodel->numleafs ; i++)
1296                 {
1297                         node = (mnode_t *)&cl.worldmodel->leafs[i+1];
1298                         do
1299                         {
1300                                 if (node->visframe == r_visframecount)
1301                                         break;
1302                                 node->visframe = r_visframecount;
1303                                 node = node->parent;
1304                         } while (node);
1305                 }
1306         }
1307         else
1308         {
1309                 vis = Mod_LeafPVS (r_viewleaf, cl.worldmodel);
1310                 
1311                 for (i=0 ; i<cl.worldmodel->numleafs ; i++)
1312                 {
1313                         if (vis[i>>3] & (1<<(i&7)))
1314                         {
1315                                 node = (mnode_t *)&cl.worldmodel->leafs[i+1];
1316                                 do
1317                                 {
1318                                         if (node->visframe == r_visframecount)
1319                                                 break;
1320                                         node->visframe = r_visframecount;
1321                                         node = node->parent;
1322                                 } while (node);
1323                         }
1324                 }
1325         }
1326 }
1327
1328
1329
1330 /*
1331 =============================================================================
1332
1333   LIGHTMAP ALLOCATION
1334
1335 =============================================================================
1336 */
1337
1338 // returns a texture number and the position inside it
1339 int AllocBlock (int w, int h, int *x, int *y)
1340 {
1341         int             i, j;
1342         int             best, best2;
1343         int             texnum;
1344
1345         for (texnum=0 ; texnum<MAX_LIGHTMAPS ; texnum++)
1346         {
1347                 best = BLOCK_HEIGHT;
1348
1349                 for (i=0 ; i<BLOCK_WIDTH-w ; i+=lightmapalign) // LordHavoc: NVIDIA has broken subimage, so align the lightmaps
1350                 {
1351                         best2 = 0;
1352
1353                         for (j=0 ; j<w ; j++)
1354                         {
1355                                 if (allocated[texnum][i+j] >= best)
1356                                         break;
1357                                 if (allocated[texnum][i+j] > best2)
1358                                         best2 = allocated[texnum][i+j];
1359                         }
1360                         if (j == w)
1361                         {       // this is a valid spot
1362                                 *x = i;
1363                                 *y = best = best2;
1364                         }
1365                 }
1366
1367                 if (best + h > BLOCK_HEIGHT)
1368                         continue;
1369
1370                 if (nosubimagefragments || nosubimage)
1371                 {
1372                         if (!lightmaps[texnum])
1373                                 lightmaps[texnum] = calloc(BLOCK_WIDTH*BLOCK_HEIGHT*4, 1);
1374                 }
1375                 // LordHavoc: clear texture to blank image, fragments are uploaded using subimage
1376                 else if (!allocated[texnum][0])
1377                 {
1378                         byte blank[BLOCK_WIDTH*BLOCK_HEIGHT*3];
1379                         memset(blank, 0, sizeof(blank));
1380                         glBindTexture(GL_TEXTURE_2D, lightmap_textures + texnum);
1381                         glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1382                         glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1383                         if (lightmaprgba)
1384                                 glTexImage2D (GL_TEXTURE_2D, 0, 3, BLOCK_WIDTH, BLOCK_HEIGHT, 0, GL_RGBA, GL_UNSIGNED_BYTE, blank);
1385                         else
1386                                 glTexImage2D (GL_TEXTURE_2D, 0, 3, BLOCK_WIDTH, BLOCK_HEIGHT, 0, GL_RGB, GL_UNSIGNED_BYTE, blank);
1387                 }
1388
1389                 for (i=0 ; i<w ; i++)
1390                         allocated[texnum][*x + i] = best + h;
1391
1392                 return texnum;
1393         }
1394
1395         Sys_Error ("AllocBlock: full");
1396         return 0;
1397 }
1398
1399
1400 mvertex_t       *r_pcurrentvertbase;
1401 model_t         *currentmodel;
1402
1403 int     nColinElim;
1404
1405 /*
1406 ================
1407 BuildSurfaceDisplayList
1408 ================
1409 */
1410 void BuildSurfaceDisplayList (msurface_t *fa)
1411 {
1412         int                     i, lindex, lnumverts;
1413         medge_t         *pedges, *r_pedge;
1414         int                     vertpage;
1415         float           *vec;
1416         float           s, t;
1417         glpoly_t        *poly;
1418
1419 // reconstruct the polygon
1420         pedges = currentmodel->edges;
1421         lnumverts = fa->numedges;
1422         vertpage = 0;
1423
1424         //
1425         // draw texture
1426         //
1427         poly = Hunk_Alloc (sizeof(glpoly_t) + (lnumverts-4) * VERTEXSIZE*sizeof(float));
1428         poly->next = fa->polys;
1429         poly->flags = fa->flags;
1430         fa->polys = poly;
1431         poly->numverts = lnumverts;
1432
1433         for (i=0 ; i<lnumverts ; i++)
1434         {
1435                 lindex = currentmodel->surfedges[fa->firstedge + i];
1436
1437                 if (lindex > 0)
1438                 {
1439                         r_pedge = &pedges[lindex];
1440                         vec = r_pcurrentvertbase[r_pedge->v[0]].position;
1441                 }
1442                 else
1443                 {
1444                         r_pedge = &pedges[-lindex];
1445                         vec = r_pcurrentvertbase[r_pedge->v[1]].position;
1446                 }
1447                 s = DotProduct (vec, fa->texinfo->vecs[0]) + fa->texinfo->vecs[0][3];
1448                 s /= fa->texinfo->texture->width;
1449
1450                 t = DotProduct (vec, fa->texinfo->vecs[1]) + fa->texinfo->vecs[1][3];
1451                 t /= fa->texinfo->texture->height;
1452
1453                 VectorCopy (vec, poly->verts[i]);
1454                 poly->verts[i][3] = s;
1455                 poly->verts[i][4] = t;
1456
1457                 //
1458                 // lightmap texture coordinates
1459                 //
1460                 s = DotProduct (vec, fa->texinfo->vecs[0]) + fa->texinfo->vecs[0][3];
1461                 s -= fa->texturemins[0];
1462                 poly->verts[i][7] = bound(0l, ((int)s>>4), (fa->extents[0]>>4)); // LordHavoc: raw lightmap coordinates
1463                 s += fa->light_s*16;
1464                 s += 8;
1465                 s /= BLOCK_WIDTH*16; //fa->texinfo->texture->width;
1466
1467                 t = DotProduct (vec, fa->texinfo->vecs[1]) + fa->texinfo->vecs[1][3];
1468                 t -= fa->texturemins[1];
1469                 poly->verts[i][8] = bound(0l, ((int)t>>4), (fa->extents[1]>>4)); // LordHavoc: raw lightmap coordinates
1470                 t += fa->light_t*16;
1471                 t += 8;
1472                 t /= BLOCK_HEIGHT*16; //fa->texinfo->texture->height;
1473
1474                 poly->verts[i][5] = s;
1475                 poly->verts[i][6] = t;
1476         }
1477
1478         //
1479         // remove co-linear points - Ed
1480         //
1481         /*
1482         if (!gl_keeptjunctions.value)
1483         {
1484                 for (i = 0 ; i < lnumverts ; ++i)
1485                 {
1486                         vec3_t v1, v2;
1487                         float *prev, *this, *next;
1488
1489                         prev = poly->verts[(i + lnumverts - 1) % lnumverts];
1490                         this = poly->verts[i];
1491                         next = poly->verts[(i + 1) % lnumverts];
1492
1493                         VectorSubtract( this, prev, v1 );
1494                         VectorNormalize( v1 );
1495                         VectorSubtract( next, prev, v2 );
1496                         VectorNormalize( v2 );
1497
1498                         // skip co-linear points
1499                         #define COLINEAR_EPSILON 0.001
1500                         if ((fabs( v1[0] - v2[0] ) <= COLINEAR_EPSILON) &&
1501                                 (fabs( v1[1] - v2[1] ) <= COLINEAR_EPSILON) && 
1502                                 (fabs( v1[2] - v2[2] ) <= COLINEAR_EPSILON))
1503                         {
1504                                 int j;
1505                                 for (j = i + 1; j < lnumverts; ++j)
1506                                 {
1507                                         int k;
1508                                         for (k = 0; k < VERTEXSIZE; ++k)
1509                                                 poly->verts[j - 1][k] = poly->verts[j][k];
1510                                 }
1511                                 --lnumverts;
1512                                 ++nColinElim;
1513                                 // retry next vertex next time, which is now current vertex
1514                                 --i;
1515                         }
1516                 }
1517         }
1518         */
1519         poly->numverts = lnumverts;
1520
1521 }
1522
1523 /*
1524 ========================
1525 GL_CreateSurfaceLightmap
1526 ========================
1527 */
1528 void GL_CreateSurfaceLightmap (msurface_t *surf)
1529 {
1530         int             smax, tmax;
1531
1532         if (surf->flags & (SURF_DRAWSKY|SURF_DRAWTURB))
1533                 return;
1534
1535         smax = (surf->extents[0]>>4)+1;
1536         tmax = (surf->extents[1]>>4)+1;
1537
1538         surf->lightmaptexturenum = AllocBlock (smax, tmax, &surf->light_s, &surf->light_t);
1539         if (nosubimage || nosubimagefragments)
1540                 return;
1541         glBindTexture(GL_TEXTURE_2D, lightmap_textures + surf->lightmaptexturenum);
1542         smax = ((surf->extents[0]>>4)+lightmapalign) & lightmapalignmask;
1543         if (lightmaprgba)
1544         {
1545                 R_BuildLightMap (surf, templight, smax * 4);
1546                 glTexSubImage2D(GL_TEXTURE_2D, 0, surf->light_s, surf->light_t, smax, tmax, GL_RGBA, GL_UNSIGNED_BYTE, templight);
1547         }
1548         else
1549         {
1550                 R_BuildLightMap (surf, templight, smax * 3);
1551                 glTexSubImage2D(GL_TEXTURE_2D, 0, surf->light_s, surf->light_t, smax, tmax, GL_RGB , GL_UNSIGNED_BYTE, templight);
1552         }
1553 }
1554
1555
1556 /*
1557 ==================
1558 GL_BuildLightmaps
1559
1560 Builds the lightmap texture
1561 with all the surfaces from all brush models
1562 ==================
1563 */
1564 void GL_BuildLightmaps (void)
1565 {
1566         int             i, j;
1567         model_t *m;
1568
1569         memset (allocated, 0, sizeof(allocated));
1570
1571         r_framecount = 1;               // no dlightcache
1572
1573         if (gl_nosubimagefragments.value)
1574                 nosubimagefragments = 1;
1575         else
1576                 nosubimagefragments = 0;
1577
1578         if (gl_nosubimage.value)
1579                 nosubimage = 1;
1580         else
1581                 nosubimage = 0;
1582
1583         if (gl_lightmaprgba.value)
1584         {
1585                 lightmaprgba = true;
1586                 lightmapbytes = 4;
1587         }
1588         else
1589         {
1590                 lightmaprgba = false;
1591                 lightmapbytes = 3;
1592         }
1593
1594         // LordHavoc: NVIDIA seems to have a broken glTexSubImage2D,
1595         //            it needs to be aligned on 4 pixel boundaries...
1596         //            so I implemented an adjustable lightmap alignment
1597         if (gl_lightmapalign.value < 1)
1598                 gl_lightmapalign.value = 1;
1599         if (gl_lightmapalign.value > 16)
1600                 gl_lightmapalign.value = 16;
1601         lightmapalign = 1;
1602         while (lightmapalign < gl_lightmapalign.value)
1603                 lightmapalign <<= 1;
1604         gl_lightmapalign.value = lightmapalign;
1605         lightmapalignmask = ~(lightmapalign - 1);
1606         if (nosubimagefragments || nosubimage)
1607         {
1608                 lightmapalign = 1;
1609                 lightmapalignmask = ~0;
1610         }
1611
1612         if (!lightmap_textures)
1613         {
1614                 lightmap_textures = texture_extension_number;
1615                 texture_extension_number += MAX_LIGHTMAPS;
1616         }
1617
1618         for (j=1 ; j<MAX_MODELS ; j++)
1619         {
1620                 m = cl.model_precache[j];
1621                 if (!m)
1622                         break;
1623                 if (m->name[0] == '*')
1624                         continue;
1625                 r_pcurrentvertbase = m->vertexes;
1626                 currentmodel = m;
1627                 for (i=0 ; i<m->numsurfaces ; i++)
1628                 {
1629                         if ( m->surfaces[i].flags & SURF_DRAWTURB )
1630                                 continue;
1631                         if ( m->surfaces[i].flags & SURF_DRAWSKY )
1632                                 continue;
1633                         GL_CreateSurfaceLightmap (m->surfaces + i);
1634                         BuildSurfaceDisplayList (m->surfaces + i);
1635                 }
1636         }
1637
1638         if (nosubimage || nosubimagefragments)
1639         {
1640                 if (gl_mtexable)
1641                         qglSelectTexture(gl_mtex_enum+1);
1642                 for (i = 0;i < MAX_LIGHTMAPS;i++)
1643                 {
1644                         if (!allocated[i][0])
1645                                 break;
1646                         lightmapupdate[i][0] = BLOCK_HEIGHT;
1647                         lightmapupdate[i][1] = 0;
1648                         glBindTexture(GL_TEXTURE_2D, lightmap_textures + i);
1649                         glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1650                         glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1651                         if (lightmaprgba)
1652                                 glTexImage2D(GL_TEXTURE_2D, 0, 3, BLOCK_WIDTH, BLOCK_HEIGHT, 0, GL_RGBA, GL_UNSIGNED_BYTE, lightmaps[i]);
1653                         else
1654                                 glTexImage2D(GL_TEXTURE_2D, 0, 3, BLOCK_WIDTH, BLOCK_HEIGHT, 0, GL_RGB, GL_UNSIGNED_BYTE, lightmaps[i]);
1655                 }
1656                 if (gl_mtexable)
1657                         qglSelectTexture(gl_mtex_enum+0);
1658         }
1659 }
1660