Home | History | Annotate | Download | only in WinQuake
      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			skytexturenum;
     25 
     26 #ifndef GL_RGBA4
     27 #define	GL_RGBA4	0
     28 #endif
     29 
     30 
     31 int		lightmap_bytes;		// 1, 2, or 4
     32 
     33 int		lightmap_textures;
     34 
     35 unsigned		blocklights[18*18];
     36 
     37 #define	BLOCK_WIDTH		128
     38 #define	BLOCK_HEIGHT	128
     39 
     40 #define	MAX_LIGHTMAPS	64
     41 int			active_lightmaps;
     42 
     43 typedef struct glRect_s {
     44   unsigned char l,t,w,h;
     45 } glRect_t;
     46 
     47 glpoly_t	*lightmap_polys[MAX_LIGHTMAPS];
     48 qboolean	lightmap_modified[MAX_LIGHTMAPS];
     49 glRect_t	lightmap_rectchange[MAX_LIGHTMAPS];
     50 
     51 int			allocated[MAX_LIGHTMAPS][BLOCK_WIDTH];
     52 
     53 // the lightmap texture data needs to be kept in
     54 // main memory so texsubimage can update properly
     55 byte		lightmaps[4*MAX_LIGHTMAPS*BLOCK_WIDTH*BLOCK_HEIGHT];
     56 
     57 // For gl_texsort 0
     58 msurface_t  *skychain = NULL;
     59 msurface_t  *waterchain = NULL;
     60 
     61 void R_RenderDynamicLightmaps (msurface_t *fa);
     62 
     63 /*
     64 ===============
     65 R_AddDynamicLights
     66 ===============
     67 */
     68 void R_AddDynamicLights (msurface_t *surf)
     69 {
     70   int			lnum;
     71   int			sd, td;
     72   float		dist, rad, minlight;
     73   vec3_t		impact, local;
     74   int			s, t;
     75   int			i;
     76   int			smax, tmax;
     77   mtexinfo_t	*tex;
     78 
     79   smax = (surf->extents[0]>>4)+1;
     80   tmax = (surf->extents[1]>>4)+1;
     81   tex = surf->texinfo;
     82 
     83   for (lnum=0 ; lnum<MAX_DLIGHTS ; lnum++)
     84   {
     85     if ( !(surf->dlightbits & (1<<lnum) ) )
     86       continue;		// not lit by this light
     87 
     88     rad = cl_dlights[lnum].radius;
     89     dist = DotProduct (cl_dlights[lnum].origin, surf->plane->normal) -
     90         surf->plane->dist;
     91     rad -= fabs(dist);
     92     minlight = cl_dlights[lnum].minlight;
     93     if (rad < minlight)
     94       continue;
     95     minlight = rad - minlight;
     96 
     97     for (i=0 ; i<3 ; i++)
     98     {
     99       impact[i] = cl_dlights[lnum].origin[i] -
    100           surf->plane->normal[i]*dist;
    101     }
    102 
    103     local[0] = DotProduct (impact, tex->vecs[0]) + tex->vecs[0][3];
    104     local[1] = DotProduct (impact, tex->vecs[1]) + tex->vecs[1][3];
    105 
    106     local[0] -= surf->texturemins[0];
    107     local[1] -= surf->texturemins[1];
    108 
    109     for (t = 0 ; t<tmax ; t++)
    110     {
    111       td = (int)(local[1] - t*16);
    112       if (td < 0)
    113         td = -td;
    114       for (s=0 ; s<smax ; s++)
    115       {
    116         sd = (int)(local[0] - s*16);
    117         if (sd < 0)
    118           sd = -sd;
    119         if (sd > td)
    120           dist = sd + (td>>1);
    121         else
    122           dist = td + (sd>>1);
    123         if (dist < minlight)
    124           blocklights[t*smax + s] += (int)((rad - dist)*256);
    125       }
    126     }
    127   }
    128 }
    129 
    130 
    131 /*
    132 ===============
    133 R_BuildLightMap
    134 
    135 Combine and scale multiple lightmaps into the 8.8 format in blocklights
    136 ===============
    137 */
    138 void R_BuildLightMap (msurface_t *surf, byte *dest, int stride)
    139 {
    140   int			smax, tmax;
    141   int			t;
    142   int			i, j, size;
    143   byte		*lightmap;
    144   unsigned	scale;
    145   int			maps;
    146   int			lightadj[4];
    147   unsigned	*bl;
    148 
    149   surf->cached_dlight = (surf->dlightframe == r_framecount);
    150 
    151   smax = (surf->extents[0]>>4)+1;
    152   tmax = (surf->extents[1]>>4)+1;
    153   size = smax*tmax;
    154   lightmap = surf->samples;
    155 
    156 // set to full bright if no light data
    157   if (r_fullbright.value || !cl.worldmodel->lightdata)
    158   {
    159     for (i=0 ; i<size ; i++)
    160       blocklights[i] = 255*256;
    161     goto store;
    162   }
    163 
    164 // clear to no light
    165   for (i=0 ; i<size ; i++)
    166     blocklights[i] = 0;
    167 
    168 // add all the lightmaps
    169   if (lightmap)
    170     for (maps = 0 ; maps < MAXLIGHTMAPS && surf->styles[maps] != 255 ;
    171        maps++)
    172     {
    173       scale = d_lightstylevalue[surf->styles[maps]];
    174       surf->cached_light[maps] = scale;	// 8.8 fraction
    175       for (i=0 ; i<size ; i++)
    176         blocklights[i] += lightmap[i] * scale;
    177       lightmap += size;	// skip to next lightmap
    178     }
    179 
    180 // add all the dynamic lights
    181   if (surf->dlightframe == r_framecount)
    182     R_AddDynamicLights (surf);
    183 
    184 // bound, invert, and shift
    185 store:
    186   switch (gl_lightmap_format)
    187   {
    188   case GL_RGBA:
    189     stride -= (smax<<2);
    190     bl = blocklights;
    191     for (i=0 ; i<tmax ; i++, dest += stride)
    192     {
    193       for (j=0 ; j<smax ; j++)
    194       {
    195         t = *bl++;
    196         t >>= 7;
    197         if (t > 255)
    198           t = 255;
    199         dest[3] = 255-t;
    200         dest += 4;
    201       }
    202     }
    203     break;
    204   case GL_ALPHA:
    205   case GL_LUMINANCE:
    206   case GL_INTENSITY:
    207     bl = blocklights;
    208     for (i=0 ; i<tmax ; i++, dest += stride)
    209     {
    210       for (j=0 ; j<smax ; j++)
    211       {
    212         t = *bl++;
    213         t >>= 7;
    214         if (t > 255)
    215           t = 255;
    216         dest[j] = 255-t;
    217       }
    218     }
    219     break;
    220   default:
    221     Sys_Error ("Bad lightmap format");
    222   }
    223 }
    224 
    225 
    226 /*
    227 ===============
    228 R_TextureAnimation
    229 
    230 Returns the proper texture for a given time and base texture
    231 ===============
    232 */
    233 texture_t *R_TextureAnimation (texture_t *base)
    234 {
    235   int		reletive;
    236   int		count;
    237 
    238   if (currententity->frame)
    239   {
    240     if (base->alternate_anims)
    241       base = base->alternate_anims;
    242   }
    243 
    244   if (!base->anim_total)
    245     return base;
    246 
    247   reletive = (int)(cl.time*10) % base->anim_total;
    248 
    249   count = 0;
    250   while (base->anim_min > reletive || base->anim_max <= reletive)
    251   {
    252     base = base->anim_next;
    253     if (!base)
    254       Sys_Error ("R_TextureAnimation: broken cycle");
    255     if (++count > 100)
    256       Sys_Error ("R_TextureAnimation: infinite cycle");
    257   }
    258 
    259   return base;
    260 }
    261 
    262 
    263 /*
    264 =============================================================
    265 
    266   BRUSH MODELS
    267 
    268 =============================================================
    269 */
    270 
    271 
    272 extern	int		solidskytexture;
    273 extern	int		alphaskytexture;
    274 extern	float	speedscale;		// for top sky and bottom sky
    275 
    276 void DrawGLWaterPoly (glpoly_t *p);
    277 void DrawGLWaterPolyLightmap (glpoly_t *p);
    278 
    279 #ifdef _WIN32
    280 lpMTexFUNC qglMTexCoord2fSGIS = NULL;
    281 lpSelTexFUNC qglSelectTextureSGIS = NULL;
    282 #endif
    283 
    284 qboolean mtexenabled = false;
    285 
    286 void GL_SelectTexture (GLenum target);
    287 
    288 void GL_DisableMultitexture(void)
    289 {
    290   if (mtexenabled) {
    291     glDisable(GL_TEXTURE_2D);
    292     GL_SelectTexture(TEXTURE0_SGIS);
    293     mtexenabled = false;
    294   }
    295 }
    296 
    297 void GL_EnableMultitexture(void)
    298 {
    299   if (gl_mtexable) {
    300     GL_SelectTexture(TEXTURE1_SGIS);
    301     glEnable(GL_TEXTURE_2D);
    302     mtexenabled = true;
    303   }
    304 }
    305 
    306 #if 0
    307 /*
    308 ================
    309 R_DrawSequentialPoly
    310 
    311 Systems that have fast state and texture changes can
    312 just do everything as it passes with no need to sort
    313 ================
    314 */
    315 void R_DrawSequentialPoly (msurface_t *s)
    316 {
    317   glpoly_t	*p;
    318   float		*v;
    319   int			i;
    320   texture_t	*t;
    321 
    322   //
    323   // normal lightmaped poly
    324   //
    325   if (! (s->flags & (SURF_DRAWSKY|SURF_DRAWTURB|SURF_UNDERWATER) ) )
    326   {
    327     p = s->polys;
    328 
    329     t = R_TextureAnimation (s->texinfo->texture);
    330     GL_Bind (t->gl_texturenum);
    331     glBegin (GL_POLYGON);
    332     v = p->verts[0];
    333     for (i=0 ; i<p->numverts ; i++, v+= VERTEXSIZE)
    334     {
    335       glTexCoord2f (v[3], v[4]);
    336       glVertex3fv (v);
    337     }
    338     glEnd ();
    339 
    340     GL_Bind (lightmap_textures + s->lightmaptexturenum);
    341     glEnable (GL_BLEND);
    342     glBegin (GL_POLYGON);
    343     v = p->verts[0];
    344     for (i=0 ; i<p->numverts ; i++, v+= VERTEXSIZE)
    345     {
    346       glTexCoord2f (v[5], v[6]);
    347       glVertex3fv (v);
    348     }
    349     glEnd ();
    350 
    351     glDisable (GL_BLEND);
    352 
    353     return;
    354   }
    355 
    356   //
    357   // subdivided water surface warp
    358   //
    359   if (s->flags & SURF_DRAWTURB)
    360   {
    361     GL_Bind (s->texinfo->texture->gl_texturenum);
    362     EmitWaterPolys (s);
    363     return;
    364   }
    365 
    366   //
    367   // subdivided sky warp
    368   //
    369   if (s->flags & SURF_DRAWSKY)
    370   {
    371     GL_Bind (solidskytexture);
    372     speedscale = realtime*8;
    373     speedscale -= (int)speedscale;
    374 
    375     EmitSkyPolys (s);
    376 
    377     glEnable (GL_BLEND);
    378     glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    379     GL_Bind (alphaskytexture);
    380     speedscale = realtime*16;
    381     speedscale -= (int)speedscale;
    382     EmitSkyPolys (s);
    383     if (gl_lightmap_format == GL_LUMINANCE)
    384       glBlendFunc (GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
    385 
    386     glDisable (GL_BLEND);
    387   }
    388 
    389   //
    390   // underwater warped with lightmap
    391   //
    392   p = s->polys;
    393 
    394   t = R_TextureAnimation (s->texinfo->texture);
    395   GL_Bind (t->gl_texturenum);
    396   DrawGLWaterPoly (p);
    397 
    398   GL_Bind (lightmap_textures + s->lightmaptexturenum);
    399   glEnable (GL_BLEND);
    400   DrawGLWaterPolyLightmap (p);
    401   glDisable (GL_BLEND);
    402 }
    403 #else
    404 /*
    405 ================
    406 R_DrawSequentialPoly
    407 
    408 Systems that have fast state and texture changes can
    409 just do everything as it passes with no need to sort
    410 ================
    411 */
    412 void R_DrawSequentialPoly (msurface_t *s)
    413 {
    414   glpoly_t	*p;
    415   float		*v;
    416   int			i;
    417   texture_t	*t;
    418   vec3_t		nv, dir;
    419   float		ss, ss2, length;
    420   float		s1, t1;
    421   glRect_t	*theRect;
    422 
    423   //
    424   // normal lightmaped poly
    425   //
    426 
    427   if (! (s->flags & (SURF_DRAWSKY|SURF_DRAWTURB|SURF_UNDERWATER) ) )
    428   {
    429     R_RenderDynamicLightmaps (s);
    430     if (gl_mtexable) {
    431       p = s->polys;
    432 
    433       t = R_TextureAnimation (s->texinfo->texture);
    434       // Binds world to texture env 0
    435       GL_SelectTexture(TEXTURE0_SGIS);
    436       GL_Bind (t->gl_texturenum);
    437       glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
    438 
    439       // Binds lightmap to texenv 1
    440       GL_EnableMultitexture(); // Same as SelectTexture (TEXTURE1)
    441       GL_Bind (lightmap_textures + s->lightmaptexturenum);
    442       i = s->lightmaptexturenum;
    443       if (lightmap_modified[i])
    444       {
    445         lightmap_modified[i] = false;
    446         theRect = &lightmap_rectchange[i];
    447         glTexSubImage2D(GL_TEXTURE_2D, 0, 0, theRect->t,
    448           BLOCK_WIDTH, theRect->h, gl_lightmap_format, GL_UNSIGNED_BYTE,
    449           lightmaps+(i* BLOCK_HEIGHT + theRect->t) *BLOCK_WIDTH*lightmap_bytes);
    450         theRect->l = BLOCK_WIDTH;
    451         theRect->t = BLOCK_HEIGHT;
    452         theRect->h = 0;
    453         theRect->w = 0;
    454       }
    455       glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_BLEND);
    456 
    457 #ifdef USE_OPENGLES
    458 
    459       glTexCoordPointer(2, GL_FLOAT, VERTEXSIZE*sizeof(float), &p->verts[0][3]);
    460             glClientActiveTexture(GL_TEXTURE1);
    461             glEnableClientState(GL_TEXTURE_COORD_ARRAY);
    462       glTexCoordPointer(2, GL_FLOAT, VERTEXSIZE*sizeof(float), &p->verts[0][5]);
    463       glVertexPointer(3, GL_FLOAT, VERTEXSIZE*sizeof(float), &p->verts[0][0]);
    464             glDrawArrays(GL_TRIANGLE_FAN, 0, p->numverts);
    465             glDisableClientState(GL_TEXTURE_COORD_ARRAY);
    466             glClientActiveTexture(GL_TEXTURE0);
    467 
    468 #else
    469       glBegin(GL_POLYGON);
    470       v = p->verts[0];
    471       for (i=0 ; i<p->numverts ; i++, v+= VERTEXSIZE)
    472       {
    473         qglMTexCoord2fSGIS (TEXTURE0_SGIS, v[3], v[4]);
    474         qglMTexCoord2fSGIS (TEXTURE1_SGIS, v[5], v[6]);
    475         glVertex3fv (v);
    476       }
    477       glEnd ();
    478 #endif
    479       return;
    480     } else {
    481       p = s->polys;
    482 
    483       t = R_TextureAnimation (s->texinfo->texture);
    484       GL_Bind (t->gl_texturenum);
    485 #ifdef USE_OPENGLES
    486       glVertexPointer(3, GL_FLOAT, VERTEXSIZE*sizeof(float), &p->verts[0][0]);
    487       glTexCoordPointer(2, GL_FLOAT, VERTEXSIZE*sizeof(float), &p->verts[0][3]);
    488       glDrawArrays(GL_TRIANGLE_FAN, 0, p->numverts);
    489 #else
    490       glBegin (GL_POLYGON);
    491       v = p->verts[0];
    492       for (i=0 ; i<p->numverts ; i++, v+= VERTEXSIZE)
    493       {
    494         glTexCoord2f (v[3], v[4]);
    495         glVertex3fv (v);
    496       }
    497       glEnd ();
    498 #endif
    499 
    500       GL_Bind (lightmap_textures + s->lightmaptexturenum);
    501       glEnable (GL_BLEND);
    502 #ifdef USE_OPENGLES
    503       glTexCoordPointer(2, GL_FLOAT, VERTEXSIZE*sizeof(float), &p->verts[0][5]);
    504       glDrawArrays(GL_TRIANGLE_FAN, 0, p->numverts);
    505 #else
    506       glBegin (GL_POLYGON);
    507       v = p->verts[0];
    508       for (i=0 ; i<p->numverts ; i++, v+= VERTEXSIZE)
    509       {
    510         glTexCoord2f (v[5], v[6]);
    511         glVertex3fv (v);
    512       }
    513       glEnd ();
    514 #endif
    515 
    516       glDisable (GL_BLEND);
    517     }
    518 
    519     return;
    520   }
    521 
    522   //
    523   // subdivided water surface warp
    524   //
    525 
    526   if (s->flags & SURF_DRAWTURB)
    527   {
    528     GL_DisableMultitexture();
    529     GL_Bind (s->texinfo->texture->gl_texturenum);
    530     EmitWaterPolys (s);
    531     return;
    532   }
    533 
    534   //
    535   // subdivided sky warp
    536   //
    537   if (s->flags & SURF_DRAWSKY)
    538   {
    539     GL_DisableMultitexture();
    540     GL_Bind (solidskytexture);
    541     speedscale = realtime*8;
    542     speedscale -= (int)speedscale & ~127;
    543 
    544     EmitSkyPolys (s);
    545 
    546     glEnable (GL_BLEND);
    547     GL_Bind (alphaskytexture);
    548     speedscale = realtime*16;
    549     speedscale -= (int)speedscale & ~127;
    550     EmitSkyPolys (s);
    551 
    552     glDisable (GL_BLEND);
    553     return;
    554   }
    555 
    556   //
    557   // underwater warped with lightmap
    558   //
    559   R_RenderDynamicLightmaps (s);
    560   if (gl_mtexable) {
    561     p = s->polys;
    562 
    563     t = R_TextureAnimation (s->texinfo->texture);
    564     GL_SelectTexture(TEXTURE0_SGIS);
    565     GL_Bind (t->gl_texturenum);
    566     glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
    567     GL_EnableMultitexture();
    568     GL_Bind (lightmap_textures + s->lightmaptexturenum);
    569     i = s->lightmaptexturenum;
    570     if (lightmap_modified[i])
    571     {
    572       lightmap_modified[i] = false;
    573       theRect = &lightmap_rectchange[i];
    574       glTexSubImage2D(GL_TEXTURE_2D, 0, 0, theRect->t,
    575         BLOCK_WIDTH, theRect->h, gl_lightmap_format, GL_UNSIGNED_BYTE,
    576         lightmaps+(i* BLOCK_HEIGHT + theRect->t) *BLOCK_WIDTH*lightmap_bytes);
    577       theRect->l = BLOCK_WIDTH;
    578       theRect->t = BLOCK_HEIGHT;
    579       theRect->h = 0;
    580       theRect->w = 0;
    581     }
    582     glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_BLEND);
    583 #ifdef USE_OPENGLES
    584     {
    585       float* pPos = gVertexBuffer;
    586       v = p->verts[0];
    587       for (i=0 ; i<p->numverts ; i++, v+= VERTEXSIZE)
    588       {
    589         *pPos++ = v[0] + 8*sinf(v[1]*0.05f+realtime)*sinf(v[2]*0.05f+realtime);
    590         *pPos++ = v[1] + 8*sinf(v[0]*0.05f+realtime)*sinf(v[2]*0.05f+realtime);
    591         *pPos++ = v[2];
    592       }
    593     }
    594         glTexCoordPointer(2, GL_FLOAT, VERTEXSIZE*sizeof(float), &p->verts[0][3]);
    595         glClientActiveTexture(GL_TEXTURE1);
    596         glEnableClientState(GL_TEXTURE_COORD_ARRAY);
    597         glTexCoordPointer(2, GL_FLOAT, VERTEXSIZE*sizeof(float), &p->verts[0][5]);
    598         glVertexPointer(3, GL_FLOAT, VERTEXSIZE*sizeof(float), &p->verts[0][0]);
    599         glDrawArrays(GL_TRIANGLE_FAN, 0, p->numverts);
    600         glDisableClientState(GL_TEXTURE_COORD_ARRAY);
    601         glClientActiveTexture(GL_TEXTURE0);
    602 #else
    603     glBegin (GL_TRIANGLE_FAN);
    604     v = p->verts[0];
    605     for (i=0 ; i<p->numverts ; i++, v+= VERTEXSIZE)
    606     {
    607       qglMTexCoord2fSGIS (TEXTURE0_SGIS, v[3], v[4]);
    608       qglMTexCoord2fSGIS (TEXTURE1_SGIS, v[5], v[6]);
    609 
    610       nv[0] = v[0] + 8*sin(v[1]*0.05+realtime)*sin(v[2]*0.05+realtime);
    611       nv[1] = v[1] + 8*sin(v[0]*0.05+realtime)*sin(v[2]*0.05+realtime);
    612       nv[2] = v[2];
    613 
    614       glVertex3fv (nv);
    615     }
    616     glEnd ();
    617 #endif
    618 
    619   } else {
    620     p = s->polys;
    621 
    622     t = R_TextureAnimation (s->texinfo->texture);
    623     GL_Bind (t->gl_texturenum);
    624     DrawGLWaterPoly (p);
    625 
    626     GL_Bind (lightmap_textures + s->lightmaptexturenum);
    627     glEnable (GL_BLEND);
    628     DrawGLWaterPolyLightmap (p);
    629     glDisable (GL_BLEND);
    630   }
    631 }
    632 #endif
    633 
    634 
    635 /*
    636 ================
    637 DrawGLWaterPoly
    638 
    639 Warp the vertex coordinates
    640 ================
    641 */
    642 void DrawGLWaterPoly (glpoly_t *p)
    643 {
    644   int		i;
    645   float	*v;
    646   float	s, t, os, ot;
    647   vec3_t	nv;
    648 
    649   GL_DisableMultitexture();
    650 
    651 #ifdef USE_OPENGLES
    652   glVertexPointer(3, GL_FLOAT, 0, gVertexBuffer);
    653   glTexCoordPointer(2, GL_FLOAT, VERTEXSIZE*sizeof(float), &p->verts[0][3]);
    654 
    655   v = p->verts[0];
    656   {
    657     float* pnv = gVertexBuffer;
    658     for (i=0 ; i<p->numverts ; i++, v+= VERTEXSIZE)
    659     {
    660       pnv[0] = v[0] + 8*sinf(v[1]*0.05f+realtime)*sinf(v[2]*0.05f+realtime);
    661       pnv[1] = v[1] + 8*sinf(v[0]*0.05f+realtime)*sinf(v[2]*0.05f+realtime);
    662       pnv[2] = v[2];
    663 
    664       pnv += 3;
    665     }
    666   }
    667   glDrawArrays(GL_TRIANGLE_FAN, 0, p->numverts);
    668 #else
    669   glBegin (GL_TRIANGLE_FAN);
    670   v = p->verts[0];
    671   for (i=0 ; i<p->numverts ; i++, v+= VERTEXSIZE)
    672   {
    673     glTexCoord2f (v[3], v[4]);
    674 
    675     nv[0] = v[0] + 8*sin(v[1]*0.05+realtime)*sin(v[2]*0.05+realtime);
    676     nv[1] = v[1] + 8*sin(v[0]*0.05+realtime)*sin(v[2]*0.05+realtime);
    677     nv[2] = v[2];
    678 
    679     glVertex3fv (nv);
    680   }
    681   glEnd ();
    682 #endif
    683 }
    684 
    685 void DrawGLWaterPolyLightmap (glpoly_t *p)
    686 {
    687   int		i;
    688   float	*v;
    689   float	s, t, os, ot;
    690   vec3_t	nv;
    691 
    692   GL_DisableMultitexture();
    693 
    694 #ifdef USE_OPENGLES
    695   glVertexPointer(3, GL_FLOAT, 0, gVertexBuffer);
    696   glTexCoordPointer(2, GL_FLOAT, VERTEXSIZE*sizeof(float), &p->verts[0][5]);
    697 
    698   v = p->verts[0];
    699   {
    700     float* pnv = gVertexBuffer;
    701     for (i=0 ; i<p->numverts ; i++, v+= VERTEXSIZE)
    702     {
    703       pnv[0] = v[0] + 8*sinf(v[1]*0.05f+realtime)*sinf(v[2]*0.05f+realtime);
    704       pnv[1] = v[1] + 8*sinf(v[0]*0.05f+realtime)*sinf(v[2]*0.05f+realtime);
    705       pnv[2] = v[2];
    706 
    707       pnv += 3;
    708     }
    709   }
    710   glDrawArrays(GL_TRIANGLE_FAN, 0, p->numverts);
    711 
    712 #else
    713   glBegin (GL_TRIANGLE_FAN);
    714   v = p->verts[0];
    715   for (i=0 ; i<p->numverts ; i++, v+= VERTEXSIZE)
    716   {
    717     glTexCoord2f (v[5], v[6]);
    718 
    719     nv[0] = v[0] + 8*sin(v[1]*0.05+realtime)*sin(v[2]*0.05+realtime);
    720     nv[1] = v[1] + 8*sin(v[0]*0.05+realtime)*sin(v[2]*0.05+realtime);
    721     nv[2] = v[2];
    722 
    723     glVertex3fv (nv);
    724   }
    725   glEnd ();
    726 #endif
    727 }
    728 
    729 /*
    730 ================
    731 DrawGLPoly
    732 ================
    733 */
    734 void DrawGLPoly (glpoly_t *p)
    735 {
    736   int		i;
    737   float	*v;
    738 
    739 #ifdef USE_OPENGLES
    740   glVertexPointer(3, GL_FLOAT, VERTEXSIZE*sizeof(float), &p->verts[0][0]);
    741   glTexCoordPointer(2, GL_FLOAT, VERTEXSIZE*sizeof(float), &p->verts[0][3]);
    742   glDrawArrays(GL_TRIANGLE_FAN, 0, p->numverts);
    743 #else
    744   glBegin (GL_POLYGON);
    745   v = p->verts[0];
    746   for (i=0 ; i<p->numverts ; i++, v+= VERTEXSIZE)
    747   {
    748     glTexCoord2f (v[3], v[4]);
    749     glVertex3fv (v);
    750   }
    751   glEnd ();
    752 #endif
    753 }
    754 
    755 
    756 /*
    757 ================
    758 R_BlendLightmaps
    759 ================
    760 */
    761 void R_BlendLightmaps (void)
    762 {
    763   int			i, j;
    764   glpoly_t	*p;
    765   float		*v;
    766   glRect_t	*theRect;
    767 
    768   if (r_fullbright.value)
    769     return;
    770   if (!gl_texsort.value)
    771     return;
    772 
    773   glDepthMask (0);		// don't bother writing Z
    774 
    775   if (gl_lightmap_format == GL_LUMINANCE)
    776     glBlendFunc (GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
    777   else if (gl_lightmap_format == GL_INTENSITY)
    778   {
    779     glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
    780     glColor4f (0,0,0,1);
    781     glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    782   }
    783 
    784   if (!r_lightmap.value)
    785   {
    786     glEnable (GL_BLEND);
    787   }
    788 
    789   for (i=0 ; i<MAX_LIGHTMAPS ; i++)
    790   {
    791     p = lightmap_polys[i];
    792     if (!p)
    793       continue;
    794     GL_Bind(lightmap_textures+i);
    795     if (lightmap_modified[i])
    796     {
    797       lightmap_modified[i] = false;
    798       theRect = &lightmap_rectchange[i];
    799 //			glTexImage2DHelper (GL_TEXTURE_2D, 0, lightmap_bytes
    800 //			, BLOCK_WIDTH, BLOCK_HEIGHT, 0,
    801 //			gl_lightmap_format, GL_UNSIGNED_BYTE, lightmaps+i*BLOCK_WIDTH*BLOCK_HEIGHT*lightmap_bytes);
    802 //			glTexImage2DHelper (GL_TEXTURE_2D, 0, lightmap_bytes
    803 //				, BLOCK_WIDTH, theRect->h, 0,
    804 //				gl_lightmap_format, GL_UNSIGNED_BYTE, lightmaps+(i*BLOCK_HEIGHT+theRect->t)*BLOCK_WIDTH*lightmap_bytes);
    805       glTexSubImage2D(GL_TEXTURE_2D, 0, 0, theRect->t,
    806         BLOCK_WIDTH, theRect->h, gl_lightmap_format, GL_UNSIGNED_BYTE,
    807         lightmaps+(i* BLOCK_HEIGHT + theRect->t) *BLOCK_WIDTH*lightmap_bytes);
    808       theRect->l = BLOCK_WIDTH;
    809       theRect->t = BLOCK_HEIGHT;
    810       theRect->h = 0;
    811       theRect->w = 0;
    812     }
    813     for ( ; p ; p=p->chain)
    814     {
    815       if (p->flags & SURF_UNDERWATER)
    816         DrawGLWaterPolyLightmap (p);
    817       else
    818       {
    819 #ifdef USE_OPENGLES
    820         glVertexPointer(3, GL_FLOAT, VERTEXSIZE*sizeof(float), &p->verts[0][0]);
    821         glTexCoordPointer(2, GL_FLOAT, VERTEXSIZE*sizeof(float), &p->verts[0][5]);
    822         glDrawArrays(GL_TRIANGLE_FAN, 0, p->numverts);
    823 #else
    824         glBegin (GL_POLYGON);
    825         v = p->verts[0];
    826         for (j=0 ; j<p->numverts ; j++, v+= VERTEXSIZE)
    827         {
    828           glTexCoord2f (v[5], v[6]);
    829           glVertex3fv (v);
    830         }
    831         glEnd ();
    832 #endif
    833       }
    834     }
    835   }
    836 
    837   glDisable (GL_BLEND);
    838   if (gl_lightmap_format == GL_LUMINANCE)
    839     glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    840   else if (gl_lightmap_format == GL_INTENSITY)
    841   {
    842     glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
    843     glColor4f (1,1,1,1);
    844   }
    845 
    846   glDepthMask (1);		// back to normal Z buffering
    847 }
    848 
    849 /*
    850 ================
    851 R_RenderBrushPoly
    852 ================
    853 */
    854 void R_RenderBrushPoly (msurface_t *fa)
    855 {
    856   texture_t	*t;
    857   byte		*base;
    858   int			maps;
    859   glRect_t    *theRect;
    860   int smax, tmax;
    861 
    862   c_brush_polys++;
    863 
    864   if (fa->flags & SURF_DRAWSKY)
    865   {	// warp texture, no lightmaps
    866     EmitBothSkyLayers (fa);
    867     return;
    868   }
    869 
    870   t = R_TextureAnimation (fa->texinfo->texture);
    871   GL_Bind (t->gl_texturenum);
    872 
    873   if (fa->flags & SURF_DRAWTURB)
    874   {	// warp texture, no lightmaps
    875     EmitWaterPolys (fa);
    876     return;
    877   }
    878 
    879   if (fa->flags & SURF_UNDERWATER)
    880     DrawGLWaterPoly (fa->polys);
    881   else
    882     DrawGLPoly (fa->polys);
    883 
    884   // add the poly to the proper lightmap chain
    885 
    886   fa->polys->chain = lightmap_polys[fa->lightmaptexturenum];
    887   lightmap_polys[fa->lightmaptexturenum] = fa->polys;
    888 
    889   // check for lightmap modification
    890   for (maps = 0 ; maps < MAXLIGHTMAPS && fa->styles[maps] != 255 ;
    891      maps++)
    892     if (d_lightstylevalue[fa->styles[maps]] != fa->cached_light[maps])
    893       goto dynamic;
    894 
    895   if (fa->dlightframe == r_framecount	// dynamic this frame
    896     || fa->cached_dlight)			// dynamic previously
    897   {
    898 dynamic:
    899     if (r_dynamic.value)
    900     {
    901       lightmap_modified[fa->lightmaptexturenum] = true;
    902       theRect = &lightmap_rectchange[fa->lightmaptexturenum];
    903       if (fa->light_t < theRect->t) {
    904         if (theRect->h)
    905           theRect->h += theRect->t - fa->light_t;
    906         theRect->t = fa->light_t;
    907       }
    908       if (fa->light_s < theRect->l) {
    909         if (theRect->w)
    910           theRect->w += theRect->l - fa->light_s;
    911         theRect->l = fa->light_s;
    912       }
    913       smax = (fa->extents[0]>>4)+1;
    914       tmax = (fa->extents[1]>>4)+1;
    915       if ((theRect->w + theRect->l) < (fa->light_s + smax))
    916         theRect->w = (fa->light_s-theRect->l)+smax;
    917       if ((theRect->h + theRect->t) < (fa->light_t + tmax))
    918         theRect->h = (fa->light_t-theRect->t)+tmax;
    919       base = lightmaps + fa->lightmaptexturenum*lightmap_bytes*BLOCK_WIDTH*BLOCK_HEIGHT;
    920       base += fa->light_t * BLOCK_WIDTH * lightmap_bytes + fa->light_s * lightmap_bytes;
    921       R_BuildLightMap (fa, base, BLOCK_WIDTH*lightmap_bytes);
    922     }
    923   }
    924 }
    925 
    926 /*
    927 ================
    928 R_RenderDynamicLightmaps
    929 Multitexture
    930 ================
    931 */
    932 void R_RenderDynamicLightmaps (msurface_t *fa)
    933 {
    934   texture_t	*t;
    935   byte		*base;
    936   int			maps;
    937   glRect_t    *theRect;
    938   int smax, tmax;
    939 
    940   c_brush_polys++;
    941 
    942   if (fa->flags & ( SURF_DRAWSKY | SURF_DRAWTURB) )
    943     return;
    944 
    945   fa->polys->chain = lightmap_polys[fa->lightmaptexturenum];
    946   lightmap_polys[fa->lightmaptexturenum] = fa->polys;
    947 
    948   // check for lightmap modification
    949   for (maps = 0 ; maps < MAXLIGHTMAPS && fa->styles[maps] != 255 ;
    950      maps++)
    951     if (d_lightstylevalue[fa->styles[maps]] != fa->cached_light[maps])
    952       goto dynamic;
    953 
    954   if (fa->dlightframe == r_framecount	// dynamic this frame
    955     || fa->cached_dlight)			// dynamic previously
    956   {
    957 dynamic:
    958     if (r_dynamic.value)
    959     {
    960       lightmap_modified[fa->lightmaptexturenum] = true;
    961       theRect = &lightmap_rectchange[fa->lightmaptexturenum];
    962       if (fa->light_t < theRect->t) {
    963         if (theRect->h)
    964           theRect->h += theRect->t - fa->light_t;
    965         theRect->t = fa->light_t;
    966       }
    967       if (fa->light_s < theRect->l) {
    968         if (theRect->w)
    969           theRect->w += theRect->l - fa->light_s;
    970         theRect->l = fa->light_s;
    971       }
    972       smax = (fa->extents[0]>>4)+1;
    973       tmax = (fa->extents[1]>>4)+1;
    974       if ((theRect->w + theRect->l) < (fa->light_s + smax))
    975         theRect->w = (fa->light_s-theRect->l)+smax;
    976       if ((theRect->h + theRect->t) < (fa->light_t + tmax))
    977         theRect->h = (fa->light_t-theRect->t)+tmax;
    978       base = lightmaps + fa->lightmaptexturenum*lightmap_bytes*BLOCK_WIDTH*BLOCK_HEIGHT;
    979       base += fa->light_t * BLOCK_WIDTH * lightmap_bytes + fa->light_s * lightmap_bytes;
    980       R_BuildLightMap (fa, base, BLOCK_WIDTH*lightmap_bytes);
    981     }
    982   }
    983 }
    984 
    985 /*
    986 ================
    987 R_MirrorChain
    988 ================
    989 */
    990 void R_MirrorChain (msurface_t *s)
    991 {
    992   if (mirror)
    993     return;
    994   mirror = true;
    995   mirror_plane = s->plane;
    996 }
    997 
    998 
    999 #if 0
   1000 /*
   1001 ================
   1002 R_DrawWaterSurfaces
   1003 ================
   1004 */
   1005 void R_DrawWaterSurfaces (void)
   1006 {
   1007   int			i;
   1008   msurface_t	*s;
   1009   texture_t	*t;
   1010 
   1011   if (r_wateralpha.value == 1.0)
   1012     return;
   1013 
   1014   //
   1015   // go back to the world matrix
   1016   //
   1017     glLoadMatrixf (r_world_matrix);
   1018 
   1019   glEnable (GL_BLEND);
   1020   glColor4f (1,1,1,r_wateralpha.value);
   1021   glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
   1022 
   1023   for (i=0 ; i<cl.worldmodel->numtextures ; i++)
   1024   {
   1025     t = cl.worldmodel->textures[i];
   1026     if (!t)
   1027       continue;
   1028     s = t->texturechain;
   1029     if (!s)
   1030       continue;
   1031     if ( !(s->flags & SURF_DRAWTURB) )
   1032       continue;
   1033 
   1034     // set modulate mode explicitly
   1035     GL_Bind (t->gl_texturenum);
   1036 
   1037     for ( ; s ; s=s->texturechain)
   1038       R_RenderBrushPoly (s);
   1039 
   1040     t->texturechain = NULL;
   1041   }
   1042 
   1043   glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
   1044 
   1045   glColor4f (1,1,1,1);
   1046   glDisable (GL_BLEND);
   1047 }
   1048 #else
   1049 /*
   1050 ================
   1051 R_DrawWaterSurfaces
   1052 ================
   1053 */
   1054 void R_DrawWaterSurfaces (void)
   1055 {
   1056   int			i;
   1057   msurface_t	*s;
   1058   texture_t	*t;
   1059 
   1060   if (r_wateralpha.value == 1.0 && gl_texsort.value)
   1061     return;
   1062 
   1063   //
   1064   // go back to the world matrix
   1065   //
   1066 
   1067     glLoadMatrixf (r_world_matrix);
   1068 
   1069   if (r_wateralpha.value < 1.0) {
   1070     glEnable (GL_BLEND);
   1071     glColor4f (1,1,1,r_wateralpha.value);
   1072     glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
   1073   }
   1074 
   1075   if (!gl_texsort.value) {
   1076     if (!waterchain)
   1077       return;
   1078 
   1079     for ( s = waterchain ; s ; s=s->texturechain) {
   1080       GL_Bind (s->texinfo->texture->gl_texturenum);
   1081       EmitWaterPolys (s);
   1082     }
   1083 
   1084     waterchain = NULL;
   1085   } else {
   1086 
   1087     for (i=0 ; i<cl.worldmodel->numtextures ; i++)
   1088     {
   1089       t = cl.worldmodel->textures[i];
   1090       if (!t)
   1091         continue;
   1092       s = t->texturechain;
   1093       if (!s)
   1094         continue;
   1095       if ( !(s->flags & SURF_DRAWTURB ) )
   1096         continue;
   1097 
   1098       // set modulate mode explicitly
   1099 
   1100       GL_Bind (t->gl_texturenum);
   1101 
   1102       for ( ; s ; s=s->texturechain)
   1103         EmitWaterPolys (s);
   1104 
   1105       t->texturechain = NULL;
   1106     }
   1107 
   1108   }
   1109 
   1110   if (r_wateralpha.value < 1.0) {
   1111     glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
   1112 
   1113     glColor4f (1,1,1,1);
   1114     glDisable (GL_BLEND);
   1115   }
   1116 
   1117 }
   1118 
   1119 #endif
   1120 
   1121 /*
   1122 ================
   1123 DrawTextureChains
   1124 ================
   1125 */
   1126 void DrawTextureChains (void)
   1127 {
   1128   int		i;
   1129   msurface_t	*s;
   1130   texture_t	*t;
   1131 
   1132   if (!gl_texsort.value) {
   1133     GL_DisableMultitexture();
   1134 
   1135     if (skychain) {
   1136       R_DrawSkyChain(skychain);
   1137       skychain = NULL;
   1138     }
   1139 
   1140     return;
   1141   }
   1142 
   1143   for (i=0 ; i<cl.worldmodel->numtextures ; i++)
   1144   {
   1145     t = cl.worldmodel->textures[i];
   1146     if (!t)
   1147       continue;
   1148     s = t->texturechain;
   1149     if (!s)
   1150       continue;
   1151     if (i == skytexturenum)
   1152       R_DrawSkyChain (s);
   1153     else if (i == mirrortexturenum && r_mirroralpha.value != 1.0)
   1154     {
   1155       R_MirrorChain (s);
   1156       continue;
   1157     }
   1158     else
   1159     {
   1160       if ((s->flags & SURF_DRAWTURB) && r_wateralpha.value != 1.0)
   1161         continue;	// draw translucent water later
   1162       for ( ; s ; s=s->texturechain)
   1163         R_RenderBrushPoly (s);
   1164     }
   1165 
   1166     t->texturechain = NULL;
   1167   }
   1168 }
   1169 
   1170 /*
   1171 =================
   1172 R_DrawBrushModel
   1173 =================
   1174 */
   1175 void R_DrawBrushModel (entity_t *e)
   1176 {
   1177   int			j, k;
   1178   vec3_t		mins, maxs;
   1179   int			i, numsurfaces;
   1180   msurface_t	*psurf;
   1181   float		dot;
   1182   mplane_t	*pplane;
   1183   model_t		*clmodel;
   1184   qboolean	rotated;
   1185 
   1186   currententity = e;
   1187   currenttexture = -1;
   1188 
   1189   clmodel = e->model;
   1190 
   1191   if (e->angles[0] || e->angles[1] || e->angles[2])
   1192   {
   1193     rotated = true;
   1194     for (i=0 ; i<3 ; i++)
   1195     {
   1196       mins[i] = e->origin[i] - clmodel->radius;
   1197       maxs[i] = e->origin[i] + clmodel->radius;
   1198     }
   1199   }
   1200   else
   1201   {
   1202     rotated = false;
   1203     VectorAdd (e->origin, clmodel->mins, mins);
   1204     VectorAdd (e->origin, clmodel->maxs, maxs);
   1205   }
   1206 
   1207   if (R_CullBox (mins, maxs))
   1208     return;
   1209 
   1210   glColor3f (1,1,1);
   1211   memset (lightmap_polys, 0, sizeof(lightmap_polys));
   1212 
   1213   VectorSubtract (r_refdef.vieworg, e->origin, modelorg);
   1214   if (rotated)
   1215   {
   1216     vec3_t	temp;
   1217     vec3_t	forward, right, up;
   1218 
   1219     VectorCopy (modelorg, temp);
   1220     AngleVectors (e->angles, forward, right, up);
   1221     modelorg[0] = DotProduct (temp, forward);
   1222     modelorg[1] = -DotProduct (temp, right);
   1223     modelorg[2] = DotProduct (temp, up);
   1224   }
   1225 
   1226   psurf = &clmodel->surfaces[clmodel->firstmodelsurface];
   1227 
   1228 // calculate dynamic lighting for bmodel if it's not an
   1229 // instanced model
   1230   if (clmodel->firstmodelsurface != 0 && !gl_flashblend.value)
   1231   {
   1232     for (k=0 ; k<MAX_DLIGHTS ; k++)
   1233     {
   1234       if ((cl_dlights[k].die < cl.time) ||
   1235         (!cl_dlights[k].radius))
   1236         continue;
   1237 
   1238       R_MarkLights (&cl_dlights[k], 1<<k,
   1239         clmodel->nodes + clmodel->hulls[0].firstclipnode);
   1240     }
   1241   }
   1242 
   1243     glPushMatrix ();
   1244 e->angles[0] = -e->angles[0];	// stupid quake bug
   1245   R_RotateForEntity (e);
   1246 e->angles[0] = -e->angles[0];	// stupid quake bug
   1247 
   1248   //
   1249   // draw texture
   1250   //
   1251   for (i=0 ; i<clmodel->nummodelsurfaces ; i++, psurf++)
   1252   {
   1253   // find which side of the node we are on
   1254     pplane = psurf->plane;
   1255 
   1256     dot = DotProduct (modelorg, pplane->normal) - pplane->dist;
   1257 
   1258   // draw the polygon
   1259     if (((psurf->flags & SURF_PLANEBACK) && (dot < -BACKFACE_EPSILON)) ||
   1260       (!(psurf->flags & SURF_PLANEBACK) && (dot > BACKFACE_EPSILON)))
   1261     {
   1262       if (gl_texsort.value)
   1263         R_RenderBrushPoly (psurf);
   1264       else
   1265         R_DrawSequentialPoly (psurf);
   1266     }
   1267   }
   1268 
   1269   R_BlendLightmaps ();
   1270 
   1271   glPopMatrix ();
   1272 }
   1273 
   1274 /*
   1275 =============================================================
   1276 
   1277   WORLD MODEL
   1278 
   1279 =============================================================
   1280 */
   1281 
   1282 /*
   1283 ================
   1284 R_RecursiveWorldNode
   1285 ================
   1286 */
   1287 void R_RecursiveWorldNode (mnode_t *node)
   1288 {
   1289   int			i, c, side, *pindex;
   1290   vec3_t		acceptpt, rejectpt;
   1291   mplane_t	*plane;
   1292   msurface_t	*surf, **mark;
   1293   mleaf_t		*pleaf;
   1294   double		d, dot;
   1295   vec3_t		mins, maxs;
   1296 
   1297   if (node->contents == CONTENTS_SOLID)
   1298     return;		// solid
   1299 
   1300   if (node->visframe != r_visframecount)
   1301     return;
   1302   if (R_CullBox (node->minmaxs, node->minmaxs+3))
   1303     return;
   1304 
   1305 // if a leaf node, draw stuff
   1306   if (node->contents < 0)
   1307   {
   1308     pleaf = (mleaf_t *)node;
   1309 
   1310     mark = pleaf->firstmarksurface;
   1311     c = pleaf->nummarksurfaces;
   1312 
   1313     if (c)
   1314     {
   1315       do
   1316       {
   1317         (*mark)->visframe = r_framecount;
   1318         mark++;
   1319       } while (--c);
   1320     }
   1321 
   1322   // deal with model fragments in this leaf
   1323     if (pleaf->efrags)
   1324       R_StoreEfrags (&pleaf->efrags);
   1325 
   1326     return;
   1327   }
   1328 
   1329 // node is just a decision point, so go down the apropriate sides
   1330 
   1331 // find which side of the node we are on
   1332   plane = node->plane;
   1333 
   1334   switch (plane->type)
   1335   {
   1336   case PLANE_X:
   1337     dot = modelorg[0] - plane->dist;
   1338     break;
   1339   case PLANE_Y:
   1340     dot = modelorg[1] - plane->dist;
   1341     break;
   1342   case PLANE_Z:
   1343     dot = modelorg[2] - plane->dist;
   1344     break;
   1345   default:
   1346     dot = DotProduct (modelorg, plane->normal) - plane->dist;
   1347     break;
   1348   }
   1349 
   1350   if (dot >= 0)
   1351     side = 0;
   1352   else
   1353     side = 1;
   1354 
   1355 // recurse down the children, front side first
   1356   R_RecursiveWorldNode (node->children[side]);
   1357 
   1358 // draw stuff
   1359   c = node->numsurfaces;
   1360 
   1361   if (c)
   1362   {
   1363     surf = cl.worldmodel->surfaces + node->firstsurface;
   1364 
   1365     if (dot < 0 -BACKFACE_EPSILON)
   1366       side = SURF_PLANEBACK;
   1367     else if (dot > BACKFACE_EPSILON)
   1368       side = 0;
   1369     {
   1370       for ( ; c ; c--, surf++)
   1371       {
   1372         if (surf->visframe != r_framecount)
   1373           continue;
   1374 
   1375         // don't backface underwater surfaces, because they warp
   1376         if ( !(surf->flags & SURF_UNDERWATER) && ( (dot < 0) ^ !!(surf->flags & SURF_PLANEBACK)) )
   1377           continue;		// wrong side
   1378 
   1379         // if sorting by texture, just store it out
   1380         if (gl_texsort.value)
   1381         {
   1382           if (!mirror
   1383           || surf->texinfo->texture != cl.worldmodel->textures[mirrortexturenum])
   1384           {
   1385             surf->texturechain = surf->texinfo->texture->texturechain;
   1386             surf->texinfo->texture->texturechain = surf;
   1387           }
   1388         } else if (surf->flags & SURF_DRAWSKY) {
   1389           surf->texturechain = skychain;
   1390           skychain = surf;
   1391         } else if (surf->flags & SURF_DRAWTURB) {
   1392           surf->texturechain = waterchain;
   1393           waterchain = surf;
   1394         } else
   1395           R_DrawSequentialPoly (surf);
   1396 
   1397       }
   1398     }
   1399 
   1400   }
   1401 
   1402 // recurse down the back side
   1403   R_RecursiveWorldNode (node->children[!side]);
   1404 }
   1405 
   1406 
   1407 
   1408 /*
   1409 =============
   1410 R_DrawWorld
   1411 =============
   1412 */
   1413 void R_DrawWorld (void)
   1414 {
   1415   entity_t	ent;
   1416   int			i;
   1417 
   1418   memset (&ent, 0, sizeof(ent));
   1419   ent.model = cl.worldmodel;
   1420 
   1421   VectorCopy (r_refdef.vieworg, modelorg);
   1422 
   1423   currententity = &ent;
   1424   currenttexture = -1;
   1425 
   1426   glColor3f (1,1,1);
   1427   memset (lightmap_polys, 0, sizeof(lightmap_polys));
   1428 #ifdef QUAKE2
   1429   R_ClearSkyBox ();
   1430 #endif
   1431 
   1432   R_RecursiveWorldNode (cl.worldmodel->nodes);
   1433 
   1434   DrawTextureChains ();
   1435 
   1436   R_BlendLightmaps ();
   1437 
   1438 #ifdef QUAKE2
   1439   R_DrawSkyBox ();
   1440 #endif
   1441 }
   1442 
   1443 
   1444 /*
   1445 ===============
   1446 R_MarkLeaves
   1447 ===============
   1448 */
   1449 void R_MarkLeaves (void)
   1450 {
   1451   byte	*vis;
   1452   mnode_t	*node;
   1453   int		i;
   1454   byte	solid[4096];
   1455 
   1456   if (r_oldviewleaf == r_viewleaf && !r_novis.value)
   1457     return;
   1458 
   1459   if (mirror)
   1460     return;
   1461 
   1462   r_visframecount++;
   1463   r_oldviewleaf = r_viewleaf;
   1464 
   1465   if (r_novis.value)
   1466   {
   1467     vis = solid;
   1468     memset (solid, 0xff, (cl.worldmodel->numleafs+7)>>3);
   1469   }
   1470   else
   1471     vis = Mod_LeafPVS (r_viewleaf, cl.worldmodel);
   1472 
   1473   for (i=0 ; i<cl.worldmodel->numleafs ; i++)
   1474   {
   1475     if (vis[i>>3] & (1<<(i&7)))
   1476     {
   1477       node = (mnode_t *)&cl.worldmodel->leafs[i+1];
   1478       do
   1479       {
   1480         if (node->visframe == r_visframecount)
   1481           break;
   1482         node->visframe = r_visframecount;
   1483         node = node->parent;
   1484       } while (node);
   1485     }
   1486   }
   1487 }
   1488 
   1489 
   1490 
   1491 /*
   1492 =============================================================================
   1493 
   1494   LIGHTMAP ALLOCATION
   1495 
   1496 =============================================================================
   1497 */
   1498 
   1499 // returns a texture number and the position inside it
   1500 int AllocBlock (int w, int h, int *x, int *y)
   1501 {
   1502   int		i, j;
   1503   int		best, best2;
   1504   int		bestx;
   1505   int		texnum;
   1506 
   1507   for (texnum=0 ; texnum<MAX_LIGHTMAPS ; texnum++)
   1508   {
   1509     best = BLOCK_HEIGHT;
   1510 
   1511     for (i=0 ; i<BLOCK_WIDTH-w ; i++)
   1512     {
   1513       best2 = 0;
   1514 
   1515       for (j=0 ; j<w ; j++)
   1516       {
   1517         if (allocated[texnum][i+j] >= best)
   1518           break;
   1519         if (allocated[texnum][i+j] > best2)
   1520           best2 = allocated[texnum][i+j];
   1521       }
   1522       if (j == w)
   1523       {	// this is a valid spot
   1524         *x = i;
   1525         *y = best = best2;
   1526       }
   1527     }
   1528 
   1529     if (best + h > BLOCK_HEIGHT)
   1530       continue;
   1531 
   1532     for (i=0 ; i<w ; i++)
   1533       allocated[texnum][*x + i] = best + h;
   1534 
   1535     return texnum;
   1536   }
   1537 
   1538   Sys_Error ("AllocBlock: full");
   1539   return 0;
   1540 }
   1541 
   1542 
   1543 mvertex_t	*r_pcurrentvertbase;
   1544 model_t		*currentmodel;
   1545 
   1546 int	nColinElim;
   1547 
   1548 /*
   1549 ================
   1550 BuildSurfaceDisplayList
   1551 ================
   1552 */
   1553 void BuildSurfaceDisplayList (msurface_t *fa)
   1554 {
   1555   int			i, lindex, lnumverts, s_axis, t_axis;
   1556   float		dist, lastdist, lzi, scale, u, v, frac;
   1557   unsigned	mask;
   1558   vec3_t		local, transformed;
   1559   medge_t		*pedges, *r_pedge;
   1560   mplane_t	*pplane;
   1561   int			vertpage, newverts, newpage, lastvert;
   1562   qboolean	visible;
   1563   float		*vec;
   1564   float		s, t;
   1565   glpoly_t	*poly;
   1566 
   1567 // reconstruct the polygon
   1568   pedges = currentmodel->edges;
   1569   lnumverts = fa->numedges;
   1570   vertpage = 0;
   1571 
   1572   //
   1573   // draw texture
   1574   //
   1575   poly = (glpoly_t*) Hunk_Alloc (sizeof(glpoly_t) + (lnumverts-4) * VERTEXSIZE*sizeof(float));
   1576   poly->next = fa->polys;
   1577   poly->flags = fa->flags;
   1578   fa->polys = poly;
   1579   poly->numverts = lnumverts;
   1580 
   1581   for (i=0 ; i<lnumverts ; i++)
   1582   {
   1583     lindex = currentmodel->surfedges[fa->firstedge + i];
   1584 
   1585     if (lindex > 0)
   1586     {
   1587       r_pedge = &pedges[lindex];
   1588       vec = r_pcurrentvertbase[r_pedge->v[0]].position;
   1589     }
   1590     else
   1591     {
   1592       r_pedge = &pedges[-lindex];
   1593       vec = r_pcurrentvertbase[r_pedge->v[1]].position;
   1594     }
   1595     s = DotProduct (vec, fa->texinfo->vecs[0]) + fa->texinfo->vecs[0][3];
   1596     s /= fa->texinfo->texture->width;
   1597 
   1598     t = DotProduct (vec, fa->texinfo->vecs[1]) + fa->texinfo->vecs[1][3];
   1599     t /= fa->texinfo->texture->height;
   1600 
   1601     VectorCopy (vec, poly->verts[i]);
   1602     poly->verts[i][3] = s;
   1603     poly->verts[i][4] = t;
   1604 
   1605     //
   1606     // lightmap texture coordinates
   1607     //
   1608     s = DotProduct (vec, fa->texinfo->vecs[0]) + fa->texinfo->vecs[0][3];
   1609     s -= fa->texturemins[0];
   1610     s += fa->light_s*16;
   1611     s += 8;
   1612     s /= BLOCK_WIDTH*16; //fa->texinfo->texture->width;
   1613 
   1614     t = DotProduct (vec, fa->texinfo->vecs[1]) + fa->texinfo->vecs[1][3];
   1615     t -= fa->texturemins[1];
   1616     t += fa->light_t*16;
   1617     t += 8;
   1618     t /= BLOCK_HEIGHT*16; //fa->texinfo->texture->height;
   1619 
   1620     poly->verts[i][5] = s;
   1621     poly->verts[i][6] = t;
   1622   }
   1623 
   1624   //
   1625   // remove co-linear points - Ed
   1626   //
   1627   if (!gl_keeptjunctions.value && !(fa->flags & SURF_UNDERWATER) )
   1628   {
   1629     for (i = 0 ; i < lnumverts ; ++i)
   1630     {
   1631       vec3_t v1, v2;
   1632       float *prev, *thiz, *next;
   1633       float f;
   1634 
   1635       prev = poly->verts[(i + lnumverts - 1) % lnumverts];
   1636       thiz = poly->verts[i];
   1637       next = poly->verts[(i + 1) % lnumverts];
   1638 
   1639       VectorSubtract( thiz, prev, v1 );
   1640       VectorNormalize( v1 );
   1641       VectorSubtract( next, prev, v2 );
   1642       VectorNormalize( v2 );
   1643 
   1644       // skip co-linear points
   1645       #define COLINEAR_EPSILON 0.001
   1646       if ((fabs( v1[0] - v2[0] ) <= COLINEAR_EPSILON) &&
   1647         (fabs( v1[1] - v2[1] ) <= COLINEAR_EPSILON) &&
   1648         (fabs( v1[2] - v2[2] ) <= COLINEAR_EPSILON))
   1649       {
   1650         int j;
   1651         for (j = i + 1; j < lnumverts; ++j)
   1652         {
   1653           int k;
   1654           for (k = 0; k < VERTEXSIZE; ++k)
   1655             poly->verts[j - 1][k] = poly->verts[j][k];
   1656         }
   1657         --lnumverts;
   1658         ++nColinElim;
   1659         // retry next vertex next time, which is now current vertex
   1660         --i;
   1661       }
   1662     }
   1663   }
   1664   poly->numverts = lnumverts;
   1665 
   1666 }
   1667 
   1668 /*
   1669 ========================
   1670 GL_CreateSurfaceLightmap
   1671 ========================
   1672 */
   1673 void GL_CreateSurfaceLightmap (msurface_t *surf)
   1674 {
   1675   int		smax, tmax, s, t, l, i;
   1676   byte	*base;
   1677 
   1678   if (surf->flags & (SURF_DRAWSKY|SURF_DRAWTURB))
   1679     return;
   1680 
   1681   smax = (surf->extents[0]>>4)+1;
   1682   tmax = (surf->extents[1]>>4)+1;
   1683 
   1684   surf->lightmaptexturenum = AllocBlock (smax, tmax, &surf->light_s, &surf->light_t);
   1685   base = lightmaps + surf->lightmaptexturenum*lightmap_bytes*BLOCK_WIDTH*BLOCK_HEIGHT;
   1686   base += (surf->light_t * BLOCK_WIDTH + surf->light_s) * lightmap_bytes;
   1687   R_BuildLightMap (surf, base, BLOCK_WIDTH*lightmap_bytes);
   1688 }
   1689 
   1690 
   1691 
   1692 void GL_UploadLightmaps()
   1693 {
   1694    if (!gl_texsort.value)
   1695      GL_SelectTexture(TEXTURE1_SGIS);
   1696 
   1697   //
   1698   // upload all lightmaps that were filled
   1699   //
   1700   for (int i=0 ; i<MAX_LIGHTMAPS ; i++)
   1701   {
   1702     if (!allocated[i][0])
   1703       break;		// no more used
   1704     lightmap_modified[i] = false;
   1705     lightmap_rectchange[i].l = BLOCK_WIDTH;
   1706     lightmap_rectchange[i].t = BLOCK_HEIGHT;
   1707     lightmap_rectchange[i].w = 0;
   1708     lightmap_rectchange[i].h = 0;
   1709     GL_Bind(lightmap_textures + i);
   1710     glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
   1711     glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
   1712     glTexImage2DHelper (GL_TEXTURE_2D, 0, lightmap_bytes
   1713     , BLOCK_WIDTH, BLOCK_HEIGHT, 0,
   1714     gl_lightmap_format, GL_UNSIGNED_BYTE, lightmaps+i*BLOCK_WIDTH*BLOCK_HEIGHT*lightmap_bytes);
   1715   }
   1716 
   1717    if (!gl_texsort.value)
   1718      GL_SelectTexture(TEXTURE0_SGIS);
   1719 
   1720 }
   1721 
   1722 /*
   1723 ==================
   1724 GL_BuildLightmaps
   1725 
   1726 Builds the lightmap texture
   1727 with all the surfaces from all brush models
   1728 ==================
   1729 */
   1730 void GL_BuildLightmaps (void)
   1731 {
   1732   int		i, j;
   1733   model_t	*m;
   1734   extern qboolean isPermedia;
   1735 
   1736   memset (allocated, 0, sizeof(allocated));
   1737 
   1738   r_framecount = 1;		// no dlightcache
   1739 
   1740   if (!lightmap_textures)
   1741   {
   1742     lightmap_textures = texture_extension_number;
   1743     texture_extension_number += MAX_LIGHTMAPS;
   1744   }
   1745 
   1746   gl_lightmap_format = GL_LUMINANCE;
   1747   // default differently on the Permedia
   1748   if (isPermedia)
   1749     gl_lightmap_format = GL_RGBA;
   1750 
   1751   if (COM_CheckParm ("-lm_1"))
   1752     gl_lightmap_format = GL_LUMINANCE;
   1753   if (COM_CheckParm ("-lm_a"))
   1754     gl_lightmap_format = GL_ALPHA;
   1755   if (COM_CheckParm ("-lm_i"))
   1756     gl_lightmap_format = GL_INTENSITY;
   1757   if (COM_CheckParm ("-lm_2"))
   1758     gl_lightmap_format = GL_RGBA4;
   1759   if (COM_CheckParm ("-lm_4"))
   1760     gl_lightmap_format = GL_RGBA;
   1761 
   1762   switch (gl_lightmap_format)
   1763   {
   1764   case GL_RGBA:
   1765     lightmap_bytes = 4;
   1766     break;
   1767   case GL_RGBA4:
   1768     lightmap_bytes = 2;
   1769     break;
   1770   case GL_LUMINANCE:
   1771   case GL_INTENSITY:
   1772   case GL_ALPHA:
   1773     lightmap_bytes = 1;
   1774     break;
   1775   }
   1776 
   1777   for (j=1 ; j<MAX_MODELS ; j++)
   1778   {
   1779     m = cl.model_precache[j];
   1780     if (!m)
   1781       break;
   1782     if (m->name[0] == '*')
   1783       continue;
   1784     r_pcurrentvertbase = m->vertexes;
   1785     currentmodel = m;
   1786     for (i=0 ; i<m->numsurfaces ; i++)
   1787     {
   1788       GL_CreateSurfaceLightmap (m->surfaces + i);
   1789       if ( m->surfaces[i].flags & SURF_DRAWTURB )
   1790         continue;
   1791 #ifndef QUAKE2
   1792       if ( m->surfaces[i].flags & SURF_DRAWSKY )
   1793         continue;
   1794 #endif
   1795       BuildSurfaceDisplayList (m->surfaces + i);
   1796     }
   1797   }
   1798 
   1799   GL_UploadLightmaps();
   1800 }
   1801 
   1802 
   1803