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