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