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