1
0
Fork 0
forked from fte/fteqw

Initial checkin of OpenGL renderer

git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@6 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Spoike 2004-08-22 22:29:09 +00:00
parent f64029bbc8
commit 8aa0eee611
22 changed files with 27620 additions and 0 deletions

949
engine/gl/LTFACE.C Normal file
View file

@ -0,0 +1,949 @@
#include "bothdefs.h"
#if defined(GLQUAKE) || (!defined(GLQUAKE) && !defined(SWQUAKE))
#ifdef RUNTIMELIGHTING
#if defined(GLQUAKE)
#include "quakedef.h"
extern model_t *lightmodel;
#define bsptexinfo(i) (*i)
#define dsurfedges lightmodel->surfedges
#define dvertexes lightmodel->vertexes
#define dedges lightmodel->edges
#define texinfo_t mtexinfo_t
#define Q_PI M_PI
#define Error Host_Error
#define byte qbyte
#define dfaces lightmodel->surfaces
#define dplanes lightmodel->planes
#define dface_t msurface_t
#define dvertex_t mvertex_t
#define point position
#define side flags & SURF_PLANEBACK
#define scaledist 1
#define rangescale 0.5
#define extrasamples 1
#define scalecos 0.5
typedef struct mentity_s {
vec3_t origin;
float light;
float angle;
float cone;
int style;
vec3_t colour;
char classname[64];
char target[64];
char targetname[64];
struct mentity_s *targetent;
} mentity_t;
static mentity_t entities[8192];
static int num_entities;
#define bsp_origin vec3_origin
/*
============
CastRay
Returns the distance between the points, or -1 if blocked
=============
*/
vec_t CastRay (vec3_t p1, vec3_t p2)
{
trace_t trace;
vec3_t move;
hull_t *hull;
hull = &lightmodel->hulls[0];
memset (&trace, 0, sizeof(trace));
if (!hull->funcs.RecursiveHullCheck (hull, hull->firstclipnode, 0, 1, p1, p2, &trace))
return -1;
VectorSubtract(p1, p2, move);
return VectorLength(move);
}
static void ParseEpair (mentity_t *mapent, char *key, char *value)
{
double vec[3];
if (!strcmp(key, "classname"))
strcpy(mapent->classname, value);
else if (!strcmp(key, "target"))
strcpy(mapent->target, value);
else if (!strcmp(key, "targetname"))
strcpy(mapent->targetname, value);
else if (!strcmp(key, "light") || !strcmp(key, "_light"))
mapent->light = atoi(value);
else if (!strcmp(key, "style") || !strcmp(key, "_style"))
mapent->style = atoi(value);
else if (!strcmp(key, "angle") || !strcmp(key, "_angle"))
mapent->angle = atof(value);
else if (!strcmp(key, "cone") || !strcmp(key, "_cone"))
mapent->cone = atof(value);
else if (!strcmp(key, "origin"))
{
sscanf (value, "%lf %lf %lf", &vec[0], &vec[1], &vec[2]);
mapent->origin[0]=vec[0];
mapent->origin[1]=vec[1];
mapent->origin[2]=vec[2];
}
else if (!strcmp(key, "colour") || !strcmp(key, "color") || !strcmp(key, "_colour") || !strcmp(key, "_color"))
{
sscanf (value, "%lf %lf %lf", &vec[0], &vec[1], &vec[2]);
mapent->colour[0]=vec[0];
mapent->colour[1]=vec[1];
mapent->colour[2]=vec[2];
}
}
void LightLoadEntities(char *entstring)
{
#define DEFAULTLIGHTLEVEL 300
mentity_t *mapent;
char key[1024];
int i;
int switchedstyle=32;
num_entities = 0;
while(1)
{
entstring = COM_Parse(entstring);
if (!entstring || !*com_token)
break;
if (strcmp(com_token, "{"))
Host_Error("token wasn't an open brace\n");
mapent = &entities[num_entities];
memset(mapent, 0, sizeof(*mapent));
mapent->colour[0] = 0;
mapent->colour[1] = 0;
mapent->colour[2] = 0;
while(1)
{
entstring = COM_Parse(entstring);
if (!strcmp(com_token, "}"))
break;
strcpy(key, com_token);
entstring = COM_Parse(entstring);
ParseEpair(mapent, key, com_token);
}
if (!mapent->colour[0] && !mapent->colour[1] && !mapent->colour[2])
{
int cont;
vec3_t v;
hull_t *hull = &lightmodel->hulls[0];
v[0] = mapent->origin[0];
v[1] = mapent->origin[1];
cont=0;
for (i = 0; i < 256; i+=16)
{
v[2] = mapent->origin[2]-i;
cont = hull->funcs.HullPointContents (hull, v);
if (cont & (FTECONTENTS_LAVA | FTECONTENTS_SLIME | FTECONTENTS_SOLID))
break;
}
if (cont & FTECONTENTS_LAVA)
{
mapent->colour[0] = 1;
mapent->colour[1] = i/256.0;
mapent->colour[2] = i/256.0;
}
else if (cont & FTECONTENTS_SLIME)
{
mapent->colour[0] = 0.5+0.5*i/256.0;
mapent->colour[1] = 1;
mapent->colour[2] = 0.5+0.5*i/256.0;
}
else
{
if (mapent->style == 9) //hmm..
{
mapent->colour[1] = 1;
}
else
{
if (!strncmp(mapent->classname, "light_torch_small_walltorch", 12))
{
mapent->colour[0] = 1;
mapent->colour[1] = 0.7;
mapent->colour[2] = 0.7;
}
else
{
mapent->colour[0] = 1;
mapent->colour[1] = 1;
if (strncmp(mapent->classname, "light_fluoro", 12))
mapent->colour[2] = 1;
}
}
}
}
if (!mapent->light && !strncmp (mapent->classname, "light", 5))
mapent->light = DEFAULTLIGHTLEVEL;
if (*mapent->targetname && !mapent->style && !strcmp(mapent->classname, "light"))
{
for (i = 0; i <= num_entities; i++)
{
if (entities[i].style >= 32 && !strcmp(entities[i].targetname, mapent->targetname))
{
mapent->style = entities[i].style;
break;
}
}
if (i == num_entities)
mapent->style = switchedstyle++;
}
num_entities++;
}
for (mapent = entities; mapent < &entities[num_entities]; mapent++)
{
if (*mapent->target)
{
for (i = 0; i < num_entities; i++)
{
if (mapent == &entities[i])
continue;
if (!strcmp(mapent->target, entities[i].targetname))
{
mapent->targetent = &entities[i];
break;
}
}
}
}
}
#else
#define mentity_t entity_t
#define UTILITY
#include "light.h"
#define bsptexinfo(i) texinfo[i]
/*
============
CastRay
Returns the distance between the points, or -1 if blocked
=============
*/
vec_t CastRay (vec3_t p1, vec3_t p2)
{
int i;
vec_t t;
qboolean trace;
trace = TestLine (p1, p2);
if (!trace)
return -1; // ray was blocked
t = 0;
for (i=0 ; i< 3 ; i++)
t += (p2[i]-p1[i]) * (p2[i]-p1[i]);
if (t < 1)
t = 1; // don't blow up...
return sqrt(t);
}
#endif
/*
===============================================================================
SAMPLE POINT DETERMINATION
void SetupBlock (dface_t *f) Returns with surfpt[] set
This is a little tricky because the lightmap covers more area than the face.
If done in the straightforward fashion, some of the
sample points will be inside walls or on the other side of walls, causing
false shadows and light bleeds.
To solve this, I only consider a sample point valid if a line can be drawn
between it and the exact midpoint of the face. If invalid, it is adjusted
towards the center until it is valid.
(this doesn't completely work)
===============================================================================
*/
#define SINGLEMAP (18*18*4)
typedef struct
{
vec3_t lightmaps[MAXLIGHTMAPS][SINGLEMAP];
vec3_t lightnorm[MAXLIGHTMAPS][SINGLEMAP];
int numlightstyles;
vec_t *light;
vec_t facedist;
vec3_t facenormal;
int numsurfpt;
vec3_t surfpt[SINGLEMAP];
vec3_t texorg;
vec3_t worldtotex[2]; // s = (world - texorg) . worldtotex[0]
vec3_t textoworld[2]; // world = texorg + s * textoworld[0]
vec_t exactmins[2], exactmaxs[2];
int texmins[2], texsize[2];
int lightstyles[256];
int surfnum;
dface_t *face;
} llightinfo_t;
/*
================
CalcFaceVectors
Fills in texorg, worldtotex. and textoworld
================
*/
static void LightCalcFaceVectors (llightinfo_t *l)
{
texinfo_t *tex;
int i, j;
vec3_t texnormal;
float distscale;
vec_t dist, len;
tex = &bsptexinfo(l->face->texinfo);
// convert from float to vec_t
for (i=0 ; i<2 ; i++)
for (j=0 ; j<3 ; j++)
l->worldtotex[i][j] = tex->vecs[i][j];
// calculate a normal to the texture axis. points can be moved along this
// without changing their S/T
texnormal[0] = tex->vecs[1][1]*tex->vecs[0][2]
- tex->vecs[1][2]*tex->vecs[0][1];
texnormal[1] = tex->vecs[1][2]*tex->vecs[0][0]
- tex->vecs[1][0]*tex->vecs[0][2];
texnormal[2] = tex->vecs[1][0]*tex->vecs[0][1]
- tex->vecs[1][1]*tex->vecs[0][0];
VectorNormalize (texnormal);
// flip it towards plane normal
distscale = DotProduct (texnormal, l->facenormal);
if (!distscale)
Error ("Texture axis perpendicular to face");
if (distscale < 0)
{
distscale = -distscale;
VectorSubtract (vec3_origin, texnormal, texnormal);
}
// distscale is the ratio of the distance along the texture normal to
// the distance along the plane normal
distscale = 1/distscale;
for (i=0 ; i<2 ; i++)
{
len = VectorLength (l->worldtotex[i]);
dist = DotProduct (l->worldtotex[i], l->facenormal);
dist *= distscale;
VectorMA (l->worldtotex[i], -dist, texnormal, l->textoworld[i]);
VectorScale (l->textoworld[i], (1/len)*(1/len), l->textoworld[i]);
}
// calculate texorg on the texture plane
for (i=0 ; i<3 ; i++)
l->texorg[i] = -tex->vecs[0][3]* l->textoworld[0][i] - tex->vecs[1][3] * l->textoworld[1][i];
// project back to the face plane
dist = DotProduct (l->texorg, l->facenormal) - l->facedist - 1;
dist *= distscale;
VectorMA (l->texorg, -dist, texnormal, l->texorg);
}
/*
================
CalcFaceExtents
Fills in s->texmins[] and s->texsize[]
also sets exactmins[] and exactmaxs[]
================
*/
static void LightCalcFaceExtents (llightinfo_t *l)
{
dface_t *s;
vec_t mins[2], maxs[2], val;
int i,j, e;
dvertex_t *v;
texinfo_t *tex;
s = l->face;
mins[0] = mins[1] = 999999;
maxs[0] = maxs[1] = -99999;
tex = &bsptexinfo(s->texinfo);
for (i=0 ; i<s->numedges ; i++)
{
e = dsurfedges[s->firstedge+i];
if (e >= 0)
v = dvertexes + dedges[e].v[0];
else
v = dvertexes + dedges[-e].v[1];
for (j=0 ; j<2 ; j++)
{
val = v->point[0] * tex->vecs[j][0] +
v->point[1] * tex->vecs[j][1] +
v->point[2] * tex->vecs[j][2] +
tex->vecs[j][3];
if (val < mins[j])
mins[j] = val;
if (val > maxs[j])
maxs[j] = val;
}
}
for (i=0 ; i<2 ; i++)
{
l->exactmins[i] = mins[i];
l->exactmaxs[i] = maxs[i];
mins[i] = floor(mins[i]/16);
maxs[i] = ceil(maxs[i]/16);
l->texmins[i] = mins[i];
l->texsize[i] = maxs[i] - mins[i];
if (l->texsize[i] > 17)
Error ("Bad surface extents");
}
}
/*
=================
CalcPoints
For each texture aligned grid point, back project onto the plane
to get the world xyz value of the sample point
=================
*/
int c_bad;
static void LightCalcPoints (llightinfo_t *l)
{
int i;
int s, t, j;
int w, h, step;
vec_t starts, startt, us, ut;
vec_t *surf;
vec_t mids, midt;
vec3_t facemid, move;
//
// fill in surforg
// the points are biased towards the center of the surface
// to help avoid edge cases just inside walls
//
surf = l->surfpt[0];
mids = (l->exactmaxs[0] + l->exactmins[0])/2;
midt = (l->exactmaxs[1] + l->exactmins[1])/2;
for (j=0 ; j<3 ; j++)
facemid[j] = l->texorg[j] + l->textoworld[0][j]*mids + l->textoworld[1][j]*midt;
if (extrasamples)
{ // extra filtering
h = (l->texsize[1]+1)*2;
w = (l->texsize[0]+1)*2;
starts = (l->texmins[0]-0.5)*16;
startt = (l->texmins[1]-0.5)*16;
step = 8;
}
else
{
h = l->texsize[1]+1;
w = l->texsize[0]+1;
starts = l->texmins[0]*16;
startt = l->texmins[1]*16;
step = 16;
}
l->numsurfpt = w * h;
for (t=0 ; t<h ; t++)
{
for (s=0 ; s<w ; s++, surf+=3)
{
us = starts + s*step;
ut = startt + t*step;
// if a line can be traced from surf to facemid, the point is good
for (i=0 ; i<6 ; i++)
{
// calculate texture point
for (j=0 ; j<3 ; j++)
surf[j] = l->texorg[j] + l->textoworld[0][j]*us
+ l->textoworld[1][j]*ut;
if (CastRay (facemid, surf) != -1)
break; // got it
if (i & 1)
{
if (us > mids)
{
us -= 8;
if (us < mids)
us = mids;
}
else
{
us += 8;
if (us > mids)
us = mids;
}
}
else
{
if (ut > midt)
{
ut -= 8;
if (ut < midt)
ut = midt;
}
else
{
ut += 8;
if (ut > midt)
ut = midt;
}
}
// move surf 8 pixels towards the center
VectorSubtract (facemid, surf, move);
VectorNormalize (move);
VectorMA (surf, 8, move, surf);
}
if (i == 2)
c_bad++;
}
}
}
/*
===============================================================================
FACE LIGHTING
===============================================================================
*/
int c_culldistplane, c_proper;
/*
================
SingleLightFace
================
*/
static void SingleLightFace (mentity_t *light, llightinfo_t *l)
{
vec_t dist;
vec3_t incoming;
vec_t angle;
vec_t add;
vec_t *surf;
qboolean hit;
int mapnum;
int size;
int c, i;
vec3_t rel;
vec3_t spotvec;
vec_t falloff;
vec3_t *lightsamp;
vec3_t *norms;
VectorSubtract (light->origin, bsp_origin, rel);
dist = scaledist * (DotProduct (rel, l->facenormal) - l->facedist);
// don't bother with lights behind the surface
if (dist <= 0)
return;
// don't bother with light too far away
if (dist > light->light)
{
c_culldistplane++;
return;
}
if (light->targetent)
{
VectorSubtract (light->targetent->origin, light->origin, spotvec);
VectorNormalize (spotvec);
if (!light->angle)
falloff = -cos(20*Q_PI/180);
else
falloff = -cos(light->angle/2*Q_PI/180);
}
else
falloff = 0; // shut up compiler warnings
mapnum = 0;
for (mapnum=0 ; mapnum<l->numlightstyles ; mapnum++)
if (l->lightstyles[mapnum] == light->style)
break;
lightsamp = l->lightmaps[mapnum];
norms = l->lightnorm[mapnum];
if (mapnum == l->numlightstyles)
{ // init a new light map
if (mapnum == MAXLIGHTMAPS)
{
printf ("WARNING: Too many light styles on a face\n");
return;
}
size = (l->texsize[1]+1)*(l->texsize[0]+1);
for (i=0 ; i<size ; i++)
{
lightsamp[i][0] = 0;
lightsamp[i][1] = 0;
lightsamp[i][2] = 0;
norms[i][0] = 0;
norms[i][1] = 0;
norms[i][2] = 0;
}
}
//
// check it for real
//
hit = false;
c_proper++;
surf = l->surfpt[0];
for (c=0 ; c<l->numsurfpt ; c++, surf+=3)
{
dist = CastRay(light->origin, surf)*scaledist;
if (dist < 0)
continue; // light doesn't reach
VectorSubtract (light->origin, surf, incoming);
VectorNormalize (incoming);
if (light->targetent)
{ // spotlight cutoff
if (DotProduct (spotvec, incoming) > falloff)
continue;
}
angle = DotProduct (incoming, l->facenormal);
angle = (1.0-scalecos) + scalecos*angle;
add = light->light - dist;
add *= angle;
if (add < 0)
continue;
lightsamp[c][0] += add*light->colour[0];
lightsamp[c][1] += add*light->colour[1];
lightsamp[c][2] += add*light->colour[2];
norms[c][0] += add * incoming[0]; //Quake doesn't make sence some times.
norms[c][1] -= add * incoming[1];
norms[c][2] -= add * incoming[2];
if (add > 1) // ignore real tiny lights
hit = true;
}
if (mapnum == l->numlightstyles && hit)
{
l->lightstyles[mapnum] = light->style;
l->numlightstyles++; // the style has some real data now
}
}
/*
============
FixMinlight
============
*/
static void FixMinlight (llightinfo_t *l)
{
int i, j;
float minlight;
minlight = 0;
// if minlight is set, there must be a style 0 light map
if (!minlight)
return;
for (i=0 ; i< l->numlightstyles ; i++)
{
if (l->lightstyles[i] == 0)
break;
}
if (i == l->numlightstyles)
{
if (l->numlightstyles == MAXLIGHTMAPS)
return; // oh well..
for (j=0 ; j<l->numsurfpt ; j++)
{
l->lightmaps[i][j][0] = minlight;
l->lightmaps[i][j][1] = minlight;
l->lightmaps[i][j][2] = minlight;
}
l->lightstyles[i] = 0;
l->numlightstyles++;
}
else
{
for (j=0 ; j<l->numsurfpt ; j++)
{
if ( l->lightmaps[i][j][0] < minlight)
l->lightmaps[i][j][0] = minlight;
if ( l->lightmaps[i][j][1] < minlight)
l->lightmaps[i][j][1] = minlight;
if ( l->lightmaps[i][j][2] < minlight)
l->lightmaps[i][j][2] = minlight;
}
}
}
/*
============
LightFace
============
*/
void LightFace (int surfnum)
{
dface_t *f;
llightinfo_t l;
int s, t;
int i,j,c,ch;
vec_t total, mean;
int size;
int lightmapwidth, lightmapsize;
#ifdef UTILITY
byte *out;
#endif
byte *rgbout;
byte *dulout;
vec3_t *light, *norm;
vec3_t wnorm, temp;
int w, h;
extern byte *runningrgblightdatabase;
extern byte *runninglightnormbase;
f = dfaces + surfnum;
//
// some surfaces don't need lightmaps
//
for (j=0 ; j<MAXLIGHTMAPS ; j++)
f->styles[j] = 255;
if ( bsptexinfo(f->texinfo).flags & TEX_SPECIAL)
{ // non-lit texture
#ifdef UTILITY
f->lightofs = -1;
#endif
return;
}
#ifndef UTILITY
if (!f->samples)
return;
#endif
memset (&l, 0, sizeof(l));
l.surfnum = surfnum;
l.face = f;
//
// rotate plane
//
#ifndef UTILITY
VectorCopy (f->plane->normal, l.facenormal);
l.facedist = f->plane->dist;
#else
VectorCopy (dplanes[f->planenum].normal, l.facenormal);
l.facedist = dplanes[f->planenum].dist;
#endif
if (f->side)
{
VectorSubtract (vec3_origin, l.facenormal, l.facenormal);
l.facedist = -l.facedist;
}
LightCalcFaceVectors (&l);
LightCalcFaceExtents (&l);
LightCalcPoints (&l);
lightmapwidth = l.texsize[0]+1;
size = lightmapwidth*(l.texsize[1]+1);
if (size > SINGLEMAP)
Error ("Bad lightmap size");
for (i=0 ; i<MAXLIGHTMAPS ; i++)
l.lightstyles[i] = 255;
//
// cast all lights
//
l.numlightstyles = 0;
for (i=0 ; i<num_entities ; i++)
{
if (entities[i].light)
SingleLightFace (&entities[i], &l);
}
FixMinlight (&l);
if (!l.numlightstyles)
{ // no light hitting it
#ifdef UTILITY
f->lightofs = -1;
#endif
return;
}
//
// save out the values
//
for (i=0 ; i <MAXLIGHTMAPS ; i++)
f->styles[i] = l.lightstyles[i];
lightmapsize = size*l.numlightstyles;
#ifdef UTILITY
if (runningrgblightdatabase)
{
out = GetFakeFileSpace(&f->lightofs, size);
rgbout = runningrgblightdatabase + f->lightofs*3;
dulout = runninglightnormbase + f->lightofs*3;
}
else
{
out = GetFileSpace (&f->lightofs, lightmapsize);
rgbout = GetRGBFileSpace (f->lightofs, lightmapsize);
dulout = GetNormFileSpace (f->lightofs, lightmapsize);
}
#else
rgbout = f->samples;
if (lightmodel->deluxdata)
dulout = f->samples - lightmodel->lightdata + lightmodel->deluxdata;
else
dulout = NULL;
#endif
// extra filtering
h = (l.texsize[1]+1)*2;
w = (l.texsize[0]+1)*2;
for (i=0 ; i< l.numlightstyles ; i++)
{
if (l.lightstyles[i] == 0xff)
Error ("Wrote empty lightmap");
light = l.lightmaps[i];
norm = l.lightnorm[i];
c = 0;
for (t=0 ; t<=l.texsize[1] ; t++)
{
for (s=0 ; s<=l.texsize[0] ; s++, c++)
{
mean = 0;
for (ch = 0; ch < 3; ch++)
{
if (extrasamples)
{ // filtered sample
total = light[t*2*w+s*2][ch] + light[t*2*w+s*2+1][ch]
+ light[(t*2+1)*w+s*2][ch] + light[(t*2+1)*w+s*2+1][ch];
total *= 0.25;
wnorm[ch] = norm[t*2*w+s*2][ch] + norm[t*2*w+s*2+1][ch]
+ norm[(t*2+1)*w+s*2][ch] + norm[(t*2+1)*w+s*2+1][ch];
}
else
{
total = light[c][ch];
wnorm[ch] = norm[c][ch];
}
total *= rangescale; // scale before clamping
#ifdef UTILITY
if (total > *out) //sorry - for qw
total = *out;
#else
if (total > *rgbout) //sorry - for qw
total = *rgbout;
#endif
if (total < 0)
Error ("light < 0");
*rgbout++ = total;
mean += total;
}
#ifdef UTILITY
*out++ = mean/3;
#endif
if (dulout)
{
temp[0] = DotProduct(wnorm, bsptexinfo(f->texinfo).vecs[0]);
temp[1] = DotProduct(wnorm, bsptexinfo(f->texinfo).vecs[1]);
temp[2] = DotProduct(wnorm, l.facenormal);
VectorNormalize(temp);
*dulout++ = (temp[0]+1)/2 * 255;
*dulout++ = (temp[1]+1)/2 * 255;
*dulout++ = (temp[2]+1)/2 * 255;
}
}
}
}
}
#endif
#endif

2476
engine/gl/gl_alias.c Normal file

File diff suppressed because it is too large Load diff

489
engine/gl/gl_backend.c Normal file
View file

