chop up gl_warp into gl_sky, pcx and tga. also break out pcx stuff from client.h

This commit is contained in:
Bill Currie 2000-10-28 19:58:22 +00:00
parent 5d07b61d7a
commit 06e50ba0c9
11 changed files with 798 additions and 660 deletions

View file

@ -518,24 +518,6 @@ void CL_ParseEntityLump(char *entdata);
// skin.c
//
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 char data; // unbounded
} pcx_t;
void Skin_Find (player_info_t *sc);
byte *Skin_Cache (skin_t *skin);
void Skin_Skins_f (void);

49
include/pcx.h Normal file
View file

@ -0,0 +1,49 @@
/*
pcx.h
pcx image hangling
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:
Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA
$Id$
*/
#ifndef __pcx_h
#define __pcx_h
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 char data; // unbounded
} pcx_t;
#endif // __pcx_h

37
include/tga.h Normal file
View file

@ -0,0 +1,37 @@
/*
tga.h
targa image hangling
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:
Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA
$Id$
*/
#ifndef __tga_h
#define __tga_h
#include "qtypes.h"
byte *
LoadTGA (QFile *fin);
#endif // __tga_h

View file

@ -148,7 +148,7 @@ endif
client_SOURCES= cl_cam.c cl_cmd.c cl_cvar.c cl_demo.c cl_ents.c cl_input.c \
cl_main.c cl_misc.c cl_parse.c cl_pred.c cl_slist.c cl_tent.c \
console.c keys.c menu.c model_alias.c model_sprite.c nonintel.c \
r_view.c sbar.c skin.c teamplay.c wad.c vid.c $(client_ASM)
pcx.c r_view.c sbar.c skin.c teamplay.c tga.c wad.c vid.c $(client_ASM)
#
# Software-rendering clients
@ -223,7 +223,7 @@ qf_client_x11_DEPENDENCIES=libqfsys_cl.a libqfsnd.a libqfcd.a libqfjs.a
ogl_SOURCES= fractalnoise.c gl_draw.c gl_dyn_fires.c gl_dyn_part.c \
gl_dyn_textures.c gl_mesh.c gl_ngraph.c gl_refrag.c \
gl_rlight.c gl_rmain.c gl_rmisc.c gl_rsurf.c gl_screen.c \
gl_trans.c gl_view.c gl_warp.c gl_model_alias.c \
gl_sky.c gl_trans.c gl_view.c gl_warp.c gl_model_alias.c \
gl_model_brush.c gl_model_fullbright.c gl_model_sprite.c
#

View file

