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