/*
Copyright (C) 1996-1997 Id Software, Inc.

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  

See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

*/
// gl_warp.c -- sky and water polygons

#include "quakedef.h"

extern  model_t *loadmodel;

int   skytexturenum;

int   solidskytexture;
int   alphaskytexture;
float speedscale;   // for top sky and bottom sky

msurface_t  *warpface;

extern cvar_t gl_subdivide_size;

void BoundPoly (int numverts, float *verts, vec3_t mins, vec3_t maxs)
{
  int   i, j;
  float *v;

  mins[0] = mins[1] = mins[2] = 9999;
  maxs[0] = maxs[1] = maxs[2] = -9999;
  v = verts;
  for (i=0 ; i<numverts ; i++)
    for (j=0 ; j<3 ; j++, v++)
    {
      if (*v < mins[j])
        mins[j] = *v;
      if (*v > maxs[j])
        maxs[j] = *v;
    }
}

void SubdividePolygon (int numverts, float *verts)
{
  int   i, j, k;
  vec3_t  mins, maxs;
  float m;
  float *v;
  vec3_t  front[64], back[64];
  int   f, b;
  float dist[64];
  float frac;
  glpoly_t  *poly;
  float s, t;

  if (numverts > 60)
    Sys_Error ("numverts = %i", numverts);

  BoundPoly (numverts, verts, mins, maxs);

  for (i=0 ; i<3 ; i++)
  {
    m = (mins[i] + maxs[i]) * 0.5;
    m = gl_subdivide_size.value * floor (m/gl_subdivide_size.value + 0.5);
    if (maxs[i] - m < 8)
      continue;
    if (m - mins[i] < 8)
      continue;

    // cut it
    v = verts + i;
    for (j=0 ; j<numverts ; j++, v+= 3)
      dist[j] = *v - m;

    // wrap cases
    dist[j] = dist[0];
    v-=i;
    VectorCopy (verts, v);

    f = b = 0;
    v = verts;
    for (j=0 ; j<numverts ; j++, v+= 3)
    {
      if (dist[j] >= 0)
      {
        VectorCopy (v, front[f]);
        f++;
      }
      if (dist[j] <= 0)
      {
        VectorCopy (v, back[b]);
        b++;
      }
      if (dist[j] == 0 || dist[j+1] == 0)
        continue;
      if ( (dist[j] > 0) != (dist[j+1] > 0) )
      {
        // clip point
        frac = dist[j] / (dist[j] - dist[j+1]);
        for (k=0 ; k<3 ; k++)
          front[f][k] = back[b][k] = v[k] + frac*(v[3+k] - v[k]);
        f++;
        b++;
      }
    }

    SubdividePolygon (f, front[0]);
    SubdividePolygon (b, back[0]);
    return;
  }

  poly = Hunk_Alloc (sizeof(glpoly_t) + (numverts-4) * VERTEXSIZE*sizeof(float));
  poly->next = warpface->polys;
  warpface->polys = poly;
  poly->numverts = numverts;
  for (i=0 ; i<numverts ; i++, verts+= 3)
  {
    VectorCopy (verts, poly->verts[i]);
    s = DotProduct (verts, warpface->texinfo->vecs[0]);
    t = DotProduct (verts, warpface->texinfo->vecs[1]);
    poly->verts[i][3] = s;
    poly->verts[i][4] = t;
  }
}

/*
================
GL_SubdivideSurface

Breaks a polygon up along axial 64 unit
boundaries so that turbulent and sky warps
can be done reasonably.
================
*/
void GL_SubdivideSurface (msurface_t *fa)
{
  vec3_t    verts[64];
  int     numverts;
  int     i;
  int     lindex;
  float   *vec;

  warpface = fa;

  //
  // convert edges back to a normal polygon
  //
  numverts = 0;
  for (i=0 ; i<fa->numedges ; i++)
  {
    lindex = loadmodel->surfedges[fa->firstedge + i];

    if (lindex > 0)
      vec = loadmodel->vertexes[loadmodel->edges[lindex].v[0]].position;
    else
      vec = loadmodel->vertexes[loadmodel->edges[-lindex].v[1]].position;
    VectorCopy (vec, verts[numverts]);
    numverts++;
  }

  SubdividePolygon (numverts, verts[0]);
}

