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