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