//=========================================================



// speed up sin calculations - Ed
float turbsin[] =
{
  #include "gl_warp_sin.h"
};
#define TURBSCALE (256.0 / (2 * M_PI))

/*
=============
EmitWaterPolys

Does a water warp on the pre-fragmented glpoly_t chain
=============
*/
void EmitWaterPolys (msurface_t *fa)
{
  glpoly_t  *p;
  float   *v;
  int     i;
  float   s, t, os, ot;


  for (p=fa->polys ; p ; p=p->next)
  {
    glBegin (GL_POLYGON);
    for (i=0,v=p->verts[0] ; i<p->numverts ; i++, v+=VERTEXSIZE)
    {
      os = v[3];
      ot = v[4];

      s = os + turbsin[(int)((ot*0.125+realtime) * TURBSCALE) & 255];
      s *= (1.0/64);

      t = ot + turbsin[(int)((os*0.125+realtime) * TURBSCALE) & 255];
      t *= (1.0/64);

      glTexCoord2f (s, t);
      glVertex3fv (v);
    }
    glEnd ();
  }
}




/*
=============
EmitSkyPolys
=============
*/
void EmitSkyPolys (msurface_t *fa)
{
  glpoly_t  *p;
  float   *v;
  int     i;
  float s, t;
  vec3_t  dir;
  float length;

  for (p=fa->polys ; p ; p=p->next)
  {
    glBegin (GL_POLYGON);
    for (i=0,v=p->verts[0] ; i<p->numverts ; i++, v+=VERTEXSIZE)
    {
      VectorSubtract (v, r_origin, dir);
      dir[2] *= 3;  // flatten the sphere

      length = dir[0]*dir[0] + dir[1]*dir[1] + dir[2]*dir[2];
      length = sqrt (length);
      length = 6*63/length;

      dir[0] *= length;
      dir[1] *= length;

      s = (speedscale + dir[0]) * (1.0/128);
      t = (speedscale + dir[1]) * (1.0/128);

      glTexCoord2f (s, t);
      glVertex3fv (v);
    }
    glEnd ();
  }
}

/*
===============
EmitBothSkyLayers

Does a sky warp on the pre-fragmented glpoly_t chain
This will be called for brushmodels, the world
will have them chained together.
===============
*/
void EmitBothSkyLayers (msurface_t *fa)
{
  GL_DisableMultitexture();

  GL_Bind (solidskytexture);
  speedscale = realtime*8;
  speedscale -= (int)speedscale & ~127 ;

  EmitSkyPolys (fa);

  glEnable (GL_BLEND);
  GL_Bind (alphaskytexture);
  speedscale = realtime*16;
  speedscale -= (int)speedscale & ~127 ;

  EmitSkyPolys (fa);

  glDisable (GL_BLEND);
}

#ifndef QUAKE2
/*
=================
R_DrawSkyChain
=================
*/
void R_DrawSkyChain (msurface_t *s)
{
  msurface_t  *fa;

  GL_DisableMultitexture();

  // used when gl_texsort is on
  GL_Bind(solidskytexture);
  speedscale = realtime*8;
  speedscale -= (int)speedscale & ~127 ;

  for (fa=s ; fa ; fa=fa->texturechain)
    EmitSkyPolys (fa);

  glEnable (GL_BLEND);
  GL_Bind (alphaskytexture);
  speedscale = realtime*16;
  speedscale -= (int)speedscale & ~127 ;

  for (fa=s ; fa ; fa=fa->texturechain)
    EmitSkyPolys (fa);

  glDisable (GL_BLEND);
}

#endif

