1/*
2Copyright (C) 1996-1997 Id Software, Inc.
3
4This program is free software; you can redistribute it and/or
5modify it under the terms of the GNU General Public License
6as published by the Free Software Foundation; either version 2
7of the License, or (at your option) any later version.
8
9This program is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13See the GNU General Public License for more details.
14
15You should have received a copy of the GNU General Public License
16along with this program; if not, write to the Free Software
17Foundation, 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
24extern	model_t	*loadmodel;
25
26int		skytexturenum;
27
28int		solidskytexture;
29int		alphaskytexture;
30float	speedscale;		// for top sky and bottom sky
31
32msurface_t	*warpface;
33
34extern cvar_t gl_subdivide_size;
35
36void 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
54void 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================
139GL_SubdivideSurface
140
141Breaks a polygon up along axial 64 unit
142boundaries so that turbulent and sky warps
143can be done reasonably.
144================
145*/
146void 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
180float	turbsin[] =
181{
182	#include "gl_warp_sin.h"
183};
184#define TURBSCALE (256.0 / (2 * M_PI))
185
186/*
187=============
188EmitWaterPolys
189
190Does a water warp on the pre-fragmented glpoly_t chain
191=============
192*/
193void 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=============
231EmitSkyPolys
232=============
233*/
234void 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===============
274EmitBothSkyLayers
275
276Does a sky warp on the pre-fragmented glpoly_t chain
277This will be called for brushmodels, the world
278will have them chained together.
279===============
280*/
281void 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=================
304R_DrawSkyChain
305=================
306*/
307void 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
355typedef 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
372byte	*pcx_rgb;
373
374/*
375============
376LoadPCX
377============
378*/
379void 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
446TARGA LOADING
447
448=========================================================
449*/
450
451typedef 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
460TargaHeader		targa_header;
461byte			*targa_rgba;
462
463int 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
473int 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=============
488LoadTGA
489=============
490*/
491void 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==================
641R_LoadSkys
642==================
643*/
644char	*suf[6] = {"rt", "bk", "lf", "ft", "up", "dn"};
645void 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
676vec3_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};
684int	c_sky;
685
686// 1 = s, 2 = t, 3 = 2048
687int	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]
703int	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
718float	skymins[2][6], skymaxs[2][6];
719
720void 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
730glBegin (GL_POLYGON);
731for (i=0 ; i<nump ; i++, vecs+=3)
732{
733	VectorAdd(vecs, r_origin, v);
734	glVertex3fv (v);
735}
736glEnd();
737return;
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
802void 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=================
895R_DrawSkyChain
896=================
897*/
898void 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==============
927R_ClearSkyBox
928==============
929*/
930void 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
942void 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==============
981R_DrawSkyBox
982==============
983*/
984int	skytexorder[6] = {0,2,1,3,4,5};
985void R_DrawSkyBox (void)
986{
987	int		i, j, k;
988	vec3_t	v;
989	float	s, t;
990
991#if 0
992glEnable (GL_BLEND);
993glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
994glColor4f (1,1,1,0.5);
995glDisable (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
1005skymins[0][i] = -1;
1006skymins[1][i] = -1;
1007skymaxs[0][i] = 1;
1008skymaxs[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
1022glDisable (GL_BLEND);
1023glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
1024glColor4f (1,1,1,0.5);
1025glEnable (GL_DEPTH_TEST);
1026#endif
1027}
1028
1029
1030#endif
1031
1032//===============================================================
1033
1034/*
1035=============
1036R_InitSky
1037
1038A sky texture is 256*128, with the right side being a masked overlay
1039==============
1040*/
1041void 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