@ -30,36 +30,19 @@
# include "config.h"
#endif
#include <math.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include "input.h"
#include "bothdefs.h" // needed by: common.h, net.h, client.h
#include "qendian.h"
#include "bspfile.h" // needed by: glquake.h
#include "vid.h"
#include "sys.h"
#include "mathlib.h" // needed by: protocol.h, render.h, client.h,
// modelgen.h, glmodel.h
#include "wad.h"
#include "cmd.h"
#include "console.h"
#include "draw.h"
#include "cvar.h"
#include "net.h" // needed by: client.h
#include "protocol.h" // needed by: client.h
#include "glquake.h"
#include "keys.h"
#include "menu.h"
#include "cmd.h"
#include "pcx.h"
#include "qendian.h"
#include "sbar.h"
#include "sound.h"
#include "screen.h"
#include "render.h" // needed by: client.h, gl_model.h, glquake.h
#include "client.h" // need cls in this file
#include "model.h" // needed by: glquake.h
#include "console.h"
#include "glquake.h"
#include "sys.h"
/*

352
source/gl_sky.c Normal file
View file

@ -0,0 +1,352 @@
/*
gl_sky.c
sky polygons
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:
Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA
$Id$
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <string.h>
#include "console.h"
#include "glquake.h"
#include "tga.h"
extern double realtime;
extern model_t *loadmodel;
extern int skytexturenum;
extern qboolean lighthalf;
int solidskytexture;
int alphaskytexture;
float speedscale; // for top sky and bottom sky
// Set to true if a valid skybox is loaded --KB
qboolean skyloaded = false;
msurface_t *warpface;
/*
=================================================================
Quake 2 environment sky
=================================================================
*/
#define SKY_TEX 2000
/*
==================
R_LoadSkys
==================
*/
char *suf[6] = {"rt", "bk", "lf", "ft", "up", "dn"};
void R_LoadSkys (char * skyname)
{
int i;
QFile *f;
char name[64];
if (stricmp (skyname, "none") == 0)
{
skyloaded = false;
return;
}
skyloaded = true;
for (i=0 ; i<6 ; i++) {
byte *targa_rgba;
glBindTexture (GL_TEXTURE_2D, SKY_TEX + i);
snprintf (name, sizeof(name),"env/%s%s.tga", skyname, suf[i]);
COM_FOpenFile (name, &f);
if (!f) {
Con_DPrintf ("Couldn't load %s\n", name);
skyloaded = false;
continue;
}
targa_rgba = LoadTGA (f);
glTexImage2D (GL_TEXTURE_2D, 0, gl_solid_format, 256, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, targa_rgba);
free (targa_rgba);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
}
if (!skyloaded)
Con_Printf ("Unable to load skybox %s, using normal sky\n",
skyname);
}
void
R_SkyBoxPolyVec(vec5_t v)
{
// avoid interpolation seams
// s = s * (254.0/256.0) + (1.0/256.0);
// t = t * (254.0/256.0) + (1.0/256.0);
glTexCoord2fv (v);
glVertex3f (r_refdef.vieworg[0] + v[2],
r_refdef.vieworg[1] + v[3],
r_refdef.vieworg[2] + v[4]);
}
#define ftc(x) (x * (254.0/256.0) + (1.0/256.0))
vec5_t skyvec[6][4] = {
{
// right
{ftc(1), ftc(0), 1024, 1024, 1024},
{ftc(1), ftc(1), 1024, 1024, -1024},
{ftc(0), ftc(1), -1024, 1024, -1024},
{ftc(0), ftc(0), -1024, 1024, 1024}
},
{
// back
{ftc(1), ftc(0), -1024, 1024, 1024},
{ftc(1), ftc(1), -1024, 1024, -1024},
{ftc(0), ftc(1), -1024, -1024, -1024},
{ftc(0), ftc(0), -1024, -1024, 1024}
},
{
// left
{ftc(1), ftc(0), -1024, -1024, 1024},
{ftc(1), ftc(1), -1024, -1024, -1024},
{ftc(0), ftc(1), 1024, -1024, -1024},
{ftc(0), ftc(0), 1024, -1024, 1024}
},
{
// front
{ftc(1), ftc(0), 1024, -1024, 1024},
{ftc(1), ftc(1), 1024, -1024, -1024},
{ftc(0), ftc(1), 1024, 1024, -1024},
{ftc(0), ftc(0), 1024, 1024, 1024}
},
{
// up
{ftc(1), ftc(0), 1024, -1024, 1024},
{ftc(1), ftc(1), 1024, 1024, 1024},
{ftc(0), ftc(1), -1024, 1024, 1024},
{ftc(0), ftc(0), -1024, -1024, 1024}
},
{
// down
{ftc(1), ftc(0), 1024, 1024, -1024},
{ftc(1), ftc(1), 1024, -1024, -1024},
{ftc(0), ftc(1), -1024, -1024, -1024},
{ftc(0), ftc(0), -1024, 1024, -1024}
}
};
#undef ftc
void
R_DrawSkyBox (void)
{
int i, j;
glDisable (GL_DEPTH_TEST);
glDepthRange (gldepthmax, gldepthmax);
for (i = 0; i < 6; i++)
{
glBindTexture(GL_TEXTURE_2D, SKY_TEX + i);
glBegin(GL_QUADS);
for (j = 0; j < 4; j++)
R_SkyBoxPolyVec(skyvec[i][j]);
glEnd();
}
glEnable (GL_DEPTH_TEST);
glDepthRange(gldepthmin, gldepthmax);
}
vec3_t domescale;
void
R_DrawSkyLayer (float s)
{
int a, b;
float x, y, a1x, a1y, a2x, a2y;
vec3_t v;
for (a = 0; a < 16; a++)
{
a1x = bubble_costable[a*2];
a1y = -bubble_sintable[a*2];
a2x = bubble_costable[(a+1)*2];
a2y = -bubble_sintable[(a+1)*2];
glBegin (GL_TRIANGLE_STRIP);
glTexCoord2f(0.5 + s * (1.0 / 128.0), 0.5 + s * (1.0 / 128.0));
glVertex3f(r_refdef.vieworg[0],
r_refdef.vieworg[1],
r_refdef.vieworg[2]+domescale[2]);
for (b = 1; b < 8; b++)
{
x = bubble_costable[b*2+16];
y = -bubble_sintable[b*2+16];
v[0] = a1x*x * domescale[0];
v[1] = a1y*x * domescale[1];
v[2] = y * domescale[2];
glTexCoord2f((v[0] + s) * (1.0 / 128.0),
(v[1] + s) * (1.0 / 128.0));
glVertex3f(v[0] + r_refdef.vieworg[0],
v[1] + r_refdef.vieworg[1],
v[2] + r_refdef.vieworg[2]);
v[0] = a2x*x * domescale[0];
v[1] = a2y*x * domescale[1];
v[2] = y * domescale[2];
glTexCoord2f((v[0] + s) * (1.0 / 128.0),
(v[1] + s) * (1.0 / 128.0));
glVertex3f(v[0] + r_refdef.vieworg[0],
v[1] + r_refdef.vieworg[1],
v[2] + r_refdef.vieworg[2]);
}
glTexCoord2f(0.5 + s * (1.0 / 128.0), 0.5 + s * (1.0 / 128.0));
glVertex3f(r_refdef.vieworg[0],
r_refdef.vieworg[1],
r_refdef.vieworg[2]-domescale[2]);
glEnd ();
}
}
void
R_DrawSkyDome (void)
{
glDisable (GL_DEPTH_TEST);
glDepthRange (gldepthmax, gldepthmax);
glDisable (GL_BLEND);
// base sky
glBindTexture (GL_TEXTURE_2D, solidskytexture);
domescale[0] = 512;
domescale[1] = 512;
domescale[2] = 128;
speedscale = realtime*8;
speedscale -= (int)speedscale & ~127;
R_DrawSkyLayer (speedscale);
glEnable (GL_BLEND);
// clouds
if (gl_skymultipass->int_val) {
glBindTexture (GL_TEXTURE_2D, alphaskytexture);
domescale[0] = 512;
domescale[1] = 512;
domescale[2] = 128;
speedscale = realtime*16;
speedscale -= (int)speedscale & ~127;
R_DrawSkyLayer (speedscale);
}
glEnable (GL_DEPTH_TEST);
glDepthRange (gldepthmin, gldepthmax);
}
void
R_DrawSky ( void )
{
if (skyloaded)
R_DrawSkyBox();
else
R_DrawSkyDome();
}
//===============================================================
/*
=============
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 int trans[128*128];
unsigned int transpix;
int r, g, b;
unsigned int *rgba;
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++;
glBindTexture (GL_TEXTURE_2D, 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++;
glBindTexture (GL_TEXTURE_2D, 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);
}

View file

@ -1,7 +1,7 @@
/*
gl_warp.c
sky and water polygons
water polygons
Copyright (C) 1996-1997 Id Software, Inc.
@ -30,33 +30,15 @@
# include "config.h"
#endif
#include <string.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#ifdef HAVE_STRINGS_H
#include <strings.h>
#endif
#include "bothdefs.h"
#include "console.h"
#include "model.h"
#include "cvar.h"
#include "glquake.h"
#include "sys.h"
extern double realtime;
extern model_t *loadmodel;
extern int skytexturenum;
extern qboolean lighthalf;
int solidskytexture;
int alphaskytexture;
float speedscale; // for top sky and bottom sky
// Set to true if a valid skybox is loaded --KB
qboolean skyloaded = false;
msurface_t *warpface;
extern cvar_t *gl_subdivide_size;
@ -253,578 +235,3 @@ void EmitWaterPolys (msurface_t *fa)
glEnd ();
}
}
/*
=================================================================
Quake 2 environment sky
=================================================================
*/
#define SKY_TEX 2000
/*
=================================================================
PCX Loading
=================================================================
*/
byte *pcx_rgb;
/*
============
LoadPCX
============
*/
void LoadPCX (QFile *f)
{
pcx_t *pcx, pcxbuf;
byte palette[768];
byte *pix;
int x, y;
int dataByte, runLength;
int count;
//
// parse the PCX file
//
Qread (f, &pcxbuf, sizeof(pcxbuf));
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
Qseek (f, -768, SEEK_END);
Qread (f, palette, 768);
Qseek (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 = Qgetc(f);
if((dataByte & 0xC0) == 0xC0)
{
runLength = dataByte & 0x3F;
dataByte = Qgetc(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 (QFile *f)
{
byte b1, b2;
b1 = Qgetc(f);
b2 = Qgetc(f);
return (short)(b1 + b2*256);
}
int fgetLittleLong (QFile *f)
{
byte b1, b2, b3, b4;
b1 = Qgetc(f);
b2 = Qgetc(f);
b3 = Qgetc(f);
b4 = Qgetc(f);
return b1 + (b2<<8) + (b3<<16) + (b4<<24);
}
/*
=============
LoadTGA
=============
*/
void LoadTGA (QFile *fin)
{
int columns, rows, numPixels;
byte *pixbuf;
int row, column;
unsigned char red = 0, green = 0, blue = 0, alphabyte = 0;
targa_header.id_length = Qgetc(fin);
targa_header.colormap_type = Qgetc(fin);
targa_header.image_type = Qgetc(fin);
targa_header.colormap_index = fgetLittleShort(fin);
targa_header.colormap_length = fgetLittleShort(fin);
targa_header.colormap_size = Qgetc(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 = Qgetc(fin);
targa_header.attributes = Qgetc(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)
Qseek(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++) {
switch (targa_header.pixel_size) {
case 24:
blue = Qgetc(fin);
green = Qgetc(fin);
red = Qgetc(fin);
*pixbuf++ = red;
*pixbuf++ = green;
*pixbuf++ = blue;
*pixbuf++ = 255;
break;
case 32:
blue = Qgetc(fin);
green = Qgetc(fin);
red = Qgetc(fin);
alphabyte = Qgetc(fin);
*pixbuf++ = red;
*pixbuf++ = green;
*pixbuf++ = blue;
*pixbuf++ = alphabyte;
break;
}
}
}
}
else if (targa_header.image_type==10) { // Runlength encoded RGB images
unsigned char packetHeader, packetSize, j;
for(row=rows-1; row>=0; row--) {
pixbuf = targa_rgba + row*columns*4;
for(column=0; column<columns; ) {
packetHeader=Qgetc(fin);
packetSize = 1 + (packetHeader & 0x7f);
if (packetHeader & 0x80) { // run-length packet
switch (targa_header.pixel_size) {
case 24:
blue = Qgetc(fin);
green = Qgetc(fin);
red = Qgetc(fin);
alphabyte = 255;
break;
case 32:
blue = Qgetc(fin);
green = Qgetc(fin);
red = Qgetc(fin);
alphabyte = Qgetc(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 = Qgetc(fin);
green = Qgetc(fin);
red = Qgetc(fin);
*pixbuf++ = red;
*pixbuf++ = green;
*pixbuf++ = blue;
*pixbuf++ = 255;
break;
case 32:
blue = Qgetc(fin);
green = Qgetc(fin);
red = Qgetc(fin);
alphabyte = Qgetc(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:;
}
}
Qclose(fin);
}
/*
==================
R_LoadSkys
==================
*/
char *suf[6] = {"rt", "bk", "lf", "ft", "up", "dn"};
void R_LoadSkys (char * skyname)
{
int i;
QFile *f;
char name[64];
if (stricmp (skyname, "none") == 0)
{
skyloaded = false;
return;
}
skyloaded = true;
for (i=0 ; i<6 ; i++)
{
glBindTexture (GL_TEXTURE_2D, SKY_TEX + i);
snprintf (name, sizeof(name),"env/%s%s.tga", skyname, suf[i]);
COM_FOpenFile (name, &f);
if (!f)
{
Con_DPrintf ("Couldn't load %s\n", name);
skyloaded = false;
continue;
}
LoadTGA (f);
glTexImage2D (GL_TEXTURE_2D, 0, gl_solid_format, 256, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, targa_rgba);
free (targa_rgba);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
}
if (!skyloaded)
Con_Printf ("Unable to load skybox %s, using normal sky\n",
skyname);
}
void
R_SkyBoxPolyVec(vec5_t v)
{
// avoid interpolation seams
// s = s * (254.0/256.0) + (1.0/256.0);
// t = t * (254.0/256.0) + (1.0/256.0);
glTexCoord2fv (v);
glVertex3f (r_refdef.vieworg[0] + v[2],
r_refdef.vieworg[1] + v[3],
r_refdef.vieworg[2] + v[4]);
}
#define ftc(x) (x * (254.0/256.0) + (1.0/256.0))
vec5_t skyvec[6][4] = {
{
// right
{ftc(1), ftc(0), 1024, 1024, 1024},
{ftc(1), ftc(1), 1024, 1024, -1024},
{ftc(0), ftc(1), -1024, 1024, -1024},
{ftc(0), ftc(0), -1024, 1024, 1024}
},
{
// back
{ftc(1), ftc(0), -1024, 1024, 1024},
{ftc(1), ftc(1), -1024, 1024, -1024},
{ftc(0), ftc(1), -1024, -1024, -1024},
{ftc(0), ftc(0), -1024, -1024, 1024}
},
{
// left
{ftc(1), ftc(0), -1024, -1024, 1024},
{ftc(1), ftc(1), -1024, -1024, -1024},
{ftc(0), ftc(1), 1024, -1024, -1024},
{ftc(0), ftc(0), 1024, -1024, 1024}
},
{
// front
{ftc(1), ftc(0), 1024, -1024, 1024},
{ftc(1), ftc(1), 1024, -1024, -1024},
{ftc(0), ftc(1), 1024, 1024, -1024},
{ftc(0), ftc(0), 1024, 1024, 1024}
},
{
// up
{ftc(1), ftc(0), 1024, -1024, 1024},
{ftc(1), ftc(1), 1024, 1024, 1024},
{ftc(0), ftc(1), -1024, 1024, 1024},
{ftc(0), ftc(0), -1024, -1024, 1024}
},
{
// down
{ftc(1), ftc(0), 1024, 1024, -1024},
{ftc(1), ftc(1), 1024, -1024, -1024},
{ftc(0), ftc(1), -1024, -1024, -1024},
{ftc(0), ftc(0), -1024, 1024, -1024}
}
};
#undef ftc
void
R_DrawSkyBox (void)
{
int i, j;
glDisable (GL_DEPTH_TEST);
glDepthRange (gldepthmax, gldepthmax);
for (i = 0; i < 6; i++)
{
glBindTexture(GL_TEXTURE_2D, SKY_TEX + i);
glBegin(GL_QUADS);
for (j = 0; j < 4; j++)
R_SkyBoxPolyVec(skyvec[i][j]);
glEnd();
}
glEnable (GL_DEPTH_TEST);
glDepthRange(gldepthmin, gldepthmax);
}
vec3_t domescale;
void
R_DrawSkyLayer (float s)
{
int a, b;
float x, y, a1x, a1y, a2x, a2y;
vec3_t v;
for (a = 0; a < 16; a++)
{
a1x = bubble_costable[a*2];
a1y = -bubble_sintable[a*2];
a2x = bubble_costable[(a+1)*2];
a2y = -bubble_sintable[(a+1)*2];
glBegin (GL_TRIANGLE_STRIP);
glTexCoord2f(0.5 + s * (1.0 / 128.0), 0.5 + s * (1.0 / 128.0));
glVertex3f(r_refdef.vieworg[0],
r_refdef.vieworg[1],
r_refdef.vieworg[2]+domescale[2]);
for (b = 1; b < 8; b++)
{
x = bubble_costable[b*2+16];
y = -bubble_sintable[b*2+16];
v[0] = a1x*x * domescale[0];
v[1] = a1y*x * domescale[1];
v[2] = y * domescale[2];
glTexCoord2f((v[0] + s) * (1.0 / 128.0),
(v[1] + s) * (1.0 / 128.0));
glVertex3f(v[0] + r_refdef.vieworg[0],
v[1] + r_refdef.vieworg[1],
v[2] + r_refdef.vieworg[2]);
v[0] = a2x*x * domescale[0];
v[1] = a2y*x * domescale[1];
v[2] = y * domescale[2];
glTexCoord2f((v[0] + s) * (1.0 / 128.0),
(v[1] + s) * (1.0 / 128.0));
glVertex3f(v[0] + r_refdef.vieworg[0],
v[1] + r_refdef.vieworg[1],
v[2] + r_refdef.vieworg[2]);
}
glTexCoord2f(0.5 + s * (1.0 / 128.0), 0.5 + s * (1.0 / 128.0));
glVertex3f(r_refdef.vieworg[0],
r_refdef.vieworg[1],
r_refdef.vieworg[2]-domescale[2]);
glEnd ();
}
}
void
R_DrawSkyDome (void)
{
glDisable (GL_DEPTH_TEST);
glDepthRange (gldepthmax, gldepthmax);
glDisable (GL_BLEND);
// base sky
glBindTexture (GL_TEXTURE_2D, solidskytexture);
domescale[0] = 512;
domescale[1] = 512;
domescale[2] = 128;
speedscale = realtime*8;
speedscale -= (int)speedscale & ~127;
R_DrawSkyLayer (speedscale);
glEnable (GL_BLEND);
// clouds
if (gl_skymultipass->int_val) {
glBindTexture (GL_TEXTURE_2D, alphaskytexture);
domescale[0] = 512;
domescale[1] = 512;
domescale[2] = 128;
speedscale = realtime*16;
speedscale -= (int)speedscale & ~127;
R_DrawSkyLayer (speedscale);
}
glEnable (GL_DEPTH_TEST);
glDepthRange (gldepthmin, gldepthmax);
}
void
R_DrawSky ( void )
{
if (skyloaded)
R_DrawSkyBox();
else
R_DrawSkyDome();
}
//===============================================================
/*
=============
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 int trans[128*128];
unsigned int transpix;
int r, g, b;
unsigned int *rgba;
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++;
glBindTexture (GL_TEXTURE_2D, 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++;
glBindTexture (GL_TEXTURE_2D, 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);
}

100
source/pcx.c Normal file
View file

@ -0,0 +1,100 @@
/*
pcx.c
pcx image handling
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:
Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA
$Id$
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "console.h"
#include "pcx.h"
#include "qtypes.h"
#include "quakefs.h"
byte *pcx_rgb;
/*
LoadPCX
*/
void LoadPCX (QFile *f)
{
pcx_t *pcx, pcxbuf;
byte palette[768];
byte *pix;
int x, y;
int dataByte, runLength;
int count;
//
// parse the PCX file
//
Qread (f, &pcxbuf, sizeof(pcxbuf));
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
Qseek (f, -768, SEEK_END);
Qread (f, palette, 768);
Qseek (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 = Qgetc(f);
if((dataByte & 0xC0) == 0xC0) {
runLength = dataByte & 0x3F;
dataByte = Qgetc(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++;
}
}
}
}

View file

@ -29,25 +29,26 @@
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include "input.h"
#include "sys.h"
#include "screen.h"
#include "r_local.h"
#include "wad.h"
#include "compat.h"
#include "draw.h"
#include "quakedef.h"
#include "keys.h"
#include "console.h"
#include "msg.h"
#include "sbar.h"
#include "menu.h"
#include "qendian.h"
#include "cmd.h"
#include <time.h>
#include <string.h>
#include "client.h"
#include "cmd.h"
#include "console.h"
#include "cvar.h"
#include "draw.h"
#include "keys.h"
#include "menu.h"
#include "msg.h"
#include "pcx.h"
#include "qendian.h"
#include "quakedef.h"
#include "r_local.h"
#include "sbar.h"
#include "sys.h"
#include "vid.h"
/*
background clear

View file

@ -29,16 +29,17 @@
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include "sys.h"
#include "cmd.h"
#include "msg.h"
#include "client.h"
#include "console.h"
#include "commdef.h"
#include "va.h"
#include <string.h>
#include "client.h"
#include "cmd.h"
#include "console.h"
#include "msg.h"
#include "pcx.h"
#include "sys.h"
#include "va.h"
cvar_t *baseskin;
cvar_t *noskins;

226
source/tga.c Normal file
View file

@ -0,0 +1,226 @@
/*
tga.c
targa image handling
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:
Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA
$Id$
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "quakefs.h"
#include "sys.h"
#include "tga.h"
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;
static int
fgetLittleShort (QFile *f)
{
byte b1, b2;
b1 = Qgetc(f);
b2 = Qgetc(f);
return (short)(b1 + b2*256);
}
static int
fgetLittleLong (QFile *f)
{
byte b1, b2, b3, b4;
b1 = Qgetc(f);
b2 = Qgetc(f);
b3 = Qgetc(f);
b4 = Qgetc(f);
return b1 + (b2<<8) + (b3<<16) + (b4<<24);
}
/*
=============
LoadTGA
=============
*/
byte *
LoadTGA (QFile *fin)
{
int columns, rows, numPixels;
byte *pixbuf;
int row, column;
unsigned char red = 0, green = 0, blue = 0, alphabyte = 0;
TargaHeader targa_header;
byte *targa_rgba;
targa_header.id_length = Qgetc(fin);
targa_header.colormap_type = Qgetc(fin);
targa_header.image_type = Qgetc(fin);
targa_header.colormap_index = fgetLittleShort(fin);
targa_header.colormap_length = fgetLittleShort(fin);
targa_header.colormap_size = Qgetc(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 = Qgetc(fin);
targa_header.attributes = Qgetc(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)
Qseek(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++) {
switch (targa_header.pixel_size) {
case 24:
blue = Qgetc(fin);
green = Qgetc(fin);
red = Qgetc(fin);
*pixbuf++ = red;
*pixbuf++ = green;
*pixbuf++ = blue;
*pixbuf++ = 255;
break;
case 32:
blue = Qgetc(fin);
green = Qgetc(fin);
red = Qgetc(fin);
alphabyte = Qgetc(fin);
*pixbuf++ = red;
*pixbuf++ = green;
*pixbuf++ = blue;
*pixbuf++ = alphabyte;
break;
}
}
}
}
else if (targa_header.image_type==10) { // Runlength encoded RGB images
unsigned char packetHeader, packetSize, j;
for(row=rows-1; row>=0; row--) {
pixbuf = targa_rgba + row*columns*4;
for(column=0; column<columns; ) {
packetHeader=Qgetc(fin);
packetSize = 1 + (packetHeader & 0x7f);
if (packetHeader & 0x80) { // run-length packet
switch (targa_header.pixel_size) {
case 24:
blue = Qgetc(fin);
green = Qgetc(fin);
red = Qgetc(fin);
alphabyte = 255;
break;
case 32:
blue = Qgetc(fin);
green = Qgetc(fin);
red = Qgetc(fin);
alphabyte = Qgetc(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 = Qgetc(fin);
green = Qgetc(fin);
red = Qgetc(fin);
*pixbuf++ = red;
*pixbuf++ = green;
*pixbuf++ = blue;
*pixbuf++ = 255;
break;
case 32:
blue = Qgetc(fin);
green = Qgetc(fin);
red = Qgetc(fin);
alphabyte = Qgetc(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:;
}
}
Qclose(fin);
return targa_rgba;
}