/*
=================================================================

  Quake 2 environment sky

=================================================================
*/

#ifdef QUAKE2


#define SKY_TEX   2000

/*
=================================================================

  PCX Loading

=================================================================
*/

typedef struct
{
    char  manufacturer;
    char  version;
    char  encoding;
    char  bits_per_pixel;
    unsigned short  xmin,ymin,xmax,ymax;
    unsigned short  hres,vres;
    unsigned char palette[48];
    char  reserved;
    char  color_planes;
    unsigned short  bytes_per_line;
    unsigned short  palette_type;
    char  filler[58];
    unsigned  data;     // unbounded
} pcx_t;

byte  *pcx_rgb;

/*
============
LoadPCX
============
*/
void LoadPCX (FILE *f)
{
  pcx_t *pcx, pcxbuf;
  byte  palette[768];
  byte  *pix;
  int   x, y;
  int   dataByte, runLength;
  int   count;

//
// parse the PCX file
//
  fread (&pcxbuf, 1, sizeof(pcxbuf), f);

  pcx = &pcxbuf;

  if (pcx->manufacturer != 0x0a
    || pcx->version != 5
    || pcx->encoding != 1
    || pcx->bits_per_pixel != 8
    || pcx->xmax >= 320
    || pcx->ymax >= 256)
  {
    Con_Printf ("Bad pcx file\n");
    return;
  }

  // seek to palette
  fseek (f, -768, SEEK_END);
  fread (palette, 1, 768, f);

  fseek (f, sizeof(pcxbuf) - 4, SEEK_SET);

  count = (pcx->xmax+1) * (pcx->ymax+1);
  pcx_rgb = malloc( count * 4);

  for (y=0 ; y<=pcx->ymax ; y++)
  {
    pix = pcx_rgb + 4*y*(pcx->xmax+1);
    for (x=0 ; x<=pcx->ymax ; )
    {
      dataByte = fgetc(f);

      if((dataByte & 0xC0) == 0xC0)
      {
        runLength = dataByte & 0x3F;
        dataByte = fgetc(f);
      }
      else
        runLength = 1;

      while(runLength-- > 0)
      {
        pix[0] = palette[dataByte*3];
        pix[1] = palette[dataByte*3+1];
        pix[2] = palette[dataByte*3+2];
        pix[3] = 255;
        pix += 4;
        x++;
      }
    }
  }
}

/*
=========================================================

TARGA LOADING

=========================================================
*/

typedef struct _TargaHeader {
  unsigned char   id_length, colormap_type, image_type;
  unsigned short  colormap_index, colormap_length;
  unsigned char colormap_size;
  unsigned short  x_origin, y_origin, width, height;
  unsigned char pixel_size, attributes;
} TargaHeader;


TargaHeader   targa_header;
byte      *targa_rgba;

int fgetLittleShort (FILE *f)
{
  byte  b1, b2;

  b1 = fgetc(f);
  b2 = fgetc(f);

  return (short)(b1 + b2*256);
}

int fgetLittleLong (FILE *f)
{
  byte  b1, b2, b3, b4;

  b1 = fgetc(f);
  b2 = fgetc(f);
  b3 = fgetc(f);
  b4 = fgetc(f);

  return b1 + (b2<<8) + (b3<<16) + (b4<<24);
}


