1 /*
2 	gl_rsurf.c
3 
4 	surface-related refresh code
5 
6 	Copyright (C) 1996-1997  Id Software, Inc.
7 	Copyright (C) 2000       Joseph Carter <knghtbrd@debian.org>
8 
9 	This program is free software; you can redistribute it and/or
10 	modify it under the terms of the GNU General Public License
11 	as published by the Free Software Foundation; either version 2
12 	of the License, or (at your option) any later version.
13 
14 	This program is distributed in the hope that it will be useful,
15 	but WITHOUT ANY WARRANTY; without even the implied warranty of
16 	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 
18 	See the GNU General Public License for more details.
19 
20 	You should have received a copy of the GNU General Public License
21 	along with this program; if not, write to:
22 
23 		Free Software Foundation, Inc.
24 		59 Temple Place - Suite 330
25 		Boston, MA  02111-1307, USA
26 
27 */
28 #ifdef HAVE_CONFIG_H
29 # include "config.h"
30 #endif
31 
32 #define NH_DEFINE
33 #include "namehack.h"
34 
35 #ifdef HAVE_STRING_H
36 # include <string.h>
37 #endif
38 #ifdef HAVE_STRINGS_H
39 # include <strings.h>
40 #endif
41 
42 #include "qfalloca.h"
43 
44 #include <math.h>
45 #include <stdio.h>
46 
47 #include "QF/cvar.h"
48 #include "QF/render.h"
49 #include "QF/sys.h"
50 #include "QF/GL/defines.h"
51 #include "QF/GL/funcs.h"
52 #include "QF/GL/qf_lightmap.h"
53 #include "QF/GL/qf_rmain.h"
54 #include "QF/GL/qf_rsurf.h"
55 #include "QF/GL/qf_sky.h"
56 #include "QF/GL/qf_textures.h"
57 #include "QF/GL/qf_vid.h"
58 
59 #include "compat.h"
60 #include "r_internal.h"
61 
62 static instsurf_t  *waterchain = NULL;
63 static instsurf_t **waterchain_tail = &waterchain;
64 static instsurf_t  *sky_chain;
65 static instsurf_t **sky_chain_tail;
66 
67 #define CHAIN_SURF_F2B(surf,chain)							\
68 	do { 													\
69 		instsurf_t *inst = (surf)->instsurf;				\
70 		if (__builtin_expect(!inst, 1))						\
71 			(surf)->tinst = inst = get_instsurf ();			\
72 		inst->surface = (surf);								\
73 		*(chain##_tail) = inst;								\
74 		(chain##_tail) = &inst->tex_chain;					\
75 		*(chain##_tail) = 0;								\
76 	} while (0)
77 
78 #define CHAIN_SURF_B2F(surf,chain) 							\
79 	do { 													\
80 		instsurf_t *inst = (surf)->instsurf;				\
81 		if (__builtin_expect(!inst, 1))						\
82 			(surf)->tinst = inst = get_instsurf ();			\
83 		inst->surface = (surf);								\
84 		inst->tex_chain = (chain);							\
85 		(chain) = inst;										\
86 	} while (0)
87 
88 static texture_t **r_texture_chains;
89 static int  r_num_texture_chains;
90 static int  max_texture_chains;
91 
92 static instsurf_t *static_chains;
93 static instsurf_t *free_instsurfs;
94 static instsurf_t *alloced_instsurfs;
95 static instsurf_t **alloced_instsurfs_tail = &alloced_instsurfs;
96 #define NUM_INSTSURFS (64 * 6)	// most brush models are simple boxes.
97 
98 static inline instsurf_t *
get_instsurf(void)99 get_instsurf (void)
100 {
101 	instsurf_t *instsurf;
102 
103 	if (!free_instsurfs) {
104 		int         i;
105 
106 		free_instsurfs = calloc (NUM_INSTSURFS, sizeof (instsurf_t));
107 		for (i = 0; i < NUM_INSTSURFS - 1; i++)
108 			free_instsurfs[i]._next = &free_instsurfs[i + 1];
109 	}
110 	instsurf = free_instsurfs;
111 	free_instsurfs = instsurf->_next;
112 	instsurf->_next = 0;
113 	//build the chain of allocated instance surfaces so they can all be freed
114 	//in one go
115 	*alloced_instsurfs_tail = instsurf;
116 	alloced_instsurfs_tail = &instsurf->_next;
117 	return instsurf;
118 }
119 
120 static inline void
release_instsurfs(void)121 release_instsurfs (void)
122 {
123 	if (alloced_instsurfs) {
124 		*alloced_instsurfs_tail = free_instsurfs;
125 		free_instsurfs = alloced_instsurfs;
126 		alloced_instsurfs = 0;
127 		alloced_instsurfs_tail = &alloced_instsurfs;
128 	}
129 }
130 
131 void
gl_R_AddTexture(texture_t * tex)132 gl_R_AddTexture (texture_t *tex)
133 {
134 	int         i;
135 	if (r_num_texture_chains == max_texture_chains) {
136 		max_texture_chains += 64;
137 		r_texture_chains = realloc (r_texture_chains,
138 								  max_texture_chains * sizeof (texture_t *));
139 		for (i = r_num_texture_chains; i < max_texture_chains; i++)
140 			r_texture_chains[i] = 0;
141 	}
142 	r_texture_chains[r_num_texture_chains++] = tex;
143 	tex->tex_chain = NULL;
144 	tex->tex_chain_tail = &tex->tex_chain;
145 }
146 
147 void
gl_R_InitSurfaceChains(model_t * model)148 gl_R_InitSurfaceChains (model_t *model)
149 {
150 	int         i;
151 
152 	if (static_chains)
153 		free (static_chains);
154 	static_chains = calloc (model->nummodelsurfaces, sizeof (instsurf_t));
155 	for (i = 0; i < model->nummodelsurfaces; i++)
156 		model->surfaces[i].instsurf = static_chains + i;
157 
158 	release_instsurfs ();
159 }
160 
161 void
gl_R_ClearTextures(void)162 gl_R_ClearTextures (void)
163 {
164 	r_num_texture_chains = 0;
165 }
166 
167 
168 // BRUSH MODELS ===============================================================
169 
170 static void
R_RenderFullbrights(void)171 R_RenderFullbrights (void)
172 {
173 	float      *v;
174 	int         i, j;
175 	glpoly_t   *p;
176 	instsurf_t *sc;
177 	texture_t  *tex;
178 
179 	for (i = 0; i < r_num_texture_chains; i++) {
180 		if (!(tex = r_texture_chains[i]) || !tex->gl_fb_texturenum)
181 			continue;
182 		qfglBindTexture (GL_TEXTURE_2D, tex->gl_fb_texturenum);
183 		for (sc = tex->tex_chain; sc; sc = sc->tex_chain) {
184 			if (sc->transform) {
185 				qfglPushMatrix ();
186 				qfglLoadMatrixf (sc->transform);
187 			}
188 			if (sc->color)
189 				qfglColor4fv (sc->color);
190 			for (p = sc->surface->polys; p; p = p->next) {
191 				qfglBegin (GL_POLYGON);
192 				for (j = 0, v = p->verts[0]; j < p->numverts;
193 					 j++, v += VERTEXSIZE)
194 				{
195 					qfglTexCoord2fv (&v[3]);
196 					qfglVertex3fv (v);
197 				}
198 				qfglEnd ();
199 			}
200 			if (sc->transform)
201 				qfglPopMatrix ();
202 			if (sc->color)
203 				qfglColor3ubv (color_white);
204 		}
205 	}
206 }
207 
208 static inline void
R_RenderBrushPoly_3(msurface_t * fa)209 R_RenderBrushPoly_3 (msurface_t *fa)
210 {
211 	float      *v;
212 	int			i;
213 
214 	gl_c_brush_polys++;
215 
216 	qfglBegin (GL_POLYGON);
217 	v = fa->polys->verts[0];
218 
219 	for (i = 0; i < fa->polys->numverts; i++, v += VERTEXSIZE) {
220 		qglMultiTexCoord2fv (gl_mtex_enum + 0, &v[3]);
221 		qglMultiTexCoord2fv (gl_mtex_enum + 1, &v[5]);
222 		qglMultiTexCoord2fv (gl_mtex_enum + 2, &v[3]);
223 		qfglVertex3fv (v);
224 	}
225 
226 	qfglEnd ();
227 }
228 
229 static inline void
R_RenderBrushPoly_2(msurface_t * fa)230 R_RenderBrushPoly_2 (msurface_t *fa)
231 {
232 	float      *v;
233 	int			i;
234 
235 	gl_c_brush_polys++;
236 
237 	qfglBegin (GL_POLYGON);
238 	v = fa->polys->verts[0];
239 
240 	for (i = 0; i < fa->polys->numverts; i++, v += VERTEXSIZE) {
241 		qglMultiTexCoord2fv (gl_mtex_enum + 0, &v[3]);
242 		qglMultiTexCoord2fv (gl_mtex_enum + 1, &v[5]);
243 		qfglVertex3fv (v);
244 	}
245 
246 	qfglEnd ();
247 }
248 
249 static inline void
R_RenderBrushPoly_1(msurface_t * fa)250 R_RenderBrushPoly_1 (msurface_t *fa)
251 {
252 	float      *v;
253 	int			i;
254 
255 	gl_c_brush_polys++;
256 
257 	qfglBegin (GL_POLYGON);
258 	v = fa->polys->verts[0];
259 
260 	for (i = 0; i < fa->polys->numverts; i++, v += VERTEXSIZE) {
261 		qfglTexCoord2fv (&v[3]);
262 		qfglVertex3fv (v);
263 	}
264 
265 	qfglEnd ();
266 }
267 
268 static inline void
R_AddToLightmapChain(msurface_t * fa)269 R_AddToLightmapChain (msurface_t *fa)
270 {
271 	int		maps, smax, tmax;
272 	glRect_t 	*theRect;
273 	instsurf_t *sc;
274 
275 	// add the poly to the proper lightmap chain
276 	if (!(sc = fa->instsurf))
277 		sc = fa->tinst;
278 
279 	sc->lm_chain = gl_lightmap_polys[fa->lightmaptexturenum];
280 	gl_lightmap_polys[fa->lightmaptexturenum] = sc;
281 
282 	// check for lightmap modification
283 	for (maps = 0; maps < MAXLIGHTMAPS && fa->styles[maps] != 255; maps++)
284 		if (d_lightstylevalue[fa->styles[maps]] != fa->cached_light[maps])
285 			goto dynamic;
286 
287 	if ((fa->dlightframe == r_framecount) || fa->cached_dlight) {
288 	  dynamic:
289 		if (r_dynamic->int_val) {
290 			gl_lightmap_modified[fa->lightmaptexturenum] = true;
291 			theRect = &gl_lightmap_rectchange[fa->lightmaptexturenum];
292 			if (fa->light_t < theRect->t) {
293 				if (theRect->h)
294 					theRect->h += theRect->t - fa->light_t;
295 				theRect->t = fa->light_t;
296 			}
297 			if (fa->light_s < theRect->l) {
298 				if (theRect->w)
299 					theRect->w += theRect->l - fa->light_s;
300 				theRect->l = fa->light_s;
301 			}
302 			smax = (fa->extents[0] >> 4) + 1;
303 			tmax = (fa->extents[1] >> 4) + 1;
304 			if ((theRect->w + theRect->l) < (fa->light_s + smax))
305 				theRect->w = (fa->light_s - theRect->l) + smax;
306 			if ((theRect->h + theRect->t) < (fa->light_t + tmax))
307 				theRect->h = (fa->light_t - theRect->t) + tmax;
308 			gl_R_BuildLightMap (fa);
309 		}
310 	}
311 }
312 
313 void
gl_R_DrawWaterSurfaces(void)314 gl_R_DrawWaterSurfaces (void)
315 {
316 	int         i;
317 	instsurf_t *s;
318 	msurface_t *fa;
319 	float       wateralpha = max (vr_data.min_wateralpha, r_wateralpha->value);
320 
321 	if (!waterchain)
322 		return;
323 
324 	// go back to the world matrix
325 	qfglLoadMatrixf (gl_r_world_matrix);
326 
327 	if (wateralpha < 1.0) {
328 		qfglDepthMask (GL_FALSE);
329 		color_white[3] = wateralpha * 255;
330 		qfglColor4ubv (color_white);
331 	}
332 
333 	i = -1;
334 	for (s = waterchain; s; s = s->tex_chain) {
335 		fa = s->surface;
336 		if (s->transform)
337 			qfglLoadMatrixf (s->transform);
338 		else
339 			qfglLoadMatrixf (gl_r_world_matrix);
340 		if (i != fa->texinfo->texture->gl_texturenum) {
341 			i = fa->texinfo->texture->gl_texturenum;
342 			qfglBindTexture (GL_TEXTURE_2D, i);
343 		}
344 		GL_EmitWaterPolys (fa);
345 	}
346 	qfglLoadMatrixf (gl_r_world_matrix);
347 
348 	waterchain = NULL;
349 	waterchain_tail = &waterchain;
350 
351 	if (wateralpha < 1.0) {
352 		qfglDepthMask (GL_TRUE);
353 		qfglColor3ubv (color_white);
354 	}
355 }
356 
357 static void
DrawTextureChains(int disable_blend,int do_bind)358 DrawTextureChains (int disable_blend, int do_bind)
359 {
360 	int			i;
361 	instsurf_t *s;
362 	msurface_t *fa;
363 	texture_t  *tex;
364 
365 	if (gl_mtex_active_tmus >= 2) {
366 		// Lightmaps
367 		qglActiveTexture (gl_mtex_enum + 1);
368 		qfglEnable (GL_TEXTURE_2D);
369 
370 		// Base Texture
371 		qglActiveTexture (gl_mtex_enum + 0);
372 		qfglTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
373 
374 		for (i = 0; i < r_num_texture_chains; i++) {
375 			tex = r_texture_chains[i];
376 			if (!tex)
377 				continue;
378 			qfglBindTexture (GL_TEXTURE_2D, tex->gl_texturenum);
379 
380 			if (tex->gl_fb_texturenum && gl_mtex_fullbright) {
381 				qglActiveTexture (gl_mtex_enum + 2);
382 				qfglEnable (GL_TEXTURE_2D);
383 				qfglBindTexture (GL_TEXTURE_2D, tex->gl_fb_texturenum);
384 
385 				qglActiveTexture (gl_mtex_enum + 1);
386 				for (s = tex->tex_chain; s; s = s->tex_chain) {
387 					fa = s->surface;
388 					if (s->transform) {
389 						qfglPushMatrix ();
390 						qfglLoadMatrixf (s->transform);
391 					}
392 					if (s->color && do_bind)
393 						qfglColor4fv (s->color);
394 					qfglBindTexture (GL_TEXTURE_2D, gl_lightmap_textures +
395 									 fa->lightmaptexturenum);
396 
397 					R_RenderBrushPoly_3 (fa);
398 
399 					if (s->transform)
400 						qfglPopMatrix ();
401 					if (s->color && do_bind)
402 						qfglColor3ubv (color_white);
403 				}
404 
405 				qglActiveTexture (gl_mtex_enum + 2);
406 				qfglDisable (GL_TEXTURE_2D);
407 
408 				qglActiveTexture (gl_mtex_enum + 0);
409 			} else {
410 				qglActiveTexture (gl_mtex_enum + 1);
411 				for (s = tex->tex_chain; s; s = s->tex_chain) {
412 					fa = s->surface;
413 					qfglBindTexture (GL_TEXTURE_2D, gl_lightmap_textures +
414 									 fa->lightmaptexturenum);
415 
416 					if (s->transform) {
417 						qfglPushMatrix ();
418 						qfglLoadMatrixf (s->transform);
419 					}
420 					if (s->color && do_bind)
421 						qfglColor4fv (s->color);
422 					R_RenderBrushPoly_2 (fa);
423 
424 					if (s->transform)
425 						qfglPopMatrix ();
426 					if (s->color && do_bind)
427 						qfglColor3ubv (color_white);
428 				}
429 
430 				qglActiveTexture (gl_mtex_enum + 0);
431 			}
432 		}
433 		// Turn off lightmaps for other entities
434 		qglActiveTexture (gl_mtex_enum + 1);
435 		qfglDisable (GL_TEXTURE_2D);
436 
437 		// Reset mode for default TMU
438 		qglActiveTexture (gl_mtex_enum + 0);
439 		qfglTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
440 	} else {
441 		if (disable_blend)
442 			qfglDisable (GL_BLEND);
443 		for (i = 0; i < r_num_texture_chains; i++) {
444 			tex = r_texture_chains[i];
445 			if (!tex)
446 				continue;
447 			if (do_bind)
448 				qfglBindTexture (GL_TEXTURE_2D, tex->gl_texturenum);
449 
450 			for (s = tex->tex_chain; s; s = s->tex_chain) {
451 				if (s->transform) {
452 					qfglPushMatrix ();
453 					qfglLoadMatrixf (s->transform);
454 				}
455 				R_RenderBrushPoly_1 (s->surface);
456 
457 				if (s->transform)
458 					qfglPopMatrix ();
459 				if (s->color && do_bind)
460 					qfglColor3ubv (color_white);
461 			}
462 		}
463 		if (disable_blend)
464 			qfglEnable (GL_BLEND);
465 	}
466 }
467 
468 static void
clear_texture_chains(void)469 clear_texture_chains (void)
470 {
471 	int			i;
472 	texture_t  *tex;
473 
474 	for (i = 0; i < r_num_texture_chains; i++) {
475 		tex = r_texture_chains[i];
476 		if (!tex)
477 			continue;
478 		tex->tex_chain = NULL;
479 		tex->tex_chain_tail = &tex->tex_chain;
480 	}
481 	tex = r_notexture_mip;
482 	tex->tex_chain = NULL;
483 	tex->tex_chain_tail = &tex->tex_chain;
484 	release_instsurfs ();
485 
486 	memset (gl_lightmap_polys, 0, sizeof (gl_lightmap_polys));
487 }
488 
489 static inline void
chain_surface(msurface_t * surf,vec_t * transform,float * color)490 chain_surface (msurface_t *surf, vec_t *transform, float *color)
491 {
492 	instsurf_t *sc;
493 
494 	if (surf->flags & SURF_DRAWTURB) {
495 		CHAIN_SURF_B2F (surf, waterchain);
496 	} else if (surf->flags & SURF_DRAWSKY) {
497 		CHAIN_SURF_F2B (surf, sky_chain);
498 	} else {
499 		texture_t  *tex;
500 
501 		if (!surf->texinfo->texture->anim_total)
502 			tex = surf->texinfo->texture;
503 		else
504 			tex = R_TextureAnimation (surf);
505 		CHAIN_SURF_F2B (surf, tex->tex_chain);
506 
507 		R_AddToLightmapChain (surf);
508 	}
509 	if (!(sc = surf->instsurf))
510 		sc = surf->tinst;
511 	sc->transform = transform;
512 	sc->color = color;
513 }
514 
515 void
gl_R_DrawBrushModel(entity_t * e)516 gl_R_DrawBrushModel (entity_t *e)
517 {
518 	float       dot, radius;
519 	int         i;
520 	unsigned int k;
521 	model_t    *model;
522 	plane_t    *pplane;
523 	msurface_t *psurf;
524 	qboolean    rotated;
525 	vec3_t      mins, maxs;
526 
527 	model = e->model;
528 
529 	if (e->transform[0] != 1 || e->transform[5] != 1 || e->transform[10] != 1) {
530 		rotated = true;
531 		radius = model->radius;
532 #if 0 //QSG FIXME
533 		if (e->scale != 1.0)
534 			radius *= e->scale;
535 #endif
536 		if (R_CullSphere (e->origin, radius))
537 			return;
538 	} else {
539 		rotated = false;
540 		VectorAdd (e->origin, model->mins, mins);
541 		VectorAdd (e->origin, model->maxs, maxs);
542 #if 0 // QSG FIXME
543 		if (e->scale != 1.0) {
544 			VectorScale (mins, e->scale, mins);
545 			VectorScale (maxs, e->scale, maxs);
546 		}
547 #endif
548 		if (R_CullBox (mins, maxs))
549 			return;
550 	}
551 
552 	VectorSubtract (r_refdef.vieworg, e->origin, modelorg);
553 	if (rotated) {
554 		vec3_t      temp;
555 
556 		VectorCopy (modelorg, temp);
557 		modelorg[0] = DotProduct (temp, e->transform + 0);
558 		modelorg[1] = DotProduct (temp, e->transform + 4);
559 		modelorg[2] = DotProduct (temp, e->transform + 8);
560 	}
561 
562 	// calculate dynamic lighting for bmodel if it's not an instanced model
563 	if (model->firstmodelsurface != 0 && r_dlight_lightmap->int_val) {
564 		vec3_t      lightorigin;
565 
566 		for (k = 0; k < r_maxdlights; k++) {
567 			if ((r_dlights[k].die < vr_data.realtime)
568 				 || (!r_dlights[k].radius))
569 				continue;
570 
571 			VectorSubtract (r_dlights[k].origin, e->origin, lightorigin);
572 			R_RecursiveMarkLights (lightorigin, &r_dlights[k], 1 << k,
573 							model->nodes + model->hulls[0].firstclipnode);
574 		}
575 	}
576 
577 	qfglPushMatrix ();
578 	gl_R_RotateForEntity (e);
579 	qfglGetFloatv (GL_MODELVIEW_MATRIX, e->full_transform);
580 	qfglPopMatrix ();
581 
582 	psurf = &model->surfaces[model->firstmodelsurface];
583 
584 	// draw texture
585 	for (i = 0; i < model->nummodelsurfaces; i++, psurf++) {
586 		// find which side of the node we are on
587 		pplane = psurf->plane;
588 
589 		dot = DotProduct (modelorg, pplane->normal) - pplane->dist;
590 
591 		// draw the polygon
592 		if (((psurf->flags & SURF_PLANEBACK) && (dot < -BACKFACE_EPSILON)) ||
593 			(!(psurf->flags & SURF_PLANEBACK) && (dot > BACKFACE_EPSILON))) {
594 			chain_surface (psurf, e->full_transform, e->colormod);
595 		}
596 	}
597 }
598 
599 // WORLD MODEL ================================================================
600 
601 static inline void
visit_leaf(mleaf_t * leaf)602 visit_leaf (mleaf_t *leaf)
603 {
604 	// deal with model fragments in this leaf
605 	if (leaf->efrags)
606 		R_StoreEfrags (leaf->efrags);
607 }
608 
609 static inline int
get_side(mnode_t * node)610 get_side (mnode_t *node)
611 {
612 	// find which side of the node we are on
613 	plane_t    *plane = node->plane;
614 
615 	if (plane->type < 3)
616 		return (modelorg[plane->type] - plane->dist) < 0;
617 	return (DotProduct (modelorg, plane->normal) - plane->dist) < 0;
618 }
619 
620 static inline void
visit_node(mnode_t * node,int side)621 visit_node (mnode_t *node, int side)
622 {
623 	int         c;
624 	msurface_t *surf;
625 
626 	// sneaky hack for side = side ? SURF_PLANEBACK : 0;
627 	side = (~side + 1) & SURF_PLANEBACK;
628 	// draw stuff
629 	if ((c = node->numsurfaces)) {
630 		surf = r_worldentity.model->surfaces + node->firstsurface;
631 		for (; c; c--, surf++) {
632 			if (surf->visframe != r_visframecount)
633 				continue;
634 
635 			// side is either 0 or SURF_PLANEBACK
636 			if (side ^ (surf->flags & SURF_PLANEBACK))
637 				continue;				// wrong side
638 
639 			chain_surface (surf, 0, 0);
640 		}
641 	}
642 }
643 
644 static inline int
test_node(mnode_t * node)645 test_node (mnode_t *node)
646 {
647 	if (node->contents < 0)
648 		return 0;
649 	if (node->visframe != r_visframecount)
650 		return 0;
651 	if (R_CullBox (node->minmaxs, node->minmaxs + 3))
652 		return 0;
653 	return 1;
654 }
655 
656 static void
R_VisitWorldNodes(model_t * model)657 R_VisitWorldNodes (model_t *model)
658 {
659 	typedef struct {
660 		mnode_t    *node;
661 		int         side;
662 	} rstack_t;
663 	rstack_t   *node_ptr;
664 	rstack_t   *node_stack;
665 	mnode_t    *node;
666 	mnode_t    *front;
667 	int         side;
668 
669 	node = model->nodes;
670 	// +2 for paranoia
671 	node_stack = alloca ((model->depth + 2) * sizeof (rstack_t));
672 	node_ptr = node_stack;
673 
674 	while (1) {
675 		while (test_node (node)) {
676 			side = get_side (node);
677 			front = node->children[side];
678 			if (test_node (front)) {
679 				node_ptr->node = node;
680 				node_ptr->side = side;
681 				node_ptr++;
682 				node = front;
683 				continue;
684 			}
685 			if (front->contents < 0 && front->contents != CONTENTS_SOLID)
686 				visit_leaf ((mleaf_t *) front);
687 			visit_node (node, side);
688 			node = node->children[!side];
689 		}
690 		if (node->contents < 0 && node->contents != CONTENTS_SOLID)
691 			visit_leaf ((mleaf_t *) node);
692 		if (node_ptr != node_stack) {
693 			node_ptr--;
694 			node = node_ptr->node;
695 			side = node_ptr->side;
696 			visit_node (node, side);
697 			node = node->children[!side];
698 			continue;
699 		}
700 		break;
701 	}
702 	if (node->contents < 0 && node->contents != CONTENTS_SOLID)
703 		visit_leaf ((mleaf_t *) node);
704 }
705 
706 void
gl_R_DrawWorld(void)707 gl_R_DrawWorld (void)
708 {
709 	entity_t    worldent;
710 
711 	memset (&worldent, 0, sizeof (worldent));
712 	worldent.model = r_worldentity.model;
713 
714 	VectorCopy (r_refdef.vieworg, modelorg);
715 
716 	currententity = &worldent;
717 
718 	sky_chain = 0;
719 	sky_chain_tail = &sky_chain;
720 	if (!gl_sky_clip->int_val) {
721 		gl_R_DrawSky ();
722 	}
723 
724 	R_VisitWorldNodes (r_worldentity.model);
725 	if (r_drawentities->int_val) {
726 		entity_t   *ent;
727 		for (ent = r_ent_queue; ent; ent = ent->next) {
728 			if (ent->model->type != mod_brush)
729 				continue;
730 			currententity = ent;
731 
732 			gl_R_DrawBrushModel (currententity);
733 		}
734 	}
735 
736 	gl_R_CalcLightmaps ();
737 
738 	gl_R_DrawSkyChain (sky_chain);
739 
740 	if (!gl_Fog_GetDensity ()
741 		|| (gl_fb_bmodels->int_val && gl_mtex_fullbright)
742 		|| gl_mtex_active_tmus > 1) {
743 		// we have enough active TMUs to render everything in one go
744 		// or we're not doing fog
745 		DrawTextureChains (1, 1);
746 
747 		if (gl_mtex_active_tmus <= 1)
748 			gl_R_BlendLightmaps ();
749 
750 		if (gl_fb_bmodels->int_val && !gl_mtex_fullbright)
751 			R_RenderFullbrights ();
752 	} else {
753 		if (gl_mtex_active_tmus > 1) {
754 			// textures and lightmaps in one pass
755 			// black fog
756 			// no blending
757 			gl_Fog_StartAdditive ();
758 			DrawTextureChains (1, 1);
759 			// buf = fTL + (1-f)0
760 			//     = fTL
761 		} else {
762 			// texture pass + lightmap pass
763 			// no fog
764 			// no blending
765 			gl_Fog_DisableGFog ();
766 			DrawTextureChains (1, 1);
767 			// buf = T
768 			// black fog
769 			// blend: buf = zero, src (non-overbright)
770 			// FIXME overbright broken?
771 			gl_Fog_EnableGFog ();
772 			gl_Fog_StartAdditive ();
773 			gl_R_BlendLightmaps ();	//leaves blending as As, 1-As
774 			// buf = I*0 + buf*I
775 			//     = T*C
776 			//     = T(fL + (1-f)0)
777 			//     = fTL
778 		}
779 		// fullbright pass
780 		// fog is still black
781 		R_RenderFullbrights ();
782 		// buf = aI + (1-a)buf
783 		//     = aC + (1-a)fTL
784 		//     = a(fG + (1-f)0) + (1-a)fTL
785 		//     = afG + (1-a)fTL
786 		//     = f((1-a)TL + aG)
787 		gl_Fog_StopAdditive ();		// use fog color
788 		qfglDepthMask (GL_FALSE);	// don't write Z
789 		qfglBlendFunc (GL_ONE, GL_ONE);
790 		// draw black polys
791 		qfglColor4f (0, 0, 0, 1);
792 		DrawTextureChains (0, 0);
793 		// buf = I + buf
794 		//     = C + f((1-a)TL + aG)
795 		//     = (f0 + (1-f)F) + f((1-a)TL + aG)
796 		//     = (1-f)F + f((1-a)TL + aG)
797 		//     = f((1-a)TL + aG) + (1-f)F
798 		// restore state
799 		qfglColor4ubv (color_white);
800 		qfglBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
801 		qfglDepthMask (GL_TRUE);
802 	}
803 
804 	clear_texture_chains ();
805 }
806 
807 model_t    *gl_currentmodel;
808 
809 void
GL_BuildSurfaceDisplayList(msurface_t * fa)810 GL_BuildSurfaceDisplayList (msurface_t *fa)
811 {
812 	float       s, t;
813 	float      *vec;
814 	int         lindex, lnumverts, i;
815 	glpoly_t   *poly;
816 	medge_t    *pedges, *r_pedge;
817 
818 	// reconstruct the polygon
819 	pedges = gl_currentmodel->edges;
820 	lnumverts = fa->numedges;
821 
822 	// draw texture
823 	poly = Hunk_Alloc (sizeof (glpoly_t) + (lnumverts - 4) *
824 					   VERTEXSIZE * sizeof (float));
825 	poly->next = fa->polys;
826 	poly->flags = fa->flags;
827 	fa->polys = poly;
828 	poly->numverts = lnumverts;
829 
830 	for (i = 0; i < lnumverts; i++) {
831 		lindex = gl_currentmodel->surfedges[fa->firstedge + i];
832 
833 		if (lindex > 0) {
834 			r_pedge = &pedges[lindex];
835 			vec = r_pcurrentvertbase[r_pedge->v[0]].position;
836 		} else {
837 			r_pedge = &pedges[-lindex];
838 			vec = r_pcurrentvertbase[r_pedge->v[1]].position;
839 		}
840 		s = DotProduct (vec, fa->texinfo->vecs[0]) + fa->texinfo->vecs[0][3];
841 		s /= fa->texinfo->texture->width;
842 
843 		t = DotProduct (vec, fa->texinfo->vecs[1]) + fa->texinfo->vecs[1][3];
844 		t /= fa->texinfo->texture->height;
845 
846 		VectorCopy (vec, poly->verts[i]);
847 		poly->verts[i][3] = s;
848 		poly->verts[i][4] = t;
849 
850 		// lightmap texture coordinates
851 		s = DotProduct (vec, fa->texinfo->vecs[0]) + fa->texinfo->vecs[0][3];
852 		s -= fa->texturemins[0];
853 		s += fa->light_s * 16;
854 		s += 8;
855 		s /= BLOCK_WIDTH * 16;			// fa->texinfo->texture->width;
856 
857 		t = DotProduct (vec, fa->texinfo->vecs[1]) + fa->texinfo->vecs[1][3];
858 		t -= fa->texturemins[1];
859 		t += fa->light_t * 16;
860 		t += 8;
861 		t /= BLOCK_HEIGHT * 16;			// fa->texinfo->texture->height;
862 
863 		poly->verts[i][5] = s;
864 		poly->verts[i][6] = t;
865 	}
866 
867 	// remove co-linear points - Ed
868 	if (!gl_keeptjunctions->int_val && !(fa->flags & SURF_UNDERWATER)) {
869 		for (i = 0; i < lnumverts; ++i) {
870 			vec3_t      v1, v2;
871 			float      *prev, *this, *next;
872 
873 			prev = poly->verts[(i + lnumverts - 1) % lnumverts];
874 			this = poly->verts[i];
875 			next = poly->verts[(i + 1) % lnumverts];
876 
877 			VectorSubtract (this, prev, v1);
878 			VectorNormalize (v1);
879 			VectorSubtract (next, prev, v2);
880 			VectorNormalize (v2);
881 
882 			// skip co-linear points
883 #			define COLINEAR_EPSILON 0.001
884 			if ((fabs (v1[0] - v2[0]) <= COLINEAR_EPSILON) &&
885 				(fabs (v1[1] - v2[1]) <= COLINEAR_EPSILON) &&
886 				(fabs (v1[2] - v2[2]) <= COLINEAR_EPSILON)) {
887 				int         j;
888 
889 				for (j = i + 1; j < lnumverts; ++j) {
890 					int         k;
891 
892 					for (k = 0; k < VERTEXSIZE; ++k)
893 						poly->verts[j - 1][k] = poly->verts[j][k];
894 				}
895 				--lnumverts;
896 				// retry next vertex next time, which is now current vertex
897 				--i;
898 			}
899 		}
900 	}
901 	poly->numverts = lnumverts;
902 }
903