@ -0,0 +1,489 @@
#include "quakedef.h"
#include "glquake.h"
#include "shader.h"
#ifdef RGLQUAKE
#define MAX_MESH_VERTS 8192
//we don't support multitexturing yet.
static float tempstarray[MAX_MESH_VERTS*3];
static vec4_t tempxyzarray[MAX_MESH_VERTS];
shader_t nullshader, wallbumpshader, modelbumpshader;
#define frand() (rand()&32767)* (1.0/32767)
#define FTABLE_SIZE 1024
#define FTABLE_CLAMP(x) (((int)((x)*FTABLE_SIZE) & (FTABLE_SIZE-1)))
#define FTABLE_EVALUATE(table,x) (table ? table[FTABLE_CLAMP(x)] : frand())//*((x)-floor(x)))
static float r_sintable[FTABLE_SIZE];
static float r_triangletable[FTABLE_SIZE];
static float r_squaretable[FTABLE_SIZE];
static float r_sawtoothtable[FTABLE_SIZE];
static float r_inversesawtoothtable[FTABLE_SIZE];
void GLR_MeshInit(void)
{
int i;
double t;
for ( i = 0; i < FTABLE_SIZE; i++ )
{
t = (double)i / (double)FTABLE_SIZE;
r_sintable[i] = sin ( t * M_PI*2 );
if (t < 0.25)
r_triangletable[i] = t * 4.0;
else if (t < 0.75)
r_triangletable[i] = 2 - 4.0 * t;
else
r_triangletable[i] = (t - 0.75) * 4.0 - 1.0;
if (t < 0.5)
r_squaretable[i] = 1.0f;
else
r_squaretable[i] = -1.0f;
r_sawtoothtable[i] = t;
r_inversesawtoothtable[i] = 1.0 - t;
}
{
nullshader.numdeforms = 0;//1;
nullshader.deforms[0].type = DEFORMV_WAVE;
nullshader.deforms[0].args[0] = 10;
nullshader.deforms[0].func.type = SHADER_FUNC_SIN;
nullshader.deforms[0].func.args[1] = 1;
nullshader.deforms[0].func.args[3] = 10;
nullshader.pass[0].texturetype = GL_TEXTURE_2D;
nullshader.pass[0].envmode = GL_MODULATE;
nullshader.pass[0].blendsrc = GL_SRC_ALPHA;
nullshader.pass[0].blenddst = GL_ONE_MINUS_SRC_ALPHA;
nullshader.pass[1].flags |= SHADER_PASS_BLEND;
nullshader.pass[1].tcgen = TC_GEN_LIGHTMAP;
nullshader.pass[1].blendsrc = GL_SRC_ALPHA;
nullshader.pass[1].blenddst = GL_ONE_MINUS_SRC_ALPHA;
nullshader.pass[1].texturetype = GL_TEXTURE_2D;
}
{
modelbumpshader.numpasses = 3;
if (1)
modelbumpshader.pass[0].mergedpasses = 4;
else
modelbumpshader.pass[0].mergedpasses = 2;
modelbumpshader.pass[2].mergedpasses = 1;
modelbumpshader.pass[0].tcgen = TC_GEN_BASE;
modelbumpshader.pass[0].envmode = GL_COMBINE_ARB;
modelbumpshader.pass[0].combinesrc0 = GL_TEXTURE;
modelbumpshader.pass[0].combinemode = GL_REPLACE;
modelbumpshader.pass[0].blendsrc = GL_SRC_ALPHA;
modelbumpshader.pass[0].blenddst = GL_ONE_MINUS_SRC_ALPHA;
modelbumpshader.pass[0].anim_frames[0] = 0;//bumpmap
modelbumpshader.pass[0].texturetype = GL_TEXTURE_2D;
modelbumpshader.pass[1].tcgen = TC_GEN_DOTPRODUCT;
modelbumpshader.pass[1].envmode = GL_COMBINE_ARB;
modelbumpshader.pass[1].combinesrc0 = GL_TEXTURE;
modelbumpshader.pass[1].combinesrc1 = GL_PREVIOUS_ARB;
modelbumpshader.pass[1].combinemode = GL_DOT3_RGB_ARB;
modelbumpshader.pass[1].anim_frames[0] = 0;//delux
modelbumpshader.pass[1].texturetype = GL_TEXTURE_2D;
modelbumpshader.pass[2].flags |= SHADER_PASS_BLEND;
modelbumpshader.pass[2].tcgen = TC_GEN_BASE;
modelbumpshader.pass[2].envmode = GL_MODULATE;
modelbumpshader.pass[2].blendsrc = GL_DST_COLOR;
modelbumpshader.pass[2].blenddst = GL_ZERO;
modelbumpshader.pass[2].anim_frames[0] = 0;//texture
modelbumpshader.pass[2].texturetype = GL_TEXTURE_2D;
//gl_combine states that we need to use a textures.
modelbumpshader.pass[3].tcgen = TC_GEN_BASE; //multiply by colors
modelbumpshader.pass[3].envmode = GL_COMBINE_ARB;
modelbumpshader.pass[3].combinesrc0 = GL_PREVIOUS_ARB;
modelbumpshader.pass[3].combinesrc1 = GL_PRIMARY_COLOR_ARB;
modelbumpshader.pass[3].combinemode = GL_MODULATE;
modelbumpshader.pass[3].anim_frames[0] = 1; //any, has to be present
modelbumpshader.pass[3].texturetype = GL_TEXTURE_2D;
}
{
wallbumpshader.numpasses = 4;
if (1)
wallbumpshader.pass[0].mergedpasses = 4;
else
wallbumpshader.pass[0].mergedpasses = 2;
wallbumpshader.pass[2].mergedpasses = 2;
wallbumpshader.pass[0].tcgen = TC_GEN_BASE;
wallbumpshader.pass[0].envmode = GL_COMBINE_ARB;
wallbumpshader.pass[0].combinesrc0 = GL_TEXTURE;
wallbumpshader.pass[0].combinemode = GL_REPLACE;
wallbumpshader.pass[0].anim_frames[0] = 0;//bumpmap
wallbumpshader.pass[0].blendsrc = GL_SRC_ALPHA;
wallbumpshader.pass[0].blenddst = GL_ONE_MINUS_SRC_ALPHA;
wallbumpshader.pass[0].texturetype = GL_TEXTURE_2D;
wallbumpshader.pass[1].tcgen = TC_GEN_LIGHTMAP;
wallbumpshader.pass[1].envmode = GL_COMBINE_ARB;
wallbumpshader.pass[1].combinesrc0 = GL_TEXTURE;
wallbumpshader.pass[1].combinesrc1 = GL_PREVIOUS_ARB;
wallbumpshader.pass[1].combinemode = GL_DOT3_RGB_ARB;
wallbumpshader.pass[1].anim_frames[0] = 0;//delux
wallbumpshader.pass[1].texturetype = GL_TEXTURE_2D;
wallbumpshader.pass[2].flags |= SHADER_PASS_BLEND;
wallbumpshader.pass[2].tcgen = TC_GEN_BASE;
wallbumpshader.pass[2].envmode = GL_MODULATE;
wallbumpshader.pass[2].blendsrc = GL_DST_COLOR;
wallbumpshader.pass[2].blenddst = GL_ZERO;
wallbumpshader.pass[2].anim_frames[0] = 0;//texture
wallbumpshader.pass[2].texturetype = GL_TEXTURE_2D;
wallbumpshader.pass[3].tcgen = TC_GEN_LIGHTMAP;
wallbumpshader.pass[3].envmode = GL_BLEND;
wallbumpshader.pass[3].anim_frames[0] = 0;//lightmap
wallbumpshader.pass[3].texturetype = GL_TEXTURE_2D;
}
}
static float *R_TableForFunc ( unsigned int func )
{
switch (func)
{
case SHADER_FUNC_SIN:
return r_sintable;
case SHADER_FUNC_TRIANGLE:
return r_triangletable;
case SHADER_FUNC_SQUARE:
return r_squaretable;
case SHADER_FUNC_SAWTOOTH:
return r_sawtoothtable;
case SHADER_FUNC_INVERSESAWTOOTH:
return r_inversesawtoothtable;
}
// assume noise
return NULL;
}
static void MakeDeforms(shader_t *shader, vec4_t *out, vec4_t *in, int number)
{
float *table;
int d, j;
float args[4], deflect;
deformv_t *dfrm = shader->deforms;
for (d = 0; d < shader->numdeforms; d++, dfrm++)
{
switch(dfrm->type)
{
case DEFORMV_WAVE:
args[0] = dfrm->func.args[0];
args[1] = dfrm->func.args[1];
args[3] = dfrm->func.args[2] + dfrm->func.args[3] * realtime;
table = R_TableForFunc ( dfrm->func.type );
for ( j = 0; j < number; j++ ) {
deflect = dfrm->args[0] * (in[j][0]+in[j][1]+in[j][2]) + args[3];
deflect = sin(deflect)/*FTABLE_EVALUATE ( table, deflect )*/ * args[1] + args[0];
out[j][0] = in[j][0]+deflect;
out[j][1] = in[j][1]+deflect;
out[j][2] = in[j][2]+deflect;
// Deflect vertex along its normal by wave amount
// VectorMA ( out[j], deflect, normalsArray[j], in[j] );
}
break;
case DEFORMV_MOVE:
table = R_TableForFunc ( dfrm->func.type );
deflect = dfrm->func.args[2] + realtime * dfrm->func.args[3];
deflect = FTABLE_EVALUATE (table, deflect) * dfrm->func.args[1] + dfrm->func.args[0];
for ( j = 0; j < number; j++ )
VectorMA ( out[j], deflect, dfrm->args, in[j] );
break;
default:
Sys_Error("Bad deform type %i\n", dfrm->type);
}
in = out;
}
}
static void Mesh_DeformTextureCoords(mesh_t *mesh, shaderpass_t *pass)
{
int d;
tcmod_t *tcmod = pass->tcmod;
float *in, *out;
switch(pass->tcgen)
{
case TC_GEN_DOTPRODUCT: //take normals, use the dotproduct and produce texture coords for bumpmapping
{
out = tempstarray;
in = (float*)mesh->normals_array;
for (d = 0; d < mesh->numvertexes; d++)
{
out[d*3+0] = DotProduct((in+d*3), mesh->lightaxis[0]);
out[d*3+1] = DotProduct((in+d*3), mesh->lightaxis[1]);
out[d*3+2] = DotProduct((in+d*3), mesh->lightaxis[2]);
}
glTexCoordPointer(3, GL_FLOAT, 0, out);
glEnableClientState( GL_TEXTURE_COORD_ARRAY );
}
return;
case TC_GEN_LIGHTMAP:
in = (float*)mesh->lmst_array;
if (in)
break; //fallthrought
case TC_GEN_BASE:
in = (float*)mesh->st_array;
break;
default:
Sys_Error("Mesh_DeformTextureCoords: Bad TC_GEN type\n");
return;
}
/*
for (d = 0; d < pass->numtcmods; d++, dfrm++)
{
}
*/
glEnableClientState( GL_TEXTURE_COORD_ARRAY );
glTexCoordPointer(2, GL_FLOAT, 0, in);
}
static void Mesh_SetShaderpassState ( shaderpass_t *pass, qboolean mtex )
{
if ( (mtex && (pass->blendmode != GL_REPLACE)) || (pass->flags & SHADER_PASS_BLEND) )
{
glEnable (GL_BLEND);
glBlendFunc (pass->blendsrc, pass->blenddst);
}
else
{
glDisable (GL_BLEND);
}
if (pass->flags & SHADER_PASS_ALPHAFUNC)
{
glEnable (GL_ALPHA_TEST);
if (pass->alphafunc == SHADER_ALPHA_GT0)
{
glAlphaFunc (GL_GREATER, 0);
}
else if (pass->alphafunc == SHADER_ALPHA_LT128)
{
glAlphaFunc (GL_LESS, 0.5f);
}
else if (pass->alphafunc == SHADER_ALPHA_GE128)
{
glAlphaFunc (GL_GEQUAL, 0.5f);
}
}
else
{
// glDisable (GL_ALPHA_TEST);
}
// glDepthFunc (pass->depthfunc);
if (pass->flags & SHADER_PASS_DEPTHWRITE)
{
glDepthMask (GL_TRUE);
}
else
{
// glDepthMask (GL_FALSE);
}
}
static void Mesh_DrawPass(shaderpass_t *pass, mesh_t *mesh)
{
Mesh_SetShaderpassState(pass, false);
if (pass->mergedpasses>1 && gl_mtexarbable)
{
int p;
// Mesh_DrawPass(pass+2,mesh);
// return;
for (p = 0; p < pass->mergedpasses; p++)
{
qglActiveTextureARB(GL_TEXTURE0_ARB+p);
qglClientActiveTextureARB(GL_TEXTURE0_ARB+p);
GL_BindType(pass[p].texturetype, pass[p].anim_frames[0]);
glEnable(pass[p].texturetype);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, pass[p].envmode);
if (pass[p].envmode == GL_COMBINE_ARB)
{
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, pass[p].combinesrc0);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, pass[p].combinesrc1);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, pass[p].combinemode);
}
Mesh_DeformTextureCoords(mesh, pass+p);
}
glDrawElements(GL_TRIANGLES, mesh->numindexes, GL_UNSIGNED_INT, mesh->indexes);
for (p = pass->mergedpasses-1; p >= 0; p--)
{
qglActiveTextureARB(GL_TEXTURE0_ARB+p);
qglClientActiveTextureARB(GL_TEXTURE0_ARB+p);
glDisable(pass[p].texturetype);
glDisableClientState( GL_TEXTURE_COORD_ARRAY );
}
}
else
{
Mesh_DeformTextureCoords(mesh, pass);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, pass->envmode);
GL_Bind(pass->anim_frames[0]);
if (pass->texturetype != GL_TEXTURE_2D)
{
glDisable(pass->texturetype);
glEnable(pass->texturetype);
}
glDrawElements(GL_TRIANGLES, mesh->numindexes, GL_UNSIGNED_INT, mesh->indexes);
if (pass->texturetype != GL_TEXTURE_2D)
{
glDisable(pass->texturetype);
glEnable(GL_TEXTURE_2D);
}
glDisableClientState( GL_TEXTURE_COORD_ARRAY );
}
}
void GL_DrawMesh(mesh_t *mesh, shader_t *shader, int texturenum, int lmtexturenum)
{
int i;
if (!shader)
{
shader = &nullshader;
shader->pass[0].anim_frames[0] = texturenum;
shader->pass[0].mergedpasses=1;
if (lmtexturenum && !texturenum)
{
shader->pass[0].anim_frames[0] = lmtexturenum;
shader->numpasses = 1;
shader->pass[0].flags |= SHADER_PASS_BLEND;
}
else if (lmtexturenum)
{
shader->numpasses = 2;
shader->pass[1].anim_frames[0] = lmtexturenum;//lmtexture;
shader->pass[0].flags &= ~SHADER_PASS_BLEND;
}
else
{
shader->pass[0].flags &= ~SHADER_PASS_BLEND;
shader->numpasses = 1;
}
shader->pass[0].texturetype = GL_TEXTURE_2D;
}
if (!shader->numdeforms)
glVertexPointer(3, GL_FLOAT, 16, mesh->xyz_array);
else
{
MakeDeforms(shader, tempxyzarray, mesh->xyz_array, mesh->numvertexes);
glVertexPointer(3, GL_FLOAT, 16, tempxyzarray);
}
if (mesh->normals_array && glNormalPointer)
{
glNormalPointer(GL_FLOAT, 0, mesh->normals_array);
glEnableClientState( GL_NORMAL_ARRAY );
}
glEnableClientState( GL_VERTEX_ARRAY );
if (mesh->colors_array && glColorPointer)
{
glColorPointer(4, GL_UNSIGNED_BYTE, 0, mesh->colors_array);
glEnableClientState( GL_COLOR_ARRAY );
}
for (i =0 ; i < shader->numpasses; i+=shader->pass[i].mergedpasses)
Mesh_DrawPass(shader->pass+i, mesh);
glDisableClientState( GL_VERTEX_ARRAY );
glDisableClientState( GL_COLOR_ARRAY );
glDisableClientState( GL_NORMAL_ARRAY );
/* //show normals
if (mesh->normals_array)
{
glColor3f(1,1,1);
glDisable(GL_TEXTURE_2D);
glBegin(GL_LINES);
for (i = 0; i < mesh->numvertexes; i++)
{
glVertex3f( mesh->xyz_array[i][0],
mesh->xyz_array[i][1],
mesh->xyz_array[i][2]);
glVertex3f( mesh->xyz_array[i][0] + mesh->normals_array[i][0],
mesh->xyz_array[i][1] + mesh->normals_array[i][1],
mesh->xyz_array[i][2] + mesh->normals_array[i][2]);
}
glEnd();
glEnable(GL_TEXTURE_2D);
}
*/
}
void GL_DrawMeshBump(mesh_t *mesh, int texturenum, int lmtexturenum, int bumpnum, int deluxnum)
{
shader_t *shader;
extern int normalisationCubeMap;
if (lmtexturenum)
{
shader = &wallbumpshader;
shader->pass[3].anim_frames[0] = lmtexturenum;
}
else
shader = &modelbumpshader;
shader->pass[0].anim_frames[0] = bumpnum;
if (deluxnum)
{
shader->pass[1].anim_frames[0] = deluxnum;
shader->pass[1].tcgen = TC_GEN_LIGHTMAP;
shader->pass[1].texturetype = GL_TEXTURE_2D;
}
else
{
shader->pass[1].anim_frames[0] = normalisationCubeMap;
shader->pass[1].tcgen = TC_GEN_DOTPRODUCT;
shader->pass[1].texturetype = GL_TEXTURE_CUBE_MAP_ARB;
}
shader->pass[2].anim_frames[0] = texturenum;
// mesh->colors_array=NULL; //don't bother coloring it.
GL_DrawMesh(mesh, shader, 0, 0);
}
#endif

3005
engine/gl/gl_draw.c Normal file

File diff suppressed because it is too large Load diff

649
engine/gl/gl_hlmdl.c Normal file
View file

@ -0,0 +1,649 @@
#include "bothdefs.h"
#ifdef HALFLIFEMODELS
#include "quakedef.h"
#include "glquake.h"
/*
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Half-Life Model Renderer (Experimental) Copyright (C) 2001 James 'Ender' Brown [ender@quakesrc.org] 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. fromquake.h -
render.c - apart from calculations (mostly range checking or value conversion code is a mix of standard Quake 1
meshing, and vertex deforms. The rendering loop uses standard Quake 1 drawing, after SetupBones deforms the vertex.
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Also, please note that it won't do all hl models....
Nor will it work 100%
*/
#include "model_hl.h"
void VectorTransform (const vec3_t in1, const float in2[3][4], vec3_t out);
void QuaternionGLMatrix(float x, float y, float z, float w, vec4_t *GLM)
{
GLM[0][0] = 1 - 2 * y * y - 2 * z * z;
GLM[1][0] = 2 * x * y + 2 * w * z;
GLM[2][0] = 2 * x * z - 2 * w * y;
GLM[0][1] = 2 * x * y - 2 * w * z;
GLM[1][1] = 1 - 2 * x * x - 2 * z * z;
GLM[2][1] = 2 * y * z + 2 * w * x;
GLM[0][2] = 2 * x * z + 2 * w * y;
GLM[1][2] = 2 * y * z - 2 * w * x;
GLM[2][2] = 1 - 2 * x * x - 2 * y * y;
}
/*
=======================================================================================================================
QuaternionGLAngle - Convert a GL angle to a quaternion matrix
=======================================================================================================================
*/
void QuaternionGLAngle(const vec3_t angles, vec4_t quaternion)
{
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
float yaw = angles[2] * 0.5;
float pitch = angles[1] * 0.5;
float roll = angles[0] * 0.5;
float siny = sin(yaw);
float cosy = cos(yaw);
float sinp = sin(pitch);
float cosp = cos(pitch);
float sinr = sin(roll);
float cosr = cos(roll);
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
quaternion[0] = sinr * cosp * cosy - cosr * sinp * siny;
quaternion[1] = cosr * sinp * cosy + sinr * cosp * siny;
quaternion[2] = cosr * cosp * siny - sinr * sinp * cosy;
quaternion[3] = cosr * cosp * cosy + sinr * sinp * siny;
}
float transform_matrix[128][3][4]; /* Vertex transformation matrix */
void GL_Draw_HL_AliasFrame(short *order, vec3_t *transformed, float tex_w, float tex_h);
/*
=======================================================================================================================
Mod_LoadHLModel - read in the model's constituent parts
=======================================================================================================================
*/
extern char loadname[];
void Mod_LoadHLModel (model_t *mod, void *buffer)
{
/*~~*/
int i;
hlmodelcache_t *model;
hlmdl_header_t *header;
hlmdl_tex_t *tex;
hlmdl_bone_t *bones;
hlmdl_bonecontroller_t *bonectls;
int start, end, total;
/*~~*/
//checksum the model
if (!strcmp(mod->name, "progs/player.mdl") ||
!strcmp(mod->name, "progs/eyes.mdl")) {
unsigned short crc;
qbyte *p;
int len;
char st[40];
CRC_Init(&crc);
for (len = com_filesize, p = buffer; len; len--, p++)
CRC_ProcessByte(&crc, *p);
sprintf(st, "%d", (int) crc);
Info_SetValueForKey (cls.userinfo,
!strcmp(mod->name, "progs/player.mdl") ? pmodel_name : emodel_name,
st, MAX_INFO_STRING);
if (cls.state >= ca_connected) {
MSG_WriteByte (&cls.netchan.message, clc_stringcmd);
sprintf(st, "setinfo %s %d",
!strcmp(mod->name, "progs/player.mdl") ? pmodel_name : emodel_name,
(int)crc);
SZ_Print (&cls.netchan.message, st);
}
}
start = Hunk_LowMark ();
//load the model into hunk
model = Hunk_Alloc(sizeof(hlmodelcache_t));
header = Hunk_Alloc(com_filesize);
memcpy(header, buffer, com_filesize);
if (header->version != 10)
Host_EndGame("Cannot load model %s - unknown version %i\n", mod->name, header->version);
tex = (hlmdl_tex_t *) ((qbyte *) header + header->textures);
bones = (hlmdl_bone_t *) ((qbyte *) header + header->boneindex);
bonectls = (hlmdl_bonecontroller_t *) ((qbyte *) header + header->controllerindex);
/* won't work - doesn't know exact sizes.
header = Hunk_Alloc(sizeof(hlmdl_header_t));
memcpy(header, (hlmdl_header_t *) buffer, sizeof(hlmdl_header_t));
tex = Hunk_Alloc(sizeof(hlmdl_tex_t)*header->numtextures);
memcpy(tex, (hlmdl_tex_t *) buffer, sizeof(hlmdl_tex_t)*header->numtextures);
bones = Hunk_Alloc(sizeof(hlmdl_bone_t)*header->numtextures);
memcpy(bones, (hlmdl_bone_t *) buffer, sizeof(hlmdl_bone_t)*header->numbones);
bonectls = Hunk_Alloc(sizeof(hlmdl_bonecontroller_t)*header->numcontrollers);
memcpy(bonectls, (hlmdl_bonecontroller_t *) buffer, sizeof(hlmdl_bonecontroller_t)*header->numcontrollers);
*/
model->header = (char *)header - (char *)model;
model->textures = (char *)tex - (char *)model;
model->bones = (char *)bones - (char *)model;
model->bonectls = (char *)bonectls - (char *)model;
for(i = 0; i < header->numtextures; i++)
{
tex[i].i = GL_LoadTexture8Pal24("", tex[i].w, tex[i].h, (qbyte *) header + tex[i].i, (qbyte *) header + tex[i].w * tex[i].h + tex[i].i, true, false);
}
//
// move the complete, relocatable alias model to the cache
//
end = Hunk_LowMark ();
total = end - start;
mod->type = mod_halflife;
Cache_Alloc (&mod->cache, total, loadname);
if (!mod->cache.data)
return;
memcpy (mod->cache.data, model, total);
Hunk_FreeToLowMark (start);
}
/*
=======================================================================================================================
HL_CurSequence - return the current sequence
=======================================================================================================================
*/
int HL_CurSequence(hlmodel_t model)
{
return model.sequence;
}
/*
=======================================================================================================================
HL_NewSequence - animation control (just some range checking really)
=======================================================================================================================
*/
int HL_NewSequence(hlmodel_t *model, int _inew)
{
if(_inew < 0)
_inew = model->header->numseq - 1;
else if(_inew >= model->header->numseq)
_inew = 0;
model->sequence = _inew;
model->frame = 0;
{
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
hlmdl_sequencelist_t *pseqdesc;
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
if(_inew == 0)
{
pseqdesc = (hlmdl_sequencelist_t *) ((qbyte *) model->header + model->header->seqindex) + model->sequence;
}
else
{
pseqdesc = (hlmdl_sequencelist_t *) ((qbyte *) model->header + model->header->seqindex) + model->sequence;
}
Sys_Printf("Current Sequence: %s\n", pseqdesc->name);
}
return model->sequence;
}
/*
=======================================================================================================================
HL_SetController - control where the model is facing (upper body usually)
=======================================================================================================================
*/
void HL_SetController(hlmodel_t *model, int num, float value)
{
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
int real, limit;
hlmdl_bonecontroller_t *control = (hlmdl_bonecontroller_t *)
((qbyte *) model->header + model->header->controllerindex);
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
if(num >= model->header->numcontrollers) return;
if(num == 4)
{
limit = 64;
}
else
{
limit = 255;
}
if(control->type & (0x0008 | 0x0010 | 0x0020))
{
if(control->end < control->start) value = -value;
if(control->start + 359.0 >= control->end)
{
if(value > ((control->start + control->end) / 2.0) + 180) value = value - 360;
if(value < ((control->start + control->end) / 2.0) - 180) value = value + 360;
}
else
{
if(value > 360)
value = value - (int) (value / 360.0) * 360.0;
else if(value < 0)
value = value + (int) ((value / -360.0) + 1) * 360.0;
}
}
real = limit * (value - control[num].start) / (control[num].end - control[num].start);
if(real < 0) real = 0;
if(real > limit) real = limit;
model->controller[num] = real;
}
/*
=======================================================================================================================
HL_CalculateBones - calculate bone positions - quaternion+vector in one function
=======================================================================================================================
*/
void HL_CalculateBones
(
int offset,
int frame,
vec4_t adjust,
hlmdl_bone_t *bone,
hlmdl_anim_t *animation,
float *destination
)
{
/*~~~~~~~~~~*/
int i;
vec3_t angle;
/*~~~~~~~~~~*/
/* For each vector */
for(i = 0; i < 3; i++)
{
/*~~~~~~~~~~~~~~~*/
int o = i + offset; /* Take the value offset - allows quaternion & vector in one function */
/*~~~~~~~~~~~~~~~*/
angle[i] = bone->value[o]; /* Take the bone value */
if(animation->offset[o] != 0)
{
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
int tempframe = frame;
hlmdl_animvalue_t *animvalue = (hlmdl_animvalue_t *) ((qbyte *) animation + animation->offset[o]);
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
/* find values including the required frame */
while(animvalue->num.total <= tempframe)
{
tempframe -= animvalue->num.total;
animvalue += animvalue->num.valid + 1;
}
if(animvalue->num.valid > tempframe)
{
if(animvalue->num.valid > (tempframe + 1))
angle[i] += animvalue[tempframe + 1].value * 1; // + 0 * animvalue[tempframe + 2].value * bone->scale[o];
else
angle[i] = animvalue[animvalue->num.valid].value;
angle[i] = bone->value[o] + angle[i] * bone->scale[o];
}
else
{
if(animvalue->num.total <= tempframe + 1)
{
angle[i] +=
(animvalue[animvalue->num.valid].value * 1 +
0 * animvalue[animvalue->num.valid + 2].value) *
bone->scale[o];
}
else
{
angle[i] += animvalue[animvalue->num.valid].value * bone->scale[o];
}
}
}
if(bone->bonecontroller[o] != -1) { /* Add the programmable offset. */
angle[i] += adjust[bone->bonecontroller[o]];
}
}
if(offset < 3)
{
VectorCopy(angle, destination); /* Just a standard vector */
}
else
{
QuaternionGLAngle(angle, destination); /* A quaternion */
}
}
/*
=======================================================================================================================
HL_CalcBoneAdj - Calculate the adjustment values for the programmable controllers
=======================================================================================================================
*/
void HL_CalcBoneAdj(hlmodel_t *model)
{
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
int i;
float value;
hlmdl_bonecontroller_t *control = (hlmdl_bonecontroller_t *)
((qbyte *) model->header + model->header->controllerindex);
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
for(i = 0; i < model->header->numcontrollers; i++)
{
/*~~~~~~~~~~~~~~~~~~~~~*/
int j = control[i].index;
/*~~~~~~~~~~~~~~~~~~~~~*/
if(control[i].type & 0x8000)
{
value = model->controller[j] * (360.0 / 256.0) + control[i].start;
}
else
{
value = model->controller[j] / 255.0;
if(value < 0)
value = 0;
else if(value > 1.0)
value = 1.0;
value = (1.0 - value) * control[i].start + value * control[i].end;
}
/* Rotational controllers need their values converted */
if(control[i].type >= 0x0008 && control[i].type <= 0x0020)
model->adjust[i] = M_PI * value / 180;
else
model->adjust[i] = value;
}
}
/*
=======================================================================================================================
HL_SetupBones - determine where vertex should be using bone movements
=======================================================================================================================
*/
void HL_SetupBones(hlmodel_t *model)
{
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
int i;
float matrix[3][4];
static vec3_t positions[128];
static vec4_t quaternions[128];
hlmdl_sequencelist_t *sequence = (hlmdl_sequencelist_t *) ((qbyte *) model->header + model->header->seqindex) +
model->sequence;
hlmdl_sequencedata_t *sequencedata = (hlmdl_sequencedata_t *)
((qbyte *) model->header + model->header->seqgroups) +
sequence->seqindex;
hlmdl_anim_t *animation = (hlmdl_anim_t *)
((qbyte *) model->header + sequencedata->data + sequence->index);
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
HL_CalcBoneAdj(model); /* Deal with programmable controllers */
if(sequence->motiontype & 0x0001) positions[sequence->motionbone][0] = 0.0;
if(sequence->motiontype & 0x0002) positions[sequence->motionbone][1] = 0.0;
if(sequence->motiontype & 0x0004) positions[sequence->motionbone][2] = 0.0;
/* Sys_Printf("Frame: %i\n", model->frame); */
for(i = 0; i < model->header->numbones; i++)
{
/*
* There are two vector offsets in the structure. The first seems to be the
* positions of the bones, the second the quats of the bone matrix itself. We
* convert it inside the routine - Inconsistant, but hey.. so's the whole model
* format.
*/
HL_CalculateBones(0, model->frame, model->adjust, model->bones + i, animation + i, positions[i]);
HL_CalculateBones(3, model->frame, model->adjust, model->bones + i, animation + i, quaternions[i]);
/* FIXME: Blend the bones and make them cry :) */
QuaternionGLMatrix(quaternions[i][0], quaternions[i][1], quaternions[i][2], quaternions[i][3], matrix);
matrix[0][3] = positions[i][0];
matrix[1][3] = positions[i][1];
matrix[2][3] = positions[i][2];
/* If we have a parent, take the addition. Otherwise just copy the values */
if(model->bones[i].parent>=0)
{
R_ConcatTransforms(transform_matrix[model->bones[i].parent], matrix, transform_matrix[i]);
}
else
{
memcpy(transform_matrix[i], matrix, 12 * sizeof(float));
}
}
}
/*
=======================================================================================================================
R_Draw_HL_AliasModel - main drawing function
=======================================================================================================================
*/
void R_DrawHLModel(entity_t *curent)
{
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
hlmodelcache_t *modelc = Mod_Extradata(curent->model);
hlmodel_t model;
int b, m, v;
short *skins;
hlmdl_sequencelist_t *sequence;
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
//general model
model.header = (hlmdl_header_t *) ((char *)modelc + modelc->header);
model.textures = (hlmdl_tex_t *) ((char *)modelc + modelc->textures);
model.bones = (hlmdl_bone_t *) ((char *)modelc + modelc->bones);
model.bonectls = (hlmdl_bonecontroller_t *) ((char *)modelc + modelc->bonectls);
//specific to entity
model.sequence = curent->frame;
model.frame = 0;
model.frametime = 0;
HL_NewSequence(&model, curent->frame);
skins = (short *) ((qbyte *) model.header + model.header->skins);
sequence = (hlmdl_sequencelist_t *) ((qbyte *) model.header + model.header->seqindex) +
model.sequence;
model.controller[0] = 127;
model.controller[1] = 127;
model.controller[2] = 127;
model.controller[3] = 127;
model.controller[4] = 0;//sin(cl.time)*127+127;
model.frametime += (cl.time - cl.lerpents[curent->keynum].framechange)*sequence->timing;
if (model.frametime>=1)
{
model.frame += (int) model.frametime;
model.frametime -= (int)model.frametime;
}
if (!sequence->numframes)
return;
if(model.frame >= sequence->numframes)
model.frame %= sequence->numframes;
if (sequence->motiontype)
model.frame = sequence->numframes-1;
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
if (curent->alpha<1)
{
glEnable(GL_BLEND);
}
else
{
glDisable(GL_BLEND);
}
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
// Con_Printf("%s %i\n", sequence->name, sequence->unknown1[0]);
glPushMatrix();
{
vec3_t difuse, ambient, ldir;
cl.worldmodel->funcs.LightPointValues(curent->origin, difuse, ambient, ldir);
glColor4f(difuse[0]/255+ambient[0]/255, difuse[1]/255+ambient[1]/255, difuse[2]/255+ambient[2]/255, curent->alpha);
}
R_RotateForEntity (curent);
HL_SetupBones(&model); /* Setup the bones */
/* Manipulate each mesh directly */
for(b = 0; b < model.header->numbodyparts; b++)
{
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
hlmdl_bodypart_t *bodypart = (hlmdl_bodypart_t *) ((qbyte *) model.header + model.header->bodypartindex) +
b;
int bodyindex = (0 / bodypart->base) % bodypart->nummodels;
hlmdl_model_t *amodel = (hlmdl_model_t *) ((qbyte *) model.header + bodypart->modelindex) + bodyindex;
qbyte *bone = ((qbyte *) model.header + amodel->vertinfoindex);
vec3_t *verts = (vec3_t *) ((qbyte *) model.header + amodel->vertindex);
vec3_t transformed[2048];
// vec3_t *norms = (vec3_t *) ((qbyte *) model.header + amodel->unknown3[2]);
// vec3_t transformednorms[2048];
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
for(v = 0; v < amodel->numverts; v++) // Transform per the matrix
{
VectorTransform(verts[v], transform_matrix[bone[v]], transformed[v]);
// glVertex3fv(verts[v]);
// glVertex3f( verts[v][0]+10*verts[v][0],
// verts[v][1]+10*verts[v][1],
// verts[v][2]+10*verts[v][2]);
}
//Need to work out what we have!
//raw data appears to be unit vectors
//transformed gives some points on the skeleton.
//what's also weird is that the meshes use these up!
/* glDisable(GL_TEXTURE_2D);
glBegin(GL_LINES);
for(v = 0; v < amodel->unknown3[0]; v++) // Transform per the matrix
{
VectorTransform(norms[v], transform_matrix[bone[v]], transformednorms[v]);
glVertex3fv(transformednorms[v]);
glVertex3f( transformednorms[v][0]+10*transformednorms[v][0],
transformednorms[v][1]+10*transformednorms[v][1],
transformednorms[v][2]+10*transformednorms[v][2]);
}
glEnd();
glEnable(GL_TEXTURE_2D);
*/
/* Draw each mesh */
for(m = 0; m < amodel->nummesh; m++)
{
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
hlmdl_mesh_t *mesh = (hlmdl_mesh_t *) ((qbyte *) model.header + amodel->meshindex) + m;
float tex_w = 1.0f / model.textures[skins[mesh->skinindex]].w;
float tex_h = 1.0f / model.textures[skins[mesh->skinindex]].h;
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
GL_Bind(model.textures[skins[mesh->skinindex]].i);
GL_Draw_HL_AliasFrame((short *) ((qbyte *) model.header + mesh->index), transformed, tex_w, tex_h);
}
}
glPopMatrix();
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
}
/*
=======================================================================================================================
GL_Draw_HL_AliasFrame - clip and draw all triangles
=======================================================================================================================
*/
void GL_Draw_HL_AliasFrame(short *order, vec3_t *transformed, float tex_w, float tex_h)
{
/*~~~~~~~~~~*/
int count = 0;
/*~~~~~~~~~~*/
// int c_tris=0;
// int c_verts=0;
// int c_chains=0;
for(;;)
{
count = *order++; /* get the vertex count and primitive type */
if(!count) break; /* done */
if(count < 0)
{
count = -count;
glBegin(GL_TRIANGLE_FAN);
}
else
{
glBegin(GL_TRIANGLE_STRIP);
}
// c_tris += count-2;
// c_chains++;
do
{
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
float *verts = transformed[order[0]];
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
/* texture coordinates come from the draw list */
glTexCoord2f(order[2] * tex_w, order[3] * tex_h);
order += 4;
glVertex3fv(verts);
// c_verts++;
} while(--count);
glEnd();
}
}
#endif

3005
engine/gl/gl_model.c Normal file

File diff suppressed because it is too large Load diff

817
engine/gl/gl_model.h Normal file
View file