/*
=============
LoadTGA
=============
*/
void LoadTGA (FILE *fin)
{
  int       columns, rows, numPixels;
  byte      *pixbuf;
  int       row, column;

  targa_header.id_length = fgetc(fin);
  targa_header.colormap_type = fgetc(fin);
  targa_header.image_type = fgetc(fin);
  
  targa_header.colormap_index = fgetLittleShort(fin);
  targa_header.colormap_length = fgetLittleShort(fin);
  targa_header.colormap_size = fgetc(fin);
  targa_header.x_origin = fgetLittleShort(fin);
  targa_header.y_origin = fgetLittleShort(fin);
  targa_header.width = fgetLittleShort(fin);
  targa_header.height = fgetLittleShort(fin);
  targa_header.pixel_size = fgetc(fin);
  targa_header.attributes = fgetc(fin);

  if (targa_header.image_type!=2 
    && targa_header.image_type!=10) 
    Sys_Error ("LoadTGA: Only type 2 and 10 targa RGB images supported\n");

  if (targa_header.colormap_type !=0 
    || (targa_header.pixel_size!=32 && targa_header.pixel_size!=24))
    Sys_Error ("Texture_LoadTGA: Only 32 or 24 bit images supported (no colormaps)\n");

  columns = targa_header.width;
  rows = targa_header.height;
  numPixels = columns * rows;

  targa_rgba = malloc (numPixels*4);
  
  if (targa_header.id_length != 0)
    fseek(fin, targa_header.id_length, SEEK_CUR);  // skip TARGA image comment
  
  if (targa_header.image_type==2) {  // Uncompressed, RGB images
    for(row=rows-1; row>=0; row--) {
      pixbuf = targa_rgba + row*columns*4;
      for(column=0; column<columns; column++) {
        unsigned char red,green,blue,alphabyte;
        switch (targa_header.pixel_size) {
          case 24:
              
              blue = getc(fin);
              green = getc(fin);
              red = getc(fin);
              *pixbuf++ = red;
              *pixbuf++ = green;
              *pixbuf++ = blue;
              *pixbuf++ = 255;
              break;
          case 32:
              blue = getc(fin);
              green = getc(fin);
              red = getc(fin);
              alphabyte = getc(fin);
              *pixbuf++ = red;
              *pixbuf++ = green;
              *pixbuf++ = blue;
              *pixbuf++ = alphabyte;
              break;
        }
      }
    }
  }
  else if (targa_header.image_type==10) {   // Runlength encoded RGB images
    unsigned char red,green,blue,alphabyte,packetHeader,packetSize,j;
    for(row=rows-1; row>=0; row--) {
      pixbuf = targa_rgba + row*columns*4;
      for(column=0; column<columns; ) {
        packetHeader=getc(fin);
        packetSize = 1 + (packetHeader & 0x7f);
        if (packetHeader & 0x80) {        // run-length packet
          switch (targa_header.pixel_size) {
            case 24:
                blue = getc(fin);
                green = getc(fin);
                red = getc(fin);
                alphabyte = 255;
                break;
            case 32:
                blue = getc(fin);
                green = getc(fin);
                red = getc(fin);
                alphabyte = getc(fin);
                break;
          }
  
          for(j=0;j<packetSize;j++) {
            *pixbuf++=red;
            *pixbuf++=green;
            *pixbuf++=blue;
            *pixbuf++=alphabyte;
            column++;
            if (column==columns) { // run spans across rows
              column=0;
              if (row>0)
                row--;
              else
                goto breakOut;
              pixbuf = targa_rgba + row*columns*4;
            }
          }
        }
        else {                            // non run-length packet
          for(j=0;j<packetSize;j++) {
            switch (targa_header.pixel_size) {
              case 24:
                  blue = getc(fin);
                  green = getc(fin);
                  red = getc(fin);
                  *pixbuf++ = red;
                  *pixbuf++ = green;
                  *pixbuf++ = blue;
                  *pixbuf++ = 255;
                  break;
              case 32:
                  blue = getc(fin);
                  green = getc(fin);
                  red = getc(fin);
                  alphabyte = getc(fin);
                  *pixbuf++ = red;
                  *pixbuf++ = green;
                  *pixbuf++ = blue;
                  *pixbuf++ = alphabyte;
                  break;
            }
            column++;
            if (column==columns) { // pixel packet run spans across rows
              column=0;
              if (row>0)
                row--;
              else
                goto breakOut;
              pixbuf = targa_rgba + row*columns*4;
            }           
          }
        }
      }
      breakOut:;
    }
  }
  
  fclose(fin);
}

