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