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