/*
==================
R_LoadSkys
==================
*/
char  *suf[6] = {"rt", "bk", "lf", "ft", "up", "dn"};
void R_LoadSkys (void)
{
  int   i;
  FILE  *f;
  char  name[64];

  for (i=0 ; i<6 ; i++)
  {
    GL_Bind (SKY_TEX + i);
    sprintf (name, "gfx/env/bkgtst%s.tga", suf[i]);
    COM_FOpenFile (name, &f);
    if (!f)
    {
      Con_Printf ("Couldn't load %s\n", name);
      continue;
    }
    LoadTGA (f);
//    LoadPCX (f);

    glTexImage2D (GL_TEXTURE_2D, 0, gl_solid_format, 256, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, targa_rgba);
//    glTexImage2D (GL_TEXTURE_2D, 0, gl_solid_format, 256, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, pcx_rgb);

    free (targa_rgba);
//    free (pcx_rgb);

    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  }
}


vec3_t  skyclip[6] = {
  {1,1,0},
  {1,-1,0},
  {0,-1,1},
  {0,1,1},
  {1,0,1},
  {-1,0,1} 
};
int c_sky;

// 1 = s, 2 = t, 3 = 2048
int st_to_vec[6][3] =
{
  {3,-1,2},
  {-3,1,2},

  {1,3,2},
  {-1,-3,2},

  {-2,-1,3},    // 0 degrees yaw, look straight up
  {2,-1,-3}   // look straight down

//  {-1,2,3},
//  {1,2,-3}
};

// s = [0]/[2], t = [1]/[2]
int vec_to_st[6][3] =
{
  {-2,3,1},
  {2,3,-1},

  {1,3,2},
  {-1,3,-2},

  {-2,-1,3},
  {-2,1,-3}

//  {-1,2,3},
//  {1,2,-3}
};

float skymins[2][6], skymaxs[2][6];

void DrawSkyPolygon (int nump, vec3_t vecs)
{
  int   i,j;
  vec3_t  v, av;
  float s, t, dv;
  int   axis;
  float *vp;

  c_sky++;
#if 0
glBegin (GL_POLYGON);
for (i=0 ; i<nump ; i++, vecs+=3)
{
  VectorAdd(vecs, r_origin, v);
  glVertex3fv (v);
}
glEnd();
return;
#endif
  // decide which face it maps to
  VectorCopy (vec3_origin, v);
  for (i=0, vp=vecs ; i<nump ; i++, vp+=3)
  {
    VectorAdd (vp, v, v);
  }
  av[0] = fabs(v[0]);
  av[1] = fabs(v[1]);
  av[2] = fabs(v[2]);
  if (av[0] > av[1] && av[0] > av[2])
  {
    if (v[0] < 0)
      axis = 1;
    else
      axis = 0;
  }
  else if (av[1] > av[2] && av[1] > av[0])
  {
    if (v[1] < 0)
      axis = 3;
    else
      axis = 2;
  }
  else
  {
    if (v[2] < 0)
      axis = 5;
    else
      axis = 4;
  }

  // project new texture coords
  for (i=0 ; i<nump ; i++, vecs+=3)
  {
    j = vec_to_st[axis][2];
    if (j > 0)
      dv = vecs[j - 1];
    else
      dv = -vecs[-j - 1];

    j = vec_to_st[axis][0];
    if (j < 0)
      s = -vecs[-j -1] / dv;
    else
      s = vecs[j-1] / dv;
    j = vec_to_st[axis][1];
    if (j < 0)
      t = -vecs[-j -1] / dv;
    else
      t = vecs[j-1] / dv;

    if (s < skymins[0][axis])
      skymins[0][axis] = s;
    if (t < skymins[1][axis])
      skymins[1][axis] = t;
    if (s > skymaxs[0][axis])
      skymaxs[0][axis] = s;
    if (t > skymaxs[1][axis])
      skymaxs[1][axis] = t;
  }
}

