• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3 
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8 
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 
13 See the GNU General Public License for more details.
14 
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18 
19 */
20 // 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