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