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