Quake-2

Quake 2 GPL Source Release
Log | Files | Refs

gl_rsurf.c (34883B)


      1 /*
      2 Copyright (C) 1997-2001 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 // GL_RSURF.C: surface-related refresh code
     21 #include <assert.h>
     22 
     23 #include "gl_local.h"
     24 
     25 static vec3_t	modelorg;		// relative to viewpoint
     26 
     27 msurface_t	*r_alpha_surfaces;
     28 
     29 #define DYNAMIC_LIGHT_WIDTH  128
     30 #define DYNAMIC_LIGHT_HEIGHT 128
     31 
     32 #define LIGHTMAP_BYTES 4
     33 
     34 #define	BLOCK_WIDTH		128
     35 #define	BLOCK_HEIGHT	128
     36 
     37 #define	MAX_LIGHTMAPS	128
     38 
     39 int		c_visible_lightmaps;
     40 int		c_visible_textures;
     41 
     42 #define GL_LIGHTMAP_FORMAT GL_RGBA
     43 
     44 typedef struct
     45 {
     46 	int internal_format;
     47 	int	current_lightmap_texture;
     48 
     49 	msurface_t	*lightmap_surfaces[MAX_LIGHTMAPS];
     50 
     51 	int			allocated[BLOCK_WIDTH];
     52 
     53 	// the lightmap texture data needs to be kept in
     54 	// main memory so texsubimage can update properly
     55 	byte		lightmap_buffer[4*BLOCK_WIDTH*BLOCK_HEIGHT];
     56 } gllightmapstate_t;
     57 
     58 static gllightmapstate_t gl_lms;
     59 
     60 
     61 static void		LM_InitBlock( void );
     62 static void		LM_UploadBlock( qboolean dynamic );
     63 static qboolean	LM_AllocBlock (int w, int h, int *x, int *y);
     64 
     65 extern void R_SetCacheState( msurface_t *surf );
     66 extern void R_BuildLightMap (msurface_t *surf, byte *dest, int stride);
     67 
     68 /*
     69 =============================================================
     70 
     71 	BRUSH MODELS
     72 
     73 =============================================================
     74 */
     75 
     76 /*
     77 ===============
     78 R_TextureAnimation
     79 
     80 Returns the proper texture for a given time and base texture
     81 ===============
     82 */
     83 image_t *R_TextureAnimation (mtexinfo_t *tex)
     84 {
     85 	int		c;
     86 
     87 	if (!tex->next)
     88 		return tex->image;
     89 
     90 	c = currententity->frame % tex->numframes;
     91 	while (c)
     92 	{
     93 		tex = tex->next;
     94 		c--;
     95 	}
     96 
     97 	return tex->image;
     98 }
     99 
    100 #if 0
    101 /*
    102 =================
    103 WaterWarpPolyVerts
    104 
    105 Mangles the x and y coordinates in a copy of the poly
    106 so that any drawing routine can be water warped
    107 =================
    108 */
    109 glpoly_t *WaterWarpPolyVerts (glpoly_t *p)
    110 {
    111 	int		i;
    112 	float	*v, *nv;
    113 	static byte	buffer[1024];
    114 	glpoly_t *out;
    115 
    116 	out = (glpoly_t *)buffer;
    117 
    118 	out->numverts = p->numverts;
    119 	v = p->verts[0];
    120 	nv = out->verts[0];
    121 	for (i=0 ; i<p->numverts ; i++, v+= VERTEXSIZE, nv+=VERTEXSIZE)
    122 	{
    123 		nv[0] = v[0] + 4*sin(v[1]*0.05+r_newrefdef.time)*sin(v[2]*0.05+r_newrefdef.time);
    124 		nv[1] = v[1] + 4*sin(v[0]*0.05+r_newrefdef.time)*sin(v[2]*0.05+r_newrefdef.time);
    125 
    126 		nv[2] = v[2];
    127 		nv[3] = v[3];
    128 		nv[4] = v[4];
    129 		nv[5] = v[5];
    130 		nv[6] = v[6];
    131 	}
    132 
    133 	return out;
    134 }
    135 
    136 /*
    137 ================
    138 DrawGLWaterPoly
    139 
    140 Warp the vertex coordinates
    141 ================
    142 */
    143 void DrawGLWaterPoly (glpoly_t *p)
    144 {
    145 	int		i;
    146 	float	*v;
    147 
    148 	p = WaterWarpPolyVerts (p);
    149 	qglBegin (GL_TRIANGLE_FAN);
    150 	v = p->verts[0];
    151 	for (i=0 ; i<p->numverts ; i++, v+= VERTEXSIZE)
    152 	{
    153 		qglTexCoord2f (v[3], v[4]);
    154 		qglVertex3fv (v);
    155 	}
    156 	qglEnd ();
    157 }
    158 void DrawGLWaterPolyLightmap (glpoly_t *p)
    159 {
    160 	int		i;
    161 	float	*v;
    162 
    163 	p = WaterWarpPolyVerts (p);
    164 	qglBegin (GL_TRIANGLE_FAN);
    165 	v = p->verts[0];
    166 	for (i=0 ; i<p->numverts ; i++, v+= VERTEXSIZE)
    167 	{
    168 		qglTexCoord2f (v[5], v[6]);
    169 		qglVertex3fv (v);
    170 	}
    171 	qglEnd ();
    172 }
    173 #endif
    174 
    175 /*
    176 ================
    177 DrawGLPoly
    178 ================
    179 */
    180 void DrawGLPoly (glpoly_t *p)
    181 {
    182 	int		i;
    183 	float	*v;
    184 
    185 	qglBegin (GL_POLYGON);
    186 	v = p->verts[0];
    187 	for (i=0 ; i<p->numverts ; i++, v+= VERTEXSIZE)
    188 	{
    189 		qglTexCoord2f (v[3], v[4]);
    190 		qglVertex3fv (v);
    191 	}
    192 	qglEnd ();
    193 }
    194 
    195 //============
    196 //PGM
    197 /*
    198 ================
    199 DrawGLFlowingPoly -- version of DrawGLPoly that handles scrolling texture
    200 ================
    201 */
    202 void DrawGLFlowingPoly (msurface_t *fa)
    203 {
    204 	int		i;
    205 	float	*v;
    206 	glpoly_t *p;
    207 	float	scroll;
    208 
    209 	p = fa->polys;
    210 
    211 	scroll = -64 * ( (r_newrefdef.time / 40.0) - (int)(r_newrefdef.time / 40.0) );
    212 	if(scroll == 0.0)
    213 		scroll = -64.0;
    214 
    215 	qglBegin (GL_POLYGON);
    216 	v = p->verts[0];
    217 	for (i=0 ; i<p->numverts ; i++, v+= VERTEXSIZE)
    218 	{
    219 		qglTexCoord2f ((v[3] + scroll), v[4]);
    220 		qglVertex3fv (v);
    221 	}
    222 	qglEnd ();
    223 }
    224 //PGM
    225 //============
    226 
    227 /*
    228 ** R_DrawTriangleOutlines
    229 */
    230 void R_DrawTriangleOutlines (void)
    231 {
    232 	int			i, j;
    233 	glpoly_t	*p;
    234 
    235 	if (!gl_showtris->value)
    236 		return;
    237 
    238 	qglDisable (GL_TEXTURE_2D);
    239 	qglDisable (GL_DEPTH_TEST);
    240 	qglColor4f (1,1,1,1);
    241 
    242 	for (i=0 ; i<MAX_LIGHTMAPS ; i++)
    243 	{
    244 		msurface_t *surf;
    245 
    246 		for ( surf = gl_lms.lightmap_surfaces[i]; surf != 0; surf = surf->lightmapchain )
    247 		{
    248 			p = surf->polys;
    249 			for ( ; p ; p=p->chain)
    250 			{
    251 				for (j=2 ; j<p->numverts ; j++ )
    252 				{
    253 					qglBegin (GL_LINE_STRIP);
    254 					qglVertex3fv (p->verts[0]);
    255 					qglVertex3fv (p->verts[j-1]);
    256 					qglVertex3fv (p->verts[j]);
    257 					qglVertex3fv (p->verts[0]);
    258 					qglEnd ();
    259 				}
    260 			}
    261 		}
    262 	}
    263 
    264 	qglEnable (GL_DEPTH_TEST);
    265 	qglEnable (GL_TEXTURE_2D);
    266 }
    267 
    268 /*
    269 ** DrawGLPolyChain
    270 */
    271 void DrawGLPolyChain( glpoly_t *p, float soffset, float toffset )
    272 {
    273 	if ( soffset == 0 && toffset == 0 )
    274 	{
    275 		for ( ; p != 0; p = p->chain )
    276 		{
    277 			float *v;
    278 			int j;
    279 
    280 			qglBegin (GL_POLYGON);
    281 			v = p->verts[0];
    282 			for (j=0 ; j<p->numverts ; j++, v+= VERTEXSIZE)
    283 			{
    284 				qglTexCoord2f (v[5], v[6] );
    285 				qglVertex3fv (v);
    286 			}
    287 			qglEnd ();
    288 		}
    289 	}
    290 	else
    291 	{
    292 		for ( ; p != 0; p = p->chain )
    293 		{
    294 			float *v;
    295 			int j;
    296 
    297 			qglBegin (GL_POLYGON);
    298 			v = p->verts[0];
    299 			for (j=0 ; j<p->numverts ; j++, v+= VERTEXSIZE)
    300 			{
    301 				qglTexCoord2f (v[5] - soffset, v[6] - toffset );
    302 				qglVertex3fv (v);
    303 			}
    304 			qglEnd ();
    305 		}
    306 	}
    307 }
    308 
    309 /*
    310 ** R_BlendLightMaps
    311 **
    312 ** This routine takes all the given light mapped surfaces in the world and
    313 ** blends them into the framebuffer.
    314 */
    315 void R_BlendLightmaps (void)
    316 {
    317 	int			i;
    318 	msurface_t	*surf, *newdrawsurf = 0;
    319 
    320 	// don't bother if we're set to fullbright
    321 	if (r_fullbright->value)
    322 		return;
    323 	if (!r_worldmodel->lightdata)
    324 		return;
    325 
    326 	// don't bother writing Z
    327 	qglDepthMask( 0 );
    328 
    329 	/*
    330 	** set the appropriate blending mode unless we're only looking at the
    331 	** lightmaps.
    332 	*/
    333 	if (!gl_lightmap->value)
    334 	{
    335 		qglEnable (GL_BLEND);
    336 
    337 		if ( gl_saturatelighting->value )
    338 		{
    339 			qglBlendFunc( GL_ONE, GL_ONE );
    340 		}
    341 		else
    342 		{
    343 			if ( gl_monolightmap->string[0] != '0' )
    344 			{
    345 				switch ( toupper( gl_monolightmap->string[0] ) )
    346 				{
    347 				case 'I':
    348 					qglBlendFunc (GL_ZERO, GL_SRC_COLOR );
    349 					break;
    350 				case 'L':
    351 					qglBlendFunc (GL_ZERO, GL_SRC_COLOR );
    352 					break;
    353 				case 'A':
    354 				default:
    355 					qglBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
    356 					break;
    357 				}
    358 			}
    359 			else
    360 			{
    361 				qglBlendFunc (GL_ZERO, GL_SRC_COLOR );
    362 			}
    363 		}
    364 	}
    365 
    366 	if ( currentmodel == r_worldmodel )
    367 		c_visible_lightmaps = 0;
    368 
    369 	/*
    370 	** render static lightmaps first
    371 	*/
    372 	for ( i = 1; i < MAX_LIGHTMAPS; i++ )
    373 	{
    374 		if ( gl_lms.lightmap_surfaces[i] )
    375 		{
    376 			if (currentmodel == r_worldmodel)
    377 				c_visible_lightmaps++;
    378 			GL_Bind( gl_state.lightmap_textures + i);
    379 
    380 			for ( surf = gl_lms.lightmap_surfaces[i]; surf != 0; surf = surf->lightmapchain )
    381 			{
    382 				if ( surf->polys )
    383 					DrawGLPolyChain( surf->polys, 0, 0 );
    384 			}
    385 		}
    386 	}
    387 
    388 	/*
    389 	** render dynamic lightmaps
    390 	*/
    391 	if ( gl_dynamic->value )
    392 	{
    393 		LM_InitBlock();
    394 
    395 		GL_Bind( gl_state.lightmap_textures+0 );
    396 
    397 		if (currentmodel == r_worldmodel)
    398 			c_visible_lightmaps++;
    399 
    400 		newdrawsurf = gl_lms.lightmap_surfaces[0];
    401 
    402 		for ( surf = gl_lms.lightmap_surfaces[0]; surf != 0; surf = surf->lightmapchain )
    403 		{
    404 			int		smax, tmax;
    405 			byte	*base;
    406 
    407 			smax = (surf->extents[0]>>4)+1;
    408 			tmax = (surf->extents[1]>>4)+1;
    409 
    410 			if ( LM_AllocBlock( smax, tmax, &surf->dlight_s, &surf->dlight_t ) )
    411 			{
    412 				base = gl_lms.lightmap_buffer;
    413 				base += ( surf->dlight_t * BLOCK_WIDTH + surf->dlight_s ) * LIGHTMAP_BYTES;
    414 
    415 				R_BuildLightMap (surf, base, BLOCK_WIDTH*LIGHTMAP_BYTES);
    416 			}
    417 			else
    418 			{
    419 				msurface_t *drawsurf;
    420 
    421 				// upload what we have so far
    422 				LM_UploadBlock( true );
    423 
    424 				// draw all surfaces that use this lightmap
    425 				for ( drawsurf = newdrawsurf; drawsurf != surf; drawsurf = drawsurf->lightmapchain )
    426 				{
    427 					if ( drawsurf->polys )
    428 						DrawGLPolyChain( drawsurf->polys, 
    429 							              ( drawsurf->light_s - drawsurf->dlight_s ) * ( 1.0 / 128.0 ), 
    430 										( drawsurf->light_t - drawsurf->dlight_t ) * ( 1.0 / 128.0 ) );
    431 				}
    432 
    433 				newdrawsurf = drawsurf;
    434 
    435 				// clear the block
    436 				LM_InitBlock();
    437 
    438 				// try uploading the block now
    439 				if ( !LM_AllocBlock( smax, tmax, &surf->dlight_s, &surf->dlight_t ) )
    440 				{
    441 					ri.Sys_Error( ERR_FATAL, "Consecutive calls to LM_AllocBlock(%d,%d) failed (dynamic)\n", smax, tmax );
    442 				}
    443 
    444 				base = gl_lms.lightmap_buffer;
    445 				base += ( surf->dlight_t * BLOCK_WIDTH + surf->dlight_s ) * LIGHTMAP_BYTES;
    446 
    447 				R_BuildLightMap (surf, base, BLOCK_WIDTH*LIGHTMAP_BYTES);
    448 			}
    449 		}
    450 
    451 		/*
    452 		** draw remainder of dynamic lightmaps that haven't been uploaded yet
    453 		*/
    454 		if ( newdrawsurf )
    455 			LM_UploadBlock( true );
    456 
    457 		for ( surf = newdrawsurf; surf != 0; surf = surf->lightmapchain )
    458 		{
    459 			if ( surf->polys )
    460 				DrawGLPolyChain( surf->polys, ( surf->light_s - surf->dlight_s ) * ( 1.0 / 128.0 ), ( surf->light_t - surf->dlight_t ) * ( 1.0 / 128.0 ) );
    461 		}
    462 	}
    463 
    464 	/*
    465 	** restore state
    466 	*/
    467 	qglDisable (GL_BLEND);
    468 	qglBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    469 	qglDepthMask( 1 );
    470 }
    471 
    472 /*
    473 ================
    474 R_RenderBrushPoly
    475 ================
    476 */
    477 void R_RenderBrushPoly (msurface_t *fa)
    478 {
    479 	int			maps;
    480 	image_t		*image;
    481 	qboolean is_dynamic = false;
    482 
    483 	c_brush_polys++;
    484 
    485 	image = R_TextureAnimation (fa->texinfo);
    486 
    487 	if (fa->flags & SURF_DRAWTURB)
    488 	{	
    489 		GL_Bind( image->texnum );
    490 
    491 		// warp texture, no lightmaps
    492 		GL_TexEnv( GL_MODULATE );
    493 		qglColor4f( gl_state.inverse_intensity, 
    494 			        gl_state.inverse_intensity,
    495 					gl_state.inverse_intensity,
    496 					1.0F );
    497 		EmitWaterPolys (fa);
    498 		GL_TexEnv( GL_REPLACE );
    499 
    500 		return;
    501 	}
    502 	else
    503 	{
    504 		GL_Bind( image->texnum );
    505 
    506 		GL_TexEnv( GL_REPLACE );
    507 	}
    508 
    509 //======
    510 //PGM
    511 	if(fa->texinfo->flags & SURF_FLOWING)
    512 		DrawGLFlowingPoly (fa);
    513 	else
    514 		DrawGLPoly (fa->polys);
    515 //PGM
    516 //======
    517 
    518 	/*
    519 	** check for lightmap modification
    520 	*/
    521 	for ( maps = 0; maps < MAXLIGHTMAPS && fa->styles[maps] != 255; maps++ )
    522 	{
    523 		if ( r_newrefdef.lightstyles[fa->styles[maps]].white != fa->cached_light[maps] )
    524 			goto dynamic;
    525 	}
    526 
    527 	// dynamic this frame or dynamic previously
    528 	if ( ( fa->dlightframe == r_framecount ) )
    529 	{
    530 dynamic:
    531 		if ( gl_dynamic->value )
    532 		{
    533 			if (!( fa->texinfo->flags & (SURF_SKY|SURF_TRANS33|SURF_TRANS66|SURF_WARP ) ) )
    534 			{
    535 				is_dynamic = true;
    536 			}
    537 		}
    538 	}
    539 
    540 	if ( is_dynamic )
    541 	{
    542 		if ( ( fa->styles[maps] >= 32 || fa->styles[maps] == 0 ) && ( fa->dlightframe != r_framecount ) )
    543 		{
    544 			unsigned	temp[34*34];
    545 			int			smax, tmax;
    546 
    547 			smax = (fa->extents[0]>>4)+1;
    548 			tmax = (fa->extents[1]>>4)+1;
    549 
    550 			R_BuildLightMap( fa, (void *)temp, smax*4 );
    551 			R_SetCacheState( fa );
    552 
    553 			GL_Bind( gl_state.lightmap_textures + fa->lightmaptexturenum );
    554 
    555 			qglTexSubImage2D( GL_TEXTURE_2D, 0,
    556 							  fa->light_s, fa->light_t, 
    557 							  smax, tmax, 
    558 							  GL_LIGHTMAP_FORMAT, 
    559 							  GL_UNSIGNED_BYTE, temp );
    560 
    561 			fa->lightmapchain = gl_lms.lightmap_surfaces[fa->lightmaptexturenum];
    562 			gl_lms.lightmap_surfaces[fa->lightmaptexturenum] = fa;
    563 		}
    564 		else
    565 		{
    566 			fa->lightmapchain = gl_lms.lightmap_surfaces[0];
    567 			gl_lms.lightmap_surfaces[0] = fa;
    568 		}
    569 	}
    570 	else
    571 	{
    572 		fa->lightmapchain = gl_lms.lightmap_surfaces[fa->lightmaptexturenum];
    573 		gl_lms.lightmap_surfaces[fa->lightmaptexturenum] = fa;
    574 	}
    575 }
    576 
    577 
    578 /*
    579 ================
    580 R_DrawAlphaSurfaces
    581 
    582 Draw water surfaces and windows.
    583 The BSP tree is waled front to back, so unwinding the chain
    584 of alpha_surfaces will draw back to front, giving proper ordering.
    585 ================
    586 */
    587 void R_DrawAlphaSurfaces (void)
    588 {
    589 	msurface_t	*s;
    590 	float		intens;
    591 
    592 	//
    593 	// go back to the world matrix
    594 	//
    595     qglLoadMatrixf (r_world_matrix);
    596 
    597 	qglEnable (GL_BLEND);
    598 	GL_TexEnv( GL_MODULATE );
    599 
    600 	// the textures are prescaled up for a better lighting range,
    601 	// so scale it back down
    602 	intens = gl_state.inverse_intensity;
    603 
    604 	for (s=r_alpha_surfaces ; s ; s=s->texturechain)
    605 	{
    606 		GL_Bind(s->texinfo->image->texnum);
    607 		c_brush_polys++;
    608 		if (s->texinfo->flags & SURF_TRANS33)
    609 			qglColor4f (intens,intens,intens,0.33);
    610 		else if (s->texinfo->flags & SURF_TRANS66)
    611 			qglColor4f (intens,intens,intens,0.66);
    612 		else
    613 			qglColor4f (intens,intens,intens,1);
    614 		if (s->flags & SURF_DRAWTURB)
    615 			EmitWaterPolys (s);
    616 		else
    617 			DrawGLPoly (s->polys);
    618 	}
    619 
    620 	GL_TexEnv( GL_REPLACE );
    621 	qglColor4f (1,1,1,1);
    622 	qglDisable (GL_BLEND);
    623 
    624 	r_alpha_surfaces = NULL;
    625 }
    626 
    627 /*
    628 ================
    629 DrawTextureChains
    630 ================
    631 */
    632 void DrawTextureChains (void)
    633 {
    634 	int		i;
    635 	msurface_t	*s;
    636 	image_t		*image;
    637 
    638 	c_visible_textures = 0;
    639 
    640 //	GL_TexEnv( GL_REPLACE );
    641 
    642 	if ( !qglSelectTextureSGIS )
    643 	{
    644 		for ( i = 0, image=gltextures ; i<numgltextures ; i++,image++)
    645 		{
    646 			if (!image->registration_sequence)
    647 				continue;
    648 			s = image->texturechain;
    649 			if (!s)
    650 				continue;
    651 			c_visible_textures++;
    652 
    653 			for ( ; s ; s=s->texturechain)
    654 				R_RenderBrushPoly (s);
    655 
    656 			image->texturechain = NULL;
    657 		}
    658 	}
    659 	else
    660 	{
    661 		for ( i = 0, image=gltextures ; i<numgltextures ; i++,image++)
    662 		{
    663 			if (!image->registration_sequence)
    664 				continue;
    665 			if (!image->texturechain)
    666 				continue;
    667 			c_visible_textures++;
    668 
    669 			for ( s = image->texturechain; s ; s=s->texturechain)
    670 			{
    671 				if ( !( s->flags & SURF_DRAWTURB ) )
    672 					R_RenderBrushPoly (s);
    673 			}
    674 		}
    675 
    676 		GL_EnableMultitexture( false );
    677 		for ( i = 0, image=gltextures ; i<numgltextures ; i++,image++)
    678 		{
    679 			if (!image->registration_sequence)
    680 				continue;
    681 			s = image->texturechain;
    682 			if (!s)
    683 				continue;
    684 
    685 			for ( ; s ; s=s->texturechain)
    686 			{
    687 				if ( s->flags & SURF_DRAWTURB )
    688 					R_RenderBrushPoly (s);
    689 			}
    690 
    691 			image->texturechain = NULL;
    692 		}
    693 //		GL_EnableMultitexture( true );
    694 	}
    695 
    696 	GL_TexEnv( GL_REPLACE );
    697 }
    698 
    699 
    700 static void GL_RenderLightmappedPoly( msurface_t *surf )
    701 {
    702 	int		i, nv = surf->polys->numverts;
    703 	int		map;
    704 	float	*v;
    705 	image_t *image = R_TextureAnimation( surf->texinfo );
    706 	qboolean is_dynamic = false;
    707 	unsigned lmtex = surf->lightmaptexturenum;
    708 	glpoly_t *p;
    709 
    710 	for ( map = 0; map < MAXLIGHTMAPS && surf->styles[map] != 255; map++ )
    711 	{
    712 		if ( r_newrefdef.lightstyles[surf->styles[map]].white != surf->cached_light[map] )
    713 			goto dynamic;
    714 	}
    715 
    716 	// dynamic this frame or dynamic previously
    717 	if ( ( surf->dlightframe == r_framecount ) )
    718 	{
    719 dynamic:
    720 		if ( gl_dynamic->value )
    721 		{
    722 			if ( !(surf->texinfo->flags & (SURF_SKY|SURF_TRANS33|SURF_TRANS66|SURF_WARP ) ) )
    723 			{
    724 				is_dynamic = true;
    725 			}
    726 		}
    727 	}
    728 
    729 	if ( is_dynamic )
    730 	{
    731 		unsigned	temp[128*128];
    732 		int			smax, tmax;
    733 
    734 		if ( ( surf->styles[map] >= 32 || surf->styles[map] == 0 ) && ( surf->dlightframe != r_framecount ) )
    735 		{
    736 			smax = (surf->extents[0]>>4)+1;
    737 			tmax = (surf->extents[1]>>4)+1;
    738 
    739 			R_BuildLightMap( surf, (void *)temp, smax*4 );
    740 			R_SetCacheState( surf );
    741 
    742 			GL_MBind( GL_TEXTURE1_SGIS, gl_state.lightmap_textures + surf->lightmaptexturenum );
    743 
    744 			lmtex = surf->lightmaptexturenum;
    745 
    746 			qglTexSubImage2D( GL_TEXTURE_2D, 0,
    747 							  surf->light_s, surf->light_t, 
    748 							  smax, tmax, 
    749 							  GL_LIGHTMAP_FORMAT, 
    750 							  GL_UNSIGNED_BYTE, temp );
    751 
    752 		}
    753 		else
    754 		{
    755 			smax = (surf->extents[0]>>4)+1;
    756 			tmax = (surf->extents[1]>>4)+1;
    757 
    758 			R_BuildLightMap( surf, (void *)temp, smax*4 );
    759 
    760 			GL_MBind( GL_TEXTURE1_SGIS, gl_state.lightmap_textures + 0 );
    761 
    762 			lmtex = 0;
    763 
    764 			qglTexSubImage2D( GL_TEXTURE_2D, 0,
    765 							  surf->light_s, surf->light_t, 
    766 							  smax, tmax, 
    767 							  GL_LIGHTMAP_FORMAT, 
    768 							  GL_UNSIGNED_BYTE, temp );
    769 
    770 		}
    771 
    772 		c_brush_polys++;
    773 
    774 		GL_MBind( GL_TEXTURE0_SGIS, image->texnum );
    775 		GL_MBind( GL_TEXTURE1_SGIS, gl_state.lightmap_textures + lmtex );
    776 
    777 //==========
    778 //PGM
    779 		if (surf->texinfo->flags & SURF_FLOWING)
    780 		{
    781 			float scroll;
    782 		
    783 			scroll = -64 * ( (r_newrefdef.time / 40.0) - (int)(r_newrefdef.time / 40.0) );
    784 			if(scroll == 0.0)
    785 				scroll = -64.0;
    786 
    787 			for ( p = surf->polys; p; p = p->chain )
    788 			{
    789 				v = p->verts[0];
    790 				qglBegin (GL_POLYGON);
    791 				for (i=0 ; i< nv; i++, v+= VERTEXSIZE)
    792 				{
    793 					qglMTexCoord2fSGIS( GL_TEXTURE0_SGIS, (v[3]+scroll), v[4]);
    794 					qglMTexCoord2fSGIS( GL_TEXTURE1_SGIS, v[5], v[6]);
    795 					qglVertex3fv (v);
    796 				}
    797 				qglEnd ();
    798 			}
    799 		}
    800 		else
    801 		{
    802 			for ( p = surf->polys; p; p = p->chain )
    803 			{
    804 				v = p->verts[0];
    805 				qglBegin (GL_POLYGON);
    806 				for (i=0 ; i< nv; i++, v+= VERTEXSIZE)
    807 				{
    808 					qglMTexCoord2fSGIS( GL_TEXTURE0_SGIS, v[3], v[4]);
    809 					qglMTexCoord2fSGIS( GL_TEXTURE1_SGIS, v[5], v[6]);
    810 					qglVertex3fv (v);
    811 				}
    812 				qglEnd ();
    813 			}
    814 		}
    815 //PGM
    816 //==========
    817 	}
    818 	else
    819 	{
    820 		c_brush_polys++;
    821 
    822 		GL_MBind( GL_TEXTURE0_SGIS, image->texnum );
    823 		GL_MBind( GL_TEXTURE1_SGIS, gl_state.lightmap_textures + lmtex );
    824 
    825 //==========
    826 //PGM
    827 		if (surf->texinfo->flags & SURF_FLOWING)
    828 		{
    829 			float scroll;
    830 		
    831 			scroll = -64 * ( (r_newrefdef.time / 40.0) - (int)(r_newrefdef.time / 40.0) );
    832 			if(scroll == 0.0)
    833 				scroll = -64.0;
    834 
    835 			for ( p = surf->polys; p; p = p->chain )
    836 			{
    837 				v = p->verts[0];
    838 				qglBegin (GL_POLYGON);
    839 				for (i=0 ; i< nv; i++, v+= VERTEXSIZE)
    840 				{
    841 					qglMTexCoord2fSGIS( GL_TEXTURE0_SGIS, (v[3]+scroll), v[4]);
    842 					qglMTexCoord2fSGIS( GL_TEXTURE1_SGIS, v[5], v[6]);
    843 					qglVertex3fv (v);
    844 				}
    845 				qglEnd ();
    846 			}
    847 		}
    848 		else
    849 		{
    850 //PGM
    851 //==========
    852 			for ( p = surf->polys; p; p = p->chain )
    853 			{
    854 				v = p->verts[0];
    855 				qglBegin (GL_POLYGON);
    856 				for (i=0 ; i< nv; i++, v+= VERTEXSIZE)
    857 				{
    858 					qglMTexCoord2fSGIS( GL_TEXTURE0_SGIS, v[3], v[4]);
    859 					qglMTexCoord2fSGIS( GL_TEXTURE1_SGIS, v[5], v[6]);
    860 					qglVertex3fv (v);
    861 				}
    862 				qglEnd ();
    863 			}
    864 //==========
    865 //PGM
    866 		}
    867 //PGM
    868 //==========
    869 	}
    870 }
    871 
    872 /*
    873 =================
    874 R_DrawInlineBModel
    875 =================
    876 */
    877 void R_DrawInlineBModel (void)
    878 {
    879 	int			i, k;
    880 	cplane_t	*pplane;
    881 	float		dot;
    882 	msurface_t	*psurf;
    883 	dlight_t	*lt;
    884 
    885 	// calculate dynamic lighting for bmodel
    886 	if ( !gl_flashblend->value )
    887 	{
    888 		lt = r_newrefdef.dlights;
    889 		for (k=0 ; k<r_newrefdef.num_dlights ; k++, lt++)
    890 		{
    891 			R_MarkLights (lt, 1<<k, currentmodel->nodes + currentmodel->firstnode);
    892 		}
    893 	}
    894 
    895 	psurf = &currentmodel->surfaces[currentmodel->firstmodelsurface];
    896 
    897 	if ( currententity->flags & RF_TRANSLUCENT )
    898 	{
    899 		qglEnable (GL_BLEND);
    900 		qglColor4f (1,1,1,0.25);
    901 		GL_TexEnv( GL_MODULATE );
    902 	}
    903 
    904 	//
    905 	// draw texture
    906 	//
    907 	for (i=0 ; i<currentmodel->nummodelsurfaces ; i++, psurf++)
    908 	{
    909 	// find which side of the node we are on
    910 		pplane = psurf->plane;
    911 
    912 		dot = DotProduct (modelorg, pplane->normal) - pplane->dist;
    913 
    914 	// draw the polygon
    915 		if (((psurf->flags & SURF_PLANEBACK) && (dot < -BACKFACE_EPSILON)) ||
    916 			(!(psurf->flags & SURF_PLANEBACK) && (dot > BACKFACE_EPSILON)))
    917 		{
    918 			if (psurf->texinfo->flags & (SURF_TRANS33|SURF_TRANS66) )
    919 			{	// add to the translucent chain
    920 				psurf->texturechain = r_alpha_surfaces;
    921 				r_alpha_surfaces = psurf;
    922 			}
    923 			else if ( qglMTexCoord2fSGIS && !( psurf->flags & SURF_DRAWTURB ) )
    924 			{
    925 				GL_RenderLightmappedPoly( psurf );
    926 			}
    927 			else
    928 			{
    929 				GL_EnableMultitexture( false );
    930 				R_RenderBrushPoly( psurf );
    931 				GL_EnableMultitexture( true );
    932 			}
    933 		}
    934 	}
    935 
    936 	if ( !(currententity->flags & RF_TRANSLUCENT) )
    937 	{
    938 		if ( !qglMTexCoord2fSGIS )
    939 			R_BlendLightmaps ();
    940 	}
    941 	else
    942 	{
    943 		qglDisable (GL_BLEND);
    944 		qglColor4f (1,1,1,1);
    945 		GL_TexEnv( GL_REPLACE );
    946 	}
    947 }
    948 
    949 /*
    950 =================
    951 R_DrawBrushModel
    952 =================
    953 */
    954 void R_DrawBrushModel (entity_t *e)
    955 {
    956 	vec3_t		mins, maxs;
    957 	int			i;
    958 	qboolean	rotated;
    959 
    960 	if (currentmodel->nummodelsurfaces == 0)
    961 		return;
    962 
    963 	currententity = e;
    964 	gl_state.currenttextures[0] = gl_state.currenttextures[1] = -1;
    965 
    966 	if (e->angles[0] || e->angles[1] || e->angles[2])
    967 	{
    968 		rotated = true;
    969 		for (i=0 ; i<3 ; i++)
    970 		{
    971 			mins[i] = e->origin[i] - currentmodel->radius;
    972 			maxs[i] = e->origin[i] + currentmodel->radius;
    973 		}
    974 	}
    975 	else
    976 	{
    977 		rotated = false;
    978 		VectorAdd (e->origin, currentmodel->mins, mins);
    979 		VectorAdd (e->origin, currentmodel->maxs, maxs);
    980 	}
    981 
    982 	if (R_CullBox (mins, maxs))
    983 		return;
    984 
    985 	qglColor3f (1,1,1);
    986 	memset (gl_lms.lightmap_surfaces, 0, sizeof(gl_lms.lightmap_surfaces));
    987 
    988 	VectorSubtract (r_newrefdef.vieworg, e->origin, modelorg);
    989 	if (rotated)
    990 	{
    991 		vec3_t	temp;
    992 		vec3_t	forward, right, up;
    993 
    994 		VectorCopy (modelorg, temp);
    995 		AngleVectors (e->angles, forward, right, up);
    996 		modelorg[0] = DotProduct (temp, forward);
    997 		modelorg[1] = -DotProduct (temp, right);
    998 		modelorg[2] = DotProduct (temp, up);
    999 	}
   1000 
   1001     qglPushMatrix ();
   1002 e->angles[0] = -e->angles[0];	// stupid quake bug
   1003 e->angles[2] = -e->angles[2];	// stupid quake bug
   1004 	R_RotateForEntity (e);
   1005 e->angles[0] = -e->angles[0];	// stupid quake bug
   1006 e->angles[2] = -e->angles[2];	// stupid quake bug
   1007 
   1008 	GL_EnableMultitexture( true );
   1009 	GL_SelectTexture( GL_TEXTURE0_SGIS );
   1010 	GL_TexEnv( GL_REPLACE );
   1011 	GL_SelectTexture( GL_TEXTURE1_SGIS );
   1012 	GL_TexEnv( GL_MODULATE );
   1013 
   1014 	R_DrawInlineBModel ();
   1015 	GL_EnableMultitexture( false );
   1016 
   1017 	qglPopMatrix ();
   1018 }
   1019 
   1020 /*
   1021 =============================================================
   1022 
   1023 	WORLD MODEL
   1024 
   1025 =============================================================
   1026 */
   1027 
   1028 /*
   1029 ================
   1030 R_RecursiveWorldNode
   1031 ================
   1032 */
   1033 void R_RecursiveWorldNode (mnode_t *node)
   1034 {
   1035 	int			c, side, sidebit;
   1036 	cplane_t	*plane;
   1037 	msurface_t	*surf, **mark;
   1038 	mleaf_t		*pleaf;
   1039 	float		dot;
   1040 	image_t		*image;
   1041 
   1042 	if (node->contents == CONTENTS_SOLID)
   1043 		return;		// solid
   1044 
   1045 	if (node->visframe != r_visframecount)
   1046 		return;
   1047 	if (R_CullBox (node->minmaxs, node->minmaxs+3))
   1048 		return;
   1049 	
   1050 // if a leaf node, draw stuff
   1051 	if (node->contents != -1)
   1052 	{
   1053 		pleaf = (mleaf_t *)node;
   1054 
   1055 		// check for door connected areas
   1056 		if (r_newrefdef.areabits)
   1057 		{
   1058 			if (! (r_newrefdef.areabits[pleaf->area>>3] & (1<<(pleaf->area&7)) ) )
   1059 				return;		// not visible
   1060 		}
   1061 
   1062 		mark = pleaf->firstmarksurface;
   1063 		c = pleaf->nummarksurfaces;
   1064 
   1065 		if (c)
   1066 		{
   1067 			do
   1068 			{
   1069 				(*mark)->visframe = r_framecount;
   1070 				mark++;
   1071 			} while (--c);
   1072 		}
   1073 
   1074 		return;
   1075 	}
   1076 
   1077 // node is just a decision point, so go down the apropriate sides
   1078 
   1079 // find which side of the node we are on
   1080 	plane = node->plane;
   1081 
   1082 	switch (plane->type)
   1083 	{
   1084 	case PLANE_X:
   1085 		dot = modelorg[0] - plane->dist;
   1086 		break;
   1087 	case PLANE_Y:
   1088 		dot = modelorg[1] - plane->dist;
   1089 		break;
   1090 	case PLANE_Z:
   1091 		dot = modelorg[2] - plane->dist;
   1092 		break;
   1093 	default:
   1094 		dot = DotProduct (modelorg, plane->normal) - plane->dist;
   1095 		break;
   1096 	}
   1097 
   1098 	if (dot >= 0)
   1099 	{
   1100 		side = 0;
   1101 		sidebit = 0;
   1102 	}
   1103 	else
   1104 	{
   1105 		side = 1;
   1106 		sidebit = SURF_PLANEBACK;
   1107 	}
   1108 
   1109 // recurse down the children, front side first
   1110 	R_RecursiveWorldNode (node->children[side]);
   1111 
   1112 	// draw stuff
   1113 	for ( c = node->numsurfaces, surf = r_worldmodel->surfaces + node->firstsurface; c ; c--, surf++)
   1114 	{
   1115 		if (surf->visframe != r_framecount)
   1116 			continue;
   1117 
   1118 		if ( (surf->flags & SURF_PLANEBACK) != sidebit )
   1119 			continue;		// wrong side
   1120 
   1121 		if (surf->texinfo->flags & SURF_SKY)
   1122 		{	// just adds to visible sky bounds
   1123 			R_AddSkySurface (surf);
   1124 		}
   1125 		else if (surf->texinfo->flags & (SURF_TRANS33|SURF_TRANS66))
   1126 		{	// add to the translucent chain
   1127 			surf->texturechain = r_alpha_surfaces;
   1128 			r_alpha_surfaces = surf;
   1129 		}
   1130 		else
   1131 		{
   1132 			if ( qglMTexCoord2fSGIS && !( surf->flags & SURF_DRAWTURB ) )
   1133 			{
   1134 				GL_RenderLightmappedPoly( surf );
   1135 			}
   1136 			else
   1137 			{
   1138 				// the polygon is visible, so add it to the texture
   1139 				// sorted chain
   1140 				// FIXME: this is a hack for animation
   1141 				image = R_TextureAnimation (surf->texinfo);
   1142 				surf->texturechain = image->texturechain;
   1143 				image->texturechain = surf;
   1144 			}
   1145 		}
   1146 	}
   1147 
   1148 	// recurse down the back side
   1149 	R_RecursiveWorldNode (node->children[!side]);
   1150 /*
   1151 	for ( ; c ; c--, surf++)
   1152 	{
   1153 		if (surf->visframe != r_framecount)
   1154 			continue;
   1155 
   1156 		if ( (surf->flags & SURF_PLANEBACK) != sidebit )
   1157 			continue;		// wrong side
   1158 
   1159 		if (surf->texinfo->flags & SURF_SKY)
   1160 		{	// just adds to visible sky bounds
   1161 			R_AddSkySurface (surf);
   1162 		}
   1163 		else if (surf->texinfo->flags & (SURF_TRANS33|SURF_TRANS66))
   1164 		{	// add to the translucent chain
   1165 //			surf->texturechain = alpha_surfaces;
   1166 //			alpha_surfaces = surf;
   1167 		}
   1168 		else
   1169 		{
   1170 			if ( qglMTexCoord2fSGIS && !( surf->flags & SURF_DRAWTURB ) )
   1171 			{
   1172 				GL_RenderLightmappedPoly( surf );
   1173 			}
   1174 			else
   1175 			{
   1176 				// the polygon is visible, so add it to the texture
   1177 				// sorted chain
   1178 				// FIXME: this is a hack for animation
   1179 				image = R_TextureAnimation (surf->texinfo);
   1180 				surf->texturechain = image->texturechain;
   1181 				image->texturechain = surf;
   1182 			}
   1183 		}
   1184 	}
   1185 */
   1186 }
   1187 
   1188 
   1189 /*
   1190 =============
   1191 R_DrawWorld
   1192 =============
   1193 */
   1194 void R_DrawWorld (void)
   1195 {
   1196 	entity_t	ent;
   1197 
   1198 	if (!r_drawworld->value)
   1199 		return;
   1200 
   1201 	if ( r_newrefdef.rdflags & RDF_NOWORLDMODEL )
   1202 		return;
   1203 
   1204 	currentmodel = r_worldmodel;
   1205 
   1206 	VectorCopy (r_newrefdef.vieworg, modelorg);
   1207 
   1208 	// auto cycle the world frame for texture animation
   1209 	memset (&ent, 0, sizeof(ent));
   1210 	ent.frame = (int)(r_newrefdef.time*2);
   1211 	currententity = &ent;
   1212 
   1213 	gl_state.currenttextures[0] = gl_state.currenttextures[1] = -1;
   1214 
   1215 	qglColor3f (1,1,1);
   1216 	memset (gl_lms.lightmap_surfaces, 0, sizeof(gl_lms.lightmap_surfaces));
   1217 	R_ClearSkyBox ();
   1218 
   1219 	if ( qglMTexCoord2fSGIS )
   1220 	{
   1221 		GL_EnableMultitexture( true );
   1222 
   1223 		GL_SelectTexture( GL_TEXTURE0_SGIS );
   1224 		GL_TexEnv( GL_REPLACE );
   1225 		GL_SelectTexture( GL_TEXTURE1_SGIS );
   1226 
   1227 		if ( gl_lightmap->value )
   1228 			GL_TexEnv( GL_REPLACE );
   1229 		else 
   1230 			GL_TexEnv( GL_MODULATE );
   1231 
   1232 		R_RecursiveWorldNode (r_worldmodel->nodes);
   1233 
   1234 		GL_EnableMultitexture( false );
   1235 	}
   1236 	else
   1237 	{
   1238 		R_RecursiveWorldNode (r_worldmodel->nodes);
   1239 	}
   1240 
   1241 	/*
   1242 	** theoretically nothing should happen in the next two functions
   1243 	** if multitexture is enabled
   1244 	*/
   1245 	DrawTextureChains ();
   1246 	R_BlendLightmaps ();
   1247 	
   1248 	R_DrawSkyBox ();
   1249 
   1250 	R_DrawTriangleOutlines ();
   1251 }
   1252 
   1253 
   1254 /*
   1255 ===============
   1256 R_MarkLeaves
   1257 
   1258 Mark the leaves and nodes that are in the PVS for the current
   1259 cluster
   1260 ===============
   1261 */
   1262 void R_MarkLeaves (void)
   1263 {
   1264 	byte	*vis;
   1265 	byte	fatvis[MAX_MAP_LEAFS/8];
   1266 	mnode_t	*node;
   1267 	int		i, c;
   1268 	mleaf_t	*leaf;
   1269 	int		cluster;
   1270 
   1271 	if (r_oldviewcluster == r_viewcluster && r_oldviewcluster2 == r_viewcluster2 && !r_novis->value && r_viewcluster != -1)
   1272 		return;
   1273 
   1274 	// development aid to let you run around and see exactly where
   1275 	// the pvs ends
   1276 	if (gl_lockpvs->value)
   1277 		return;
   1278 
   1279 	r_visframecount++;
   1280 	r_oldviewcluster = r_viewcluster;
   1281 	r_oldviewcluster2 = r_viewcluster2;
   1282 
   1283 	if (r_novis->value || r_viewcluster == -1 || !r_worldmodel->vis)
   1284 	{
   1285 		// mark everything
   1286 		for (i=0 ; i<r_worldmodel->numleafs ; i++)
   1287 			r_worldmodel->leafs[i].visframe = r_visframecount;
   1288 		for (i=0 ; i<r_worldmodel->numnodes ; i++)
   1289 			r_worldmodel->nodes[i].visframe = r_visframecount;
   1290 		return;
   1291 	}
   1292 
   1293 	vis = Mod_ClusterPVS (r_viewcluster, r_worldmodel);
   1294 	// may have to combine two clusters because of solid water boundaries
   1295 	if (r_viewcluster2 != r_viewcluster)
   1296 	{
   1297 		memcpy (fatvis, vis, (r_worldmodel->numleafs+7)/8);
   1298 		vis = Mod_ClusterPVS (r_viewcluster2, r_worldmodel);
   1299 		c = (r_worldmodel->numleafs+31)/32;
   1300 		for (i=0 ; i<c ; i++)
   1301 			((int *)fatvis)[i] |= ((int *)vis)[i];
   1302 		vis = fatvis;
   1303 	}
   1304 	
   1305 	for (i=0,leaf=r_worldmodel->leafs ; i<r_worldmodel->numleafs ; i++, leaf++)
   1306 	{
   1307 		cluster = leaf->cluster;
   1308 		if (cluster == -1)
   1309 			continue;
   1310 		if (vis[cluster>>3] & (1<<(cluster&7)))
   1311 		{
   1312 			node = (mnode_t *)leaf;
   1313 			do
   1314 			{
   1315 				if (node->visframe == r_visframecount)
   1316 					break;
   1317 				node->visframe = r_visframecount;
   1318 				node = node->parent;
   1319 			} while (node);
   1320 		}
   1321 	}
   1322 
   1323 #if 0
   1324 	for (i=0 ; i<r_worldmodel->vis->numclusters ; i++)
   1325 	{
   1326 		if (vis[i>>3] & (1<<(i&7)))
   1327 		{
   1328 			node = (mnode_t *)&r_worldmodel->leafs[i];	// FIXME: cluster
   1329 			do
   1330 			{
   1331 				if (node->visframe == r_visframecount)
   1332 					break;
   1333 				node->visframe = r_visframecount;
   1334 				node = node->parent;
   1335 			} while (node);
   1336 		}
   1337 	}
   1338 #endif
   1339 }
   1340 
   1341 
   1342 
   1343 /*
   1344 =============================================================================
   1345 
   1346   LIGHTMAP ALLOCATION
   1347 
   1348 =============================================================================
   1349 */
   1350 
   1351 static void LM_InitBlock( void )
   1352 {
   1353 	memset( gl_lms.allocated, 0, sizeof( gl_lms.allocated ) );
   1354 }
   1355 
   1356 static void LM_UploadBlock( qboolean dynamic )
   1357 {
   1358 	int texture;
   1359 	int height = 0;
   1360 
   1361 	if ( dynamic )
   1362 	{
   1363 		texture = 0;
   1364 	}
   1365 	else
   1366 	{
   1367 		texture = gl_lms.current_lightmap_texture;
   1368 	}
   1369 
   1370 	GL_Bind( gl_state.lightmap_textures + texture );
   1371 	qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
   1372 	qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
   1373 
   1374 	if ( dynamic )
   1375 	{
   1376 		int i;
   1377 
   1378 		for ( i = 0; i < BLOCK_WIDTH; i++ )
   1379 		{
   1380 			if ( gl_lms.allocated[i] > height )
   1381 				height = gl_lms.allocated[i];
   1382 		}
   1383 
   1384 		qglTexSubImage2D( GL_TEXTURE_2D, 
   1385 						  0,
   1386 						  0, 0,
   1387 						  BLOCK_WIDTH, height,
   1388 						  GL_LIGHTMAP_FORMAT,
   1389 						  GL_UNSIGNED_BYTE,
   1390 						  gl_lms.lightmap_buffer );
   1391 	}
   1392 	else
   1393 	{
   1394 		qglTexImage2D( GL_TEXTURE_2D, 
   1395 					   0, 
   1396 					   gl_lms.internal_format,
   1397 					   BLOCK_WIDTH, BLOCK_HEIGHT, 
   1398 					   0, 
   1399 					   GL_LIGHTMAP_FORMAT, 
   1400 					   GL_UNSIGNED_BYTE, 
   1401 					   gl_lms.lightmap_buffer );
   1402 		if ( ++gl_lms.current_lightmap_texture == MAX_LIGHTMAPS )
   1403 			ri.Sys_Error( ERR_DROP, "LM_UploadBlock() - MAX_LIGHTMAPS exceeded\n" );
   1404 	}
   1405 }
   1406 
   1407 // returns a texture number and the position inside it
   1408 static qboolean LM_AllocBlock (int w, int h, int *x, int *y)
   1409 {
   1410 	int		i, j;
   1411 	int		best, best2;
   1412 
   1413 	best = BLOCK_HEIGHT;
   1414 
   1415 	for (i=0 ; i<BLOCK_WIDTH-w ; i++)
   1416 	{
   1417 		best2 = 0;
   1418 
   1419 		for (j=0 ; j<w ; j++)
   1420 		{
   1421 			if (gl_lms.allocated[i+j] >= best)
   1422 				break;
   1423 			if (gl_lms.allocated[i+j] > best2)
   1424 				best2 = gl_lms.allocated[i+j];
   1425 		}
   1426 		if (j == w)
   1427 		{	// this is a valid spot
   1428 			*x = i;
   1429 			*y = best = best2;
   1430 		}
   1431 	}
   1432 
   1433 	if (best + h > BLOCK_HEIGHT)
   1434 		return false;
   1435 
   1436 	for (i=0 ; i<w ; i++)
   1437 		gl_lms.allocated[*x + i] = best + h;
   1438 
   1439 	return true;
   1440 }
   1441 
   1442 /*
   1443 ================
   1444 GL_BuildPolygonFromSurface
   1445 ================
   1446 */
   1447 void GL_BuildPolygonFromSurface(msurface_t *fa)
   1448 {
   1449 	int			i, lindex, lnumverts;
   1450 	medge_t		*pedges, *r_pedge;
   1451 	int			vertpage;
   1452 	float		*vec;
   1453 	float		s, t;
   1454 	glpoly_t	*poly;
   1455 	vec3_t		total;
   1456 
   1457 // reconstruct the polygon
   1458 	pedges = currentmodel->edges;
   1459 	lnumverts = fa->numedges;
   1460 	vertpage = 0;
   1461 
   1462 	VectorClear (total);
   1463 	//
   1464 	// draw texture
   1465 	//
   1466 	poly = Hunk_Alloc (sizeof(glpoly_t) + (lnumverts-4) * VERTEXSIZE*sizeof(float));
   1467 	poly->next = fa->polys;
   1468 	poly->flags = fa->flags;
   1469 	fa->polys = poly;
   1470 	poly->numverts = lnumverts;
   1471 
   1472 	for (i=0 ; i<lnumverts ; i++)
   1473 	{
   1474 		lindex = currentmodel->surfedges[fa->firstedge + i];
   1475 
   1476 		if (lindex > 0)
   1477 		{
   1478 			r_pedge = &pedges[lindex];
   1479 			vec = currentmodel->vertexes[r_pedge->v[0]].position;
   1480 		}
   1481 		else
   1482 		{
   1483 			r_pedge = &pedges[-lindex];
   1484 			vec = currentmodel->vertexes[r_pedge->v[1]].position;
   1485 		}
   1486 		s = DotProduct (vec, fa->texinfo->vecs[0]) + fa->texinfo->vecs[0][3];
   1487 		s /= fa->texinfo->image->width;
   1488 
   1489 		t = DotProduct (vec, fa->texinfo->vecs[1]) + fa->texinfo->vecs[1][3];
   1490 		t /= fa->texinfo->image->height;
   1491 
   1492 		VectorAdd (total, vec, total);
   1493 		VectorCopy (vec, poly->verts[i]);
   1494 		poly->verts[i][3] = s;
   1495 		poly->verts[i][4] = t;
   1496 
   1497 		//
   1498 		// lightmap texture coordinates
   1499 		//
   1500 		s = DotProduct (vec, fa->texinfo->vecs[0]) + fa->texinfo->vecs[0][3];
   1501 		s -= fa->texturemins[0];
   1502 		s += fa->light_s*16;
   1503 		s += 8;
   1504 		s /= BLOCK_WIDTH*16; //fa->texinfo->texture->width;
   1505 
   1506 		t = DotProduct (vec, fa->texinfo->vecs[1]) + fa->texinfo->vecs[1][3];
   1507 		t -= fa->texturemins[1];
   1508 		t += fa->light_t*16;
   1509 		t += 8;
   1510 		t /= BLOCK_HEIGHT*16; //fa->texinfo->texture->height;
   1511 
   1512 		poly->verts[i][5] = s;
   1513 		poly->verts[i][6] = t;
   1514 	}
   1515 
   1516 	poly->numverts = lnumverts;
   1517 
   1518 }
   1519 
   1520 /*
   1521 ========================
   1522 GL_CreateSurfaceLightmap
   1523 ========================
   1524 */
   1525 void GL_CreateSurfaceLightmap (msurface_t *surf)
   1526 {
   1527 	int		smax, tmax;
   1528 	byte	*base;
   1529 
   1530 	if (surf->flags & (SURF_DRAWSKY|SURF_DRAWTURB))
   1531 		return;
   1532 
   1533 	smax = (surf->extents[0]>>4)+1;
   1534 	tmax = (surf->extents[1]>>4)+1;
   1535 
   1536 	if ( !LM_AllocBlock( smax, tmax, &surf->light_s, &surf->light_t ) )
   1537 	{
   1538 		LM_UploadBlock( false );
   1539 		LM_InitBlock();
   1540 		if ( !LM_AllocBlock( smax, tmax, &surf->light_s, &surf->light_t ) )
   1541 		{
   1542 			ri.Sys_Error( ERR_FATAL, "Consecutive calls to LM_AllocBlock(%d,%d) failed\n", smax, tmax );
   1543 		}
   1544 	}
   1545 
   1546 	surf->lightmaptexturenum = gl_lms.current_lightmap_texture;
   1547 
   1548 	base = gl_lms.lightmap_buffer;
   1549 	base += (surf->light_t * BLOCK_WIDTH + surf->light_s) * LIGHTMAP_BYTES;
   1550 
   1551 	R_SetCacheState( surf );
   1552 	R_BuildLightMap (surf, base, BLOCK_WIDTH*LIGHTMAP_BYTES);
   1553 }
   1554 
   1555 
   1556 /*
   1557 ==================
   1558 GL_BeginBuildingLightmaps
   1559 
   1560 ==================
   1561 */
   1562 void GL_BeginBuildingLightmaps (model_t *m)
   1563 {
   1564 	static lightstyle_t	lightstyles[MAX_LIGHTSTYLES];
   1565 	int				i;
   1566 	unsigned		dummy[128*128];
   1567 
   1568 	memset( gl_lms.allocated, 0, sizeof(gl_lms.allocated) );
   1569 
   1570 	r_framecount = 1;		// no dlightcache
   1571 
   1572 	GL_EnableMultitexture( true );
   1573 	GL_SelectTexture( GL_TEXTURE1_SGIS );
   1574 
   1575 	/*
   1576 	** setup the base lightstyles so the lightmaps won't have to be regenerated
   1577 	** the first time they're seen
   1578 	*/
   1579 	for (i=0 ; i<MAX_LIGHTSTYLES ; i++)
   1580 	{
   1581 		lightstyles[i].rgb[0] = 1;
   1582 		lightstyles[i].rgb[1] = 1;
   1583 		lightstyles[i].rgb[2] = 1;
   1584 		lightstyles[i].white = 3;
   1585 	}
   1586 	r_newrefdef.lightstyles = lightstyles;
   1587 
   1588 	if (!gl_state.lightmap_textures)
   1589 	{
   1590 		gl_state.lightmap_textures	= TEXNUM_LIGHTMAPS;
   1591 //		gl_state.lightmap_textures	= gl_state.texture_extension_number;
   1592 //		gl_state.texture_extension_number = gl_state.lightmap_textures + MAX_LIGHTMAPS;
   1593 	}
   1594 
   1595 	gl_lms.current_lightmap_texture = 1;
   1596 
   1597 	/*
   1598 	** if mono lightmaps are enabled and we want to use alpha
   1599 	** blending (a,1-a) then we're likely running on a 3DLabs
   1600 	** Permedia2.  In a perfect world we'd use a GL_ALPHA lightmap
   1601 	** in order to conserve space and maximize bandwidth, however 
   1602 	** this isn't a perfect world.
   1603 	**
   1604 	** So we have to use alpha lightmaps, but stored in GL_RGBA format,
   1605 	** which means we only get 1/16th the color resolution we should when
   1606 	** using alpha lightmaps.  If we find another board that supports
   1607 	** only alpha lightmaps but that can at least support the GL_ALPHA
   1608 	** format then we should change this code to use real alpha maps.
   1609 	*/
   1610 	if ( toupper( gl_monolightmap->string[0] ) == 'A' )
   1611 	{
   1612 		gl_lms.internal_format = gl_tex_alpha_format;
   1613 	}
   1614 	/*
   1615 	** try to do hacked colored lighting with a blended texture
   1616 	*/
   1617 	else if ( toupper( gl_monolightmap->string[0] ) == 'C' )
   1618 	{
   1619 		gl_lms.internal_format = gl_tex_alpha_format;
   1620 	}
   1621 	else if ( toupper( gl_monolightmap->string[0] ) == 'I' )
   1622 	{
   1623 		gl_lms.internal_format = GL_INTENSITY8;
   1624 	}
   1625 	else if ( toupper( gl_monolightmap->string[0] ) == 'L' ) 
   1626 	{
   1627 		gl_lms.internal_format = GL_LUMINANCE8;
   1628 	}
   1629 	else
   1630 	{
   1631 		gl_lms.internal_format = gl_tex_solid_format;
   1632 	}
   1633 
   1634 	/*
   1635 	** initialize the dynamic lightmap texture
   1636 	*/
   1637 	GL_Bind( gl_state.lightmap_textures + 0 );
   1638 	qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
   1639 	qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
   1640 	qglTexImage2D( GL_TEXTURE_2D, 
   1641 				   0, 
   1642 				   gl_lms.internal_format,
   1643 				   BLOCK_WIDTH, BLOCK_HEIGHT, 
   1644 				   0, 
   1645 				   GL_LIGHTMAP_FORMAT, 
   1646 				   GL_UNSIGNED_BYTE, 
   1647 				   dummy );
   1648 }
   1649 
   1650 /*
   1651 =======================
   1652 GL_EndBuildingLightmaps
   1653 =======================
   1654 */
   1655 void GL_EndBuildingLightmaps (void)
   1656 {
   1657 	LM_UploadBlock( false );
   1658 	GL_EnableMultitexture( false );
   1659 }
   1660