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