@ -0,0 +1,817 @@
/*
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.
*/
#ifndef __MODEL__
#define __MODEL__
#include "modelgen.h"
#include "spritegn.h"
struct hull_s;
struct trace_s;
struct edict_s;
typedef struct {
qboolean (*RecursiveHullCheck) (struct hull_s *hull, int num, float p1f, float p2f, vec3_t p1, vec3_t p2, struct trace_s *trace);
int (*HullPointContents) (struct hull_s *hull, vec3_t p); //return FTE contents
} hullfuncs_t;
typedef struct {
void (*FatPVS) (vec3_t org, qboolean add);
qboolean (*EdictInFatPVS) (struct edict_s *edict);
void (*FindTouchedLeafs_Q1) (struct edict_s *ent); //edict system as opposed to q2 game dll system.
void (*LightPointValues) (vec3_t point, vec3_t res_diffuse, vec3_t res_ambient, vec3_t res_dir);
void (*StainNode) (struct mnode_s *node, float *parms);
void (*MarkLights) (struct dlight_s *light, int bit, struct mnode_s *node);
qbyte *(*LeafPVS) (int num, struct model_s *model, qbyte *buffer);
int (*LeafForPoint) (vec3_t point, struct model_s *model);
} bspfuncs_t;
typedef struct mesh_s
{
int numvertexes;
vec4_t *xyz_array; //structure is used only at load.
vec3_t *normals_array; //so what harm is there in doing this?
vec2_t *st_array;
vec2_t *lmst_array;
byte_vec4_t *colors_array;
int numindexes;
int *indexes;
int *trneighbors;
vec3_t *trnormals;
vec3_t mins, maxs;
float radius;
vec3_t lightaxis[3];
unsigned int patchWidth;
unsigned int patchHeight;
} mesh_t;
extern int gl_canbumpmap;
/*
d*_t structures are on-disk representations
m*_t structures are in-memory
*/
// entity effects
#define EF_BRIGHTFIELD 1
#define EF_MUZZLEFLASH 2
#define EF_BRIGHTLIGHT 4
#define EF_DIMLIGHT 8
#define EF_FLAG1 16
#define EF_FLAG2 32
#define EF_BLUE 64
#define EF_RED 128
#define EF_NODRAW 0x80 //this is going to get complicated...
/*
==============================================================================
BRUSH MODELS
==============================================================================
*/
//
// in memory representation
//
// !!! if this is changed, it must be changed in asm_draw.h too !!!
typedef struct
{
vec3_t position;
} mvertex_t;
#define SIDE_FRONT 0
#define SIDE_BACK 1
#define SIDE_ON 2
// plane_t structure
// !!! if this is changed, it must be changed in asm_i386.h too !!!
typedef struct mplane_s
{
vec3_t normal;
float dist;
qbyte type; // for texture axis selection and fast side tests
qbyte signbits; // signx + signy<<1 + signz<<1
qbyte pad[2];
} mplane_t;
typedef struct texture_s
{
char name[64];
unsigned width, height;
qbyte pixbytes;
qbyte alphaed; //gl_blend needed on this surface.
int parttype;
int gl_texturenum;
int gl_texturenumfb;
int gl_texturenumbumpmap;
struct msurface_s *texturechain; // for gl_texsort drawing
int anim_total; // total tenths in sequence ( 0 = no)
int anim_min, anim_max; // time for this frame min <=time< max
struct texture_s *anim_next; // in the animation sequence
struct texture_s *alternate_anims; // bmodels in frmae 1 use these
unsigned offsets[MIPLEVELS]; // four mip maps stored
} texture_t;
#define SURF_DRAWSKYBOX 1
#define SURF_PLANEBACK 2
#define SURF_DRAWSKY 4
#define SURF_DRAWSPRITE 8
#define SURF_DRAWTURB 0x10
#define SURF_DRAWTILED 0x20
#define SURF_DRAWBACKGROUND 0x40
#define SURF_UNDERWATER 0x80
#define SURF_DONTWARP 0x100
#define SURF_BULLETEN 0x200
#define SURF_DRAWALPHA 0x10000
// !!! if this is changed, it must be changed in asm_draw.h too !!!
typedef struct
{
unsigned short v[2];
unsigned int cachededgeoffset;
} medge_t;
typedef struct mtexinfo_s
{
float vecs[2][4];
float mipadjust;
texture_t *texture;
int flags;
//it's a q2 thing.
int numframes;
struct mtexinfo_s *next;
} mtexinfo_t;
#define VERTEXSIZE 7
typedef struct glpoly_s
{
struct glpoly_s *next;
struct glpoly_s *chain;
int numverts;
int flags; // for SURF_UNDERWATER
#ifdef SHADERS
float texcenter[2]; //center of texture made by adveraging the tex coords
#endif
float verts[4][VERTEXSIZE]; // variable sized (xyz s1t1 s2t2)
} glpoly_t;
typedef struct msurface_s
{
int visframe; // should be drawn when node is crossed
int shadowframe;
mplane_t *plane;
int flags;
int firstedge; // look up in model->surfedges[], negative numbers
int numedges; // are backwards edges
#ifdef SWQUAKE
struct surfcache_s *cachespots[MIPLEVELS];
#endif
struct msurface_s *nextalphasurface;
short texturemins[2];
short extents[2];
int light_s, light_t; // gl lightmap coordinates
mesh_t *mesh;
entity_t *ownerent;
glpoly_t *polys; // multiple if warped
vec3_t center; //adverage
float radius; //max dist from center
struct msurface_s *texturechain;
vec3_t normal;
mtexinfo_t *texinfo;
// lighting info
int dlightframe;
int dlightbits;
int lightmaptexturenum;
qbyte styles[MAXLIGHTMAPS];
int cached_light[MAXLIGHTMAPS]; // values currently used in lightmap
qboolean cached_dlight; // true if dynamic light in cache
#ifdef PEXT_LIGHTSTYLECOL
qbyte cached_colour[MAXLIGHTMAPS];
#endif
#ifndef NOSTAINS
qboolean stained;
#endif
qbyte *samples; // [numstyles*surfsize]
} msurface_t;
typedef struct mnode_s
{
// common with leaf
int contents; // 0, to differentiate from leafs
int visframe; // node needs to be traversed if current
int shadowframe;
float minmaxs[6]; // for bounding box culling
struct mnode_s *parent;
// node specific
mplane_t *plane;
struct mnode_s *children[2];
#ifdef Q2BSPS
int childnum[2];
#endif
unsigned short firstsurface;
unsigned short numsurfaces;
} mnode_t;
typedef struct mleaf_s
{
// common with node
int contents; // wil be a negative contents number
int visframe; // node needs to be traversed if current
int shadowframe;
float minmaxs[6]; // for bounding box culling
struct mnode_s *parent;
// leaf specific
qbyte *compressed_vis;
struct efrag_s *efrags;
msurface_t **firstmarksurface;
int nummarksurfaces;
int key; // BSP sequence number for leaf's contents
qbyte ambient_sound_level[NUM_AMBIENTS];
#ifdef Q2BSPS
//it's a q2 thing
int cluster;
int area;
unsigned short firstleafbrush;
unsigned short numleafbrushes;
unsigned short firstleafface; //q3 addititions
unsigned short numleaffaces;
unsigned short numleafpatches;
unsigned short firstleafpatch;
struct mleaf_s *vischain;
#endif
} mleaf_t;
typedef struct
{
float mins[3], maxs[3];
float origin[3];
int headnode[MAX_MAP_HULLSM];
int visleafs; // not including the solid leaf 0
int firstface, numfaces;
qboolean hullavailable[MAX_MAP_HULLSM];
} mmodel_t;
// !!! if this is changed, it must be changed in asm_i386.h too !!!
typedef struct hull_s
{
dclipnode_t *clipnodes;
mplane_t *planes;
int firstclipnode;
int lastclipnode;
vec3_t clip_mins;
vec3_t clip_maxs;
int available;
hullfuncs_t funcs;
} hull_t;
void Q1BSP_SetHullFuncs(hull_t *hull);
/*
==============================================================================
SPRITE MODELS
==============================================================================
*/
// FIXME: shorten these?
typedef struct mspriteframe_s
{
int width;
int height;
float up, down, left, right;
int gl_texturenum;
#ifdef SWQUAKE
qbyte pixels[4];
#endif
} mspriteframe_t;
typedef struct
{
int numframes;
float *intervals;
mspriteframe_t *frames[1];
} mspritegroup_t;
typedef struct
{
spriteframetype_t type;
mspriteframe_t *frameptr;
} mspriteframedesc_t;
typedef struct
{
int type;
int maxwidth;
int maxheight;
int numframes;
float beamlength; // remove?
void *cachespot; // remove?
mspriteframedesc_t frames[1];
} msprite_t;
/*
==============================================================================
ALIAS MODELS
Alias models are position independent, so the cache manager can move them.
==============================================================================
*/
typedef struct {
int s;
int t;
} mstvert_t;
typedef struct
{
#ifdef SWQUAKE
aliasframetype_t type;
#endif
int firstpose;
int numposes;
float interval;
dtrivertx_t bboxmin;
dtrivertx_t bboxmax;
vec3_t scale;
vec3_t scale_origin;
int frame;
char name[16];
} maliasframedesc_t;
typedef struct
{
dtrivertx_t bboxmin;
dtrivertx_t bboxmax;
int frame;
} maliasgroupframedesc_t;
typedef struct
{
int numframes;
int intervals;
maliasgroupframedesc_t frames[1];
} maliasgroup_t;
// !!! if this is changed, it must be changed in asm_draw.h too !!!
typedef struct mtriangle_s {
int xyz_index[3];
int st_index[3];
int neighbors[3];
} mtriangle_t;
#define MAX_SKINS 32
typedef struct {
int ident;
int version;
vec3_t scale;
vec3_t scale_origin;
float boundingradius;
vec3_t eyeposition;
int numskins;
int skinwidth;
int skinheight;
int numverts;
int numtris;
int numframes;
synctype_t synctype;
int flags;
float size;
#ifdef SWQUAKE
int model;
int stverts;
int skindesc;
#endif
int numposes;
int poseverts;
int posedata; // numposes*poseverts trivert_t
int baseposedata; //original verts for triangles to reference
int triangles; //we need tri data for shadow volumes
int commands; // gl command list with embedded s/t
int gl_texturenum[MAX_SKINS][4];
int texels[MAX_SKINS];
maliasframedesc_t frames[1]; // variable sized
} aliashdr_t;
#define MAXALIASVERTS 2048
#define ALIAS_Z_CLIP_PLANE 5
#define MAXALIASFRAMES 256
#define MAXALIASTRIS 2048
extern aliashdr_t *pheader;
extern mstvert_t stverts[MAXALIASVERTS*2];
extern mtriangle_t triangles[MAXALIASTRIS];
extern dtrivertx_t *poseverts[MAXALIASFRAMES];
/*
========================================================================
.MD2 triangle model file format
========================================================================
*/
// LordHavoc: grabbed this from the Q2 utility source,
// renamed a things to avoid conflicts
#define MD2IDALIASHEADER (('2'<<24)+('P'<<16)+('D'<<8)+'I')
#define MD2ALIAS_VERSION 8
#define MD2MAX_TRIANGLES 4096
#define MD2MAX_VERTS 2048
#define MD2MAX_FRAMES 512
#define MD2MAX_SKINS 32
#define MD2MAX_SKINNAME 64
// sanity checking size
#define MD2MAX_SIZE (1024*4200)
typedef struct
{
short s;
short t;
} md2stvert_t;
typedef struct
{
short index_xyz[3];
short index_st[3];
} md2triangle_t;
typedef struct
{
qbyte v[3]; // scaled qbyte to fit in frame mins/maxs
qbyte lightnormalindex;
} md2trivertx_t;
#define MD2TRIVERTX_V0 0
#define MD2TRIVERTX_V1 1
#define MD2TRIVERTX_V2 2
#define MD2TRIVERTX_LNI 3
#define MD2TRIVERTX_SIZE 4
typedef struct
{
float scale[3]; // multiply qbyte verts by this
float translate[3]; // then add this
char name[16]; // frame name from grabbing
md2trivertx_t verts[1]; // variable sized
} md2frame_t;
// the glcmd format:
// a positive integer starts a tristrip command, followed by that many
// vertex structures.
// a negative integer starts a trifan command, followed by -x vertexes
// a zero indicates the end of the command list.
// a vertex consists of a floating point s, a floating point t,
// and an integer vertex index.
typedef struct
{
int ident;
int version;
int skinwidth;
int skinheight;
int framesize; // qbyte size of each frame
int num_skins;
int num_xyz;
int num_st; // greater than num_xyz for seams
int num_tris;
int num_glcmds; // dwords in strip/fan command list
int num_frames;
int ofs_skins; // each skin is a MAX_SKINNAME string
int ofs_st; // qbyte offset from start for stverts
int ofs_tris; // offset for dtriangles
int ofs_frames; // offset for first frame
int ofs_glcmds;
int ofs_end; // end of file
int gl_texturenum[MAX_SKINS];
} md2_t;
#define ALIASTYPE_MDL 1
#define ALIASTYPE_MD2 2
//===================================================================
typedef struct
{
qbyte ambient[3];
qbyte diffuse[3];
qbyte direction[2];
} dq3gridlight_t;
typedef struct {
vec3_t gridBounds;
vec3_t gridMins;
vec3_t gridSize;
int numlightgridelems;
dq3gridlight_t lightgrid[1];
} q3lightgridinfo_t;
//
// Whole model
//
typedef enum {mod_brush, mod_sprite, mod_alias, mod_dummy, mod_halflife} modtype_t;
typedef enum {fg_quake, fg_quake2, fg_quake3, fg_halflife, fg_new, fg_doom} fromgame_t; //useful when we have very similar model types. (eg quake/halflife bsps)
#define EF_ROCKET 1 // leave a trail
#define EF_GRENADE 2 // leave a trail
#define EF_GIB 4 // leave a trail
#define EF_ROTATE 8 // rotate (bonus items)
#define EF_TRACER 16 // green split trail
#define EF_ZOMGIB 32 // small blood trail
#define EF_TRACER2 64 // orange split trail + rotate
#define EF_TRACER3 128 // purple trail
//hexen2.
#define EF_FIREBALL 256 // Yellow transparent trail in all directions
#define EF_ICE 512 // Blue-white transparent trail, with gravity
#define EF_MIP_MAP 1024 // This model has mip-maps
#define EF_SPIT 2048 // Black transparent trail with negative light
#define EF_TRANSPARENT 4096 // Transparent sprite
#define EF_SPELL 8192 // Vertical spray of particles
#define EF_HOLEY 16384 // Solid model with color 0
#define EF_SPECIAL_TRANS 32768 // Translucency through the particle table
#define EF_FACE_VIEW 65536 // Poly Model always faces you
#define EF_VORP_MISSILE 131072 // leave a trail at top and bottom of model
#define EF_SET_STAFF 262144 // slowly move up and left/right
#define EF_MAGICMISSILE 524288 // a trickle of blue/white particles with gravity
#define EF_BONESHARD 1048576 // a trickle of brown particles with gravity
#define EF_SCARAB 2097152 // white transparent particles with little gravity
#define EF_ACIDBALL 4194304 // Green drippy acid shit
#define EF_BLOODSHOT 8388608 // Blood rain shot trail
typedef union {
struct {
int numlinedefs;
int numsidedefs;
int numsectors;
} doom;
} specificmodeltype_t;
typedef struct model_s
{
char name[MAX_QPATH];
qboolean needload; // bmodels and sprites don't cache normally
modtype_t type;
fromgame_t fromgame;
int numframes;
synctype_t synctype;
int flags;
int particleeffect;
qboolean particleengulphs;
int particletrail;
qboolean nodefaulttrail;
qboolean rgblighting; //.lit, halflife.
//
// volume occupied by the model graphics
//
vec3_t mins, maxs;
float radius;
//
// solid volume for clipping
//
qboolean clipbox;
vec3_t clipmins, clipmaxs;
//
// brush model
//
int firstmodelsurface, nummodelsurfaces;
int numsubmodels;
mmodel_t *submodels;
int numplanes;
mplane_t *planes;
int numleafs; // number of visible leafs, not counting 0
mleaf_t *leafs;
int numvertexes;
mvertex_t *vertexes;
int numedges;
medge_t *edges;
int numnodes;
mnode_t *nodes;
int numtexinfo;
mtexinfo_t *texinfo;
int numsurfaces;
msurface_t *surfaces;
int numsurfedges;
int *surfedges;
int numclipnodes;
dclipnode_t *clipnodes;
int nummarksurfaces;
msurface_t **marksurfaces;
hull_t hulls[MAX_MAP_HULLSM];
int numtextures;
texture_t **textures;
qbyte *visdata;
void *vis;
qbyte *lightdata;
qbyte *deluxdata;
q3lightgridinfo_t *lightgrid;
char *entities;
struct terrain_s *terrain;
unsigned checksum;
unsigned checksum2;
bspfuncs_t funcs;
//
// additional model data
//
cache_user_t cache; // only access through Mod_Extradata
} model_t;
//============================================================================
/*
void Mod_Init (void);
void Mod_ClearAll (void);
model_t *Mod_ForName (char *name, qboolean crash);
model_t *Mod_FindName (char *name);
void *Mod_Extradata (model_t *mod); // handles caching
void Mod_TouchModel (char *name);
mleaf_t *Mod_PointInLeaf (float *p, model_t *model);
qbyte *Mod_LeafPVS (mleaf_t *leaf, model_t *model);
*/
#endif // __MODEL__
#ifdef Q2BSPS
#ifdef __cplusplus
//#pragma message (" c++ stinks")
#else
void CM_Init(void);
qboolean CM_SetAreaPortalState (int portalnum, qboolean open);
qboolean CM_HeadnodeVisible (int nodenum, qbyte *visbits);
qboolean CM_AreasConnected (int area1, int area2);
int CM_NumClusters (void);
int CM_ClusterSize (void);
int CM_LeafContents (int leafnum);
int CM_LeafCluster (int leafnum);
int CM_LeafArea (int leafnum);
int CM_WriteAreaBits (qbyte *buffer, int area);
int CM_PointLeafnum (vec3_t p);
qbyte *CM_ClusterPVS (int cluster, qbyte *buffer);
qbyte *CM_ClusterPHS (int cluster);
int CM_BoxLeafnums (vec3_t mins, vec3_t maxs, int *list, int listsize, int *topnode);
int CM_PointContents (vec3_t p, int headnode);
struct trace_s CM_BoxTrace (vec3_t start, vec3_t end, vec3_t mins, vec3_t maxs, int headnode, int brushmask);
int CM_HeadnodeForBox (vec3_t mins, vec3_t maxs);
struct trace_s CM_TransformedBoxTrace (vec3_t start, vec3_t end, vec3_t mins, vec3_t maxs, int headnode, int brushmask, vec3_t origin, vec3_t angles);
void Mod_ParseInfoFromEntityLump(char *data);
qboolean CMQ2_SetAreaPortalState (int portalnum, qboolean open);
#endif
#ifdef SWQUAKE
typedef struct
{
aliasskintype_t type;
void *pcachespot;
int skin;
} maliasskindesc_t;
typedef struct
{
int numskins;
int intervals;
maliasskindesc_t skindescs[1];
} maliasskingroup_t;
#endif
#endif //__MODEL__

143
engine/gl/gl_ngraph.c Normal file
View file

@ -0,0 +1,143 @@
/*
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_ngraph.c
#include "quakedef.h"
#include "glquake.h"
extern qbyte *draw_chars; // 8*8 graphic characters
int netgraphtexture; // netgraph texture
#define NET_GRAPHHEIGHT 32
static qbyte ngraph_texels[NET_GRAPHHEIGHT][NET_TIMINGS];
static void R_LineGraph (int x, int h)
{
int i;
int s;
int color;
s = NET_GRAPHHEIGHT;
if (h == 10000)
color = 0x6f; // yellow
else if (h == 9999)
color = 0x4f; // red
else if (h == 9998)
color = 0xd0; // blue
else
color = 0xfe; // white
if (h>s)
h = s;
for (i=0 ; i<h ; i++)
if (i & 1)
ngraph_texels[NET_GRAPHHEIGHT - i - 1][x] = 0xff;
else
ngraph_texels[NET_GRAPHHEIGHT - i - 1][x] = (qbyte)color;
for ( ; i<s ; i++)
ngraph_texels[NET_GRAPHHEIGHT - i - 1][x] = (qbyte)0xff;
}
void Draw_CharToNetGraph (int x, int y, int num)
{
int row, col;
qbyte *source;
int drawline;
int nx;
row = num>>4;
col = num&15;
source = draw_chars + (row<<10) + (col<<3);
for (drawline = 8; drawline; drawline--, y++)
{
for (nx=0 ; nx<8 ; nx++)
if (source[nx] != 255)
ngraph_texels[y][nx+x] = 0x60 + source[nx];
source += 128;
}
}
/*
==============
R_NetGraph
==============
*/
void GLR_NetGraph (void)
{
int a, x, i, y;
int lost;
char st[80];
unsigned ngraph_pixels[NET_GRAPHHEIGHT][NET_TIMINGS];
x = 0;
lost = CL_CalcNet();
for (a=0 ; a<NET_TIMINGS ; a++)
{
i = (cls.netchan.outgoing_sequence-a) & NET_TIMINGSMASK;
R_LineGraph (NET_TIMINGS-1-a, packet_latency[i]);
}
// now load the netgraph texture into gl and draw it
for (y = 0; y < NET_GRAPHHEIGHT; y++)
for (x = 0; x < NET_TIMINGS; x++)
ngraph_pixels[y][x] = d_8to24rgbtable[ngraph_texels[y][x]];
x = ((vid.width - 320)>>1);
x=-x;
y = vid.height - sb_lines - 24 - NET_GRAPHHEIGHT - 1;
M_DrawTextBox (x, y, NET_TIMINGS/8, NET_GRAPHHEIGHT/8 + 1);
y += 8;
sprintf(st, "%3i%% packet loss", lost);
Draw_String(8, y, st);
y += 8;
GL_Bind(netgraphtexture);
glTexImage2D (GL_TEXTURE_2D, 0, gl_alpha_format,
NET_TIMINGS, NET_GRAPHHEIGHT, 0, GL_RGBA,
GL_UNSIGNED_BYTE, ngraph_pixels);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
x = 8;
glColor3f (1,1,1);
glBegin (GL_QUADS);
glTexCoord2f (0, 0);
glVertex2f (x, y);
glTexCoord2f (1, 0);
glVertex2f (x+NET_TIMINGS, y);
glTexCoord2f (1, 1);
glVertex2f (x+NET_TIMINGS, y+NET_GRAPHHEIGHT);
glTexCoord2f (0, 1);
glVertex2f (x, y+NET_GRAPHHEIGHT);
glEnd ();
}

2297
engine/gl/gl_ppl.c Normal file

File diff suppressed because it is too large Load diff

926
engine/gl/gl_rlight.c Normal file
View file

