Home | History | Annotate | Download | only in WinQuake
      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 
     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 
     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 = (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 ================
    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 */
    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     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
    181 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 */
    194 void 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 =============
    252 EmitSkyPolys
    253 =============
    254 */
    255 void 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 ===============
    319 EmitBothSkyLayers
    320 
    321 Does a sky warp on the pre-fragmented glpoly_t chain
    322 This will be called for brushmodels, the world
    323 will have them chained together.
    324 ===============
    325 */
    326 void 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 =================
    353 R_DrawSkyChain
    354 =================
    355 */
    356 void 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 
    404 typedef 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 
    421 byte    *pcx_rgb;
    422 
    423 /*
    424 ============
    425 LoadPCX
    426 ============
    427 */
    428 void 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 
    495 TARGA LOADING
    496 
    497 =========================================================
    498 */
    499 
    500 typedef 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 
    509 TargaHeader     targa_header;
    510 byte            *targa_rgba;
    511 
    512 int 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 
    522 int 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 =============
    537 LoadTGA
    538 =============
    539 */
    540 void 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 ==================
    690 R_LoadSkys
    691 ==================
    692 */
    693 char    *suf[6] = {"rt", "bk", "lf", "ft", "up", "dn"};
    694 void 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 
    725 vec3_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 };
    733 int c_sky;
    734 
    735 // 1 = s, 2 = t, 3 = 2048
    736 int 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]
    752 int 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 
    767 float   skymins[2][6], skymaxs[2][6];
    768 
    769 void 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
    779 glBegin (GL_POLYGON);
    780 for (i=0 ; i<nump ; i++, vecs+=3)
    781 {
    782     VectorAdd(vecs, r_origin, v);
    783     glVertex3fv (v);
    784 }
    785 glEnd();
    786 return;
    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
    851 void 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 =================
    944 R_DrawSkyChain
    945 =================
    946 */
    947 void 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 ==============
    976 R_ClearSkyBox
    977 ==============
    978 */
    979 void 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 
    991 void 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 ==============
   1030 R_DrawSkyBox
   1031 ==============
   1032 */
   1033 int skytexorder[6] = {0,2,1,3,4,5};
   1034 void R_DrawSkyBox (void)
   1035 {
   1036     int     i, j, k;
   1037     vec3_t  v;
   1038     float   s, t;
   1039 
   1040 #if 0
   1041 glEnable (GL_BLEND);
   1042 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
   1043 glColor4f (1,1,1,0.5);
   1044 glDisable (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
   1054 skymins[0][i] = -1;
   1055 skymins[1][i] = -1;
   1056 skymaxs[0][i] = 1;
   1057 skymaxs[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
   1067 glDisable (GL_BLEND);
   1068 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
   1069 glColor4f (1,1,1,0.5);
   1070 glEnable (GL_DEPTH_TEST);
   1071 #endif
   1072 }
   1073 
   1074 
   1075 #endif
   1076 
   1077 //===============================================================
   1078 
   1079 static texture_t* current_sky_mt;
   1080 
   1081 /*
   1082 =============
   1083 R_InitSky
   1084 
   1085 A sky texture is 256*128, with the right side being a masked overlay
   1086 ==============
   1087 */
   1088 void 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 
   1149 void R_ReloadSky() {
   1150     if (current_sky_mt) {
   1151         R_InitSky(current_sky_mt);
   1152     }
   1153 }
   1154