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