@ -0,0 +1,926 @@
/*
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.
*/
// r_light.c
#include "quakedef.h"
#include "glquake.h"
int r_dlightframecount;
/*
==================
R_AnimateLight
==================
*/
void GLR_AnimateLight (void)
{
int i,j,k;
//
// light animations
// 'm' is normal light, 'a' is no light, 'z' is double bright
i = (int)(cl.time*10);
for (j=0 ; j<MAX_LIGHTSTYLES ; j++)
{
if (!cl_lightstyle[j].length)
{
d_lightstylevalue[j] = 256;
continue;
}
k = i % cl_lightstyle[j].length;
k = cl_lightstyle[j].map[k] - 'a';
k = k*22;
d_lightstylevalue[j] = k;
}
}
/*
=============================================================================
DYNAMIC LIGHTS BLEND RENDERING
=============================================================================
*/
void AddLightBlend (float r, float g, float b, float a2)
{
float a;
v_blend[3] = a = v_blend[3] + a2*(1-v_blend[3]);
a2 = a2/a;
v_blend[0] = v_blend[1]*(1-a2) + r*a2;
v_blend[1] = v_blend[1]*(1-a2) + g*a2;
v_blend[2] = v_blend[2]*(1-a2) + b*a2;
//Con_Printf("AddLightBlend(): %4.2f %4.2f %4.2f %4.6f\n", v_blend[0], v_blend[1], v_blend[2], v_blend[3]);
}
float bubble_sintable[17], bubble_costable[17];
void R_InitBubble() {
float a;
int i;
float *bub_sin, *bub_cos;
bub_sin = bubble_sintable;
bub_cos = bubble_costable;
for (i=16 ; i>=0 ; i--)
{
a = i/16.0 * M_PI*2;
*bub_sin++ = sin(a);
*bub_cos++ = cos(a);
}
}
void R_RenderDlight (dlight_t *light)
{
int i, j;
// float a;
vec3_t v;
float rad;
float *bub_sin, *bub_cos;
bub_sin = bubble_sintable;
bub_cos = bubble_costable;
rad = light->radius * 0.35;
VectorSubtract (light->origin, r_origin, v);
if (Length (v) < rad)
{ // view is inside the dlight
AddLightBlend (1, 0.5, 0, light->radius * 0.0003);
return;
}
glBegin (GL_TRIANGLE_FAN);
// glColor3f (0.2,0.1,0.0);
// glColor3f (0.2,0.1,0.05); // changed dimlight effect
glColor4f (light->color[0]*2, light->color[1]*2, light->color[2]*2,
1);//light->color[3]);
for (i=0 ; i<3 ; i++)
v[i] = light->origin[i] - vpn[i]*rad/1.5;
glVertex3fv (v);
glColor3f (0,0,0);
for (i=16 ; i>=0 ; i--)
{
// a = i/16.0 * M_PI*2;
for (j=0 ; j<3 ; j++)
v[j] = light->origin[j] + (vright[j]*(*bub_cos) +
+ vup[j]*(*bub_sin)) * rad;
bub_sin++;
bub_cos++;
glVertex3fv (v);
}
glEnd ();
}
/*
=============
R_RenderDlights
=============
*/
void R_RenderDlights (void)
{
int i;
dlight_t *l;
if (!r_flashblend.value)
return;
// r_dlightframecount = r_framecount + 1; // because the count hasn't
// advanced yet for this frame
glDepthMask (0);
glDisable (GL_TEXTURE_2D);
glShadeModel (GL_SMOOTH);
glEnable (GL_BLEND);
glBlendFunc (GL_ONE, GL_ONE);
l = cl_dlights;
for (i=0 ; i<MAX_DLIGHTS ; i++, l++)
{
if (l->die < cl.time || !l->radius)
continue;
R_RenderDlight (l);
}
glColor3f (1,1,1);
glDisable (GL_BLEND);
glEnable (GL_TEXTURE_2D);
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glDepthMask (1);
}
/*
=============================================================================
DYNAMIC LIGHTS
=============================================================================
*/
/*
=============
R_MarkLights
=============
*/
/*void GLR_MarkLights (dlight_t *light, int bit, mnode_t *node)
{
mplane_t *splitplane;
float dist;
msurface_t *surf;
int i;
if (node->contents < 0)
return;
splitplane = node->plane;
dist = DotProduct (light->origin, splitplane->normal) - splitplane->dist;
if (dist > light->radius)
{
GLR_MarkLights (light, bit, node->children[0]);
return;
}
if (dist < -light->radius)
{
GLR_MarkLights (light, bit, node->children[1]);
return;
}
// mark the polygons
surf = cl.worldmodel->surfaces + node->firstsurface;
for (i=0 ; i<node->numsurfaces ; i++, surf++)
{
if (surf->dlightframe != r_dlightframecount)
{
surf->dlightbits = 0;
surf->dlightframe = r_dlightframecount;
}
surf->dlightbits |= bit;
}
GLR_MarkLights (light, bit, node->children[0]);
GLR_MarkLights (light, bit, node->children[1]);
}*/
/*void Q2BSP_MarkLights (dlight_t *light, int bit, mnode_t *node)
{
mplane_t *splitplane;
float dist;
msurface_t *surf;
int i;
if (node->contents != -1)
return;
splitplane = node->plane;
dist = DotProduct (light->origin, splitplane->normal) - splitplane->dist;
if (dist > light->radius)
{
Q2BSP_MarkLights (light, bit, node->children[0]);
return;
}
if (dist < -light->radius)
{
Q2BSP_MarkLights (light, bit, node->children[1]);
return;
}
// mark the polygons
surf = cl.worldmodel->surfaces + node->firstsurface;
for (i=0 ; i<node->numsurfaces ; i++, surf++)
{
if (surf->dlightframe != r_dlightframecount)
{
surf->dlightbits = 0;
surf->dlightframe = r_dlightframecount;
}
surf->dlightbits |= bit;
}
Q2BSP_MarkLights (light, bit, node->children[0]);
Q2BSP_MarkLights (light, bit, node->children[1]);
}*/
void GLR_MarkQ3Lights (dlight_t *light, int bit, mnode_t *node)
{
mplane_t *splitplane;
float dist;
msurface_t *surf;
int i;
return; //we need to get the texinfos right first.
/*
//mark all
for (surf = cl.worldmodel->surfaces, i = 0; i < cl.worldmodel->numsurfaces; i++, surf++)
{
if (surf->dlightframe != r_dlightframecount)
{
surf->dlightbits = 0;
surf->dlightframe = r_dlightframecount;
}
surf->dlightbits |= bit;
}
return;
*/
if (node->contents != -1)
{
msurface_t **mark;
mleaf_t *leaf;
// mark the polygons
leaf = (mleaf_t *)node;
mark = leaf->firstmarksurface;
for (i=0 ; i<leaf->nummarksurfaces ; i++, surf++)
{
surf = *mark++;
if (surf->dlightframe != r_dlightframecount)
{
surf->dlightbits = 0;
surf->dlightframe = r_dlightframecount;
}
surf->dlightbits |= bit;
}
return;
}
splitplane = node->plane;
dist = DotProduct (light->origin, splitplane->normal) - splitplane->dist;
if (dist > light->radius)
{
GLR_MarkQ3Lights (light, bit, node->children[0]);
return;
}
if (dist < -light->radius)
{
GLR_MarkQ3Lights (light, bit, node->children[1]);
return;
}
GLR_MarkQ3Lights (light, bit, node->children[0]);
GLR_MarkQ3Lights (light, bit, node->children[1]);
}
/*
=============
R_PushDlights
=============
*/
void GLR_PushDlights (void)
{
int i;
dlight_t *l;
r_dlightframecount = r_framecount + 1; // because the count hasn't
// advanced yet for this frame
if (!r_dynamic.value)
return;
// if (!cl.worldmodel->nodes)
// return;
l = cl_dlights;
for (i=0 ; i<MAX_DLIGHTS ; i++, l++)
{
if (l->die < cl.time || !l->radius)
continue;
cl.worldmodel->funcs.MarkLights( l, 1<<i, cl.worldmodel->nodes );
}
/*
if (cl.worldmodel->fromgame == fg_quake3)
{
for (i=0 ; i<MAX_DLIGHTS ; i++, l++)
{
if (l->die < cl.time || !l->radius)
continue;
GLR_MarkQ3Lights ( l, 1<<i, cl.worldmodel->nodes );
}
return;
}
if (cl.worldmodel->fromgame == fg_quake2)
{
for (i=0 ; i<MAX_DLIGHTS ; i++, l++)
{
if (l->die < cl.time || !l->radius)
continue;
GLR_MarkQ2Lights ( l, 1<<i, cl.worldmodel->nodes );
}
return;
}
for (i=0 ; i<MAX_DLIGHTS ; i++, l++)
{
if (l->die < cl.time || !l->radius)
continue;
GLR_MarkLights ( l, 1<<i, cl.worldmodel->nodes );
}*/
}
/*
=============================================================================
LIGHT SAMPLING
=============================================================================
*/
mplane_t *lightplane;
vec3_t lightspot;
void GLQ3_LightGrid(vec3_t point, vec3_t res_diffuse, vec3_t res_ambient, vec3_t res_dir)
{
q3lightgridinfo_t *lg = (q3lightgridinfo_t *)cl.worldmodel->lightgrid;
int index[4];
int vi[3];
int i, j;
float t[8], direction_uv[3];
vec3_t vf, vf2;
vec3_t ambient, diffuse;
res_dir[0] = 1;
res_dir[1] = 1;
res_dir[2] = 0.1;
if (!lg)
{
res_ambient[0] = 255;
res_ambient[1] = 255;
res_ambient[2] = 255;
return;
}
//If in doubt, steal someone else's code...
//Thanks QFusion.
for ( i = 0; i < 3; i++ )
{
vf[i] = (point[i] - lg->gridMins[i]) / lg->gridSize[i];
vi[i] = (int)vf[i];
vf[i] = vf[i] - floor(vf[i]);
vf2[i] = 1.0f - vf[i];
}
index[0] = vi[2]*lg->gridBounds[3] + vi[1]*lg->gridBounds[0] + vi[0];
index[1] = index[0] + lg->gridBounds[0];
index[2] = index[0] + lg->gridBounds[3];
index[3] = index[2] + lg->gridBounds[0];
for ( i = 0; i < 4; i++ )
{
if ( index[i] < 0 || index[i] >= (lg->numlightgridelems-1) )
{
res_ambient[0] = 255; //out of the map
res_ambient[1] = 255;
res_ambient[2] = 255;
return;
}
}
t[0] = vf2[0] * vf2[1] * vf2[2];
t[1] = vf[0] * vf2[1] * vf2[2];
t[2] = vf2[0] * vf[1] * vf2[2];
t[3] = vf[0] * vf[1] * vf2[2];
t[4] = vf2[0] * vf2[1] * vf[2];
t[5] = vf[0] * vf2[1] * vf[2];
t[6] = vf2[0] * vf[1] * vf[2];
t[7] = vf[0] * vf[1] * vf[2];
for ( j = 0; j < 3; j++ )
{
ambient[j] = 0;
diffuse[j] = 0;
for ( i = 0; i < 4; i++ )
{
ambient[j] += t[i*2] * lg->lightgrid[ index[i] ].ambient[j];
ambient[j] += t[i*2+1] * lg->lightgrid[ index[i] + 1 ].ambient[j];
diffuse[j] += t[i*2] * lg->lightgrid[ index[i] ].diffuse[j];
diffuse[j] += t[i*2+1] * lg->lightgrid[ index[i] + 1 ].diffuse[j];
}
}
for ( j = 0; j < 2; j++ )
{
direction_uv[j] = 0;
for ( i = 0; i < 4; i++ )
{
direction_uv[j] += t[i*2] * lg->lightgrid[ index[i] ].direction[j];
direction_uv[j] += t[i*2+1] * lg->lightgrid[ index[i] + 1 ].direction[j];
}
direction_uv[j] = anglemod ( direction_uv[j] );
}
VectorCopy(ambient, res_ambient);
if (res_diffuse)
VectorCopy(diffuse, res_diffuse);
if (res_dir)
{
vec3_t right, left;
direction_uv[2] = 0;
AngleVectors(direction_uv, res_dir, right, left);
}
}
int GLRecursiveLightPoint (mnode_t *node, vec3_t start, vec3_t end)
{
int r;
float front, back, frac;
int side;
mplane_t *plane;
vec3_t mid;
msurface_t *surf;
int s, t, ds, dt;
int i;
mtexinfo_t *tex;
qbyte *lightmap;
unsigned scale;
int maps;
if (cl.worldmodel->fromgame == fg_quake2)
{
if (node->contents != -1)
return -1; // solid
}
else if (node->contents < 0)
return -1; // didn't hit anything
// calculate mid point
// FIXME: optimize for axial
plane = node->plane;
front = DotProduct (start, plane->normal) - plane->dist;
back = DotProduct (end, plane->normal) - plane->dist;
side = front < 0;
if ( (back < 0) == side)
return GLRecursiveLightPoint (node->children[side], start, end);
frac = front / (front-back);
mid[0] = start[0] + (end[0] - start[0])*frac;
mid[1] = start[1] + (end[1] - start[1])*frac;
mid[2] = start[2] + (end[2] - start[2])*frac;
// go down front side
r = GLRecursiveLightPoint (node->children[side], start, mid);
if (r >= 0)
return r; // hit something
if ( (back < 0) == side )
return -1; // didn't hit anuthing
// check for impact on this node
VectorCopy (mid, lightspot);
lightplane = plane;
surf = cl.worldmodel->surfaces + node->firstsurface;
for (i=0 ; i<node->numsurfaces ; i++, surf++)
{
if (surf->flags & SURF_DRAWTILED)
continue; // no lightmaps
tex = surf->texinfo;
s = DotProduct (mid, tex->vecs[0]) + tex->vecs[0][3];
t = DotProduct (mid, tex->vecs[1]) + tex->vecs[1][3];;
if (s < surf->texturemins[0] ||
t < surf->texturemins[1])
continue;
ds = s - surf->texturemins[0];
dt = t - surf->texturemins[1];
if ( ds > surf->extents[0] || dt > surf->extents[1] )
continue;
if (!surf->samples)
return 0;
ds >>= 4;
dt >>= 4;
lightmap = surf->samples;
r = 0;
if (lightmap)
{
if (cl.worldmodel->rgblighting)
{
lightmap += (dt * ((surf->extents[0]>>4)+1) + ds)*3;
for (maps = 0 ; maps < MAXLIGHTMAPS && surf->styles[maps] != 255 ;
maps++)
{
scale = d_lightstylevalue[surf->styles[maps]];
r += (lightmap[0]+lightmap[1]+lightmap[2]) * scale / 3;
lightmap += ((surf->extents[0]>>4)+1) *
((surf->extents[1]>>4)+1)*3;
}
}
else
{
lightmap += dt * ((surf->extents[0]>>4)+1) + ds;
for (maps = 0 ; maps < MAXLIGHTMAPS && surf->styles[maps] != 255 ;
maps++)
{
scale = d_lightstylevalue[surf->styles[maps]];
r += *lightmap * scale;
lightmap += ((surf->extents[0]>>4)+1) *
((surf->extents[1]>>4)+1);
}
}
r >>= 8;
}
return r;
}
// go down back side
return GLRecursiveLightPoint (node->children[!side], mid, end);
}
int GLR_LightPoint (vec3_t p)
{
vec3_t end;
int r;
if (r_refdef.flags & 1)
return 255;
if (!cl.worldmodel || !cl.worldmodel->lightdata)
return 255;
if (cl.worldmodel->fromgame == fg_quake3)
{
GLQ3_LightGrid(p, NULL, end, NULL);
return (end[0] + end[1] + end[2])/3;
}
end[0] = p[0];
end[1] = p[1];
end[2] = p[2] - 2048;
r = GLRecursiveLightPoint (cl.worldmodel->nodes, p, end);
if (r == -1)
r = 0;
return r;
}
#ifdef PEXT_LIGHTSTYLECOL
float *GLRecursiveLightPoint3C (mnode_t *node, vec3_t start, vec3_t end)
{
static float l[6];
float *r;
float front, back, frac;
int side;
mplane_t *plane;
vec3_t mid;
msurface_t *surf;
int s, t, ds, dt;
int i;
mtexinfo_t *tex;
qbyte *lightmap, *deluxmap;
float scale;
int maps;
if (cl.worldmodel->fromgame == fg_quake2)
{
if (node->contents != -1)
return NULL; // solid
}
else if (node->contents < 0)
return NULL; // didn't hit anything
// calculate mid point
// FIXME: optimize for axial
plane = node->plane;
front = DotProduct (start, plane->normal) - plane->dist;
back = DotProduct (end, plane->normal) - plane->dist;
side = front < 0;
if ( (back < 0) == side)
return GLRecursiveLightPoint3C (node->children[side], start, end);
frac = front / (front-back);
mid[0] = start[0] + (end[0] - start[0])*frac;
mid[1] = start[1] + (end[1] - start[1])*frac;
mid[2] = start[2] + (end[2] - start[2])*frac;
// go down front side
r = GLRecursiveLightPoint3C (node->children[side], start, mid);
if (r && r[0]+r[1]+r[2] >= 0)
return r; // hit something
if ( (back < 0) == side )
return NULL; // didn't hit anuthing
// check for impact on this node
VectorCopy (mid, lightspot);
lightplane = plane;
surf = cl.worldmodel->surfaces + node->firstsurface;
for (i=0 ; i<node->numsurfaces ; i++, surf++)
{
if (surf->flags & SURF_DRAWTILED)
continue; // no lightmaps
tex = surf->texinfo;
s = DotProduct (mid, tex->vecs[0]) + tex->vecs[0][3];
t = DotProduct (mid, tex->vecs[1]) + tex->vecs[1][3];
if (s < surf->texturemins[0] ||
t < surf->texturemins[1])
continue;
ds = s - surf->texturemins[0];
dt = t - surf->texturemins[1];
if ( ds > surf->extents[0] || dt > surf->extents[1] )
continue;
if (!surf->samples)
{
l[0]=0;l[1]=0;l[2]=0;
l[3]=0;l[4]=1;l[5]=1;
return l;
}
ds >>= 4;
dt >>= 4;
lightmap = surf->samples;
l[0]=0;l[1]=0;l[2]=0;
l[3]=0;l[4]=0;l[5]=0;
if (lightmap)
{
if (cl.worldmodel->deluxdata)
{
if (cl.worldmodel->rgblighting)
{
deluxmap = surf->samples - cl.worldmodel->lightdata + cl.worldmodel->deluxdata;
lightmap += (dt * ((surf->extents[0]>>4)+1) + ds)*3;
deluxmap += (dt * ((surf->extents[0]>>4)+1) + ds)*3;
for (maps = 0 ; maps < MAXLIGHTMAPS && surf->styles[maps] != 255 ;
maps++)
{
scale = d_lightstylevalue[surf->styles[maps]]/256.0f;
if (cl_lightstyle[surf->styles[maps]].colour & 1)
l[0] += lightmap[0] * scale;
if (cl_lightstyle[surf->styles[maps]].colour & 2)
l[1] += lightmap[1] * scale;
if (cl_lightstyle[surf->styles[maps]].colour & 4)
l[2] += lightmap[2] * scale;
l[3] += (deluxmap[0]-127)*scale;
l[4] += (deluxmap[1]-127)*scale;
l[5] += (deluxmap[2]-127)*scale;
lightmap += ((surf->extents[0]>>4)+1) *
((surf->extents[1]>>4)+1) * 3;
deluxmap += ((surf->extents[0]>>4)+1) *
((surf->extents[1]>>4)+1) * 3;
}
}
else
{
deluxmap = (surf->samples - cl.worldmodel->lightdata)*3 + cl.worldmodel->deluxdata;
lightmap += (dt * ((surf->extents[0]>>4)+1) + ds);
deluxmap += (dt * ((surf->extents[0]>>4)+1) + ds)*3;
for (maps = 0 ; maps < MAXLIGHTMAPS && surf->styles[maps] != 255 ;
maps++)
{
scale = d_lightstylevalue[surf->styles[maps]]/256.0f;
if (cl_lightstyle[surf->styles[maps]].colour & 1)
l[0] += *lightmap * scale;
if (cl_lightstyle[surf->styles[maps]].colour & 2)
l[1] += *lightmap * scale;
if (cl_lightstyle[surf->styles[maps]].colour & 4)
l[2] += *lightmap * scale;
l[3] += deluxmap[0]*scale;
l[4] += deluxmap[1]*scale;
l[5] += deluxmap[2]*scale;
lightmap += ((surf->extents[0]>>4)+1) *
((surf->extents[1]>>4)+1);
deluxmap += ((surf->extents[0]>>4)+1) *
((surf->extents[1]>>4)+1) * 3;
}
}
}
else
{
if (cl.worldmodel->rgblighting)
{
lightmap += (dt * ((surf->extents[0]>>4)+1) + ds)*3;
for (maps = 0 ; maps < MAXLIGHTMAPS && surf->styles[maps] != 255 ;
maps++)
{
scale = d_lightstylevalue[surf->styles[maps]]/256.0f;
if (cl_lightstyle[surf->styles[maps]].colour & 1)
l[0] += lightmap[0] * scale;
if (cl_lightstyle[surf->styles[maps]].colour & 2)
l[1] += lightmap[1] * scale;
if (cl_lightstyle[surf->styles[maps]].colour & 4)
l[2] += lightmap[2] * scale;
lightmap += ((surf->extents[0]>>4)+1) *
((surf->extents[1]>>4)+1) * 3;
}
}
else
{
lightmap += (dt * ((surf->extents[0]>>4)+1) + ds);
for (maps = 0 ; maps < MAXLIGHTMAPS && surf->styles[maps] != 255 ;
maps++)
{
scale = d_lightstylevalue[surf->styles[maps]]/256.0f;
if (cl_lightstyle[surf->styles[maps]].colour & 1)
l[0] += *lightmap * scale;
if (cl_lightstyle[surf->styles[maps]].colour & 2)
l[1] += *lightmap * scale;
if (cl_lightstyle[surf->styles[maps]].colour & 4)
l[2] += *lightmap * scale;
lightmap += ((surf->extents[0]>>4)+1) *
((surf->extents[1]>>4)+1);
}
}
}
}
return l;
}
// go down back side
return GLRecursiveLightPoint3C (node->children[!side], mid, end);
}
float *GLR_LightPoint3C (vec3_t p)
{
static vec3_t l = {255, 255, 255};
static vec3_t nl = {0, 0, 0};
float *r;
vec3_t end;
if (!cl.worldmodel->lightdata)
{
return l;
}
if (cl.worldmodel->fromgame == fg_quake3)
return nl;
if (cl.worldmodel->fromgame == fg_doom)
return nl;
end[0] = p[0];
end[1] = p[1];
end[2] = p[2] - 2048;
r = GLRecursiveLightPoint3C (cl.worldmodel->nodes, p, end);
if (r == NULL)
return nl;
return r;
}
#endif
void GLQ1BSP_LightPointValues(vec3_t point, vec3_t res_diffuse, vec3_t res_ambient, vec3_t res_dir)
{
vec3_t end;
float *r;
end[0] = point[0];
end[1] = point[1];
end[2] = point[2] - 2048;
r = GLRecursiveLightPoint3C(cl.worldmodel->nodes, point, end);
if (r == NULL)
{
res_diffuse[0] = 0;
res_diffuse[1] = 0;
res_diffuse[2] = 0;
res_ambient[0] = 0;
res_ambient[1] = 0;
res_ambient[2] = 0;
res_dir[0] = 0;
res_dir[1] = 1;
res_dir[2] = 1;
}
else
{
res_diffuse[0] = r[0];
res_diffuse[1] = r[1];
res_diffuse[2] = r[2];
res_ambient[0] = r[0];
res_ambient[1] = r[1];
res_ambient[2] = r[2];
res_dir[0] = r[3];
res_dir[1] = r[4];
res_dir[2] = -r[5];
VectorNormalize(res_dir);
if (!res_dir[0] && !res_dir[1] && !res_dir[2])
res_dir[1] = res_dir[2] = 1;
}
}

1607
engine/gl/gl_rmain.c Normal file

File diff suppressed because it is too large Load diff

940
engine/gl/gl_rmisc.c Normal file
View file