#define MAX_CLIP_VERTS  64
void ClipSkyPolygon (int nump, vec3_t vecs, int stage)
{
  float *norm;
  float *v;
  qboolean  front, back;
  float d, e;
  float dists[MAX_CLIP_VERTS];
  int   sides[MAX_CLIP_VERTS];
  vec3_t  newv[2][MAX_CLIP_VERTS];
  int   newc[2];
  int   i, j;

  if (nump > MAX_CLIP_VERTS-2)
    Sys_Error ("ClipSkyPolygon: MAX_CLIP_VERTS");
  if (stage == 6)
  { // fully clipped, so draw it
    DrawSkyPolygon (nump, vecs);
    return;
  }

  front = back = false;
  norm = skyclip[stage];
  for (i=0, v = vecs ; i<nump ; i++, v+=3)
  {
    d = DotProduct (v, norm);
    if (d > ON_EPSILON)
    {
      front = true;
      sides[i] = SIDE_FRONT;
    }
    else if (d < ON_EPSILON)
    {
      back = true;
      sides[i] = SIDE_BACK;
    }
    else
      sides[i] = SIDE_ON;
    dists[i] = d;
  }

  if (!front || !back)
  { // not clipped
    ClipSkyPolygon (nump, vecs, stage+1);
    return;
  }

  // clip it
  sides[i] = sides[0];
  dists[i] = dists[0];
  VectorCopy (vecs, (vecs+(i*3)) );
  newc[0] = newc[1] = 0;

  for (i=0, v = vecs ; i<nump ; i++, v+=3)
  {
    switch (sides[i])
    {
    case SIDE_FRONT:
      VectorCopy (v, newv[0][newc[0]]);
      newc[0]++;
      break;
    case SIDE_BACK:
      VectorCopy (v, newv[1][newc[1]]);
      newc[1]++;
      break;
    case SIDE_ON:
      VectorCopy (v, newv[0][newc[0]]);
      newc[0]++;
      VectorCopy (v, newv[1][newc[1]]);
      newc[1]++;
      break;
    }

    if (sides[i] == SIDE_ON || sides[i+1] == SIDE_ON || sides[i+1] == sides[i])
      continue;

    d = dists[i] / (dists[i] - dists[i+1]);
    for (j=0 ; j<3 ; j++)
    {
      e = v[j] + d*(v[j+3] - v[j]);
      newv[0][newc[0]][j] = e;
      newv[1][newc[1]][j] = e;
    }
    newc[0]++;
    newc[1]++;
  }

  // continue
  ClipSkyPolygon (newc[0], newv[0][0], stage+1);
  ClipSkyPolygon (newc[1], newv[1][0], stage+1);
}

/*
=================
R_DrawSkyChain
=================
*/
void R_DrawSkyChain (msurface_t *s)
{
  msurface_t  *fa;

  int   i;
  vec3_t  verts[MAX_CLIP_VERTS];
  glpoly_t  *p;

  c_sky = 0;
  GL_Bind(solidskytexture);

  // calculate vertex values for sky box

  for (fa=s ; fa ; fa=fa->texturechain)
  {
    for (p=fa->polys ; p ; p=p->next)
    {
      for (i=0 ; i<p->numverts ; i++)
      {
        VectorSubtract (p->verts[i], r_origin, verts[i]);
      }
      ClipSkyPolygon (p->numverts, verts[0], 0);
    }
  }
}


/*
==============
R_ClearSkyBox
==============
*/
void R_ClearSkyBox (void)
{
  int   i;

  for (i=0 ; i<6 ; i++)
  {
    skymins[0][i] = skymins[1][i] = 9999;
    skymaxs[0][i] = skymaxs[1][i] = -9999;
  }
}


