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 // gl_warp.c -- sky and water polygons
21
22 #include "quakedef.h"
23
24 extern model_t *loadmodel;
25
26 //int skytexturenum;
27
28 int solidskytexture;
29 int alphaskytexture;
30 float speedscale; // for top sky and bottom sky
31
32 msurface_t *warpface;
33
34 extern cvar_t gl_subdivide_size;
35
BoundPoly(int numverts,float * verts,vec3_t mins,vec3_t maxs)36 void BoundPoly (int numverts, float *verts, vec3_t mins, vec3_t maxs)
37 {
38 int i, j;
39 float *v;
40
41 mins[0] = mins[1] = mins[2] = 9999;
42 maxs[0] = maxs[1] = maxs[2] = -9999;
43 v = verts;
44 for (i=0 ; i<numverts ; i++)
45 for (j=0 ; j<3 ; j++, v++)
46 {
47 if (*v < mins[j])
48 mins[j] = *v;
49 if (*v > maxs[j])
50 maxs[j] = *v;
51 }
52 }
53
SubdividePolygon(int numverts,float * verts)54 void SubdividePolygon (int numverts, float *verts)
55 {
56 int i, j, k;
57 vec3_t mins, maxs;
58 float m;
59 float *v;
60 vec3_t front[64], back[64];
61 int f, b;
62 float dist[64];
63 float frac;
64 glpoly_t *poly;
65 float s, t;
66
67 if (numverts > 60)
68 Sys_Error ("numverts = %i", numverts);
69
70 BoundPoly (numverts, verts, mins, maxs);
71
72 for (i=0 ; i<3 ; i++)
73 {
74 m = (mins[i] + maxs[i]) * 0.5;
75 m = gl_subdivide_size.value * floor (m/gl_subdivide_size.value + 0.5);
76 if (maxs[i] - m < 8)
77 continue;
78 if (m - mins[i] < 8)
79 continue;
80
81 // cut it
82 v = verts + i;
83 for (j=0 ; j<numverts ; j++, v+= 3)
84 dist[j] = *v - m;
85
86 // wrap cases
87 dist[j] = dist[0];
88 v-=i;
89 VectorCopy (verts, v);
90
91 f = b = 0;
92 v = verts;
93 for (j=0 ; j<numverts ; j++, v+= 3)
94 {
95 if (dist[j] >= 0)
96 {
97 VectorCopy (v, front[f]);
98 f++;
99 }
100 if (dist[j] <= 0)
101 {
102 VectorCopy (v, back[b]);
103 b++;
104 }
105 if (dist[j] == 0 || dist[j+1] == 0)
106 continue;
107 if ( (dist[j] > 0) != (dist[j+1] > 0) )
108 {
109 // clip point
110 frac = dist[j] / (dist[j] - dist[j+1]);
111 for (k=0 ; k<3 ; k++)
112 front[f][k] = back[b][k] = v[k] + frac*(v[3+k] - v[k]);
113 f++;
114 b++;
115 }
116 }
117
118 SubdividePolygon (f, front[0]);
119 SubdividePolygon (b, back[0]);
120 return;
121 }
122
123 poly = (glpoly_t*) Hunk_Alloc (sizeof(glpoly_t) + (numverts-4) * VERTEXSIZE*sizeof(float));
124 poly->next = warpface->polys;
125 warpface->polys = poly;
126 poly->numverts = numverts;
127 for (i=0 ; i<numverts ; i++, verts+= 3)
128 {
129 VectorCopy (verts, poly->verts[i]);
130 s = DotProduct (verts, warpface->texinfo->vecs[0]);
131 t = DotProduct (verts, warpface->texinfo->vecs[1]);
132 poly->verts[i][3] = s;
133 poly->verts[i][4] = t;
134 }
135 }
136
137 /*
138 ================
139 GL_SubdivideSurface
140
141 Breaks a polygon up along axial 64 unit
142 boundaries so that turbulent and sky warps
143 can be done reasonably.
144 ================
145 */
GL_SubdivideSurface(msurface_t * fa)146 void GL_SubdivideSurface (msurface_t *fa)
147 {
148 vec3_t verts[64];
149 int numverts;
150 int i;
151 int lindex;
152 float *vec;
153 texture_t *t;
154
155 warpface = fa;
156
157 //
158 // convert edges back to a normal polygon
159 //
160 numverts = 0;
161 for (i=0 ; i<fa->numedges ; i++)
162 {
163 lindex = loadmodel->surfedges[fa->firstedge + i];
164
165 if (lindex > 0)
166 vec = loadmodel->vertexes[loadmodel->edges[lindex].v[0]].position;
167 else
168 vec = loadmodel->vertexes[loadmodel->edges[-lindex].v[1]].position;
169 VectorCopy (vec, verts[numverts]);
170 numverts++;
171 }
172
173 SubdividePolygon (numverts, verts[0]);
174 }
175
176 //=========================================================
177
178
179
180 // speed up sin calculations - Ed
181 float turbsin[] =
182 {
183 #include "gl_warp_sin.h"
184 };
185 #define TURBSCALE (256.0 / (2 * M_PI))
186
187 /*
188 =============
189 EmitWaterPolys
190
191 Does a water warp on the pre-fragmented glpoly_t chain
192 =============
193 */
EmitWaterPolys(msurface_t * fa)194 void EmitWaterPolys (msurface_t *fa)
195 {
196 glpoly_t *p;
197 float *v;
198 int i;
199 float s, t, os, ot;
200
201
202 for (p=fa->polys ; p ; p=p->next)
203 {
204 #ifdef USE_OPENGLES
205 {
206 float* pUV = gTexCoordBuffer;
207 for (i=0,v=p->verts[0] ; i<p->numverts ; i++, v+=VERTEXSIZE)
208 {
209 os = v[3];
210 ot = v[4];
211
212 s = os + turbsin[(int)((ot*0.125+realtime) * TURBSCALE) & 255];
213 s *= (1.0/64);
214
215 t = ot + turbsin[(int)((os*0.125+realtime) * TURBSCALE) & 255];
216 t *= (1.0/64);
217
218 *pUV++ = s;
219 *pUV++ = t;
220 }
221 }
222
223 glVertexPointer(3, GL_FLOAT, VERTEXSIZE*sizeof(float), &p->verts[0][0]);
224 glTexCoordPointer(2, GL_FLOAT, 0, gTexCoordBuffer);
225 glDrawArrays(GL_TRIANGLE_FAN, 0, p->numverts);
226 #else
227 glBegin (GL_POLYGON);
228 for (i=0,v=p->verts[0] ; i<p->numverts ; i++, v+=VERTEXSIZE)
229 {
230 os = v[3];
231 ot = v[4];
232
233 s = os + turbsin[(int)((ot*0.125+realtime) * TURBSCALE) & 255];
234 s *= (1.0/64);
235
236 t = ot + turbsin[(int)((os*0.125+realtime) * TURBSCALE) & 255];
237 t *= (1.0/64);
238
239 glTexCoord2f (s, t);
240 glVertex3fv (v);
241 }
242 glEnd ();
243 #endif
244 }
245 }
246
247
248
249
250 /*
251 =============
252 EmitSkyPolys
253 =============
254 */
EmitSkyPolys(msurface_t * fa)255 void EmitSkyPolys (msurface_t *fa)
256 {
257 glpoly_t *p;
258 float *v;
259 int i;
260 float s, t;
261 vec3_t dir;
262 float length;
263
264 for (p=fa->polys ; p ; p=p->next)
265 {
266 #ifdef USE_OPENGLES
267 {
268 float* pUV = gTexCoordBuffer;
269 for (i=0,v=p->verts[0] ; i<p->numverts ; i++, v+=VERTEXSIZE)
270 {
271 VectorSubtract (v, r_origin, dir);
272 dir[2] *= 3; // flatten the sphere
273
274 length = dir[0]*dir[0] + dir[1]*dir[1] + dir[2]*dir[2];
275 length = sqrt (length);
276 length = 6*63/length;
277
278 dir[0] *= length;
279 dir[1] *= length;
280
281 s = (speedscale + dir[0]) * (1.0/128);
282 t = (speedscale + dir[1]) * (1.0/128);
283
284 *pUV++ = s;
285 *pUV++ = t;
286 }
287 }
288
289 glVertexPointer(3, GL_FLOAT, VERTEXSIZE*sizeof(float), &p->verts[0][0]);
290 glTexCoordPointer(2, GL_FLOAT, 0, gTexCoordBuffer);
291 glDrawArrays(GL_TRIANGLE_FAN, 0, p->numverts);
292 #else
293 glBegin (GL_POLYGON);
294 for (i=0,v=p->verts[0] ; i<p->numverts ; i++, v+=VERTEXSIZE)
295 {
296 VectorSubtract (v, r_origin, dir);
297 dir[2] *= 3; // flatten the sphere
298
299 length = dir[0]*dir[0] + dir[1]*dir[1] + dir[2]*dir[2];
300 length = sqrt (length);
301 length = 6*63/length;
302
303 dir[0] *= length;
304 dir[1] *= length;
305
306 s = (speedscale + dir[0]) * (1.0/128);
307 t = (speedscale + dir[1]) * (1.0/128);
308
309 glTexCoord2f (s, t);
310 glVertex3fv (v);
311 }
312 glEnd ();
313 #endif
314 }
315 }
316
317 /*
318 ===============
319 EmitBothSkyLayers
320
321 Does a sky warp on the pre-fragmented glpoly_t chain
322 This will be called for brushmodels, the world
323 will have them chained together.
324 ===============
325 */
EmitBothSkyLayers(msurface_t * fa)326 void EmitBothSkyLayers (msurface_t *fa)
327 {
328 int i;
329 int lindex;
330 float *vec;
331
332 GL_DisableMultitexture();
333
334 GL_Bind (solidskytexture);
335 speedscale = realtime*8;
336 speedscale -= (int)speedscale & ~127 ;
337
338 EmitSkyPolys (fa);
339
340 glEnable (GL_BLEND);
341 GL_Bind (alphaskytexture);
342 speedscale = realtime*16;
343 speedscale -= (int)speedscale & ~127 ;
344
345 EmitSkyPolys (fa);
346
347 glDisable (GL_BLEND);
348 }
349
350 #ifndef QUAKE2
351 /*
352 =================
353 R_DrawSkyChain
354 =================
355 */
R_DrawSkyChain(msurface_t * s)356 void R_DrawSkyChain (msurface_t *s)
357 {
358 msurface_t *fa;
359
360 GL_DisableMultitexture();
361
362 // used when gl_texsort is on
363 GL_Bind(solidskytexture);
364 speedscale = realtime*8;
365 speedscale -= (int)speedscale & ~127 ;
366
367 for (fa=s ; fa ; fa=fa->texturechain)
368 EmitSkyPolys (fa);
369
370 glEnable (GL_BLEND);
371 GL_Bind (alphaskytexture);
372 speedscale = realtime*16;
373 speedscale -= (int)speedscale & ~127 ;
374
375 for (fa=s ; fa ; fa=fa->texturechain)
376 EmitSkyPolys (fa);
377
378 glDisable (GL_BLEND);
379 }
380
381 #endif
382
383 /*
384 =================================================================
385
386 Quake 2 environment sky
387
388 =================================================================
389 */
390
391 #ifdef QUAKE2
392
393
394 #define SKY_TEX 2000
395
396 /*
397 =================================================================
398
399 PCX Loading
400
401 =================================================================
402 */
403
404 typedef struct
405 {
406 char manufacturer;
407 char version;
408 char encoding;
409 char bits_per_pixel;
410 unsigned short xmin,ymin,xmax,ymax;
411 unsigned short hres,vres;
412 unsigned char palette[48];
413 char reserved;
414 char color_planes;
415 unsigned short bytes_per_line;
416 unsigned short palette_type;
417 char filler[58];
418 unsigned data; // unbounded
419 } pcx_t;
420
421 byte *pcx_rgb;
422
423 /*
424 ============
425 LoadPCX
426 ============
427 */
LoadPCX(FILE * f)428 void LoadPCX (FILE *f)
429 {
430 pcx_t *pcx, pcxbuf;
431 byte palette[768];
432 byte *pix;
433 int x, y;
434 int dataByte, runLength;
435 int count;
436
437 //
438 // parse the PCX file
439 //
440 fread (&pcxbuf, 1, sizeof(pcxbuf), f);
441
442 pcx = &pcxbuf;
443
444 if (pcx->manufacturer != 0x0a
445 || pcx->version != 5
446 || pcx->encoding != 1
447 || pcx->bits_per_pixel != 8
448 || pcx->xmax >= 320
449 || pcx->ymax >= 256)
450 {
451 Con_Printf ("Bad pcx file\n");
452 return;
453 }
454
455 // seek to palette
456 fseek (f, -768, SEEK_END);
457 fread (palette, 1, 768, f);
458
459 fseek (f, sizeof(pcxbuf) - 4, SEEK_SET);
460
461 count = (pcx->xmax+1) * (pcx->ymax+1);
462 pcx_rgb = malloc( count * 4);
463
464 for (y=0 ; y<=pcx->ymax ; y++)
465 {
466 pix = pcx_rgb + 4*y*(pcx->xmax+1);
467 for (x=0 ; x<=pcx->ymax ; )
468 {
469 dataByte = fgetc(f);
470
471 if((dataByte & 0xC0) == 0xC0)
472 {
473 runLength = dataByte & 0x3F;
474 dataByte = fgetc(f);
475 }
476 else
477 runLength = 1;
478
479 while(runLength-- > 0)
480 {
481 pix[0] = palette[dataByte*3];
482 pix[1] = palette[dataByte*3+1];
483 pix[2] = palette[dataByte*3+2];
484 pix[3] = 255;
485 pix += 4;
486 x++;
487 }
488 }
489 }
490 }
491
492 /*
493 =========================================================
494
495 TARGA LOADING
496
497 =========================================================
498 */
499
500 typedef struct _TargaHeader {
501 unsigned char id_length, colormap_type, image_type;
502 unsigned short colormap_index, colormap_length;
503 unsigned char colormap_size;
504 unsigned short x_origin, y_origin, width, height;
505 unsigned char pixel_size, attributes;
506 } TargaHeader;
507
508
509 TargaHeader targa_header;
510 byte *targa_rgba;
511
fgetLittleShort(FILE * f)512 int fgetLittleShort (FILE *f)
513 {
514 byte b1, b2;
515
516 b1 = fgetc(f);
517 b2 = fgetc(f);
518
519 return (short)(b1 + b2*256);
520 }
521
fgetLittleLong(FILE * f)522 int fgetLittleLong (FILE *f)
523 {
524 byte b1, b2, b3, b4;
525
526 b1 = fgetc(f);
527 b2 = fgetc(f);
528 b3 = fgetc(f);
529 b4 = fgetc(f);
530
531 return b1 + (b2<<8) + (b3<<16) + (b4<<24);
532 }
533
534
535 /*
536 =============
537 LoadTGA
538 =============
539 */
LoadTGA(FILE * fin)540 void LoadTGA (FILE *fin)
541 {
542 int columns, rows, numPixels;
543 byte *pixbuf;
544 int row, column;
545
546 targa_header.id_length = fgetc(fin);
547 targa_header.colormap_type = fgetc(fin);
548 targa_header.image_type = fgetc(fin);
549
550 targa_header.colormap_index = fgetLittleShort(fin);
551 targa_header.colormap_length = fgetLittleShort(fin);
552 targa_header.colormap_size = fgetc(fin);
553 targa_header.x_origin = fgetLittleShort(fin);
554 targa_header.y_origin = fgetLittleShort(fin);
555 targa_header.width = fgetLittleShort(fin);
556 targa_header.height = fgetLittleShort(fin);
557 targa_header.pixel_size = fgetc(fin);
558 targa_header.attributes = fgetc(fin);
559
560 if (targa_header.image_type!=2
561 && targa_header.image_type!=10)
562 Sys_Error ("LoadTGA: Only type 2 and 10 targa RGB images supported\n");
563
564 if (targa_header.colormap_type !=0
565 || (targa_header.pixel_size!=32 && targa_header.pixel_size!=24))
566 Sys_Error ("Texture_LoadTGA: Only 32 or 24 bit images supported (no colormaps)\n");
567
568 columns = targa_header.width;
569 rows = targa_header.height;
570 numPixels = columns * rows;
571
572 targa_rgba = malloc (numPixels*4);
573
574 if (targa_header.id_length != 0)
575 fseek(fin, targa_header.id_length, SEEK_CUR); // skip TARGA image comment
576
577 if (targa_header.image_type==2) { // Uncompressed, RGB images
578 for(row=rows-1; row>=0; row--) {
579 pixbuf = targa_rgba + row*columns*4;
580 for(column=0; column<columns; column++) {
581 unsigned char red,green,blue,alphabyte;
582 switch (targa_header.pixel_size) {
583 case 24:
584
585 blue = getc(fin);
586 green = getc(fin);
587 red = getc(fin);
588 *pixbuf++ = red;
589 *pixbuf++ = green;
590 *pixbuf++ = blue;
591 *pixbuf++ = 255;
592 break;
593 case 32:
594 blue = getc(fin);
595 green = getc(fin);
596 red = getc(fin);
597 alphabyte = getc(fin);
598 *pixbuf++ = red;
599 *pixbuf++ = green;
600 *pixbuf++ = blue;
601 *pixbuf++ = alphabyte;
602 break;
603 }
604 }
605 }
606 }
607 else if (targa_header.image_type==10) { // Runlength encoded RGB images
608 unsigned char red,green,blue,alphabyte,packetHeader,packetSize,j;
609 for(row=rows-1; row>=0; row--) {
610 pixbuf = targa_rgba + row*columns*4;
611 for(column=0; column<columns; ) {
612 packetHeader=getc(fin);
613 packetSize = 1 + (packetHeader & 0x7f);
614 if (packetHeader & 0x80) { // run-length packet
615 switch (targa_header.pixel_size) {
616 case 24:
617 blue = getc(fin);
618 green = getc(fin);
619 red = getc(fin);
620 alphabyte = 255;
621 break;
622 case 32:
623 blue = getc(fin);
624 green = getc(fin);
625 red = getc(fin);
626 alphabyte = getc(fin);
627 break;
628 }
629
630 for(j=0;j<packetSize;j++) {
631 *pixbuf++=red;
632 *pixbuf++=green;
633 *pixbuf++=blue;
634 *pixbuf++=alphabyte;
635 column++;
636 if (column==columns) { // run spans across rows
637 column=0;
638 if (row>0)
639 row--;
640 else
641 goto breakOut;
642 pixbuf = targa_rgba + row*columns*4;
643 }
644 }
645 }
646 else { // non run-length packet
647 for(j=0;j<packetSize;j++) {
648 switch (targa_header.pixel_size) {
649 case 24:
650 blue = getc(fin);
651 green = getc(fin);
652 red = getc(fin);
653 *pixbuf++ = red;
654 *pixbuf++ = green;
655 *pixbuf++ = blue;
656 *pixbuf++ = 255;
657 break;
658 case 32:
659 blue = getc(fin);
660 green = getc(fin);
661 red = getc(fin);
662 alphabyte = getc(fin);
663 *pixbuf++ = red;
664 *pixbuf++ = green;
665 *pixbuf++ = blue;
666 *pixbuf++ = alphabyte;
667 break;
668 }
669 column++;
670 if (column==columns) { // pixel packet run spans across rows
671 column=0;
672 if (row>0)
673 row--;
674 else
675 goto breakOut;
676 pixbuf = targa_rgba + row*columns*4;
677 }
678 }
679 }
680 }
681 breakOut:;
682 }
683 }
684
685 fclose(fin);
686 }
687
688 /*
689 ==================
690 R_LoadSkys
691 ==================
692 */
693 char *suf[6] = {"rt", "bk", "lf", "ft", "up", "dn"};
R_LoadSkys(void)694 void R_LoadSkys (void)
695 {
696 int i;
697 FILE *f;
698 char name[64];
699
700 for (i=0 ; i<6 ; i++)
701 {
702 GL_Bind (SKY_TEX + i);
703 sprintf (name, "gfx/env/bkgtst%s.tga", suf[i]);
704 COM_FOpenFile (name, &f);
705 if (!f)
706 {
707 Con_Printf ("Couldn't load %s\n", name);
708 continue;
709 }
710 LoadTGA (f);
711 // LoadPCX (f);
712
713 glTexImage2DHelper (GL_TEXTURE_2D, 0, gl_solid_format, 256, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, targa_rgba);
714 // glTexImage2DHelper (GL_TEXTURE_2D, 0, gl_solid_format, 256, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, pcx_rgb);
715
716 free (targa_rgba);
717 // free (pcx_rgb);
718
719 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
720 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
721 }
722 }
723
724
725 vec3_t skyclip[6] = {
726 {1,1,0},
727 {1,-1,0},
728 {0,-1,1},
729 {0,1,1},
730 {1,0,1},
731 {-1,0,1}
732 };
733 int c_sky;
734
735 // 1 = s, 2 = t, 3 = 2048
736 int st_to_vec[6][3] =
737 {
738 {3,-1,2},
739 {-3,1,2},
740
741 {1,3,2},
742 {-1,-3,2},
743
744 {-2,-1,3}, // 0 degrees yaw, look straight up
745 {2,-1,-3} // look straight down
746
747 // {-1,2,3},
748 // {1,2,-3}
749 };
750
751 // s = [0]/[2], t = [1]/[2]
752 int vec_to_st[6][3] =
753 {
754 {-2,3,1},
755 {2,3,-1},
756
757 {1,3,2},
758 {-1,3,-2},
759
760 {-2,-1,3},
761 {-2,1,-3}
762
763 // {-1,2,3},
764 // {1,2,-3}
765 };
766
767 float skymins[2][6], skymaxs[2][6];
768
DrawSkyPolygon(int nump,vec3_t vecs)769 void DrawSkyPolygon (int nump, vec3_t vecs)
770 {
771 int i,j;
772 vec3_t v, av;
773 float s, t, dv;
774 int axis;
775 float *vp;
776
777 c_sky++;
778 #if 0
779 glBegin (GL_POLYGON);
780 for (i=0 ; i<nump ; i++, vecs+=3)
781 {
782 VectorAdd(vecs, r_origin, v);
783 glVertex3fv (v);
784 }
785 glEnd();
786 return;
787 #endif
788 // decide which face it maps to
789 VectorCopy (vec3_origin, v);
790 for (i=0, vp=vecs ; i<nump ; i++, vp+=3)
791 {
792 VectorAdd (vp, v, v);
793 }
794 av[0] = fabs(v[0]);
795 av[1] = fabs(v[1]);
796 av[2] = fabs(v[2]);
797 if (av[0] > av[1] && av[0] > av[2])
798 {
799 if (v[0] < 0)
800 axis = 1;
801 else
802 axis = 0;
803 }
804 else if (av[1] > av[2] && av[1] > av[0])
805 {
806 if (v[1] < 0)
807 axis = 3;
808 else
809 axis = 2;
810 }
811 else
812 {
813 if (v[2] < 0)
814 axis = 5;
815 else
816 axis = 4;
817 }
818
819 // project new texture coords
820 for (i=0 ; i<nump ; i++, vecs+=3)
821 {
822 j = vec_to_st[axis][2];
823 if (j > 0)
824 dv = vecs[j - 1];
825 else
826 dv = -vecs[-j - 1];
827
828 j = vec_to_st[axis][0];
829 if (j < 0)
830 s = -vecs[-j -1] / dv;
831 else
832 s = vecs[j-1] / dv;
833 j = vec_to_st[axis][1];
834 if (j < 0)
835 t = -vecs[-j -1] / dv;
836 else
837 t = vecs[j-1] / dv;
838
839 if (s < skymins[0][axis])
840 skymins[0][axis] = s;
841 if (t < skymins[1][axis])
842 skymins[1][axis] = t;
843 if (s > skymaxs[0][axis])
844 skymaxs[0][axis] = s;
845 if (t > skymaxs[1][axis])
846 skymaxs[1][axis] = t;
847 }
848 }
849
850 #define MAX_CLIP_VERTS 64
ClipSkyPolygon(int nump,vec3_t vecs,int stage)851 void ClipSkyPolygon (int nump, vec3_t vecs, int stage)
852 {
853 float *norm;
854 float *v;
855 qboolean front, back;
856 float d, e;
857 float dists[MAX_CLIP_VERTS];
858 int sides[MAX_CLIP_VERTS];
859 vec3_t newv[2][MAX_CLIP_VERTS];
860 int newc[2];
861 int i, j;
862
863 if (nump > MAX_CLIP_VERTS-2)
864 Sys_Error ("ClipSkyPolygon: MAX_CLIP_VERTS");
865 if (stage == 6)
866 { // fully clipped, so draw it
867 DrawSkyPolygon (nump, vecs);
868 return;
869 }
870
871 front = back = false;
872 norm = skyclip[stage];
873 for (i=0, v = vecs ; i<nump ; i++, v+=3)
874 {
875 d = DotProduct (v, norm);
876 if (d > ON_EPSILON)
877 {
878 front = true;
879 sides[i] = SIDE_FRONT;
880 }
881 else if (d < ON_EPSILON)
882 {
883 back = true;
884 sides[i] = SIDE_BACK;
885 }
886 else
887 sides[i] = SIDE_ON;
888 dists[i] = d;
889 }
890
891 if (!front || !back)
892 { // not clipped
893 ClipSkyPolygon (nump, vecs, stage+1);
894 return;
895 }
896
897 // clip it
898 sides[i] = sides[0];
899 dists[i] = dists[0];
900 VectorCopy (vecs, (vecs+(i*3)) );
901 newc[0] = newc[1] = 0;
902
903 for (i=0, v = vecs ; i<nump ; i++, v+=3)
904 {
905 switch (sides[i])
906 {
907 case SIDE_FRONT:
908 VectorCopy (v, newv[0][newc[0]]);
909 newc[0]++;
910 break;
911 case SIDE_BACK:
912 VectorCopy (v, newv[1][newc[1]]);
913 newc[1]++;
914 break;
915 case SIDE_ON:
916 VectorCopy (v, newv[0][newc[0]]);
917 newc[0]++;
918 VectorCopy (v, newv[1][newc[1]]);
919 newc[1]++;
920 break;
921 }
922
923 if (sides[i] == SIDE_ON || sides[i+1] == SIDE_ON || sides[i+1] == sides[i])
924 continue;
925
926 d = dists[i] / (dists[i] - dists[i+1]);
927 for (j=0 ; j<3 ; j++)
928 {
929 e = v[j] + d*(v[j+3] - v[j]);
930 newv[0][newc[0]][j] = e;
931 newv[1][newc[1]][j] = e;
932 }
933 newc[0]++;
934 newc[1]++;
935 }
936
937 // continue
938 ClipSkyPolygon (newc[0], newv[0][0], stage+1);
939 ClipSkyPolygon (newc[1], newv[1][0], stage+1);
940 }
941
942 /*
943 =================
944 R_DrawSkyChain
945 =================
946 */
R_DrawSkyChain(msurface_t * s)947 void R_DrawSkyChain (msurface_t *s)
948 {
949 msurface_t *fa;
950
951 int i;
952 vec3_t verts[MAX_CLIP_VERTS];
953 glpoly_t *p;
954
955 c_sky = 0;
956 GL_Bind(solidskytexture);
957
958 // calculate vertex values for sky box
959
960 for (fa=s ; fa ; fa=fa->texturechain)
961 {
962 for (p=fa->polys ; p ; p=p->next)
963 {
964 for (i=0 ; i<p->numverts ; i++)
965 {
966 VectorSubtract (p->verts[i], r_origin, verts[i]);
967 }
968 ClipSkyPolygon (p->numverts, verts[0], 0);
969 }
970 }
971 }
972
973
974 /*
975 ==============
976 R_ClearSkyBox
977 ==============
978 */
R_ClearSkyBox(void)979 void R_ClearSkyBox (void)
980 {
981 int i;
982
983 for (i=0 ; i<6 ; i++)
984 {
985 skymins[0][i] = skymins[1][i] = 9999;
986 skymaxs[0][i] = skymaxs[1][i] = -9999;
987 }
988 }
989
990
MakeSkyVec(float s,float t,int axis)991 void MakeSkyVec (float s, float t, int axis)
992 {
993 vec3_t v, b;
994 int j, k;
995
996 b[0] = s*2048;
997 b[1] = t*2048;
998 b[2] = 2048;
999
1000 for (j=0 ; j<3 ; j++)
1001 {
1002 k = st_to_vec[axis][j];
1003 if (k < 0)
1004 v[j] = -b[-k - 1];
1005 else
1006 v[j] = b[k - 1];
1007 v[j] += r_origin[j];
1008 }
1009
1010 // avoid bilerp seam
1011 s = (s+1)*0.5;
1012 t = (t+1)*0.5;
1013
1014 if (s < 1.0/512)
1015 s = 1.0/512;
1016 else if (s > 511.0/512)
1017 s = 511.0/512;
1018 if (t < 1.0/512)
1019 t = 1.0/512;
1020 else if (t > 511.0/512)
1021 t = 511.0/512;
1022
1023 t = 1.0 - t;
1024 glTexCoord2f (s, t);
1025 glVertex3fv (v);
1026 }
1027
1028 /*
1029 ==============
1030 R_DrawSkyBox
1031 ==============
1032 */
1033 int skytexorder[6] = {0,2,1,3,4,5};
R_DrawSkyBox(void)1034 void R_DrawSkyBox (void)
1035 {
1036 int i, j, k;
1037 vec3_t v;
1038 float s, t;
1039
1040 #if 0
1041 glEnable (GL_BLEND);
1042 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
1043 glColor4f (1,1,1,0.5);
1044 glDisable (GL_DEPTH_TEST);
1045 #endif
1046 for (i=0 ; i<6 ; i++)
1047 {
1048 if (skymins[0][i] >= skymaxs[0][i]
1049 || skymins[1][i] >= skymaxs[1][i])
1050 continue;
1051
1052 GL_Bind (SKY_TEX+skytexorder[i]);
1053 #if 0
1054 skymins[0][i] = -1;
1055 skymins[1][i] = -1;
1056 skymaxs[0][i] = 1;
1057 skymaxs[1][i] = 1;
1058 #endif
1059 glBegin (GL_QUADS);
1060 MakeSkyVec (skymins[0][i], skymins[1][i], i);
1061 MakeSkyVec (skymins[0][i], skymaxs[1][i], i);
1062 MakeSkyVec (skymaxs[0][i], skymaxs[1][i], i);
1063 MakeSkyVec (skymaxs[0][i], skymins[1][i], i);
1064 glEnd ();
1065 }
1066 #if 0
1067 glDisable (GL_BLEND);
1068 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
1069 glColor4f (1,1,1,0.5);
1070 glEnable (GL_DEPTH_TEST);
1071 #endif
1072 }
1073
1074
1075 #endif
1076
1077 //===============================================================
1078
1079 static texture_t* current_sky_mt;
1080
1081 /*
1082 =============
1083 R_InitSky
1084
1085 A sky texture is 256*128, with the right side being a masked overlay
1086 ==============
1087 */
R_InitSky(texture_t * mt)1088 void R_InitSky (texture_t *mt)
1089 {
1090 int i, j, p;
1091 byte *src;
1092 unsigned trans[128*128];
1093 unsigned transpix;
1094 int r, g, b;
1095 unsigned *rgba;
1096 // extern int skytexturenum;
1097
1098 current_sky_mt = mt;
1099
1100 src = (byte *)mt + mt->offsets[0];
1101
1102 // make an average value for the back to avoid
1103 // a fringe on the top level
1104
1105 r = g = b = 0;
1106 for (i=0 ; i<128 ; i++)
1107 for (j=0 ; j<128 ; j++)
1108 {
1109 p = src[i*256 + j + 128];
1110 rgba = &d_8to24table[p];
1111 trans[(i*128) + j] = *rgba;
1112 r += ((byte *)rgba)[0];
1113 g += ((byte *)rgba)[1];
1114 b += ((byte *)rgba)[2];
1115 }
1116
1117 ((byte *)&transpix)[0] = r/(128*128);
1118 ((byte *)&transpix)[1] = g/(128*128);
1119 ((byte *)&transpix)[2] = b/(128*128);
1120 ((byte *)&transpix)[3] = 0;
1121
1122
1123 if (!solidskytexture)
1124 solidskytexture = texture_extension_number++;
1125 GL_Bind (solidskytexture );
1126 glTexImage2DHelper (GL_TEXTURE_2D, 0, gl_solid_format, 128, 128, 0, GL_RGBA, GL_UNSIGNED_BYTE, trans);
1127 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1128 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1129
1130
1131 for (i=0 ; i<128 ; i++)
1132 for (j=0 ; j<128 ; j++)
1133 {
1134 p = src[i*256 + j];
1135 if (p == 0)
1136 trans[(i*128) + j] = transpix;
1137 else
1138 trans[(i*128) + j] = d_8to24table[p];
1139 }
1140
1141 if (!alphaskytexture)
1142 alphaskytexture = texture_extension_number++;
1143 GL_Bind(alphaskytexture);
1144 glTexImage2DHelper (GL_TEXTURE_2D, 0, gl_alpha_format, 128, 128, 0, GL_RGBA, GL_UNSIGNED_BYTE, trans);
1145 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1146 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1147 }
1148
R_ReloadSky()1149 void R_ReloadSky() {
1150 if (current_sky_mt) {
1151 R_InitSky(current_sky_mt);
1152 }
1153 }
1154