@ -0,0 +1,940 @@
/*
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.
*/
// r_misc.c
#include "quakedef.h"
#include "glquake.h"
#ifdef WATERLAYERS
cvar_t r_waterlayers = {"r_waterlayers","3"};
#endif
cvar_t gl_skyboxname = {"r_skybox", ""};
extern void R_InitBubble();
/*
==================
R_InitTextures
==================
*
void GLR_InitTextures (void)
{
int x,y, m;
qbyte *dest;
// create a simple checkerboard texture for the default
r_notexture_mip = Hunk_AllocName (sizeof(texture_t) + 16*16+8*8+4*4+2*2, "notexture");
r_notexture_mip->width = r_notexture_mip->height = 16;
r_notexture_mip->offsets[0] = sizeof(texture_t);
r_notexture_mip->offsets[1] = r_notexture_mip->offsets[0] + 16*16;
r_notexture_mip->offsets[2] = r_notexture_mip->offsets[1] + 8*8;
r_notexture_mip->offsets[3] = r_notexture_mip->offsets[2] + 4*4;
for (m=0 ; m<4 ; m++)
{
dest = (qbyte *)r_notexture_mip + r_notexture_mip->offsets[m];
for (y=0 ; y< (16>>m) ; y++)
for (x=0 ; x< (16>>m) ; x++)
{
if ( (y< (8>>m) ) ^ (x< (8>>m) ) )
*dest++ = 0;
else
*dest++ = 0xff;
}
}
}*/
//we could go for nice smooth round particles... but then we would loose a little bit of the chaotic nature of the particles.
static qbyte dottexture[8][8] =
{
{0,0,0,0,0,0,0,0},
{0,0,0,1,1,0,0,0},
{0,0,1,1,1,1,0,0},
{0,1,1,1,1,1,1,0},
{0,1,1,1,1,1,1,0},
{0,0,1,1,1,1,0,0},
{0,0,0,1,1,0,0,0},
{0,0,0,0,0,0,0,0},
};
static qbyte exptexture[16][16] =
{
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,1,0,0,0,1,0,0,1,0,0,0,0},
{0,0,0,1,1,1,1,1,3,1,1,2,1,0,0,0},
{0,0,0,1,1,1,1,4,4,4,5,4,2,1,1,0},
{0,0,1,1,6,5,5,8,6,8,3,6,3,2,1,0},
{0,0,1,5,6,7,5,6,8,8,8,3,3,1,0,0},
{0,0,0,1,6,8,9,9,9,9,4,6,3,1,0,0},
{0,0,2,1,7,7,9,9,9,9,5,3,1,0,0,0},
{0,0,2,4,6,8,9,9,9,9,8,6,1,0,0,0},
{0,0,2,2,3,5,6,8,9,8,8,4,4,1,0,0},
{0,0,1,2,4,1,8,7,8,8,6,5,4,1,0,0},
{0,1,1,1,7,8,1,6,7,5,4,7,1,0,0,0},
{0,1,2,1,1,5,1,3,4,3,1,1,0,0,0,0},
{0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
};
void R_InitParticleTexture (void)
{
int x,y;
qbyte data[16*16][4];
//
// particle texture
//
particletexture = texture_extension_number++;
GL_Bind(particletexture);
for (x=0 ; x<8 ; x++)
{
for (y=0 ; y<8 ; y++)
{
data[y*8+x][0] = 255;
data[y*8+x][1] = 255;
data[y*8+x][2] = 255;
data[y*8+x][3] = dottexture[x][y]*255;
}
}
glTexImage2D (GL_TEXTURE_2D, 0, gl_alpha_format, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
explosiontexture = texture_extension_number++;
GL_Bind(explosiontexture);
for (x=0 ; x<16 ; x++)
{
for (y=0 ; y<16 ; y++)
{
data[y*16+x][0] = 255;
data[y*16+x][1] = 255;
data[y*16+x][2] = 255;
data[y*16+x][3] = exptexture[x][y]*255/9.0;
}
}
glTexImage2D (GL_TEXTURE_2D, 0, gl_alpha_format, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
}
/*
===============
R_Envmap_f
Grab six views for environment mapping tests
===============
*/
void R_Envmap_f (void)
{
qbyte buffer[256*256*4];
glDrawBuffer (GL_FRONT);
glReadBuffer (GL_FRONT);
envmap = true;
r_refdef.vrect.x = 0;
r_refdef.vrect.y = 0;
r_refdef.vrect.width = 256;
r_refdef.vrect.height = 256;
r_refdef.viewangles[0] = 0;
r_refdef.viewangles[1] = 0;
r_refdef.viewangles[2] = 0;
GL_BeginRendering (&glx, &gly, &glwidth, &glheight);
R_RenderView ();
glReadPixels (0, 0, 256, 256, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
COM_WriteFile ("env0.rgb", buffer, sizeof(buffer));
r_refdef.viewangles[1] = 90;
GL_BeginRendering (&glx, &gly, &glwidth, &glheight);
R_RenderView ();
glReadPixels (0, 0, 256, 256, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
COM_WriteFile ("env1.rgb", buffer, sizeof(buffer));
r_refdef.viewangles[1] = 180;
GL_BeginRendering (&glx, &gly, &glwidth, &glheight);
R_RenderView ();
glReadPixels (0, 0, 256, 256, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
COM_WriteFile ("env2.rgb", buffer, sizeof(buffer));
r_refdef.viewangles[1] = 270;
GL_BeginRendering (&glx, &gly, &glwidth, &glheight);
R_RenderView ();
glReadPixels (0, 0, 256, 256, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
COM_WriteFile ("env3.rgb", buffer, sizeof(buffer));
r_refdef.viewangles[0] = -90;
r_refdef.viewangles[1] = 0;
GL_BeginRendering (&glx, &gly, &glwidth, &glheight);
R_RenderView ();
glReadPixels (0, 0, 256, 256, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
COM_WriteFile ("env4.rgb", buffer, sizeof(buffer));
r_refdef.viewangles[0] = 90;
r_refdef.viewangles[1] = 0;
GL_BeginRendering (&glx, &gly, &glwidth, &glheight);
R_RenderView ();
glReadPixels (0, 0, 256, 256, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
COM_WriteFile ("env5.rgb", buffer, sizeof(buffer));
envmap = false;
glDrawBuffer (GL_BACK);
glReadBuffer (GL_BACK);
GL_EndRendering ();
}
qboolean GenerateNormalisationCubeMap()
{
unsigned char data[32*32*3];
//some useful variables
int size=32;
float offset=0.5f;
float halfSize=16.0f;
vec3_t tempVector;
unsigned char * bytePtr;
int i, j;
//positive x
bytePtr=data;
for(j=0; j<size; j++)
{
for(i=0; i<size; i++)
{
tempVector[0] = halfSize;
tempVector[1] = -(j+offset-halfSize);
tempVector[2] = -(i+offset-halfSize);
VectorNormalize(tempVector);
bytePtr[0]=(unsigned char)((tempVector[0]/2 + 0.5)*255);
bytePtr[1]=(unsigned char)((tempVector[1]/2 + 0.5)*255);
bytePtr[2]=(unsigned char)((tempVector[2]/2 + 0.5)*255);
bytePtr+=3;
}
}
glTexImage2D( GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB,
0, GL_RGBA8, 32, 32, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
//negative x
bytePtr=data;
for(j=0; j<size; j++)
{
for(i=0; i<size; i++)
{
tempVector[0] = (-halfSize);
tempVector[1] = (-(j+offset-halfSize));
tempVector[2] = ((i+offset-halfSize));
VectorNormalize(tempVector);
bytePtr[0]=(unsigned char)((tempVector[0]/2 + 0.5)*255);
bytePtr[1]=(unsigned char)((tempVector[1]/2 + 0.5)*255);
bytePtr[2]=(unsigned char)((tempVector[2]/2 + 0.5)*255);
bytePtr+=3;
}
}
glTexImage2D( GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB,
0, GL_RGBA8, 32, 32, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
//positive y
bytePtr=data;
for(j=0; j<size; j++)
{
for(i=0; i<size; i++)
{
tempVector[0] = (i+offset-halfSize);
tempVector[1] = (halfSize);
tempVector[2] = ((j+offset-halfSize));
VectorNormalize(tempVector);
bytePtr[0]=(unsigned char)((tempVector[0]/2 + 0.5)*255);
bytePtr[1]=(unsigned char)((tempVector[1]/2 + 0.5)*255);
bytePtr[2]=(unsigned char)((tempVector[2]/2 + 0.5)*255);
bytePtr+=3;
}
}
glTexImage2D( GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB,
0, GL_RGBA8, 32, 32, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
//negative y
bytePtr=data;
for(j=0; j<size; j++)
{
for(i=0; i<size; i++)
{
tempVector[0] = (i+offset-halfSize);
tempVector[1] = (-halfSize);
tempVector[2] = (-(j+offset-halfSize));
VectorNormalize(tempVector);
bytePtr[0]=(unsigned char)((tempVector[0]/2 + 0.5)*255);
bytePtr[1]=(unsigned char)((tempVector[1]/2 + 0.5)*255);
bytePtr[2]=(unsigned char)((tempVector[2]/2 + 0.5)*255);
bytePtr+=3;
}
}
glTexImage2D( GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB,
0, GL_RGBA8, 32, 32, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
//positive z
bytePtr=data;
for(j=0; j<size; j++)
{
for(i=0; i<size; i++)
{
tempVector[0] = (i+offset-halfSize);
tempVector[1] = (-(j+offset-halfSize));
tempVector[2] = (halfSize);
VectorNormalize(tempVector);
bytePtr[0]=(unsigned char)((tempVector[0]/2 + 0.5)*255);
bytePtr[1]=(unsigned char)((tempVector[1]/2 + 0.5)*255);
bytePtr[2]=(unsigned char)((tempVector[2]/2 + 0.5)*255);
bytePtr+=3;
}
}
glTexImage2D( GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB,
0, GL_RGBA8, 32, 32, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
//negative z
bytePtr=data;
for(j=0; j<size; j++)
{
for(i=0; i<size; i++)
{
tempVector[0] = (-(i+offset-halfSize));
tempVector[1] = (-(j+offset-halfSize));
tempVector[2] = (-halfSize);
VectorNormalize(tempVector);
bytePtr[0]=(unsigned char)((tempVector[0]/2 + 0.5)*255);
bytePtr[1]=(unsigned char)((tempVector[1]/2 + 0.5)*255);
bytePtr[2]=(unsigned char)((tempVector[2]/2 + 0.5)*255);
bytePtr+=3;
}
}
glTexImage2D( GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB,
0, GL_RGBA8, 32, 32, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
return true;
}
int normalisationCubeMap;
/*
===============
R_Init
===============
*/
void GLR_ReInit (void)
{
extern int gl_bumpmappingpossible;
R_InitParticleTexture ();
#ifdef GLTEST
Test_Init ();
#endif
netgraphtexture = texture_extension_number;
texture_extension_number++;
playertextures = texture_extension_number;
texture_extension_number += MAX_CLIENTS;
if (gl_bumpmappingpossible)
{
//Create normalisation cube map
normalisationCubeMap = texture_extension_number++;
GL_BindType(GL_TEXTURE_CUBE_MAP_ARB, normalisationCubeMap);
GenerateNormalisationCubeMap();
glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
}
else
normalisationCubeMap = 0;
}
/*
typedef struct
{
long offset; // Position of the entry in WAD
long dsize; // Size of the entry in WAD file
long size; // Size of the entry in memory
char type; // type of entry
char cmprs; // Compression. 0 if none.
short dummy; // Not used
char name[16]; // we use only first 8
} wad2entry_t;
typedef struct
{
char magic[4]; //should be WAD2
long num; //number of entries
long offset; //location of directory
} wad2_t;
void R_MakeTexWad_f(void)
{
miptex_t dummymip = {"", 0, 0, {0, 0, 0, 0}};
wad2_t wad2 = {"WAD2",0,0};
wad2entry_t entry[2048];
int entries = 0, i;
FILE *f;
char base[128];
char *texname;
// qbyte b;
float scale;
int width, height;
qbyte *buf, *outmip;
qbyte *mip, *stack;
// WIN32_FIND_DATA fd;
// HANDLE h;
scale = atof(Cmd_Argv(2));
if (!scale)
scale = 2;
// h = FindFirstFile(va("%s/textures/*.tga", com_gamedir), &fd);
if (!shader)
return;
mip = BZ_Malloc(1024*1024);
// initbuf = BZ_Malloc(1024*1024*4);
stack = BZ_Malloc(1024*1024*4+1024);
f=fopen(va("%s/shadrtex.wad", com_gamedir), "wb");
fwrite(&wad2, 1, sizeof(wad2_t), f);
for (shad = shader; shad; shad=shad->next)
{
texname = shad->editorname;
if (!*texname)
continue;
COM_StripExtension(shad->name, base);
base[15]=0;
for (i =0; i < entries; i++)
if (!strcmp(entry[entries].name, base))
break;
if (i != entries)
{
Con_Printf("Skipped %s - duplicated shrunken name\n", texname);
continue;
}
entry[entries].offset = ftell(f);
entry[entries].dsize = entry[entries].size = 0;
entry[entries].type = TYP_MIPTEX;
entry[entries].cmprs = 0;
entry[entries].dummy = 0;
strcpy(entry[entries].name, base);
strcpy(dummymip.name, base);
{
qbyte *data;
int h;
float x, xi;
float y, yi;
char *path[] ={
"%s",
"override/%s.tga",
"override/%s.pcx",
"%s.tga",
"progs/%s"};
for (h = 0, buf=NULL; h < sizeof(path)/sizeof(char *); h++)
{
buf = COM_LoadStackFile(va(path[h], texname), stack, 1024*1024*4+1024);
if (buf)
break;
}
if (!buf)
{
Con_Printf("Failed to find texture \"%s\"\n", texname);
continue;
}
data = ReadTargaFile(buf, com_filesize, &width, &height, false);
if (!data)
{
BZ_Free(data);
Con_Printf("Skipped %s - file type not supported (bad bpp?)\n", texname);
continue;
}
dummymip.width = (int)(width/scale) & ~0xf;
dummymip.height = (int)(height/scale) & ~0xf;
if (dummymip.width<=0)
dummymip.width=16;
if (dummymip.height<=0)
dummymip.height=16;
dummymip.offsets[0] = sizeof(dummymip);
dummymip.offsets[1] = dummymip.offsets[0]+dummymip.width*dummymip.height;
dummymip.offsets[2] = dummymip.offsets[1]+dummymip.width/2*dummymip.height/2;
dummymip.offsets[3] = dummymip.offsets[2]+dummymip.width/4*dummymip.height/4;
entry[entries].dsize = entry[entries].size = dummymip.offsets[3]+dummymip.width/8*dummymip.height/8;
xi = (float)width/dummymip.width;
yi = (float)height/dummymip.height;
fwrite(&dummymip, 1, sizeof(dummymip), f);
outmip=mip;
for (outmip=mip, y = 0; y < height; y+=yi)
for (x = 0; x < width; x+=xi)
{
*outmip++ = GetPalette( data[(int)(x+y*width)*4+0],
data[(int)(x+y*width)*4+1],
data[(int)(x+y*width)*4+2]);
}
fwrite(mip, dummymip.width, dummymip.height, f);
for (outmip=mip, y = 0; y < height; y+=yi*2)
for (x = 0; x < width; x+=xi*2)
{
*outmip++ = GetPalette( data[(int)(x+y*width)*4+0],
data[(int)(x+y*width)*4+1],
data[(int)(x+y*width)*4+2]);
}
fwrite(mip, dummymip.width/2, dummymip.height/2, f);
for (outmip=mip, y = 0; y < height; y+=yi*4)
for (x = 0; x < width; x+=xi*4)
{
*outmip++ = GetPalette( data[(int)(x+y*width)*4+0],
data[(int)(x+y*width)*4+1],
data[(int)(x+y*width)*4+2]);
}
fwrite(mip, dummymip.width/4, dummymip.height/4, f);
for (outmip=mip, y = 0; y < height; y+=yi*8)
for (x = 0; x < width; x+=xi*8)
{
*outmip++ = GetPalette( data[(int)(x+y*width)*4+0],
data[(int)(x+y*width)*4+1],
data[(int)(x+y*width)*4+2]);
}
fwrite(mip, dummymip.width/8, dummymip.height/8, f);
BZ_Free(data);
}
entries++;
Con_Printf("Added %s\n", base);
GLSCR_UpdateScreen();
}
wad2.offset = ftell(f);
wad2.num = entries;
fwrite(entry, entries, sizeof(wad2entry_t), f);
fseek(f, 0, SEEK_SET);
fwrite(&wad2, 1, sizeof(wad2_t), f);
fclose(f);
BZ_Free(mip);
// BZ_Free(initbuf);
BZ_Free(stack);
Con_Printf("Written %i mips to textures.wad\n", entries);
}
*/
void GLR_TimeRefresh_f (void);
extern cvar_t gl_bump;
extern cvar_t r_stains, r_stainfadetime, r_stainfadeammount;
void GLR_DeInit (void)
{
Cmd_RemoveCommand ("timerefresh");
Cmd_RemoveCommand ("envmap");
Cmd_RemoveCommand ("pointfile");
Cmd_RemoveCommand ("makewad");
GLDraw_DeInit();
GLSurf_DeInit();
}
void GLR_Init (void)
{
Cmd_AddRemCommand ("timerefresh", GLR_TimeRefresh_f);
Cmd_AddRemCommand ("envmap", R_Envmap_f);
Cmd_AddRemCommand ("pointfile", R_ReadPointFile_f);
// Cmd_AddRemCommand ("makewad", R_MakeTexWad_f);
R_InitBubble();
GLR_ReInit();
}
/*
===============
R_TranslatePlayerSkin
Translates a skin texture by the per-player color lookup
===============
*/
void R_TranslatePlayerSkin (int playernum)
{
int top, bottom;
qbyte translate[256];
unsigned translate32[256];
int i, j;
qbyte *original;
unsigned pixels[512*256], *out;
unsigned scaled_width, scaled_height;
int inwidth, inheight;
int tinwidth, tinheight;
qbyte *inrow;
unsigned frac, fracstep;
player_info_t *player;
extern qbyte *player_8bit_texels/*[320*200]*/;
char s[512];
GL_DisableMultitexture();
player = &cl.players[playernum];
if (!player->name[0])
return;
strcpy(s, Info_ValueForKey(player->userinfo, "skin"));
COM_StripExtension(s, s);
if (player->skin && !stricmp(s, player->skin->name))
player->skin = NULL;
if (player->_topcolor != player->topcolor ||
player->_bottomcolor != player->bottomcolor || !player->skin) {
player->_topcolor = player->topcolor;
player->_bottomcolor = player->bottomcolor;
top = player->topcolor;
bottom = player->bottomcolor;
top = (top < 0) ? 0 : ((top > 13) ? 13 : top);
bottom = (bottom < 0) ? 0 : ((bottom > 13) ? 13 : bottom);
top *= 16;
bottom *= 16;
for (i=0 ; i<256 ; i++)
translate[i] = i;
for (i=0 ; i<16 ; i++)
{
if (top < 128) // the artists made some backwards ranges. sigh.
translate[TOP_RANGE+i] = top+i;
else
translate[TOP_RANGE+i] = top+15-i;
if (bottom < 128)
translate[BOTTOM_RANGE+i] = bottom+i;
else
translate[BOTTOM_RANGE+i] = bottom+15-i;
}
//
// locate the original skin pixels
//
// real model width
tinwidth = 296;
tinheight = 194;
if (!player->skin)
Skin_Find(player);
if ((original = Skin_Cache8(player->skin)) != NULL) {
//skin data width
inwidth = player->skin->width;
inheight = player->skin->height;
} else {
original = player_8bit_texels;
inwidth = 296;
inheight = 194;
}
//tinwidth = 251&~3;
//tinheight = 194&~3;
//tinwidth = 319&~3;
//tinheight = 199&~3;
if (!original) //can't.
return;
// because this happens during gameplay, do it fast
// instead of sending it through gl_upload 8
GL_Bind(playertextures + playernum);
#if 0
s = 320*200;
qbyte translated[320*200];
for (i=0 ; i<s ; i+=4)
{
translated[i] = translate[original[i]];
translated[i+1] = translate[original[i+1]];
translated[i+2] = translate[original[i+2]];
translated[i+3] = translate[original[i+3]];
}
// don't mipmap these, because it takes too long
GL_Upload8 (translated, paliashdr->skinwidth, paliashdr->skinheight,
false, false, true);
#endif
scaled_width = gl_max_size.value < 512 ? gl_max_size.value : 512;
scaled_height = gl_max_size.value < 256 ? gl_max_size.value : 256;
// allow users to crunch sizes down even more if they want
scaled_width >>= (int)gl_playermip.value;
scaled_height >>= (int)gl_playermip.value;
if (scaled_width < 8)
scaled_width = 8;
if (scaled_height < 8)
scaled_height = 8;
#ifdef GL_USE8BITTEX
#ifdef GL_EXT_paletted_texture
if (GLVID_Is8bit())
{// 8bit texture upload
qbyte *out2;
out2 = (qbyte *)pixels;
memset(pixels, 0, sizeof(pixels));
fracstep = tinwidth*0x10000/scaled_width;
for (i=0 ; i<scaled_height ; i++, out2 += scaled_width)
{
inrow = original + inwidth*(i*tinheight/scaled_height);
frac = fracstep >> 1;
for (j=0 ; j<scaled_width ; j+=4)
{
out2[j] = translate[inrow[frac>>16]];
frac += fracstep;
out2[j+1] = translate[inrow[frac>>16]];
frac += fracstep;
out2[j+2] = translate[inrow[frac>>16]];
frac += fracstep;
out2[j+3] = translate[inrow[frac>>16]];
frac += fracstep;
}
}
GL_Upload8_EXT ((qbyte *)pixels, scaled_width, scaled_height, false, false);
return;
}
#endif
#endif
#ifdef Q2BSP
if (cls.q2server)
{
extern unsigned char d_q28to24table[768];
for (i=0 ; i<256 ; i++)
{
translate32[i] = d_q28to24table[i*3] |
(d_q28to24table[i*3+1]<<8) |
(d_q28to24table[i*3+2]<<16) |
255<<24;
}
}
else
#endif
for (i=0 ; i<256 ; i++)
translate32[i] = d_8to24rgbtable[translate[i]];
out = pixels;
memset(pixels, 0, sizeof(pixels));
fracstep = tinwidth*0x10000/scaled_width;
for (i=0 ; i<scaled_height ; i++, out += scaled_width)
{
inrow = original + inwidth*(i*tinheight/scaled_height);
frac = fracstep >> 1;
for (j=0 ; j<scaled_width ; j+=4)
{
out[j] = translate32[inrow[frac>>16]];
frac += fracstep;
out[j+1] = translate32[inrow[frac>>16]];
frac += fracstep;
out[j+2] = translate32[inrow[frac>>16]];
frac += fracstep;
out[j+3] = translate32[inrow[frac>>16]];
frac += fracstep;
}
}
glTexImage2D (GL_TEXTURE_2D, 0, gl_solid_format,
scaled_width, scaled_height, 0, GL_RGBA,
GL_UNSIGNED_BYTE, pixels);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
}
}
/*
===============
R_NewMap
===============
*/
void GLR_NewMap (void)
{
extern cvar_t host_mapname;
int i;
/*
if (cl.worldmodel->fromgame == fg_quake3 && cls.netchan.remote_address.type != NA_LOOPBACK)
{
if (!cls.allow_cheats)
{
CL_Disconnect();
Host_EndGame("\n\nThe quake3 map implementation is still experimental and contains many bugs that could be considered cheats. Therefore, the engine is handicapped to quake3 maps only when hosting - it's single player only.\n\nYou can allow it on the server by activating cheats, at which point this check will be ignored\n");
return;
}
// Cbuf_AddText("disconnect\n", RESTRICT_LOCAL);
}
*/
for (i=0 ; i<256 ; i++)
d_lightstylevalue[i] = 264; // normal light value
memset (&r_worldentity, 0, sizeof(r_worldentity));
r_worldentity.model = cl.worldmodel;
Cvar_Set(&host_mapname, cl.worldmodel->name);
// clear out efrags in case the level hasn't been reloaded
// FIXME: is this one short?
for (i=0 ; i<cl.worldmodel->numleafs ; i++)
cl.worldmodel->leafs[i].efrags = NULL;
r_viewleaf = NULL;
r_viewcluster = -1;
r_oldviewcluster = 0;
r_viewcluster2 = -1;
R_ClearParticles ();
GLR_WipeStains();
GL_BuildLightmaps ();
// identify sky texture
if (cl.worldmodel->fromgame != fg_quake2 && cl.worldmodel->fromgame != fg_quake3)
{
skytexturenum = -1;
mirrortexturenum = -1;
}
for (i=0 ; i<cl.worldmodel->numtextures ; i++)
{
if (!cl.worldmodel->textures[i])
continue;
if (!Q_strncmp(cl.worldmodel->textures[i]->name,"sky",3) )
skytexturenum = i;
if (!Q_strncmp(cl.worldmodel->textures[i]->name,"window02_1",10) )
mirrortexturenum = i;
cl.worldmodel->textures[i]->texturechain = NULL;
}
//#ifdef QUAKE2
R_LoadSkys ();
//#endif
UI_Reset();
}
void GLR_PreNewMap(void)
{
}
/*
====================
R_TimeRefresh_f
For program optimization
====================
*/
void GLR_TimeRefresh_f (void)
{
int i;
float start, stop, time;
glDrawBuffer (GL_FRONT);
glFinish ();
start = Sys_DoubleTime ();
for (i=0 ; i<128 ; i++)
{
r_refdef.viewangles[1] = i/128.0*360.0;
R_RenderView ();
}
glFinish ();
stop = Sys_DoubleTime ();
time = stop-start;
Con_Printf ("%f seconds (%f fps)\n", time, 128/time);
glDrawBuffer (GL_BACK);
GL_EndRendering ();
}
#ifndef SWQUAKE
void D_FlushCaches (void)
{
}
#endif

3510
engine/gl/gl_rsurf.c Normal file

File diff suppressed because it is too large Load diff

239
engine/gl/gl_screen.c Normal file
View file

@ -0,0 +1,239 @@
/*
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.
*/
// screen.c -- master for refresh, status bar, console, chat, notify, etc
#include "quakedef.h"
#include "glquake.h"
#include <time.h>
void GLSCR_UpdateScreen (void);
extern qboolean scr_drawdialog;
extern cvar_t gl_triplebuffer;
extern cvar_t scr_fov;
extern qboolean scr_initialized;
extern float oldsbar;
extern qboolean scr_drawloading;
extern float oldfov;
extern int scr_chatmode;
extern cvar_t scr_chatmodecvar;
/*
==================
SCR_UpdateScreen
This is called every frame, and can also be called explicitly to flush
text to the screen.
WARNING: be very careful calling this from elsewhere, because the refresh
needs almost the entire 256k of stack space!
==================
*/
void GLSCR_UpdateScreen (void)
{
extern cvar_t gl_2dscale;
static float old2dscale=1;
int uimenu;
#ifdef TEXTEDITOR
extern qboolean editormodal, editoractive;
#endif
if (block_drawing)
return;
if (gl_2dscale.modified)
{
gl_2dscale.modified=false;
if (gl_2dscale.value < 0) //lower would be wrong
Cvar_Set(&gl_2dscale, "0");
if (gl_2dscale.value > 2) //anything higher is unreadable.
Cvar_Set(&gl_2dscale, "2");
old2dscale = gl_2dscale.value;
vid.width = vid.conwidth = (glwidth - 320) * gl_2dscale.value + 320;
vid.height = vid.conheight = (glheight - 240) * gl_2dscale.value + 240;
vid.recalc_refdef = true;
Con_CheckResize();
}
vid.numpages = 2 + gl_triplebuffer.value;
scr_copytop = 0;
scr_copyeverything = 0;
if (scr_disabled_for_loading)
{
/* if (Sys_DoubleTime() - scr_disabled_time > 60 || key_dest != key_game)
{
scr_disabled_for_loading = false;
Con_Printf ("load failed.\n");
}
else
*/ {
GL_BeginRendering (&glx, &gly, &glwidth, &glheight);
SCR_DrawLoading ();
GL_EndRendering ();
return;
}
}
if (!scr_initialized || !con_initialized)
return; // not initialized yet
uimenu = UI_MenuState();
if (oldsbar != cl_sbar.value) {
oldsbar = cl_sbar.value;
vid.recalc_refdef = true;
}
GL_BeginRendering (&glx, &gly, &glwidth, &glheight);
#ifdef TEXTEDITOR
if (editormodal)
{
Editor_Draw();
GLV_UpdatePalette ();
#if defined(_WIN32) && defined(RGLQUAKE)
Media_RecordFrame();
#endif
GLR_BrightenScreen();
GL_EndRendering ();
return;
}
#endif
if (Media_ShowFilm())
{
M_Draw(0);
GLV_UpdatePalette ();
#if defined(_WIN32) && defined(RGLQUAKE)
Media_RecordFrame();
#endif
GLR_BrightenScreen();
GL_EndRendering ();
return;
}
//
// determine size of refresh window
//
if (oldfov != scr_fov.value)
{
oldfov = scr_fov.value;
vid.recalc_refdef = true;
}
if (scr_chatmode != scr_chatmodecvar.value)
vid.recalc_refdef = true;
if (vid.recalc_refdef || scr_viewsize.modified)
SCR_CalcRefdef ();
//
// do 3D refresh drawing, and then update the screen
//
SCR_SetUpToDrawConsole ();
if (cl.worldmodel && uimenu != 1)
V_RenderView ();
GL_Set2D ();
//
// draw any areas not covered by the refresh
//
SCR_TileClear ();
if (r_netgraph.value)
GLR_NetGraph ();
if (scr_drawdialog)
{
Sbar_Draw ();
Draw_FadeScreen ();
SCR_DrawNotifyString ();
scr_copyeverything = true;
}
else if (scr_drawloading)
{
SCR_DrawLoading ();
Sbar_Draw ();
}
else if (cl.intermission == 1 && key_dest == key_game)
{
Sbar_IntermissionOverlay ();
M_Draw (uimenu);
}
else if (cl.intermission == 2 && key_dest == key_game)
{
Sbar_FinaleOverlay ();
SCR_CheckDrawCenterString ();
}
else
{
Draw_Crosshair();
SCR_DrawRam ();
SCR_DrawNet ();
SCR_DrawFPS ();
SCR_DrawTurtle ();
SCR_DrawPause ();
SCR_CheckDrawCenterString ();
Sbar_Draw ();
glTexEnvi ( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
#ifdef TEXTEDITOR
if (editoractive)
Editor_Draw();
#endif
M_Draw (uimenu);
SCR_DrawConsole (false);
}
GLR_BrightenScreen();
GLV_UpdatePalette ();
#if defined(_WIN32) && defined(RGLQUAKE)
Media_RecordFrame();
#endif
GL_EndRendering ();
}
char *GLVID_GetRGBInfo(int prepadbytes, int *truewidth, int *trueheight)
{ //returns a BZ_Malloced array
qbyte *ret = BZ_Malloc(prepadbytes + glwidth*glheight*3);
glReadPixels (glx, gly, glwidth, glheight, GL_RGB, GL_UNSIGNED_BYTE, ret + prepadbytes);
*truewidth = glwidth;
*trueheight = glheight;
return ret;
}

369
engine/gl/gl_vidcommon.c Normal file
View file

@ -0,0 +1,369 @@
#include "quakedef.h"
#include "glquake.h"
//standard 1.1 opengl calls
void (APIENTRY *qglAlphaFunc) (GLenum func, GLclampf ref);
void (APIENTRY *qglBegin) (GLenum mode);
void (APIENTRY *qglBlendFunc) (GLenum sfactor, GLenum dfactor);
void (APIENTRY *qglClear) (GLbitfield mask);
void (APIENTRY *qglClearColor) (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
void (APIENTRY *qglClearDepth) (GLclampd depth);
void (APIENTRY *qglClearStencil) (GLint s);
void (APIENTRY *qglColor3f) (GLfloat red, GLfloat green, GLfloat blue);
void (APIENTRY *qglColor3ub) (GLubyte red, GLubyte green, GLubyte blue);
void (APIENTRY *qglColor4f) (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
void (APIENTRY *qglColor4fv) (const GLfloat *v);
void (APIENTRY *qglColor4ub) (GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha);
void (APIENTRY *qglColor4ubv) (const GLubyte *v);
void (APIENTRY *qglColorMask) (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
void (APIENTRY *qglCullFace) (GLenum mode);
void (APIENTRY *qglDepthFunc) (GLenum func);
void (APIENTRY *qglDepthMask) (GLboolean flag);
void (APIENTRY *qglDepthRange) (GLclampd zNear, GLclampd zFar);
void (APIENTRY *qglDisable) (GLenum cap);
void (APIENTRY *qglDrawBuffer) (GLenum mode);
void (APIENTRY *qglDrawPixels) (GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels);
void (APIENTRY *qglEnable) (GLenum cap);
void (APIENTRY *qglEnd) (void);
void (APIENTRY *qglFinish) (void);
void (APIENTRY *qglFlush) (void);
void (APIENTRY *qglFrustum) (GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar);
void (APIENTRY *qglGetFloatv) (GLenum pname, GLfloat *params);
void (APIENTRY *qglGetIntegerv) (GLenum pname, GLint *params);
const GLubyte * (APIENTRY *qglGetString) (GLenum name);
void (APIENTRY *qglHint) (GLenum target, GLenum mode);
void (APIENTRY *qglLoadIdentity) (void);
void (APIENTRY *qglLoadMatrixf) (const GLfloat *m);
void (APIENTRY *qglNormal3f) (GLfloat nx, GLfloat ny, GLfloat nz);
void (APIENTRY *qglNormal3fv) (const GLfloat *v);
void (APIENTRY *qglMatrixMode) (GLenum mode);
void (APIENTRY *qglMultMatrixf) (const GLfloat *m);
void (APIENTRY *qglOrtho) (GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar);
void (APIENTRY *qglPolygonMode) (GLenum face, GLenum mode);
void (APIENTRY *qglPopMatrix) (void);
void (APIENTRY *qglPushMatrix) (void);
void (APIENTRY *qglReadBuffer) (GLenum mode);
void (APIENTRY *qglReadPixels) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels);
void (APIENTRY *qglRotatef) (GLfloat angle, GLfloat x, GLfloat y, GLfloat z);
void (APIENTRY *qglScalef) (GLfloat x, GLfloat y, GLfloat z);
void (APIENTRY *qglShadeModel) (GLenum mode);
void (APIENTRY *qglTexCoord1f) (GLfloat s);
void (APIENTRY *qglTexCoord2f) (GLfloat s, GLfloat t);
void (APIENTRY *qglTexCoord2fv) (const GLfloat *v);
void (APIENTRY *qglTexEnvf) (GLenum target, GLenum pname, GLfloat param);
void (APIENTRY *qglTexEnvi) (GLenum target, GLenum pname, GLint param);
void (APIENTRY *qglTexGeni) (GLenum coord, GLenum pname, GLint param);
void (APIENTRY *qglTexImage2D) (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
void (APIENTRY *qglTexParameteri) (GLenum target, GLenum pname, GLint param);
void (APIENTRY *qglTexParameterf) (GLenum target, GLenum pname, GLfloat param);
void (APIENTRY *qglTexSubImage2D) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels);
void (APIENTRY *qglTranslatef) (GLfloat x, GLfloat y, GLfloat z);
void (APIENTRY *qglVertex2f) (GLfloat x, GLfloat y);
void (APIENTRY *qglVertex3f) (GLfloat x, GLfloat y, GLfloat z);
void (APIENTRY *qglVertex3fv) (const GLfloat *v);
void (APIENTRY *qglViewport) (GLint x, GLint y, GLsizei width, GLsizei height);
void (APIENTRY *qglGetTexLevelParameteriv) (GLenum target, GLint level, GLenum pname, GLint *params);
void (APIENTRY *qglDrawElements) (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices);
void (APIENTRY *qglVertexPointer) (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
void (APIENTRY *qglNormalPointer) (GLenum type, GLsizei stride, const GLvoid *pointer);
void (APIENTRY *qglTexCoordPointer) (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
void (APIENTRY *qglColorPointer) (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
void (APIENTRY *qglDisableClientState) (GLenum array);
void (APIENTRY *qglEnableClientState) (GLenum array);
void (APIENTRY *qglStencilOp) (GLenum fail, GLenum zfail, GLenum zpass);
void (APIENTRY *qglStencilFunc) (GLenum func, GLint ref, GLuint mask);
void (APIENTRY *qglPushAttrib) (GLbitfield mask);
void (APIENTRY *qglPopAttrib) (void);
//extensions
//arb multitexture
qlpSelTexFUNC qglActiveTextureARB;
qlpSelTexFUNC qglClientActiveTextureARB;
qlpMTex3FUNC qglMultiTexCoord3fARB;
qlpMTex2FUNC qglMultiTexCoord2fARB;
//generic multitexture
lpMTexFUNC qglMTexCoord2fSGIS;
lpSelTexFUNC qglSelectTextureSGIS;
int mtexid0;
int mtexid1;
//ati_truform
PFNGLPNTRIANGLESIATIPROC qglPNTrianglesiATI;
PFNGLPNTRIANGLESFATIPROC qglPNTrianglesfATI;
//stencil shadowing
void (APIENTRY *qglStencilOpSeparateATI) (GLenum face, GLenum fail, GLenum zfail, GLenum zpass);
PFNGLACTIVESTENCILFACEEXTPROC qglActiveStencilFaceEXT;
//quick hack that made quake work on both 1 and 1.1 gl implementations.
BINDTEXFUNCPTR bindTexFunc;
qboolean gl_ext_stencil_wrap;
int gl_mtexarbable=0; //max texture units
qboolean gl_mtexable = false;
qboolean gl_compressable=false;
int gl_bumpmappingpossible;
//int texture_mode = GL_NEAREST;
//int texture_mode = GL_NEAREST_MIPMAP_NEAREST;
//int texture_mode = GL_NEAREST_MIPMAP_LINEAR;
int texture_mode = GL_LINEAR;
//int texture_mode = GL_LINEAR_MIPMAP_NEAREST;
//int texture_mode = GL_LINEAR_MIPMAP_LINEAR;
int texture_extension_number = 1;
#define fieldvector(name) QC_RegisterFieldVar(svprogfuncs, ev_vector, #name, (int)&((edict_t*)0)->v.name - (int)&((edict_t*)0)->v, -1)
#define getglcore getglfunction
#define getglext(name) getglfunction(name)
void GL_CheckExtensions (void *(*getglfunction) (char *name))
{
extern cvar_t gl_bump;
qboolean support_GL_ARB_texture_env_combine, support_GL_ARB_texture_env_dot3, support_GL_ARB_texture_cube_map;
//multitexture
gl_mtexable = false;
gl_mtexarbable = 0;
qglActiveTextureARB = NULL;
qglMultiTexCoord2fARB = NULL;
qglMultiTexCoord3fARB = NULL;
qglMTexCoord2fSGIS = NULL;
qglSelectTextureSGIS = NULL;
mtexid0 = 0;
mtexid1 = 0;
//none of them bumpmapping possabilities.
gl_bumpmappingpossible = false;
//no GL_EXT_stencil_wrap
gl_ext_stencil_wrap = false;
//no GL_ATI_separate_stencil
qglStencilOpSeparateATI = NULL;
//no GL_EXT_stencil_two_side
qglActiveStencilFaceEXT = NULL;
//no GL_ARB_texture_compression
gl_compressable = false;
//no truform. sorry.
qglPNTrianglesfATI = NULL;
qglPNTrianglesiATI = NULL;
if (strstr(gl_extensions, "GL_ARB_multitexture") && !COM_CheckParm("-noamtex"))
{ //ARB multitexture is the popular choice.
Con_SafePrintf("ARB Multitexture extensions found. Use -noamtex to disable.\n");
qglActiveTextureARB = (void *) getglext("glActiveTextureARB");
qglClientActiveTextureARB = (void *) getglext("glClientActiveTextureARB");
qglMultiTexCoord2fARB = (void *) getglext("glMultiTexCoord2fARB");
qglMultiTexCoord3fARB = (void *) getglext("glMultiTexCoord3fARB");
glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &gl_mtexarbable);
gl_mtexable = true;
qglMTexCoord2fSGIS = qglMultiTexCoord2fARB;
qglSelectTextureSGIS = qglActiveTextureARB;
mtexid0 = GL_TEXTURE0_ARB;
mtexid1 = GL_TEXTURE1_ARB;
if (!qglActiveTextureARB || !qglClientActiveTextureARB || !qglMultiTexCoord2fARB || !qglMultiTexCoord3fARB)
{
qglActiveTextureARB = NULL;
qglMultiTexCoord2fARB = NULL;
qglMultiTexCoord3fARB = NULL;
qglMTexCoord2fSGIS = NULL;
qglSelectTextureSGIS = NULL;
gl_mtexable=false;
gl_mtexarbable = false;
}
}
else if (strstr(gl_extensions, "GL_SGIS_multitexture") && !COM_CheckParm("-nomtex"))
{ //SGIS multitexture, limited in many ways but basic functionality is identical to ARB
Con_SafePrintf("Multitexture extensions found.\n");
qglMTexCoord2fSGIS = (void *) getglext("glMTexCoord2fSGIS");
qglSelectTextureSGIS = (void *) getglext("glSelectTextureSGIS");
gl_mtexable = true;
mtexid0 = GL_TEXTURE0_SGIS;
mtexid1 = GL_TEXTURE1_SGIS;
}
if (strstr(gl_extensions, "GL_EXT_stencil_wrap"))
gl_ext_stencil_wrap = true;
if (strstr(gl_extensions, "GL_ATI_separate_stencil"))
qglStencilOpSeparateATI = (void *) getglext("glStencilOpSeparateATI");
if (strstr(gl_extensions, "GL_EXT_stencil_two_side"))
qglActiveStencilFaceEXT = (void *) getglext("glActiveStencilFaceEXT");
if (strstr(gl_extensions, "GL_ARB_texture_compression"))
{
qglCompressedTexImage2DARB = (void *)getglext("glCompressedTexImage2DARB");
qglGetCompressedTexImageARB = (void *)getglext("glGetCompressedTexImageARB");
if (!qglCompressedTexImage2DARB || !qglGetCompressedTexImageARB)
{
qglCompressedTexImage2DARB = NULL;
qglGetCompressedTexImageARB = NULL;
}
else
gl_compressable = true;
}
if (strstr(gl_extensions, "GL_ATI_pn_triangles"))
{
qglPNTrianglesfATI = (void *)getglext("glPNTrianglesfATI");
qglPNTrianglesiATI = (void *)getglext("glPNTrianglesiATI");
}
if (strstr(gl_extensions, "GL_EXT_texture_object"))
{
bindTexFunc = (void *)getglext("glBindTextureEXT");
if (!bindTexFunc) //grrr
bindTexFunc = (void *)getglext("glBindTexture");
}
support_GL_ARB_texture_env_combine = !!strstr(gl_extensions, "GL_ARB_texture_env_combine");
support_GL_ARB_texture_env_dot3 = !!strstr(gl_extensions, "GL_ARB_texture_env_dot3");
support_GL_ARB_texture_cube_map = !!strstr(gl_extensions, "GL_ARB_texture_cube_map");
if (gl_mtexarbable && support_GL_ARB_texture_cube_map && support_GL_ARB_texture_env_combine && support_GL_ARB_texture_env_dot3 && !COM_CheckParm("-nobump") && gl_bump.value)
gl_bumpmappingpossible = true;
}
//the vid routines have initialised a window, and now they are giving us a reference to some of of GetProcAddress to get pointers to the funcs.
void GL_Init(void *(*getglfunction) (char *name))
{
qglAlphaFunc = (void *)getglcore("glAlphaFunc");
qglBegin = (void *)getglcore("glBegin");
qglBlendFunc = (void *)getglcore("glBlendFunc");
bindTexFunc = (void *)getglcore("glBindTexture"); //for compleateness
qglClear = (void *)getglcore("glClear");
qglClearColor = (void *)getglcore("glClearColor");
qglClearDepth = (void *)getglcore("glClearDepth");
qglClearStencil = (void *)getglcore("glClearStencil");
qglColor3f = (void *)getglcore("glColor3f");
qglColor3ub = (void *)getglcore("glColor3ub");
qglColor4f = (void *)getglcore("glColor4f");
qglColor4fv = (void *)getglcore("glColor4fv");
qglColor4ub = (void *)getglcore("glColor4ub");
qglColor4ubv = (void *)getglcore("glColor4ubv");
qglColorMask = (void *)getglcore("glColorMask");
qglCullFace = (void *)getglcore("glCullFace");
qglDepthFunc = (void *)getglcore("glDepthFunc");
qglDepthMask = (void *)getglcore("glDepthMask");
qglDepthRange = (void *)getglcore("glDepthRange");
qglDisable = (void *)getglcore("glDisable");
qglDrawBuffer = (void *)getglcore("glDrawBuffer");
qglDrawPixels = (void *)getglcore("glDrawPixels");
qglEnable = (void *)getglcore("glEnable");
qglEnd = (void *)getglcore("glEnd");
qglFinish = (void *)getglcore("glFinish");
qglFlush = (void *)getglcore("glFlush");
qglFrustum = (void *)getglcore("glFrustum");
qglGetFloatv = (void *)getglcore("glGetFloatv");
qglGetIntegerv = (void *)getglcore("glGetIntegerv");
qglGetString = (void *)getglcore("glGetString");
qglGetTexLevelParameteriv = (void *)getglcore("glGetTexLevelParameteriv");
qglHint = (void *)getglcore("glHint");
qglLoadIdentity = (void *)getglcore("glLoadIdentity");
qglLoadMatrixf = (void *)getglcore("glLoadMatrixf");
qglNormal3f = (void *)getglcore("glNormal3f");
qglNormal3fv = (void *)getglcore("glNormal3fv");
qglMatrixMode = (void *)getglcore("glMatrixMode");
qglMultMatrixf = (void *)getglcore("glMultMatrixf");
qglOrtho = (void *)getglcore("glOrtho");
qglPolygonMode = (void *)getglcore("glPolygonMode");
qglPopMatrix = (void *)getglcore("glPopMatrix");
qglPushMatrix = (void *)getglcore("glPushMatrix");
qglReadBuffer = (void *)getglcore("glReadBuffer");
qglReadPixels = (void *)getglcore("glReadPixels");
qglRotatef = (void *)getglcore("glRotatef");
qglScalef = (void *)getglcore("glScalef");
qglShadeModel = (void *)getglcore("glShadeModel");
qglTexCoord1f = (void *)getglcore("glTexCoord1f");
qglTexCoord2f = (void *)getglcore("glTexCoord2f");
qglTexCoord2fv = (void *)getglcore("glTexCoord2fv");
qglTexEnvf = (void *)getglcore("glTexEnvf");
qglTexEnvi = (void *)getglcore("glTexEnvi");
qglTexGeni = (void *)getglcore("glTexGeni");
qglTexImage2D = (void *)getglcore("glTexImage2D");
qglTexParameteri = (void *)getglcore("glTexParameteri");
qglTexParameterf = (void *)getglcore("glTexParameterf");
qglTexSubImage2D = (void *)getglcore("glTexSubImage2D");
qglTranslatef = (void *)getglcore("glTranslatef");
qglVertex2f = (void *)getglcore("glVertex2f");
qglVertex3f = (void *)getglcore("glVertex3f");
qglVertex3fv = (void *)getglcore("glVertex3fv");
qglViewport = (void *)getglcore("glViewport");
//fixme: make non-core?
qglDrawElements = (void *)getglcore("glDrawElements");
qglVertexPointer = (void *)getglcore("glVertexPointer");
qglNormalPointer = (void *)getglcore("glNormalPointer");
qglTexCoordPointer = (void *)getglcore("glTexCoordPointer");
qglColorPointer = (void *)getglcore("glColorPointer");
qglEnableClientState = (void *)getglcore("glEnableClientState");
qglDisableClientState = (void *)getglcore("glDisableClientState");
//fixme: definatly make non-core
qglStencilOp = (void *)getglcore("glStencilOp");
qglStencilFunc = (void *)getglcore("glStencilFunc");
qglPushAttrib = (void *)getglcore("glPushAttrib");
qglPopAttrib = (void *)getglcore("glPopAttrib");
gl_vendor = glGetString (GL_VENDOR);
Con_SafePrintf ("GL_VENDOR: %s\n", gl_vendor);
gl_renderer = glGetString (GL_RENDERER);
Con_SafePrintf ("GL_RENDERER: %s\n", gl_renderer);
gl_version = glGetString (GL_VERSION);
Con_SafePrintf ("GL_VERSION: %s\n", gl_version);
gl_extensions = glGetString (GL_EXTENSIONS);
Con_DPrintf ("GL_EXTENSIONS: %s\n", gl_extensions);
GL_CheckExtensions (getglfunction);
glClearColor (0,0,0,0); //clear to black so that it looks a little nicer on start.
glClear(GL_COLOR_BUFFER_BIT);
glClearColor (1,0,0,0);
glCullFace(GL_FRONT);
glEnable(GL_TEXTURE_2D);
glEnable(GL_ALPHA_TEST);
glAlphaFunc(GL_GREATER, 0.666);
glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
glShadeModel (GL_FLAT);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
// glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
}
unsigned int d_8to24rgbtable[256];

899
engine/gl/gl_vidlinuxglx.c Normal file
View file

@ -0,0 +1,899 @@
/*
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.
*/
#include <termios.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#ifndef __CYGWIN__
#include <sys/vt.h>
#endif
#include <stdarg.h>
#include <stdio.h>
#include <signal.h>
#include <dlfcn.h>
#include "quakedef.h"
#include "glquake.h"
#include <GL/glx.h>
#include <X11/keysym.h>
#include <X11/cursorfont.h>
#ifdef USE_DGA
#include <X11/extensions/xf86dga.h>
#endif
#define WITH_VMODE //undefine this if the following include fails.
#ifdef WITH_VMODE
#include <X11/extensions/xf86vmode.h>
#endif
#define WARP_WIDTH 320
#define WARP_HEIGHT 200
#ifdef SWQUAKE
Display *vid_dpy = NULL;
#else
static Display *vid_dpy = NULL;
#endif
static Window vid_window;
static GLXContext ctx = NULL;
int scrnum;
static float old_windowed_mouse = 0;
#define KEY_MASK (KeyPressMask | KeyReleaseMask)
#define MOUSE_MASK (ButtonPressMask | ButtonReleaseMask | \
PointerMotionMask)
#define X_MASK (KEY_MASK | MOUSE_MASK | FocusChangeMask | VisibilityChangeMask)
#ifdef WITH_VMODE
static qboolean vidmode_ext = false;
static XF86VidModeModeInfo **vidmodes;
static int num_vidmodes;
static qboolean vidmode_active = false;
#endif
extern cvar_t _windowed_mouse;
#ifndef SWQUAKE
cvar_t m_filter = {"m_filter", "0"};
#ifdef IN_XFLIP
cvar_t in_xflip = {"in_xflip", "0"};
#endif
static float mouse_x, mouse_y;
static float old_mouse_x, old_mouse_y;
#else
extern float mouse_x, mouse_y;
extern float old_mouse_x, old_mouse_y;
#endif
static int scr_width, scr_height;
/*-----------------------------------------------------------------------*/
float gldepthmin, gldepthmax;
const char *gl_vendor;
const char *gl_renderer;
const char *gl_version;
const char *gl_extensions;
qboolean is8bit = false;
qboolean isPermedia = false;
float vid_gamma = 1.0;
qboolean mouseactive = false;
qboolean has_focus = false;
int gl_canstencil;
/*-----------------------------------------------------------------------*/
static void *gllibrary;
XVisualInfo* (*qglXChooseVisual) (Display *dpy, int screen, int *attribList);
void (*qglXSwapBuffers) (Display *dpy, GLXDrawable drawable);
Bool (*qglXMakeCurrent) (Display *dpy, GLXDrawable drawable, GLXContext ctx);
GLXContext (*qglXCreateContext) (Display *dpy, XVisualInfo *vis, GLXContext shareList, Bool direct);
void (*qglXDestroyContext) (Display *dpy, GLXContext ctx);
void *(*qglXGetProcAddress) (char *name);
void GLX_CloseLibrary(void)
{
dlclose(gllibrary);
gllibrary = NULL;
}
qboolean GLX_InitLibrary(char *driver)
{
if (driver && *driver)
gllibrary = dlopen(driver, RTLD_LOCAL | RTLD_LAZY);
else
gllibrary = NULL;
if (!gllibrary)
gllibrary = dlopen("libGL.so", RTLD_LOCAL | RTLD_LAZY);
if (!gllibrary)
return false;
qglXChooseVisual = dlsym(gllibrary, "glXChooseVisual");
qglXSwapBuffers = dlsym(gllibrary, "glXSwapBuffers");
qglXMakeCurrent = dlsym(gllibrary, "glXMakeCurrent");
qglXCreateContext = dlsym(gllibrary, "glXCreateContext");
qglXDestroyContext = dlsym(gllibrary, "glXDestroyContext");
qglXDestroyContext = dlsym(gllibrary, "glXDestroyContext");
qglXGetProcAddress = dlsym(gllibrary, "glXGetProcAddress");
if (!qglXGetProcAddress)
qglXGetProcAddress = dlsym(gllibrary, "glXGetProcAddressARB");
if (!qglXSwapBuffers && !qglXDestroyContext && !qglXCreateContext && !qglXMakeCurrent && !qglXChooseVisual)
return false;
return true;
}
void *GLX_GetSymbol(char *name)
{
void *symb;
if (qglXGetProcAddress)
symb = qglXGetProcAddress(name);
else
symb = NULL;
if (!symb)
symb = dlsym(gllibrary, name);
return symb;
}
void GLD_BeginDirectRect (int x, int y, qbyte *pbitmap, int width, int height)
{
}
void GLD_EndDirectRect (int x, int y, int width, int height)
{
}
static int XLateKey(XKeyEvent *ev)
{
int key;
char buf[64];
KeySym keysym;
key = 0;
XLookupString(ev, buf, sizeof buf, &keysym, 0);
switch(keysym)
{
case XK_KP_Page_Up:
case XK_Page_Up: key = K_PGUP; break;
case XK_KP_Page_Down:
case XK_Page_Down: key = K_PGDN; break;
case XK_KP_Home:
case XK_Home: key = K_HOME; break;
case XK_KP_End:
case XK_End: key = K_END; break;
case XK_KP_Left:
case XK_Left: key = K_LEFTARROW; break;
case XK_KP_Right:
case XK_Right: key = K_RIGHTARROW; break;
case XK_KP_Down:
case XK_Down: key = K_DOWNARROW; break;
case XK_KP_Up:
case XK_Up: key = K_UPARROW; break;
case XK_Escape: key = K_ESCAPE; break;
case XK_KP_Enter:
case XK_Return: key = K_ENTER; break;
case XK_Tab: key = K_TAB; break;
case XK_F1: key = K_F1; break;
case XK_F2: key = K_F2; break;
case XK_F3: key = K_F3; break;
case XK_F4: key = K_F4; break;
case XK_F5: key = K_F5; break;
case XK_F6: key = K_F6; break;
case XK_F7: key = K_F7; break;
case XK_F8: key = K_F8; break;
case XK_F9: key = K_F9; break;
case XK_F10: key = K_F10; break;
case XK_F11: key = K_F11; break;
case XK_F12: key = K_F12; break;
case XK_BackSpace: key = K_BACKSPACE; break;
case XK_KP_Delete:
case XK_Delete: key = K_DEL; break;
case XK_Pause: key = K_PAUSE; break;
case XK_Shift_L:
case XK_Shift_R: key = K_SHIFT; break;
case XK_Execute:
case XK_Control_L:
case XK_Control_R: key = K_CTRL; break;
case XK_Alt_L:
case XK_Meta_L:
case XK_Alt_R:
case XK_Meta_R: key = K_ALT; break;
case XK_KP_Begin: key = '5'; break;
case XK_KP_Insert:
case XK_Insert:key = K_INS; break;
case XK_KP_Multiply: key = '*'; break;
case XK_KP_Add: key = '+'; break;
case XK_KP_Subtract: key = '-'; break;
case XK_KP_Divide: key = '/'; break;
#if 0
case 0x021: key = '1';break;/* [!] */
case 0x040: key = '2';break;/* [@] */
case 0x023: key = '3';break;/* [#] */
case 0x024: key = '4';break;/* [$] */
case 0x025: key = '5';break;/* [%] */
case 0x05e: key = '6';break;/* [^] */
case 0x026: key = '7';break;/* [&] */
case 0x02a: key = '8';break;/* [*] */
case 0x028: key = '9';;break;/* [(] */
case 0x029: key = '0';break;/* [)] */
case 0x05f: key = '-';break;/* [_] */
case 0x02b: key = '=';break;/* [+] */
case 0x07c: key = '\'';break;/* [|] */
case 0x07d: key = '[';break;/* [}] */
case 0x07b: key = ']';break;/* [{] */
case 0x022: key = '\'';break;/* ["] */
case 0x03a: key = ';';break;/* [:] */
case 0x03f: key = '/';break;/* [?] */
case 0x03e: key = '.';break;/* [>] */
case 0x03c: key = ',';break;/* [<] */
#endif
default:
key = *(unsigned char*)buf;
if (key >= 'A' && key <= 'Z')
key = key - 'A' + 'a';
break;
}
return key;
}
static void install_grabs(void)
{
XGrabPointer(vid_dpy, vid_window,
True,
0,
GrabModeAsync, GrabModeAsync,
vid_window,
None,
CurrentTime);
#ifdef USE_DGA
XF86DGADirectVideo(vid_dpy, DefaultScreen(vid_dpy), XF86DGADirectMouse);
dgamouse = 1;
#else
XWarpPointer(vid_dpy, None, vid_window,
0, 0, 0, 0,
vid.width / 2, vid.height / 2);
#endif
// XSync(vid_dpy, True);
}
static void uninstall_grabs(void)
{
#ifdef USE_DGA
XF86DGADirectVideo(vid_dpy, DefaultScreen(vid_dpy), 0);
dgamouse = 0;
#endif
XUngrabPointer(vid_dpy, CurrentTime);
// XSync(vid_dpy, True);
}
static void GetEvent(void)
{
XEvent event;
int b;
qboolean wantwindowed;
if (!vid_dpy)
return;
XNextEvent(vid_dpy, &event);
switch (event.type) {
case KeyPress:
case KeyRelease:
Key_Event(XLateKey(&event.xkey), event.type == KeyPress);
break;
case MotionNotify:
#ifdef USE_DGA
if (dgamouse && old_windowed_mouse)
{
mouse_x = event.xmotion.x_root;
mouse_y = event.xmotion.y_root;
}
else
#endif
{
if (old_windowed_mouse)
{
mouse_x = (float) ((int)event.xmotion.x - (int)(vid.width/2));
mouse_y = (float) ((int)event.xmotion.y - (int)(vid.height/2));
/* move the mouse to the window center again */
XSelectInput(vid_dpy, vid_window, X_MASK & ~PointerMotionMask);
XWarpPointer(vid_dpy, None, vid_window, 0, 0, 0, 0,
(vid.width/2), (vid.height/2));
XSelectInput(vid_dpy, vid_window, X_MASK);
}
}
break;
case ButtonPress:
b=-1;
if (event.xbutton.button == 1)
b = 0;
else if (event.xbutton.button == 2)
b = 2;
else if (event.xbutton.button == 3)
b = 1;
if (b>=0)
Key_Event(K_MOUSE1 + b, true);
break;
case ButtonRelease:
b=-1;
if (event.xbutton.button == 1)
b = 0;
else if (event.xbutton.button == 2)
b = 2;
else if (event.xbutton.button == 3)
b = 1;
if (b>=0)
Key_Event(K_MOUSE1 + b, false);
break;
case FocusIn:
has_focus = true;
break;
case FocusOut:
has_focus = false;
break;
}
wantwindowed = !!_windowed_mouse.value;
if (!has_focus)
wantwindowed = false;
if (key_dest == key_console)
wantwindowed = false;
if (old_windowed_mouse != wantwindowed)
{
old_windowed_mouse = wantwindowed;
if (!wantwindowed)
{
/* ungrab the pointer */
uninstall_grabs();
}
else
{
/* grab the pointer */
install_grabs();
}
}
}
void GLVID_Shutdown(void)
{
printf("GLVID_Shutdown");
if (!ctx)
return;
XUngrabKeyboard(vid_dpy, CurrentTime);
if (old_windowed_mouse)
uninstall_grabs();
qglXDestroyContext(vid_dpy, ctx);
if (vid_window)
XDestroyWindow(vid_dpy, vid_window);
#ifdef WITH_VMODE
if (vid_dpy) {
if (vidmode_active)
XF86VidModeSwitchToMode(vid_dpy, scrnum, vidmodes[0]);
vidmode_active = false;
}
#endif
// XCloseDisplay(vid_dpy);
// vid_dpy = NULL;
vid_window = (Window)NULL;
}
void GLVID_DeInit(void) //FIXME:....
{
GLVID_Shutdown();
}
void signal_handler(int sig)
{
printf("Received signal %d, exiting...\n", sig);
Sys_Quit();
exit(0);
}
void InitSig(void)
{
signal(SIGHUP, signal_handler);
signal(SIGINT, signal_handler);
signal(SIGQUIT, signal_handler);
signal(SIGILL, signal_handler);
signal(SIGTRAP, signal_handler);
#ifndef __CYGWIN__
signal(SIGIOT, signal_handler);
#endif
signal(SIGBUS, signal_handler);
signal(SIGFPE, signal_handler);
signal(SIGSEGV, signal_handler);
signal(SIGTERM, signal_handler);
}
static Cursor CreateNullCursor(Display *display, Window root)
{
Pixmap cursormask;
XGCValues xgc;
GC gc;
XColor dummycolour;
Cursor cursor;
cursormask = XCreatePixmap(display, root, 1, 1, 1/*depth*/);
xgc.function = GXclear;
gc = XCreateGC(display, cursormask, GCFunction, &xgc);
XFillRectangle(display, cursormask, gc, 0, 0, 1, 1);
dummycolour.pixel = 0;
dummycolour.red = 0;
dummycolour.flags = 04;
cursor = XCreatePixmapCursor(display, cursormask, cursormask,
&dummycolour,&dummycolour, 0,0);
XFreePixmap(display,cursormask);
XFreeGC(display,gc);
return cursor;
}
void GLVID_ShiftPalette(unsigned char *p)
{
// VID_SetPalette(p);
}
void GLVID_SetPalette (unsigned char *palette)
{
qbyte *pal;
unsigned r,g,b;
unsigned v;
unsigned short i;
unsigned *table;
unsigned *table2;
extern qbyte gammatable[256];
//
// 8 8 8 encoding
//
Con_Printf("Converting 8to24\n");
pal = palette;
table = d_8to24rgbtable;
table2 = d_8to24bgrtable;
for (i=0 ; i<256 ; i++)
{
r = gammatable[pal[0]];
g = gammatable[pal[1]];
b = gammatable[pal[2]];
pal += 3;
// v = (255<<24) + (r<<16) + (g<<8) + (b<<0);
// v = (255<<0) + (r<<8) + (g<<16) + (b<<24);
v = (255<<24) + (r<<0) + (g<<8) + (b<<16);
*table++ = v;
*table2++ = (255<<24) + (r<<16) + (g<<8) + (b<<0);
}
d_8to24bgrtable[255] &= 0xffffff; // 255 is transparent
d_8to24rgbtable[255] &= 0xffffff; // 255 is transparent
}
/*
=================
GL_BeginRendering
=================
*/
void GL_BeginRendering (int *x, int *y, int *width, int *height)
{
*x = *y = 0;
*width = scr_width;
*height = scr_height;
// if (!wglMakeCurrent( maindc, baseRC ))
// Sys_Error ("wglMakeCurrent failed");
// glViewport (*x, *y, *width, *height);
}
void GL_EndRendering (void)
{
//return;
glFlush();
qglXSwapBuffers(vid_dpy, vid_window);
}
qboolean GLVID_Is8bit(void)
{
return is8bit;
}
qboolean GLVID_Init (rendererstate_t *info, unsigned char *palette)
{
int i;
int attrib[] = {
GLX_RGBA,
GLX_RED_SIZE, 1,
GLX_GREEN_SIZE, 1,
GLX_BLUE_SIZE, 1,
GLX_DOUBLEBUFFER,
GLX_DEPTH_SIZE, 1,
None
};
char gldir[MAX_OSPATH];
XSetWindowAttributes attr;
unsigned long mask;
Window root;
XVisualInfo *visinfo;
#ifdef WITH_VMODE
qboolean fullscreen = false;
int MajorVersion, MinorVersion, actualWidth, actualHeight;
if (info->fullscreen)
fullscreen = true;
#endif
S_Startup();
GLX_InitLibrary(info->glrenderer);
vid.maxwarpwidth = WARP_WIDTH;
vid.maxwarpheight = WARP_HEIGHT;
vid.colormap = host_colormap;
// interpret command-line params
// set vid parameters
if ((i = COM_CheckParm("-conwidth")) != 0)
vid.conwidth = Q_atoi(com_argv[i+1]);
else
vid.conwidth = 640;
vid.conwidth &= ~7; // make it a multiple of eight
if (vid.conwidth < 320)
vid.conwidth = 320;
// pick a conheight that matches with correct aspect
vid.conheight = vid.conwidth*3 / 4;
if ((i = COM_CheckParm("-conheight")) != 0)
vid.conheight = Q_atoi(com_argv[i+1]);
if (vid.conheight < 200)
vid.conheight = 200;
if (!vid_dpy)
vid_dpy = XOpenDisplay(NULL);
if (!vid_dpy)
{
Sys_Error("Error couldn't open the X display\n");
}
scrnum = DefaultScreen(vid_dpy);
root = RootWindow(vid_dpy, scrnum);
#ifdef WITH_VMODE //find out if it's supported on this pc.
MajorVersion = MinorVersion = 0;
if (!XF86VidModeQueryVersion(vid_dpy, &MajorVersion, &MinorVersion))
{
vidmode_ext = false;
}
else
{
Con_Printf("Using XF86-VidModeExtension Ver. %d.%d\n", MajorVersion, MinorVersion);
vidmode_ext = true;
}
#endif
visinfo = qglXChooseVisual(vid_dpy, scrnum, attrib);
if (!visinfo)
{
Sys_Error("qkHack: Error couldn't get an RGB, Double-buffered, Depth visual\n");
}
#ifdef WITH_VMODE
if (vidmode_ext)
{
int best_fit, best_dist, dist, x, y;
XF86VidModeGetAllModeLines(vid_dpy, scrnum, &num_vidmodes, &vidmodes);
// Are we going fullscreen? If so, let's change video mode
if (fullscreen)
{
best_dist = 9999999;
best_fit = -1;
for (i = 0; i < num_vidmodes; i++)
{
if (info->width > vidmodes[i]->hdisplay ||
info->height > vidmodes[i]->vdisplay)
continue;
x = info->width - vidmodes[i]->hdisplay;
y = info->height - vidmodes[i]->vdisplay;
dist = (x * x) + (y * y);
if (dist < best_dist)
{
best_dist = dist;
best_fit = i;
}
}
if (best_fit != -1 && (!best_dist || COM_CheckParm("-fullscreen")))
{
actualWidth = vidmodes[best_fit]->hdisplay;
actualHeight = vidmodes[best_fit]->vdisplay;
// change to the mode
XF86VidModeSwitchToMode(vid_dpy, scrnum, vidmodes[best_fit]);
vidmode_active = true;
// Move the viewport to top left
XF86VidModeSetViewPort(vid_dpy, scrnum, 0, 0);
}
else
fullscreen = 0;
}
}
#endif
/* window attributes */
attr.background_pixel = 0;
attr.border_pixel = 0;
attr.colormap = XCreateColormap(vid_dpy, root, visinfo->visual, AllocNone);
attr.event_mask = X_MASK;
mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
#ifdef WITH_VMODE //get rid of borders
// fullscreen
if (vidmode_active) {
mask = CWBackPixel | CWColormap | CWSaveUnder | CWBackingStore |
CWEventMask | CWOverrideRedirect;
attr.override_redirect = True;
attr.backing_store = NotUseful;
attr.save_under = False;
}
#endif
has_focus = false;
vid_window = XCreateWindow(vid_dpy, root, 0, 0, info->width, info->height,
0, visinfo->depth, InputOutput,
visinfo->visual, mask, &attr);
XMapWindow(vid_dpy, vid_window);
XMoveWindow(vid_dpy, vid_window, 0, 0);
#ifdef WITH_VMODE
if (vidmode_active) {
XRaiseWindow(vid_dpy, vid_window);
XWarpPointer(vid_dpy, None, vid_window, 0, 0, 0, 0, 0, 0);
XFlush(vid_dpy);
// Move the viewport to top left
XF86VidModeSetViewPort(vid_dpy, scrnum, 0, 0);
}
#endif
XStoreName(vid_dpy, vid_window, "GLX QuakeWorld Cient");
//hide the cursor.
XDefineCursor(vid_dpy, vid_window, CreateNullCursor(vid_dpy, vid_window));
XFlush(vid_dpy);
ctx = qglXCreateContext(vid_dpy, visinfo, NULL, True);
qglXMakeCurrent(vid_dpy, vid_window, ctx);
scr_width = info->width;
scr_height = info->height;
if (vid.conheight > info->height)
vid.conheight = info->height;
if (vid.conwidth > info->width)
vid.conwidth = info->width;
vid.width = vid.conwidth;
vid.height = vid.conheight;
vid.aspect = ((float)vid.height / (float)vid.width) * (320.0 / 240.0);
vid.numpages = 2;
InitSig(); // trap evil signals
GL_Init(&GLX_GetSymbol);
sprintf (gldir, "%s/glquake", com_gamedir);
Sys_mkdir (gldir);
VID_SetPalette(palette);
Con_SafePrintf ("Video mode %dx%d initialized.\n", info->width, info->height);
vid.recalc_refdef = 1; // force a surface cache flush
if (Cvar_Get("vidx_grabkeyboard", "0", 0, "Additional video options")->value)
XGrabKeyboard(vid_dpy, vid_window,
False,
GrabModeAsync, GrabModeAsync,
CurrentTime);
else
XSetInputFocus(vid_dpy, vid_window, RevertToParent, CurrentTime);
XRaiseWindow(vid_dpy, vid_window);
return true;
}
#ifdef SWQUAKE
void GLSys_SendKeyEvents(void)
#else
void Sys_SendKeyEvents(void)
#endif
{
if (vid_dpy && vid_window) {
while (XPending(vid_dpy))
GetEvent();
}
}
void Force_CenterView_f (void)
{
cl.viewangles[0][PITCH] = 0;
}
#ifndef SWQUAKE
void IN_Init(void)
{
#ifdef IN_XFLIP
Cvar_Register (&in_xflip, "Input variables");
#endif
}
void IN_Shutdown(void)
{
}
/*
===========
IN_Commands
===========
*/
void IN_Commands (void)
{
}
/*
===========
IN_Move
===========
*/
void IN_MouseMove (usercmd_t *cmd, int pnum)
{
if (m_filter.value)
{
mouse_x = (mouse_x + old_mouse_x) * 0.5;
mouse_y = (mouse_y + old_mouse_y) * 0.5;
}
old_mouse_x = mouse_x;
old_mouse_y = mouse_y;
mouse_x *= sensitivity.value;
mouse_y *= sensitivity.value;
#ifdef IN_XFLIP
if(in_xflip.value) mouse_x *= -1;
#endif
// add mouse X/Y movement to cmd
if ( (in_strafe.state[pnum] & 1) || (lookstrafe.value && (in_mlook.state[pnum] & 1) ))
cmd->sidemove += m_side.value * mouse_x;
else
cl.viewangles[pnum][YAW] -= m_yaw.value * mouse_x;
if (in_mlook.state[pnum] & 1)
V_StopPitchDrift (pnum);
if ( (in_mlook.state[pnum] & 1) && !(in_strafe.state[pnum] & 1))
{
cl.viewangles[pnum][PITCH] += m_pitch.value * mouse_y;
CL_ClampPitch(pnum);
}
else
{
if ((in_strafe.state[pnum] & 1) && noclip_anglehack)
cmd->upmove -= m_forward.value * mouse_y;
else
cmd->forwardmove -= m_forward.value * mouse_y;
}
mouse_x = mouse_y = 0.0;
}
void IN_Move (usercmd_t *cmd, int pnum)
{
IN_MouseMove(cmd, pnum);
}
#endif
void GLVID_UnlockBuffer() {}
void GLVID_LockBuffer() {}
int GLVID_ForceUnlockedAndReturnState (void) {return 0;}
void GLVID_ForceLockState (int lk) {}
void GLVID_HandlePause (qboolean pause) {}

1283
engine/gl/gl_vidnt.c Normal file

File diff suppressed because it is too large Load diff

956
engine/gl/gl_warp.c Normal file
View file

@ -0,0 +1,956 @@
/*
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"
#include "glquake.h"
extern model_t *loadmodel;
int skytexturenum;
int solidskytexture;
int alphaskytexture;
float speedscale; // for top sky and bottom sky
qboolean usingskybox;
msurface_t *warpface;
extern cvar_t gl_skyboxname;
extern cvar_t gl_waterripples;
char loadedskybox[256];
void R_DrawSkyBox (msurface_t *s);
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, float dividesize)
{
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 || numverts <= 0)
Sys_Error ("numverts = %i", numverts);
BoundPoly (numverts, verts, mins, maxs);
for (i=0 ; i<3 ; i++)
{
m = (mins[i] + maxs[i]) * 0.5;
m = dividesize * floor (m/dividesize + 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], dividesize);
SubdividePolygon (b, back[0], dividesize);
return;
}
poly = Hunk_AllocName (sizeof(glpoly_t) + (numverts-4) * VERTEXSIZE*sizeof(float), "subpoly");
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, float dividesize)
{
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++;
if(numverts >= 64)
{
Con_Printf("Too many verts on surface\n");
break;
}
}
SubdividePolygon (numverts, verts[0], dividesize);
}
//=========================================================
// 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;
#ifdef WATERLAYERS
extern cvar_t r_waterlayers;
if (gl_waterripples.value)
{
float f = 10;
glEnable(GL_AUTO_NORMAL);
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);
glNormal3f(fa->plane->normal[0] + (sin(realtime+v[0]/f+v[1]/f))/4, fa->plane->normal[1] +(sin(realtime-v[1]/f))/4, fa->plane->normal[2] + (sin(realtime+v[2]/f))/4);
glTexCoord2f (s, t);
glVertex3fv (v);
}
glEnd ();
}
glDisable(GL_AUTO_NORMAL);
}
else if (r_waterlayers.value>=1)
{
float a, stm, ttm;
int l;
glDisable(GL_ALPHA_TEST);
glEnable(GL_BLEND); //to ensure.
for (a=r_wateralphaval,l = 0; l < r_waterlayers.value; l++,a=a*4/6)
{
glColor4f(1, 1, 1, a);
stm =cos(l)/10;
ttm =sin(l)/10;
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]/(l*0.5+0.2);
ot = v[4]/(l*0.5+0.2);
s = os + turbsin[(int)((ot*0.125+cl.time+l*8) * TURBSCALE) & 255];//*r_watersurfacewarp.value;
s *= (1.0/64);
t = ot + turbsin[(int)((os*0.125+cl.time+l*8) * TURBSCALE) & 255];//*r_watersurfacewarp.value;
t *= (1.0/64);
glTexCoord2f (s+cl.time*stm, t+cl.time*ttm);
glVertex3fv (v);
}
glEnd ();
}
}
}
else
{
#endif
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 ();
}
#ifdef WATERLAYERS
}
#endif
}
/*
=============
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);
}
/*
=================
R_DrawSkyChain
=================
*/
void R_DrawSkyBoxChain (msurface_t *s);
void R_DrawSkyChain (msurface_t *s)
{
msurface_t *fa;
if (usingskybox)
{
R_DrawSkyBoxChain(s);
return;
}
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);
}
/*
=================================================================
Quake 2 environment sky
=================================================================
*/
/*
==================
R_LoadSkys
==================
*/
static char *suf[6] = {"rt", "bk", "lf", "ft", "up", "dn"};
int skyboxtex[6];
void R_LoadSkys (void)
{
int i;
char name[64];
for (i=0 ; i<6 ; i++)
{
sprintf (name, "env/%s%s.tga", gl_skyboxname.string, suf[i]);
skyboxtex[i] = Mod_LoadHiResTexture(name, false, false);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
}
Q_strncpyz(loadedskybox, gl_skyboxname.string, sizeof(loadedskybox));
gl_skyboxname.modified = false;
}
qboolean GLR_CheckSky()
{
return true;
}
void GLR_SetSky(char *name, float rotate, vec3_t axis)
{
if (*name)
Cvar_Set(&gl_skyboxname, name);
}
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];
if (dv < 0.001)
continue; // don't divide by zero
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_DrawSkyBoxChain (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_DrawSkyBox (s);
glColorMask(0, 0, 0, 0);
for (fa=s ; fa ; fa=fa->texturechain)
{
for (p=fa->polys ; p ; p=p->next)
{
glBegin(GL_POLYGON);
for (i = 0; i < p->numverts; i++)
glVertex3fv(p->verts[i]);
glEnd();
}
}
glColorMask(1, 1, 1, 1);
}
void R_AddSkySurface (msurface_t *fa)
{
int i;
vec3_t verts[MAX_CLIP_VERTS];
glpoly_t *p;
// calculate vertex values for sky box
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;
if (!cl.worldmodel) //allow skyboxes on non quake1 maps. (expect them even)
{
usingskybox = false;
return;
}
if (gl_skyboxname.modified)
R_LoadSkys();
if (!skyboxtex[0] || !skyboxtex[1] || !skyboxtex[2] || !skyboxtex[3] || !skyboxtex[4] || !skyboxtex[5])
{
usingskybox = false;
return;
}
usingskybox = true;
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*2300;
b[1] = t*2300;
b[2] = 2300;
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 (msurface_t *s)
{
msurface_t *fa;
glpoly_t *poly;
int i;
if (!usingskybox)
return;
#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 (skyboxtex[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
if (!cls.allow_skyboxes && s) //allow a little extra fps.
{
glColorMask(0, 0, 0, 0); //depth only.
for (fa = s; fa; fa = fa->texturechain)
{
for (poly = fa->polys; poly; poly = poly->next)
{
glBegin (GL_POLYGON);
for (i = 0; i < poly->numverts; i++)
glVertex3fv (&poly->verts[0][0]+i*VERTEXSIZE);
glEnd ();
}
}
glColorMask(1, 1, 1, 1);
}
}
//===============================================================
/*
=============
R_InitSky
A sky texture is 256*128, with the right side being a masked overlay
==============
*/
void GLR_InitSky (texture_t *mt)
{
int i, j, p;
qbyte *src;
unsigned trans[128*128];
unsigned transpix;
int r, g, b;
unsigned *rgba;
char name[MAX_QPATH];
src = (qbyte *)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_8to24rgbtable[p];
trans[(i*128) + j] = *rgba;
r += ((qbyte *)rgba)[0];
g += ((qbyte *)rgba)[1];
b += ((qbyte *)rgba)[2];
}
((qbyte *)&transpix)[0] = r/(128*128);
((qbyte *)&transpix)[1] = g/(128*128);
((qbyte *)&transpix)[2] = b/(128*128);
((qbyte *)&transpix)[3] = 0;
sprintf(name, "%s_solid", mt->name);
strlwr(name);
solidskytexture = Mod_LoadReplacementTexture(name, true, false);
if (!solidskytexture)
solidskytexture = GL_LoadTexture32(name, 128, 128, trans, true, false);
/*
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_8to24rgbtable[p];
}
sprintf(name, "%s_trans", mt->name);
strlwr(name);
alphaskytexture = Mod_LoadReplacementTexture(name, true, true);
if (!alphaskytexture)
alphaskytexture = GL_LoadTexture32(name, 128, 128, trans, true, true);
/*
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);
*/
}

51
engine/gl/gl_warp_sin.h Normal file
View file

@ -0,0 +1,51 @@
/*
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.
*/
0, 0.19633, 0.392541, 0.588517, 0.784137, 0.979285, 1.17384, 1.3677,
1.56072, 1.75281, 1.94384, 2.1337, 2.32228, 2.50945, 2.69512, 2.87916,
3.06147, 3.24193, 3.42044, 3.59689, 3.77117, 3.94319, 4.11282, 4.27998,
4.44456, 4.60647, 4.76559, 4.92185, 5.07515, 5.22538, 5.37247, 5.51632,
5.65685, 5.79398, 5.92761, 6.05767, 6.18408, 6.30677, 6.42566, 6.54068,
6.65176, 6.75883, 6.86183, 6.9607, 7.05537, 7.14579, 7.23191, 7.31368,
7.39104, 7.46394, 7.53235, 7.59623, 7.65552, 7.71021, 7.76025, 7.80562,
7.84628, 7.88222, 7.91341, 7.93984, 7.96148, 7.97832, 7.99036, 7.99759,
8, 7.99759, 7.99036, 7.97832, 7.96148, 7.93984, 7.91341, 7.88222,
7.84628, 7.80562, 7.76025, 7.71021, 7.65552, 7.59623, 7.53235, 7.46394,
7.39104, 7.31368, 7.23191, 7.14579, 7.05537, 6.9607, 6.86183, 6.75883,
6.65176, 6.54068, 6.42566, 6.30677, 6.18408, 6.05767, 5.92761, 5.79398,
5.65685, 5.51632, 5.37247, 5.22538, 5.07515, 4.92185, 4.76559, 4.60647,
4.44456, 4.27998, 4.11282, 3.94319, 3.77117, 3.59689, 3.42044, 3.24193,
3.06147, 2.87916, 2.69512, 2.50945, 2.32228, 2.1337, 1.94384, 1.75281,
1.56072, 1.3677, 1.17384, 0.979285, 0.784137, 0.588517, 0.392541, 0.19633,
9.79717e-16, -0.19633, -0.392541, -0.588517, -0.784137, -0.979285, -1.17384, -1.3677,
-1.56072, -1.75281, -1.94384, -2.1337, -2.32228, -2.50945, -2.69512, -2.87916,
-3.06147, -3.24193, -3.42044, -3.59689, -3.77117, -3.94319, -4.11282, -4.27998,
-4.44456, -4.60647, -4.76559, -4.92185, -5.07515, -5.22538, -5.37247, -5.51632,
-5.65685, -5.79398, -5.92761, -6.05767, -6.18408, -6.30677, -6.42566, -6.54068,
-6.65176, -6.75883, -6.86183, -6.9607, -7.05537, -7.14579, -7.23191, -7.31368,
-7.39104, -7.46394, -7.53235, -7.59623, -7.65552, -7.71021, -7.76025, -7.80562,
-7.84628, -7.88222, -7.91341, -7.93984, -7.96148, -7.97832, -7.99036, -7.99759,
-8, -7.99759, -7.99036, -7.97832, -7.96148, -7.93984, -7.91341, -7.88222,
-7.84628, -7.80562, -7.76025, -7.71021, -7.65552, -7.59623, -7.53235, -7.46394,
-7.39104, -7.31368, -7.23191, -7.14579, -7.05537, -6.9607, -6.86183, -6.75883,
-6.65176, -6.54068, -6.42566, -6.30677, -6.18408, -6.05767, -5.92761, -5.79398,
-5.65685, -5.51632, -5.37247, -5.22538, -5.07515, -4.92185, -4.76559, -4.60647,
-4.44456, -4.27998, -4.11282, -3.94319, -3.77117, -3.59689, -3.42044, -3.24193,
-3.06147, -2.87916, -2.69512, -2.50945, -2.32228, -2.1337, -1.94384, -1.75281,
-1.56072, -1.3677, -1.17384, -0.979285, -0.784137, -0.588517, -0.392541, -0.19633,

1993
engine/gl/glmod_doom.c Normal file

File diff suppressed because it is too large Load diff

813
engine/gl/glquake.h Normal file
View file

@ -0,0 +1,813 @@
/*
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.
*/
// disable data conversion warnings
#ifdef MSVCDISABLEWARNINGS
#pragma warning(disable : 4244) // MIPS
#pragma warning(disable : 4136) // X86
#pragma warning(disable : 4051) // ALPHA
#endif
#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <winsock2.h>
#endif
#ifndef APIENTRY
#define APIENTRY
#endif
typedef qbyte pal77[128][128];
pal77 *pal777to8;
void AddPointToBounds (vec3_t v, vec3_t mins, vec3_t maxs);
qboolean BoundsIntersect (vec3_t mins1, vec3_t maxs1, vec3_t mins2, vec3_t maxs2);
void ClearBounds (vec3_t mins, vec3_t maxs);
#ifdef RGLQUAKE
#include <GL/gl.h>
//#include <GL/glu.h>
#include "glsupp.h"
void GL_BeginRendering (int *x, int *y, int *width, int *height);
void GL_EndRendering (void);
void R_EmitSkyEffectTris(model_t *mod, msurface_t *fa);
void GLR_BrightenScreen (void);
void GLR_NetGraph (void);
void GLR_DrawAlphaSurfaces (void);
void GL_FlushSkinCache(void);
void GL_GAliasFlushSkinCache(void);
// Function prototypes for the Texture Object Extension routines
typedef GLboolean (APIENTRY *ARETEXRESFUNCPTR)(GLsizei, const GLuint *,
const GLboolean *);
typedef void (APIENTRY *BINDTEXFUNCPTR)(GLenum, GLuint);
typedef void (APIENTRY *DELTEXFUNCPTR)(GLsizei, const GLuint *);
typedef void (APIENTRY *GENTEXFUNCPTR)(GLsizei, GLuint *);
typedef GLboolean (APIENTRY *ISTEXFUNCPTR)(GLuint);
typedef void (APIENTRY *PRIORTEXFUNCPTR)(GLsizei, const GLuint *,
const GLclampf *);
typedef void (APIENTRY *TEXSUBIMAGEPTR)(int, int, int, int, int, int, int, int, void *);
extern BINDTEXFUNCPTR bindTexFunc;
extern DELTEXFUNCPTR delTexFunc;
extern TEXSUBIMAGEPTR TexSubImage2DFunc;
extern void (APIENTRY *qglStencilOpSeparateATI) (GLenum face, GLenum fail, GLenum zfail, GLenum zpass);
extern PFNGLCOMPRESSEDTEXIMAGE2DARBPROC qglCompressedTexImage2DARB;
extern PFNGLGETCOMPRESSEDTEXIMAGEARBPROC qglGetCompressedTexImageARB;
extern PFNGLPNTRIANGLESIATIPROC qglPNTrianglesiATI;
extern PFNGLPNTRIANGLESFATIPROC qglPNTrianglesfATI;
extern int texture_extension_number;
extern int texture_mode;
extern float gldepthmin, gldepthmax;
void GL_Upload32 (char *name, unsigned *data, int width, int height, qboolean mipmap, qboolean alpha); //name was added for texture compression output
void GL_Upload8 (qbyte *data, int width, int height, qboolean mipmap, qboolean alpha);
#ifdef GL_EXT_paletted_texture
void GL_Upload8_EXT (qbyte *data, int width, int height, qboolean mipmap, qboolean alpha);
#endif
int GL_LoadTexture (char *identifier, int width, int height, qbyte *data, qboolean mipmap, qboolean alpha);
int GL_LoadTexture8Bump (char *identifier, int width, int height, unsigned char *data, qboolean mipmap);
int GL_LoadTexture8Pal24 (char *identifier, int width, int height, qbyte *data, qbyte *palette24, qboolean mipmap, qboolean alpha);
int GL_LoadTexture32 (char *identifier, int width, int height, unsigned *data, qboolean mipmap, qboolean alpha);
int GL_LoadCompressed(char *name);
int GL_FindTexture (char *identifier);
int GL_LoadTextureFB (char *identifier, int width, int height, qbyte *data, qboolean mipmap, qboolean alpha);
void GL_Upload8Pal24 (qbyte *data, qbyte *pal, int width, int height, qboolean mipmap, qboolean alpha);
typedef struct
{
float x, y, z;
float s, t;
float r, g, b;
} glvert_t;
extern glvert_t glv;
extern int glx, gly, glwidth, glheight;
#endif
// r_local.h -- private refresh defs
#define ALIAS_BASE_SIZE_RATIO (1.0 / 11.0)
// normalizing factor so player model works out to about
// 1 pixel per triangle
#define MAX_LBM_HEIGHT 480
#define TILE_SIZE 128 // size of textures generated by R_GenTiledSurf
#define SKYSHIFT 7
#define SKYSIZE (1 << SKYSHIFT)
#define SKYMASK (SKYSIZE - 1)
#define BACKFACE_EPSILON 0.01
void R_TimeRefresh_f (void);
void R_ReadPointFile_f (void);
texture_t *SWR_TextureAnimation (texture_t *base);
texture_t *GLR_TextureAnimation (texture_t *base);
#include "particles.h"
//====================================================
extern entity_t r_worldentity;
extern qboolean r_cache_thrash; // compatability
extern vec3_t modelorg, r_entorigin;
extern entity_t *currententity;
extern int r_visframecount; // ??? what difs?
extern int r_framecount;
extern mplane_t frustum[4];
extern int c_brush_polys, c_alias_polys;
extern float r_wateralphaval;
//
// view origin
//
extern vec3_t vup;
extern vec3_t vpn;
extern vec3_t vright;
extern vec3_t r_origin;
//
// screen size info
//
extern refdef_t r_refdef;
extern mleaf_t *r_viewleaf, *r_oldviewleaf;
extern mleaf_t *r_viewleaf2, *r_oldviewleaf2;
extern int r_viewcluster, r_viewcluster2, r_oldviewcluster, r_oldviewcluster2; //q2
extern texture_t *r_notexture_mip;
extern int d_lightstylevalue[256]; // 8.8 fraction of base light value
extern qboolean envmap;
extern int currenttexture;
extern int particletexture;
extern int explosiontexture;
extern int netgraphtexture; // netgraph texture
extern int playertextures;
extern int skytexturenum; // index in cl.loadmodel, not gl texture object
extern int gl_lightmap_format;
extern int gl_solid_format;
extern int gl_alpha_format;
extern int mirrortexturenum; // quake texturenum, not gltexturenum
extern qboolean mirror;
extern mplane_t *mirror_plane;
extern float r_world_matrix[16];
extern const char *gl_vendor;
extern const char *gl_renderer;
extern const char *gl_version;
extern const char *gl_extensions;
void R_TranslatePlayerSkin (int playernum);
void GL_Bind (int texnum);
void GL_BindType (int type, int texnum);
#if defined(RGLQUAKE)
// Multitexture
#define GL_TEXTURE0_SGIS 0x835E
#define GL_TEXTURE1_SGIS 0x835F
typedef void (APIENTRY *lpMTexFUNC) (GLenum en, GLfloat f1, GLfloat f2);
typedef void (APIENTRY *lpSelTexFUNC) (GLenum en);
extern lpMTexFUNC qglMTexCoord2fSGIS;
extern lpSelTexFUNC qglSelectTextureSGIS;
extern int gl_canstencil;
extern PFNGLACTIVESTENCILFACEEXTPROC qglActiveStencilFaceEXT;
extern lpMTexFUNC qglMTexCoord2fSGIS;
extern lpSelTexFUNC qglSelectTextureSGIS;
extern qboolean gl_ext_stencil_wrap;
extern int gl_mtexarbable; //max texture units
extern qboolean gl_mtexable;
extern qboolean gl_compressable;
extern int mtexid0;
extern int mtexid1;
extern qboolean gl_mtexable;
void GL_DisableMultitexture(void);
void GL_EnableMultitexture(void);
//
// gl_warp.c
//
void GL_SubdivideSurface (msurface_t *fa, float dividesize);
void EmitBothSkyLayers (msurface_t *fa);
void EmitWaterPolys (msurface_t *fa);
void EmitSkyPolys (msurface_t *fa);
void R_DrawSkyChain (msurface_t *s);
void R_ClearSkyBox (void);
void R_AddSkySurface (msurface_t *fa);
//
// gl_draw.c
//
int GL_LoadPicTexture (qpic_t *pic);
void GL_Set2D (void);
//
// gl_rmain.c
//
qboolean R_CullBox (vec3_t mins, vec3_t maxs);
void R_RotateForEntity (entity_t *e);
void R_DrawAliasModel (entity_t *e);
//gl_alias.c
void R_DrawGAliasModel (entity_t *e);
void R_DrawGAliasShadowVolume(entity_t *e, vec3_t lightpos, float radius);
void R_DrawGAliasModelLighting (entity_t *e);
//misc model formats
void R_DrawAlias3Model (entity_t *ent);
void R_DrawHLModel(entity_t *curent);
void R_DrawGroupModel (entity_t *ent);
//typedef float m3by3_t[3][3];
//int GetTag(model_t *mod, char *tagname, int frame, float **org, m3by3_t **ang);
//
// gl_rlight.c
//
void GLR_MarkLights (dlight_t *light, int bit, mnode_t *node);
void GLR_MarkQ2Lights (dlight_t *light, int bit, mnode_t *node);
void GLR_AnimateLight (void);
void R_RenderDlights (void);
int GLR_LightPoint (vec3_t p);
void GLQ3_LightGrid(vec3_t point, vec3_t res_diffuse, vec3_t res_ambient, vec3_t res_lightdir);
//
// gl_rsurf.c
//
void R_DrawBrushModel (entity_t *e);
void R_DrawWorld (void);
void GL_BuildLightmaps (void);
void GL_LoadShaders(void);
int Mod_LoadReplacementTexture(char *name, qboolean mipmap, qboolean alpha);
int Mod_LoadHiResTexture(char *name, qboolean mipmap, qboolean alpha);
int Mod_LoadBumpmapTexture(char *name);
#define LMBLOCK_WIDTH 128
#define LMBLOCK_HEIGHT 128
typedef struct glRect_s {
unsigned char l,t,w,h;
} glRect_t;
typedef char stmap;
typedef struct {
glpoly_t *polys;
qboolean modified;
qboolean deluxmodified;
glRect_t rectchange;
glRect_t deluxrectchange;
int allocated[LMBLOCK_WIDTH];
qbyte lightmaps[4*LMBLOCK_WIDTH*LMBLOCK_HEIGHT];
qbyte deluxmaps[4*LMBLOCK_WIDTH*LMBLOCK_HEIGHT]; //fixme: make seperate structure for easy disabling with less memory usage.
stmap stainmaps[3*LMBLOCK_WIDTH*LMBLOCK_HEIGHT]; //rgb no a. added to lightmap for added (hopefully) speed.
} lightmapinfo_t;
//gl_ppl.c
void PPL_DrawWorld (void);
void RotateLightVector(vec3_t angles, vec3_t origin, vec3_t lightpoint, vec3_t result);
#endif
//
// gl_refrag.c
//
void R_StoreEfrags (efrag_t **ppefrag);
//
// gl_ngraph.c
//
void R_NetGraph (void);
#if defined(RGLQUAKE)
extern void (APIENTRY *qglAccum) (GLenum op, GLfloat value);
extern void (APIENTRY *qglAlphaFunc) (GLenum func, GLclampf ref);
extern GLboolean (APIENTRY *qglAreTexturesResident) (GLsizei n, const GLuint *textures, GLboolean *residences);
extern void (APIENTRY *qglArrayElement) (GLint i);
extern void (APIENTRY *qglBegin) (GLenum mode);
extern void (APIENTRY *qglBindTexture) (GLenum target, GLuint texture);
extern void (APIENTRY *qglBitmap) (GLsizei width, GLsizei height, GLfloat xorig, GLfloat yorig, GLfloat xmove, GLfloat ymove, const GLubyte *bitmap);
extern void (APIENTRY *qglBlendFunc) (GLenum sfactor, GLenum dfactor);
extern void (APIENTRY *qglCallList) (GLuint list);
extern void (APIENTRY *qglCallLists) (GLsizei n, GLenum type, const GLvoid *lists);
extern void (APIENTRY *qglClear) (GLbitfield mask);
extern void (APIENTRY *qglClearAccum) (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
extern void (APIENTRY *qglClearColor) (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
extern void (APIENTRY *qglClearDepth) (GLclampd depth);
extern void (APIENTRY *qglClearIndex) (GLfloat c);
extern void (APIENTRY *qglClearStencil) (GLint s);
extern void (APIENTRY *qglClipPlane) (GLenum plane, const GLdouble *equation);
extern void (APIENTRY *qglColor3b) (GLbyte red, GLbyte green, GLbyte blue);
extern void (APIENTRY *qglColor3bv) (const GLbyte *v);
extern void (APIENTRY *qglColor3d) (GLdouble red, GLdouble green, GLdouble blue);
extern void (APIENTRY *qglColor3dv) (const GLdouble *v);
extern void (APIENTRY *qglColor3f) (GLfloat red, GLfloat green, GLfloat blue);
extern void (APIENTRY *qglColor3fv) (const GLfloat *v);
extern void (APIENTRY *qglColor3i) (GLint red, GLint green, GLint blue);
extern void (APIENTRY *qglColor3iv) (const GLint *v);
extern void (APIENTRY *qglColor3s) (GLshort red, GLshort green, GLshort blue);
extern void (APIENTRY *qglColor3sv) (const GLshort *v);
extern void (APIENTRY *qglColor3ub) (GLubyte red, GLubyte green, GLubyte blue);
extern void (APIENTRY *qglColor3ubv) (const GLubyte *v);
extern void (APIENTRY *qglColor3ui) (GLuint red, GLuint green, GLuint blue);
extern void (APIENTRY *qglColor3uiv) (const GLuint *v);
extern void (APIENTRY *qglColor3us) (GLushort red, GLushort green, GLushort blue);
extern void (APIENTRY *qglColor3usv) (const GLushort *v);
extern void (APIENTRY *qglColor4b) (GLbyte red, GLbyte green, GLbyte blue, GLbyte alpha);
extern void (APIENTRY *qglColor4bv) (const GLbyte *v);
extern void (APIENTRY *qglColor4d) (GLdouble red, GLdouble green, GLdouble blue, GLdouble alpha);
extern void (APIENTRY *qglColor4dv) (const GLdouble *v);
extern void (APIENTRY *qglColor4f) (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
extern void (APIENTRY *qglColor4fv) (const GLfloat *v);
extern void (APIENTRY *qglColor4i) (GLint red, GLint green, GLint blue, GLint alpha);
extern void (APIENTRY *qglColor4iv) (const GLint *v);
extern void (APIENTRY *qglColor4s) (GLshort red, GLshort green, GLshort blue, GLshort alpha);
extern void (APIENTRY *qglColor4sv) (const GLshort *v);
extern void (APIENTRY *qglColor4ub) (GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha);
extern void (APIENTRY *qglColor4ubv) (const GLubyte *v);
extern void (APIENTRY *qglColor4ui) (GLuint red, GLuint green, GLuint blue, GLuint alpha);
extern void (APIENTRY *qglColor4uiv) (const GLuint *v);
extern void (APIENTRY *qglColor4us) (GLushort red, GLushort green, GLushort blue, GLushort alpha);
extern void (APIENTRY *qglColor4usv) (const GLushort *v);
extern void (APIENTRY *qglColorMask) (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
extern void (APIENTRY *qglColorMaterial) (GLenum face, GLenum mode);
extern void (APIENTRY *qglColorPointer) (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
extern void (APIENTRY *qglCopyPixels) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum type);
extern void (APIENTRY *qglCopyTexImage1D) (GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLint border);
extern void (APIENTRY *qglCopyTexImage2D) (GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
extern void (APIENTRY *qglCopyTexSubImage1D) (GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width);
extern void (APIENTRY *qglCopyTexSubImage2D) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
extern void (APIENTRY *qglCullFace) (GLenum mode);
extern void (APIENTRY *qglDeleteLists) (GLuint list, GLsizei range);
extern void (APIENTRY *qglDeleteTextures) (GLsizei n, const GLuint *textures);
extern void (APIENTRY *qglDepthFunc) (GLenum func);
extern void (APIENTRY *qglDepthMask) (GLboolean flag);
extern void (APIENTRY *qglDepthRange) (GLclampd zNear, GLclampd zFar);
extern void (APIENTRY *qglDisable) (GLenum cap);
extern void (APIENTRY *qglDisableClientState) (GLenum array);
extern void (APIENTRY *qglDrawArrays) (GLenum mode, GLint first, GLsizei count);
extern void (APIENTRY *qglDrawBuffer) (GLenum mode);
extern void (APIENTRY *qglDrawElements) (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices);
extern void (APIENTRY *qglDrawPixels) (GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels);
extern void (APIENTRY *qglEdgeFlag) (GLboolean flag);
extern void (APIENTRY *qglEdgeFlagPointer) (GLsizei stride, const GLvoid *pointer);
extern void (APIENTRY *qglEdgeFlagv) (const GLboolean *flag);
extern void (APIENTRY *qglEnable) (GLenum cap);
extern void (APIENTRY *qglEnableClientState) (GLenum array);
extern void (APIENTRY *qglEnd) (void);
extern void (APIENTRY *qglEndList) (void);
extern void (APIENTRY *qglEvalCoord1d) (GLdouble u);
extern void (APIENTRY *qglEvalCoord1dv) (const GLdouble *u);
extern void (APIENTRY *qglEvalCoord1f) (GLfloat u);
extern void (APIENTRY *qglEvalCoord1fv) (const GLfloat *u);
extern void (APIENTRY *qglEvalCoord2d) (GLdouble u, GLdouble v);
extern void (APIENTRY *qglEvalCoord2dv) (const GLdouble *u);
extern void (APIENTRY *qglEvalCoord2f) (GLfloat u, GLfloat v);
extern void (APIENTRY *qglEvalCoord2fv) (const GLfloat *u);
extern void (APIENTRY *qglEvalMesh1) (GLenum mode, GLint i1, GLint i2);
extern void (APIENTRY *qglEvalMesh2) (GLenum mode, GLint i1, GLint i2, GLint j1, GLint j2);
extern void (APIENTRY *qglEvalPoint1) (GLint i);
extern void (APIENTRY *qglEvalPoint2) (GLint i, GLint j);
extern void (APIENTRY *qglFeedbackBuffer) (GLsizei size, GLenum type, GLfloat *buffer);
extern void (APIENTRY *qglFinish) (void);
extern void (APIENTRY *qglFlush) (void);
extern void (APIENTRY *qglFogf) (GLenum pname, GLfloat param);
extern void (APIENTRY *qglFogfv) (GLenum pname, const GLfloat *params);
extern void (APIENTRY *qglFogi) (GLenum pname, GLint param);
extern void (APIENTRY *qglFogiv) (GLenum pname, const GLint *params);
extern void (APIENTRY *qglFrontFace) (GLenum mode);
extern void (APIENTRY *qglFrustum) (GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar);
extern GLuint (APIENTRY *qglGenLists) (GLsizei range);
extern void (APIENTRY *qglGenTextures) (GLsizei n, GLuint *textures);
extern void (APIENTRY *qglGetBooleanv) (GLenum pname, GLboolean *params);
extern void (APIENTRY *qglGetClipPlane) (GLenum plane, GLdouble *equation);
extern void (APIENTRY *qglGetDoublev) (GLenum pname, GLdouble *params);
extern GLenum (APIENTRY *qglGetError) (void);
extern void (APIENTRY *qglGetFloatv) (GLenum pname, GLfloat *params);
extern void (APIENTRY *qglGetIntegerv) (GLenum pname, GLint *params);
extern void (APIENTRY *qglGetLightfv) (GLenum light, GLenum pname, GLfloat *params);
extern void (APIENTRY *qglGetLightiv) (GLenum light, GLenum pname, GLint *params);
extern void (APIENTRY *qglGetMapdv) (GLenum target, GLenum query, GLdouble *v);
extern void (APIENTRY *qglGetMapfv) (GLenum target, GLenum query, GLfloat *v);
extern void (APIENTRY *qglGetMapiv) (GLenum target, GLenum query, GLint *v);
extern void (APIENTRY *qglGetMaterialfv) (GLenum face, GLenum pname, GLfloat *params);
extern void (APIENTRY *qglGetMaterialiv) (GLenum face, GLenum pname, GLint *params);
extern void (APIENTRY *qglGetPixelMapfv) (GLenum map, GLfloat *values);
extern void (APIENTRY *qglGetPixelMapuiv) (GLenum map, GLuint *values);
extern void (APIENTRY *qglGetPixelMapusv) (GLenum map, GLushort *values);
extern void (APIENTRY *qglGetPointerv) (GLenum pname, GLvoid* *params);
extern void (APIENTRY *qglGetPolygonStipple) (GLubyte *mask);
extern const GLubyte * (APIENTRY *qglGetString) (GLenum name);
extern void (APIENTRY *qglGetTexEnvfv) (GLenum target, GLenum pname, GLfloat *params);
extern void (APIENTRY *qglGetTexEnviv) (GLenum target, GLenum pname, GLint *params);
extern void (APIENTRY *qglGetTexGendv) (GLenum coord, GLenum pname, GLdouble *params);
extern void (APIENTRY *qglGetTexGenfv) (GLenum coord, GLenum pname, GLfloat *params);
extern void (APIENTRY *qglGetTexGeniv) (GLenum coord, GLenum pname, GLint *params);
extern void (APIENTRY *qglGetTexImage) (GLenum target, GLint level, GLenum format, GLenum type, GLvoid *pixels);
extern void (APIENTRY *qglGetTexLevelParameterfv) (GLenum target, GLint level, GLenum pname, GLfloat *params);
extern void (APIENTRY *qglGetTexLevelParameteriv) (GLenum target, GLint level, GLenum pname, GLint *params);
extern void (APIENTRY *qglGetTexParameterfv) (GLenum target, GLenum pname, GLfloat *params);
extern void (APIENTRY *qglGetTexParameteriv) (GLenum target, GLenum pname, GLint *params);
extern void (APIENTRY *qglHint) (GLenum target, GLenum mode);
extern void (APIENTRY *qglIndexMask) (GLuint mask);
extern void (APIENTRY *qglIndexPointer) (GLenum type, GLsizei stride, const GLvoid *pointer);
extern void (APIENTRY *qglIndexd) (GLdouble c);
extern void (APIENTRY *qglIndexdv) (const GLdouble *c);
extern void (APIENTRY *qglIndexf) (GLfloat c);
extern void (APIENTRY *qglIndexfv) (const GLfloat *c);
extern void (APIENTRY *qglIndexi) (GLint c);
extern void (APIENTRY *qglIndexiv) (const GLint *c);
extern void (APIENTRY *qglIndexs) (GLshort c);
extern void (APIENTRY *qglIndexsv) (const GLshort *c);
extern void (APIENTRY *qglIndexub) (GLubyte c);
extern void (APIENTRY *qglIndexubv) (const GLubyte *c);
extern void (APIENTRY *qglInitNames) (void);
extern void (APIENTRY *qglInterleavedArrays) (GLenum format, GLsizei stride, const GLvoid *pointer);
extern GLboolean (APIENTRY *qglIsEnabled) (GLenum cap);
extern GLboolean (APIENTRY *qglIsList) (GLuint list);
extern GLboolean (APIENTRY *qglIsTexture) (GLuint texture);
extern void (APIENTRY *qglLightModelf) (GLenum pname, GLfloat param);
extern void (APIENTRY *qglLightModelfv) (GLenum pname, const GLfloat *params);
extern void (APIENTRY *qglLightModeli) (GLenum pname, GLint param);
extern void (APIENTRY *qglLightModeliv) (GLenum pname, const GLint *params);
extern void (APIENTRY *qglLightf) (GLenum light, GLenum pname, GLfloat param);
extern void (APIENTRY *qglLightfv) (GLenum light, GLenum pname, const GLfloat *params);
extern void (APIENTRY *qglLighti) (GLenum light, GLenum pname, GLint param);
extern void (APIENTRY *qglLightiv) (GLenum light, GLenum pname, const GLint *params);
extern void (APIENTRY *qglLineStipple) (GLint factor, GLushort pattern);
extern void (APIENTRY *qglLineWidth) (GLfloat width);
extern void (APIENTRY *qglListBase) (GLuint base);
extern void (APIENTRY *qglLoadIdentity) (void);
extern void (APIENTRY *qglLoadMatrixd) (const GLdouble *m);
extern void (APIENTRY *qglLoadMatrixf) (const GLfloat *m);
extern void (APIENTRY *qglLoadName) (GLuint name);
extern void (APIENTRY *qglLogicOp) (GLenum opcode);
extern void (APIENTRY *qglMap1d) (GLenum target, GLdouble u1, GLdouble u2, GLint stride, GLint order, const GLdouble *points);
extern void (APIENTRY *qglMap1f) (GLenum target, GLfloat u1, GLfloat u2, GLint stride, GLint order, const GLfloat *points);
extern void (APIENTRY *qglMap2d) (GLenum target, GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, const GLdouble *points);
extern void (APIENTRY *qglMap2f) (GLenum target, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, const GLfloat *points);
extern void (APIENTRY *qglMapGrid1d) (GLint un, GLdouble u1, GLdouble u2);
extern void (APIENTRY *qglMapGrid1f) (GLint un, GLfloat u1, GLfloat u2);
extern void (APIENTRY *qglMapGrid2d) (GLint un, GLdouble u1, GLdouble u2, GLint vn, GLdouble v1, GLdouble v2);
extern void (APIENTRY *qglMapGrid2f) (GLint un, GLfloat u1, GLfloat u2, GLint vn, GLfloat v1, GLfloat v2);
extern void (APIENTRY *qglMaterialf) (GLenum face, GLenum pname, GLfloat param);
extern void (APIENTRY *qglMaterialfv) (GLenum face, GLenum pname, const GLfloat *params);
extern void (APIENTRY *qglMateriali) (GLenum face, GLenum pname, GLint param);
extern void (APIENTRY *qglMaterialiv) (GLenum face, GLenum pname, const GLint *params);
extern void (APIENTRY *qglMatrixMode) (GLenum mode);
extern void (APIENTRY *qglMultMatrixd) (const GLdouble *m);
extern void (APIENTRY *qglMultMatrixf) (const GLfloat *m);
extern void (APIENTRY *qglNewList) (GLuint list, GLenum mode);
extern void (APIENTRY *qglNormal3b) (GLbyte nx, GLbyte ny, GLbyte nz);
extern void (APIENTRY *qglNormal3bv) (const GLbyte *v);
extern void (APIENTRY *qglNormal3d) (GLdouble nx, GLdouble ny, GLdouble nz);
extern void (APIENTRY *qglNormal3dv) (const GLdouble *v);
extern void (APIENTRY *qglNormal3f) (GLfloat nx, GLfloat ny, GLfloat nz);
extern void (APIENTRY *qglNormal3fv) (const GLfloat *v);
extern void (APIENTRY *qglNormal3i) (GLint nx, GLint ny, GLint nz);
extern void (APIENTRY *qglNormal3iv) (const GLint *v);
extern void (APIENTRY *qglNormal3s) (GLshort nx, GLshort ny, GLshort nz);
extern void (APIENTRY *qglNormal3sv) (const GLshort *v);
extern void (APIENTRY *qglNormalPointer) (GLenum type, GLsizei stride, const GLvoid *pointer);
extern void (APIENTRY *qglOrtho) (GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar);
extern void (APIENTRY *qglPassThrough) (GLfloat token);
extern void (APIENTRY *qglPixelMapfv) (GLenum map, GLsizei mapsize, const GLfloat *values);
extern void (APIENTRY *qglPixelMapuiv) (GLenum map, GLsizei mapsize, const GLuint *values);
extern void (APIENTRY *qglPixelMapusv) (GLenum map, GLsizei mapsize, const GLushort *values);
extern void (APIENTRY *qglPixelStoref) (GLenum pname, GLfloat param);
extern void (APIENTRY *qglPixelStorei) (GLenum pname, GLint param);
extern void (APIENTRY *qglPixelTransferf) (GLenum pname, GLfloat param);
extern void (APIENTRY *qglPixelTransferi) (GLenum pname, GLint param);
extern void (APIENTRY *qglPixelZoom) (GLfloat xfactor, GLfloat yfactor);
extern void (APIENTRY *qglPointSize) (GLfloat size);
extern void (APIENTRY *qglPolygonMode) (GLenum face, GLenum mode);
extern void (APIENTRY *qglPolygonOffset) (GLfloat factor, GLfloat units);
extern void (APIENTRY *qglPolygonStipple) (const GLubyte *mask);
extern void (APIENTRY *qglPopAttrib) (void);
extern void (APIENTRY *qglPopClientAttrib) (void);
extern void (APIENTRY *qglPopMatrix) (void);
extern void (APIENTRY *qglPopName) (void);
extern void (APIENTRY *qglPrioritizeTextures) (GLsizei n, const GLuint *textures, const GLclampf *priorities);
extern void (APIENTRY *qglPushAttrib) (GLbitfield mask);
extern void (APIENTRY *qglPushClientAttrib) (GLbitfield mask);
extern void (APIENTRY *qglPushMatrix) (void);
extern void (APIENTRY *qglPushName) (GLuint name);
extern void (APIENTRY *qglRasterPos2d) (GLdouble x, GLdouble y);
extern void (APIENTRY *qglRasterPos2dv) (const GLdouble *v);
extern void (APIENTRY *qglRasterPos2f) (GLfloat x, GLfloat y);
extern void (APIENTRY *qglRasterPos2fv) (const GLfloat *v);
extern void (APIENTRY *qglRasterPos2i) (GLint x, GLint y);
extern void (APIENTRY *qglRasterPos2iv) (const GLint *v);
extern void (APIENTRY *qglRasterPos2s) (GLshort x, GLshort y);
extern void (APIENTRY *qglRasterPos2sv) (const GLshort *v);
extern void (APIENTRY *qglRasterPos3d) (GLdouble x, GLdouble y, GLdouble z);
extern void (APIENTRY *qglRasterPos3dv) (const GLdouble *v);
extern void (APIENTRY *qglRasterPos3f) (GLfloat x, GLfloat y, GLfloat z);
extern void (APIENTRY *qglRasterPos3fv) (const GLfloat *v);
extern void (APIENTRY *qglRasterPos3i) (GLint x, GLint y, GLint z);
extern void (APIENTRY *qglRasterPos3iv) (const GLint *v);
extern void (APIENTRY *qglRasterPos3s) (GLshort x, GLshort y, GLshort z);
extern void (APIENTRY *qglRasterPos3sv) (const GLshort *v);
extern void (APIENTRY *qglRasterPos4d) (GLdouble x, GLdouble y, GLdouble z, GLdouble w);
extern void (APIENTRY *qglRasterPos4dv) (const GLdouble *v);
extern void (APIENTRY *qglRasterPos4f) (GLfloat x, GLfloat y, GLfloat z, GLfloat w);
extern void (APIENTRY *qglRasterPos4fv) (const GLfloat *v);
extern void (APIENTRY *qglRasterPos4i) (GLint x, GLint y, GLint z, GLint w);
extern void (APIENTRY *qglRasterPos4iv) (const GLint *v);
extern void (APIENTRY *qglRasterPos4s) (GLshort x, GLshort y, GLshort z, GLshort w);
extern void (APIENTRY *qglRasterPos4sv) (const GLshort *v);
extern void (APIENTRY *qglReadBuffer) (GLenum mode);
extern void (APIENTRY *qglReadPixels) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels);
extern void (APIENTRY *qglRectd) (GLdouble x1, GLdouble y1, GLdouble x2, GLdouble y2);
extern void (APIENTRY *qglRectdv) (const GLdouble *v1, const GLdouble *v2);
extern void (APIENTRY *qglRectf) (GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2);
extern void (APIENTRY *qglRectfv) (const GLfloat *v1, const GLfloat *v2);
extern void (APIENTRY *qglRecti) (GLint x1, GLint y1, GLint x2, GLint y2);
extern void (APIENTRY *qglRectiv) (const GLint *v1, const GLint *v2);
extern void (APIENTRY *qglRects) (GLshort x1, GLshort y1, GLshort x2, GLshort y2);
extern void (APIENTRY *qglRectsv) (const GLshort *v1, const GLshort *v2);
extern GLint (APIENTRY *qglRenderMode) (GLenum mode);
extern void (APIENTRY *qglRotated) (GLdouble angle, GLdouble x, GLdouble y, GLdouble z);
extern void (APIENTRY *qglRotatef) (GLfloat angle, GLfloat x, GLfloat y, GLfloat z);
extern void (APIENTRY *qglScaled) (GLdouble x, GLdouble y, GLdouble z);
extern void (APIENTRY *qglScalef) (GLfloat x, GLfloat y, GLfloat z);
extern void (APIENTRY *qglScissor) (GLint x, GLint y, GLsizei width, GLsizei height);
extern void (APIENTRY *qglSelectBuffer) (GLsizei size, GLuint *buffer);
extern void (APIENTRY *qglShadeModel) (GLenum mode);
extern void (APIENTRY *qglStencilFunc) (GLenum func, GLint ref, GLuint mask);
extern void (APIENTRY *qglStencilMask) (GLuint mask);
extern void (APIENTRY *qglStencilOp) (GLenum fail, GLenum zfail, GLenum zpass);
extern void (APIENTRY *qglTexCoord1d) (GLdouble s);
extern void (APIENTRY *qglTexCoord1dv) (const GLdouble *v);
extern void (APIENTRY *qglTexCoord1f) (GLfloat s);
extern void (APIENTRY *qglTexCoord1fv) (const GLfloat *v);
extern void (APIENTRY *qglTexCoord1i) (GLint s);
extern void (APIENTRY *qglTexCoord1iv) (const GLint *v);
extern void (APIENTRY *qglTexCoord1s) (GLshort s);
extern void (APIENTRY *qglTexCoord1sv) (const GLshort *v);
extern void (APIENTRY *qglTexCoord2d) (GLdouble s, GLdouble t);
extern void (APIENTRY *qglTexCoord2dv) (const GLdouble *v);
extern void (APIENTRY *qglTexCoord2f) (GLfloat s, GLfloat t);
extern void (APIENTRY *qglTexCoord2fv) (const GLfloat *v);
extern void (APIENTRY *qglTexCoord2i) (GLint s, GLint t);
extern void (APIENTRY *qglTexCoord2iv) (const GLint *v);
extern void (APIENTRY *qglTexCoord2s) (GLshort s, GLshort t);
extern void (APIENTRY *qglTexCoord2sv) (const GLshort *v);
extern void (APIENTRY *qglTexCoord3d) (GLdouble s, GLdouble t, GLdouble r);
extern void (APIENTRY *qglTexCoord3dv) (const GLdouble *v);
extern void (APIENTRY *qglTexCoord3f) (GLfloat s, GLfloat t, GLfloat r);
extern void (APIENTRY *qglTexCoord3fv) (const GLfloat *v);
extern void (APIENTRY *qglTexCoord3i) (GLint s, GLint t, GLint r);
extern void (APIENTRY *qglTexCoord3iv) (const GLint *v);
extern void (APIENTRY *qglTexCoord3s) (GLshort s, GLshort t, GLshort r);
extern void (APIENTRY *qglTexCoord3sv) (const GLshort *v);
extern void (APIENTRY *qglTexCoord4d) (GLdouble s, GLdouble t, GLdouble r, GLdouble q);
extern void (APIENTRY *qglTexCoord4dv) (const GLdouble *v);
extern void (APIENTRY *qglTexCoord4f) (GLfloat s, GLfloat t, GLfloat r, GLfloat q);
extern void (APIENTRY *qglTexCoord4fv) (const GLfloat *v);
extern void (APIENTRY *qglTexCoord4i) (GLint s, GLint t, GLint r, GLint q);
extern void (APIENTRY *qglTexCoord4iv) (const GLint *v);
extern void (APIENTRY *qglTexCoord4s) (GLshort s, GLshort t, GLshort r, GLshort q);
extern void (APIENTRY *qglTexCoord4sv) (const GLshort *v);
extern void (APIENTRY *qglTexCoordPointer) (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
extern void (APIENTRY *qglTexEnvf) (GLenum target, GLenum pname, GLfloat param);
extern void (APIENTRY *qglTexEnvfv) (GLenum target, GLenum pname, const GLfloat *params);
extern void (APIENTRY *qglTexEnvi) (GLenum target, GLenum pname, GLint param);
extern void (APIENTRY *qglTexEnviv) (GLenum target, GLenum pname, const GLint *params);
extern void (APIENTRY *qglTexGend) (GLenum coord, GLenum pname, GLdouble param);
extern void (APIENTRY *qglTexGendv) (GLenum coord, GLenum pname, const GLdouble *params);
extern void (APIENTRY *qglTexGenf) (GLenum coord, GLenum pname, GLfloat param);
extern void (APIENTRY *qglTexGenfv) (GLenum coord, GLenum pname, const GLfloat *params);
extern void (APIENTRY *qglTexGeni) (GLenum coord, GLenum pname, GLint param);
extern void (APIENTRY *qglTexGeniv) (GLenum coord, GLenum pname, const GLint *params);
extern void (APIENTRY *qglTexImage1D) (GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
extern void (APIENTRY *qglTexImage2D) (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
extern void (APIENTRY *qglTexParameterf) (GLenum target, GLenum pname, GLfloat param);
extern void (APIENTRY *qglTexParameterfv) (GLenum target, GLenum pname, const GLfloat *params);
extern void (APIENTRY *qglTexParameteri) (GLenum target, GLenum pname, GLint param);
extern void (APIENTRY *qglTexParameteriv) (GLenum target, GLenum pname, const GLint *params);
extern void (APIENTRY *qglTexSubImage1D) (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels);
extern void (APIENTRY *qglTexSubImage2D) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels);
extern void (APIENTRY *qglTranslated) (GLdouble x, GLdouble y, GLdouble z);
extern void (APIENTRY *qglTranslatef) (GLfloat x, GLfloat y, GLfloat z);
extern void (APIENTRY *qglVertex2d) (GLdouble x, GLdouble y);
extern void (APIENTRY *qglVertex2dv) (const GLdouble *v);
extern void (APIENTRY *qglVertex2f) (GLfloat x, GLfloat y);
extern void (APIENTRY *qglVertex2fv) (const GLfloat *v);
extern void (APIENTRY *qglVertex2i) (GLint x, GLint y);
extern void (APIENTRY *qglVertex2iv) (const GLint *v);
extern void (APIENTRY *qglVertex2s) (GLshort x, GLshort y);
extern void (APIENTRY *qglVertex2sv) (const GLshort *v);
extern void (APIENTRY *qglVertex3d) (GLdouble x, GLdouble y, GLdouble z);
extern void (APIENTRY *qglVertex3dv) (const GLdouble *v);
extern void (APIENTRY *qglVertex3f) (GLfloat x, GLfloat y, GLfloat z);
extern void (APIENTRY *qglVertex3fv) (const GLfloat *v);
extern void (APIENTRY *qglVertex3i) (GLint x, GLint y, GLint z);
extern void (APIENTRY *qglVertex3iv) (const GLint *v);
extern void (APIENTRY *qglVertex3s) (GLshort x, GLshort y, GLshort z);
extern void (APIENTRY *qglVertex3sv) (const GLshort *v);
extern void (APIENTRY *qglVertex4d) (GLdouble x, GLdouble y, GLdouble z, GLdouble w);
extern void (APIENTRY *qglVertex4dv) (const GLdouble *v);
extern void (APIENTRY *qglVertex4f) (GLfloat x, GLfloat y, GLfloat z, GLfloat w);
extern void (APIENTRY *qglVertex4fv) (const GLfloat *v);
extern void (APIENTRY *qglVertex4i) (GLint x, GLint y, GLint z, GLint w);
extern void (APIENTRY *qglVertex4iv) (const GLint *v);
extern void (APIENTRY *qglVertex4s) (GLshort x, GLshort y, GLshort z, GLshort w);
extern void (APIENTRY *qglVertex4sv) (const GLshort *v);
extern void (APIENTRY *qglVertexPointer) (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
extern void (APIENTRY *qglViewport) (GLint x, GLint y, GLsizei width, GLsizei height);
#ifdef _WIN32
extern BOOL (WINAPI *qwglCopyContext)(HGLRC, HGLRC, UINT);
extern HGLRC (WINAPI *qwglCreateContext)(HDC);
extern HGLRC (WINAPI *qwglCreateLayerContext)(HDC, int);
extern BOOL (WINAPI *qwglDeleteContext)(HGLRC);
extern HGLRC (WINAPI *qwglGetCurrentContext)(VOID);
extern HDC (WINAPI *qwglGetCurrentDC)(VOID);
extern PROC (WINAPI *qwglGetProcAddress)(LPCSTR);
extern BOOL (WINAPI *qwglMakeCurrent)(HDC, HGLRC);
extern BOOL (WINAPI *qSwapBuffers)(HDC);
#endif
#define glAlphaFunc qglAlphaFunc
#define glBlendFunc qglBlendFunc
#define glBegin qglBegin
#define glColor3f qglColor3f
#define glColor4f qglColor4f
#define glColor4ub qglColor4ub
#define glColor4ubv qglColor4ubv
#define glColorMask qglColorMask
#define glClearDepth qglClearDepth
#define glClearStencil qglClearStencil
#define glDisable qglDisable
#define glEnable qglEnable
#define glEnd qglEnd
#define glFlush qglFlush
#define glScalef qglScalef
#define glTranslatef qglTranslatef
#define glGetInteger qglGetInteger
#define glTexCoord1f qglTexCoord1f
#define glTexCoord2f qglTexCoord2f
#define glTexCoord2fv qglTexCoord2fv
#define glTexParameterf qglTexParameterf
#define glNormal3f qglNormal3f
#define glNormal3fv qglNormal3fv
#define glTexParameteri qglTexParameteri
#define glTexImage2D qglTexImage2D
#define glMultMatrixf qglMultMatrixf
#define glGetIntegerv qglGetIntegerv
#define glTexEnvf qglTexEnvf
#define glTexEnvi qglTexEnvi
#define glTexGeni qglTexGeni
#define glVertex2f qglVertex2f
#define glVertex3f qglVertex3f
#define glVertex3fv qglVertex3fv
#define glCullFace qglCullFace
#define glPushMatrix qglPushMatrix
#define glPopMatrix qglPopMatrix
#define glViewport qglViewport
#define glRotatef qglRotatef
#define glShadeModel qglShadeModel
#define glDepthMask qglDepthMask
#define glDepthFunc qglDepthFunc
#define glClearColor qglClearColor
#define glFinish qglFinish
#define glClear qglClear
#define glHint qglHint
#define glDepthRange qglDepthRange
#define glMatrixMode qglMatrixMode
#define glOrtho qglOrtho
#define glDrawBuffer qglDrawBuffer
#define glTexSubImage2D qglTexSubImage2D
#define glGetString qglGetString
#define glPolygonMode qglPolygonMode
#define glReadPixels qglReadPixels
#define glLoadMatrixf qglLoadMatrixf
#define glColor4fv qglColor4fv
#define glFrustum qglFrustum
#define glGetFloatv qglGetFloatv
#define glReadBuffer qglReadBuffer
#define glLoadIdentity qglLoadIdentity
#define glGetTexLevelParameteriv qglGetTexLevelParameteriv
//vertex lists
#define glTexCoordPointer qglTexCoordPointer
#define glVertexPointer qglVertexPointer
#define glNormalPointer qglNormalPointer
#define glColorPointer qglColorPointer
#define glDrawElements qglDrawElements
#define glDisableClientState qglDisableClientState
#define glEnableClientState qglEnableClientState
//stencil functions
#define glStencilOp qglStencilOp
#define glStencilFunc qglStencilFunc
#define glPushAttrib qglPushAttrib
#define glPopAttrib qglPopAttrib
void GL_Init(void *(*getglfunction) (char *name));
#endif
qbyte GetPalette(int red, int green, int blue);
int Mod_ReadFlagsFromMD1(char *name, int md3version);
#ifdef SWQUAKE
#define CYCLE 128 // turbulent cycle size
extern int r_pixbytes;
#define WARP_WIDTH 320
#define WARP_HEIGHT 200
extern cvar_t r_drawflat;
extern int d_spanpixcount;
extern int r_framecount; // sequence # of current frame since Quake
// started
extern qboolean r_drawpolys; // 1 if driver wants clipped polygons
// rather than a span list
extern qboolean r_drawculledpolys; // 1 if driver wants clipped polygons that
// have been culled by the edge list
extern qboolean r_worldpolysbacktofront; // 1 if driver wants polygons
// delivered back to front rather
// than front to back
extern qboolean r_recursiveaffinetriangles; // true if a driver wants to use
// recursive triangular subdivison
// and vertex drawing via
// D_PolysetDrawFinalVerts() past
// a certain distance (normally
// only used by the software
// driver)
extern float r_aliasuvscale; // scale-up factor for screen u and v
// on Alias vertices passed to driver
extern int r_pixbytes;
extern qboolean r_dowarp;
/*extern affinetridesc_t r_affinetridesc;
extern spritedesc_t r_spritedesc;
extern zpointdesc_t r_zpointdesc;
extern polydesc_t r_polydesc;
*/
extern int d_con_indirect; // if 0, Quake will draw console directly
// to vid.buffer; if 1, Quake will
// draw console via D_DrawRect. Must be
// defined by driver
extern vec3_t r_pright, r_pup, r_ppn;
extern float xscaleshrink, yscaleshrink;
#endif

204
engine/gl/glsupp.h Normal file
View file

@ -0,0 +1,204 @@
//gl suppliment for Quake
//contains the extra things that would otherwise be found in glext.h
typedef void (APIENTRY *qlpMTex2FUNC) (GLenum, GLfloat, GLfloat);
typedef void (APIENTRY *qlpMTex3FUNC) (GLenum, GLfloat, GLfloat, GLfloat);
typedef void (APIENTRY *qlpSelTexFUNC) (GLenum);
extern qlpSelTexFUNC qglActiveTextureARB;
extern qlpSelTexFUNC qglClientActiveTextureARB;
extern qlpMTex3FUNC qglMultiTexCoord3fARB;
extern qlpMTex2FUNC qglMultiTexCoord2fARB;
//This stuff is normally supplied in the <GL/glext.h> header file. I don't actually have one of them, so it's here instead.
#if 0 //change to 1 if you do actually have the file in question.
#include <GL/glext.h> //would be ideal.
#else
//#ifndef GL_VERSION_1_2
#define GL_CLAMP_TO_EDGE 0x812F
//#endif
#ifndef GL_ARB_multitexture
#define GL_ARB_multitexture 1
#define GL_TEXTURE0_ARB 0x84C0
#define GL_TEXTURE1_ARB 0x84C1
#define GL_TEXTURE2_ARB 0x84C2
#define GL_TEXTURE3_ARB 0x84C3
#define GL_TEXTURE4_ARB 0x84C4
#define GL_TEXTURE5_ARB 0x84C5
#define GL_TEXTURE6_ARB 0x84C6
#define GL_TEXTURE7_ARB 0x84C7
#define GL_TEXTURE8_ARB 0x84C8
#define GL_TEXTURE9_ARB 0x84C9
#define GL_TEXTURE10_ARB 0x84CA
#define GL_TEXTURE11_ARB 0x84CB
#define GL_TEXTURE12_ARB 0x84CC
#define GL_TEXTURE13_ARB 0x84CD
#define GL_TEXTURE14_ARB 0x84CE
#define GL_TEXTURE15_ARB 0x84CF
#define GL_TEXTURE16_ARB 0x84D0
#define GL_TEXTURE17_ARB 0x84D1
#define GL_TEXTURE18_ARB 0x84D2
#define GL_TEXTURE19_ARB 0x84D3
#define GL_TEXTURE20_ARB 0x84D4
#define GL_TEXTURE21_ARB 0x84D5
#define GL_TEXTURE22_ARB 0x84D6
#define GL_TEXTURE23_ARB 0x84D7
#define GL_TEXTURE24_ARB 0x84D8
#define GL_TEXTURE25_ARB 0x84D9
#define GL_TEXTURE26_ARB 0x84DA
#define GL_TEXTURE27_ARB 0x84DB
#define GL_TEXTURE28_ARB 0x84DC
#define GL_TEXTURE29_ARB 0x84DD
#define GL_TEXTURE30_ARB 0x84DE
#define GL_TEXTURE31_ARB 0x84DF
#define GL_ACTIVE_TEXTURE_ARB 0x84E0
#define GL_CLIENT_ACTIVE_TEXTURE_ARB 0x84E1
#define GL_MAX_TEXTURE_UNITS_ARB 0x84E2
#endif
#ifndef GL_ARB_texture_cube_map
#define GL_ARB_texture_cube_map 1
#define GL_NORMAL_MAP_ARB 0x8511
#define GL_REFLECTION_MAP_ARB 0x8512
#define GL_TEXTURE_CUBE_MAP_ARB 0x8513
#define GL_TEXTURE_BINDING_CUBE_MAP_ARB 0x8514
#define GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB 0x8515
#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB 0x8516
#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB 0x8517
#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB 0x8518
#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB 0x8519
#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB 0x851A
#define GL_PROXY_TEXTURE_CUBE_MAP_ARB 0x851B
#define GL_MAX_CUBE_MAP_TEXTURE_SIZE_ARB 0x851C
#endif
#ifndef GL_EXT_texture3D
#define define GL_EXT_texture3D 1
#define GL_PACK_SKIP_IMAGES 0x806B
#define GL_PACK_SKIP_IMAGES_EXT 0x806B
#define GL_PACK_IMAGE_HEIGHT 0x806C
#define GL_PACK_IMAGE_HEIGHT_EXT 0x806C
#define GL_UNPACK_SKIP_IMAGES 0x806D
#define GL_UNPACK_SKIP_IMAGES_EXT 0x806D
#define GL_UNPACK_IMAGE_HEIGHT 0x806E
#define GL_UNPACK_IMAGE_HEIGHT_EXT 0x806E
#define GL_TEXTURE_3D 0x806F
#define GL_TEXTURE_3D_EXT 0x806F
#define GL_PROXY_TEXTURE_3D 0x8070
#define GL_PROXY_TEXTURE_3D_EXT 0x8070
#define GL_TEXTURE_DEPTH 0x8071
#define GL_TEXTURE_DEPTH_EXT 0x8071
#define GL_TEXTURE_WRAP_R 0x8072
#define GL_TEXTURE_WRAP_R_EXT 0x8072
#define GL_MAX_3D_TEXTURE_SIZE 0x8073
#define GL_MAX_3D_TEXTURE_SIZE_EXT 0x8073
#endif
//some of these were needed.
//They were also not in the ones I could find on the web.
#define GL_COMBINE_ARB 0x8570
#define GL_COMBINE_RGB_ARB 0x8571
#define GL_COMBINE_ALPHA_ARB 0x8572
#define GL_SOURCE0_RGB_ARB 0x8580
#define GL_SOURCE1_RGB_ARB 0x8581
#define GL_SOURCE2_RGB_ARB 0x8582
#define GL_SOURCE0_ALPHA_ARB 0x8588
#define GL_SOURCE1_ALPHA_ARB 0x8589
#define GL_SOURCE2_ALPHA_ARB 0x858A
#define GL_OPERAND0_RGB_ARB 0x8590
#define GL_OPERAND1_RGB_ARB 0x8591
#define GL_OPERAND2_RGB_ARB 0x8592
#define GL_OPERAND0_ALPHA_ARB 0x8598
#define GL_OPERAND1_ALPHA_ARB 0x8599
#define GL_OPERAND2_ALPHA_ARB 0x859A
#define GL_RGB_SCALE_ARB 0x8573
#define GL_ADD_SIGNED_ARB 0x8574
#define GL_INTERPOLATE_ARB 0x8575
#define GL_SUBTRACT_ARB 0x84E7
#define GL_CONSTANT_ARB 0x8576
#define GL_PRIMARY_COLOR_ARB 0x8577
#define GL_PREVIOUS_ARB 0x8578
#define GL_DOT3_RGB_ARB 0x86AE
#define GL_DOT3_RGBA_ARB 0x86AF
/* GL_ARB_texture_compression */
#ifndef GL_ARB_texture_compression
#define GL_ARB_texture_compression 1
#define GL_COMPRESSED_ALPHA_ARB 0x84E9
#define GL_COMPRESSED_LUMINANCE_ARB 0x84EA
#define GL_COMPRESSED_LUMINANCE_ALPHA_ARB 0x84EB
#define GL_COMPRESSED_INTENSITY_ARB 0x84EC
#define GL_COMPRESSED_RGB_ARB 0x84ED
#define GL_COMPRESSED_RGBA_ARB 0x84EE
#define GL_TEXTURE_COMPRESSION_HINT_ARB 0x84EF
#define GL_TEXTURE_COMPRESSED_IMAGE_SIZE_ARB 0x86A0
#define GL_TEXTURE_COMPRESSED_ARB 0x86A1
#define GL_NUM_COMPRESSED_TEXTURE_FORMATS_ARB 0x86A2
#define GL_COMPRESSED_TEXTURE_FORMATS_ARB 0x86A3
typedef void (APIENTRY *PFNGLCOMPRESSEDTEXIMAGE3DARBPROC) (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid* data);
typedef void (APIENTRY *PFNGLCOMPRESSEDTEXIMAGE2DARBPROC) (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid* data);
typedef void (APIENTRY *PFNGLCOMPRESSEDTEXIMAGE1DARBPROC) (GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLsizei imageSize, const GLvoid* data);
typedef void (APIENTRY *PFNGLCOMPRESSEDTEXSUBIMAGE3DARBPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid* data);
typedef void (APIENTRY *PFNGLCOMPRESSEDTEXSUBIMAGE2DARBPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid* data);
typedef void (APIENTRY *PFNGLCOMPRESSEDTEXSUBIMAGE1DARBPROC) (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const GLvoid* data);
typedef void (APIENTRY *PFNGLGETCOMPRESSEDTEXIMAGEARBPROC) (GLenum target, GLint lod, const GLvoid* img);
#endif /* GL_ARB_texture_compression */
#ifndef GL_ATI_pn_triangles //ati truform
#define GL_PN_TRIANGLES_ATI 0x87F0
#define GL_MAX_PN_TRIANGLES_TESSELATION_LEVEL_ATI 0x87F1
#define GL_PN_TRIANGLES_POINT_MODE_ATI 0x87F2
#define GL_PN_TRIANGLES_NORMAL_MODE_ATI 0x87F3
#define GL_PN_TRIANGLES_TESSELATION_LEVEL_ATI 0x87F4
#define GL_PN_TRIANGLES_POINT_MODE_LINEAR_ATI 0x87F5
#define GL_PN_TRIANGLES_POINT_MODE_CUBIC_ATI 0x87F6
#define GL_PN_TRIANGLES_NORMAL_MODE_LINEAR_ATI 0x87F7
#define GL_PN_TRIANGLES_NORMAL_MODE_QUADRATIC_ATI 0x87F8
typedef void (APIENTRY *PFNGLPNTRIANGLESIATIPROC)(GLenum pname, GLint param);
typedef void (APIENTRY *PFNGLPNTRIANGLESFATIPROC)(GLenum pname, GLfloat param);
#endif
#ifndef GL_EXT_stencil_two_side
#define GL_EXT_stencil_two_side 1
#define GL_STENCIL_TEST_TWO_SIDE_EXT 0x8910
#define GL_ACTIVE_STENCIL_FACE_EXT 0x8911
typedef void (APIENTRY * PFNGLACTIVESTENCILFACEEXTPROC) (GLenum face);
#endif
#ifndef GL_EXT_stencil_wrap
#define GL_EXT_stencil_wrap 1
#define GL_INCR_WRAP_EXT 0x8507
#define GL_DECR_WRAP_EXT 0x8508
#endif
#ifndef GL_EXT_texture_filter_anisotropic
#define GL_EXT_texture_filter_anisotropic 1
#define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE
#define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x84FF
#endif
#endif