void MakeSkyVec (float s, float t, int axis)
{
  vec3_t    v, b;
  int     j, k;

  b[0] = s*2048;
  b[1] = t*2048;
  b[2] = 2048;

  for (j=0 ; j<3 ; j++)
  {
    k = st_to_vec[axis][j];
    if (k < 0)
      v[j] = -b[-k - 1];
    else
      v[j] = b[k - 1];
    v[j] += r_origin[j];
  }

  // avoid bilerp seam
  s = (s+1)*0.5;
  t = (t+1)*0.5;

  if (s < 1.0/512)
    s = 1.0/512;
  else if (s > 511.0/512)
    s = 511.0/512;
  if (t < 1.0/512)
    t = 1.0/512;
  else if (t > 511.0/512)
    t = 511.0/512;

  t = 1.0 - t;
  glTexCoord2f (s, t);
  glVertex3fv (v);
}

/*
==============
R_DrawSkyBox
==============
*/
int skytexorder[6] = {0,2,1,3,4,5};
void R_DrawSkyBox (void)
{
  int   i, j, k;
  vec3_t  v;
  float s, t;

#if 0
glEnable (GL_BLEND);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glColor4f (1,1,1,0.5);
glDisable (GL_DEPTH_TEST);
#endif
  for (i=0 ; i<6 ; i++)
  {
    if (skymins[0][i] >= skymaxs[0][i]
    || skymins[1][i] >= skymaxs[1][i])
      continue;

    GL_Bind (SKY_TEX+skytexorder[i]);
#if 0
skymins[0][i] = -1;
skymins[1][i] = -1;
skymaxs[0][i] = 1;
skymaxs[1][i] = 1;
#endif
    glBegin (GL_QUADS);
    MakeSkyVec (skymins[0][i], skymins[1][i], i);
    MakeSkyVec (skymins[0][i], skymaxs[1][i], i);
    MakeSkyVec (skymaxs[0][i], skymaxs[1][i], i);
    MakeSkyVec (skymaxs[0][i], skymins[1][i], i);
    glEnd ();
  }
#if 0
glDisable (GL_BLEND);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glColor4f (1,1,1,0.5);
glEnable (GL_DEPTH_TEST);
#endif
}


#endif

//===============================================================

/*
=============
R_InitSky

A sky texture is 256*128, with the right side being a masked overlay
==============
*/
void R_InitSky (texture_t *mt)
{
  int     i, j, p;
  byte    *src;
  unsigned  trans[128*128];
  unsigned  transpix;
  int     r, g, b;
  unsigned  *rgba;
  extern  int     skytexturenum;

  src = (byte *)mt + mt->offsets[0];

  // make an average value for the back to avoid
  // a fringe on the top level

  r = g = b = 0;
  for (i=0 ; i<128 ; i++)
    for (j=0 ; j<128 ; j++)
    {
      p = src[i*256 + j + 128];
      rgba = &d_8to24table[p];
      trans[(i*128) + j] = *rgba;
      r += ((byte *)rgba)[0];
      g += ((byte *)rgba)[1];
      b += ((byte *)rgba)[2];
    }

  ((byte *)&transpix)[0] = r/(128*128);
  ((byte *)&transpix)[1] = g/(128*128);
  ((byte *)&transpix)[2] = b/(128*128);
  ((byte *)&transpix)[3] = 0;


  if (!solidskytexture)
    solidskytexture = texture_extension_number++;
  GL_Bind (solidskytexture );
  glTexImage2D (GL_TEXTURE_2D, 0, gl_solid_format, 128, 128, 0, GL_RGBA, GL_UNSIGNED_BYTE, trans);
  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);


  for (i=0 ; i<128 ; i++)
    for (j=0 ; j<128 ; j++)
    {
      p = src[i*256 + j];
      if (p == 0)
        trans[(i*128) + j] = transpix;
      else
        trans[(i*128) + j] = d_8to24table[p];
    }

  if (!alphaskytexture)
    alphaskytexture = texture_extension_number++;
  GL_Bind(alphaskytexture);
  glTexImage2D (GL_TEXTURE_2D, 0, gl_alpha_format, 128, 128, 0, GL_RGBA, GL_UNSIGNED_BYTE, trans);
  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
}

