GL3: added missing source files and stubs of most functions

still no 3D rendering, but in theory it should be able to load models,
bsps etc, just not render them yet.

also moved/copied md2.c and sp2.c to gl/ and gl3/ because they use
renderer-specific types
This commit is contained in:
Daniel Gibson 2017-01-29 05:21:27 +01:00
parent ebbb675cb8
commit 0b35ceabdc
20 changed files with 5120 additions and 174 deletions

View file

@ -823,9 +823,9 @@ REFGL_OBJS_ := \
src/client/refresh/gl/r_surf.o \
src/client/refresh/gl/r_warp.o \
src/client/refresh/gl/r_sdl.o \
src/client/refresh/files/md2.o \
src/client/refresh/gl/r_md2.o \
src/client/refresh/gl/r_sp2.o \
src/client/refresh/files/pcx.o \
src/client/refresh/files/sp2.o \
src/client/refresh/files/stb.o \
src/client/refresh/files/wal.o \
src/common/shared/flash.o \
@ -845,12 +845,18 @@ endif
REFGL3_OBJS_ := \
src/client/refresh/gl3/gl3_draw.o \
src/client/refresh/gl3/gl3_image.o \
src/client/refresh/gl3/gl3_light.o \
src/client/refresh/gl3/gl3_lightmap.o \
src/client/refresh/gl3/gl3_main.o \
src/client/refresh/gl3/gl3_mesh.o \
src/client/refresh/gl3/gl3_misc.o \
src/client/refresh/gl3/gl3_model.o \
src/client/refresh/gl3/gl3_sdl.o \
src/client/refresh/gl3/gl3_surf.o \
src/client/refresh/gl3/gl3_warp.o \
src/client/refresh/gl3/gl3_shaders.o \
src/client/refresh/gl3/gl3_md2.o \
src/client/refresh/gl3/gl3_sp2.o \
src/client/refresh/files/pcx.o \
src/client/refresh/files/stb.o \
src/client/refresh/files/wal.o \
@ -858,13 +864,6 @@ REFGL3_OBJS_ := \
src/common/shared/rand.o \
src/common/shared/shared.o
# TODO: filetype support for gl3 renderer - can we reuse same code?
REFGL3_TODO_ := \
src/client/refresh/files/md2.o \
src/client/refresh/files/pcx.o \
src/client/refresh/files/sp2.o
# TODO: glad_dbg support
REFGL3_OBJS_ += \
src/client/refresh/gl3/glad/src/glad.o

View file

@ -65,7 +65,6 @@
#define BLOCK_WIDTH 128
#define BLOCK_HEIGHT 128
#define REF_VERSION "Yamagi Quake II OpenGL Refresher"
#define MAX_LBM_HEIGHT 480
#define BACKFACE_EPSILON 0.01
#define LIGHTMAP_BYTES 4
#define MAX_LIGHTMAPS 128

View file

@ -1627,6 +1627,8 @@ RI_BeginFrame(float camera_separation)
/* go into 2D mode */
// FIXME: just call R_SetGL2D();
int x, w, y, h;
qboolean drawing_left_eye = gl_state.camera_separation < 0;
qboolean stereo_split_tb = ((gl_state.stereo_mode == STEREO_SPLIT_VERTICAL) && gl_state.camera_separation);

View file

@ -300,11 +300,7 @@ GL3_Draw_FadeScreen(void)
void
GL3_Draw_StretchRaw(int x, int y, int w, int h, int cols, int rows, byte *data)
{
byte *source;
float hscale = 1.0f;
int frac, fracstep;
int i, j, trows;
int row;
int i, j;
GL3_Bind(0);

View file

@ -88,6 +88,7 @@ GL3_TextureMode(char *string)
ri.Cvar_SetValue("gl_anisotropic", 0.0);
}
STUB_ONCE("TODO: fix existing textures' modes!");
#if 0 // TODO!
gl3image_t *glt;

View file

@ -0,0 +1,699 @@
/*
* Copyright (C) 1997-2001 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.
*
* =======================================================================
*
* Lightmaps and dynamic lighting
*
* =======================================================================
*/
#include "header/local.h"
#define DLIGHT_CUTOFF 64
static int r_dlightframecount;
vec3_t pointcolor;
cplane_t *lightplane; /* used as shadow plane */
vec3_t lightspot;
static float s_blocklights[34 * 34 * 3];
static void
RenderDlight(dlight_t *light)
{
STUB_ONCE("TODO: Implement!");
#if 0
int i, j;
float a;
float rad;
rad = light->intensity * 0.35;
GLfloat vtx[3*18];
GLfloat clr[4*18];
unsigned int index_vtx = 4;
unsigned int index_clr = 0;
glEnableClientState( GL_VERTEX_ARRAY );
glEnableClientState( GL_COLOR_ARRAY );
clr[index_clr++] = light->color [ 0 ] * 0.2;
clr[index_clr++] = light->color [ 1 ] * 0.2;
clr[index_clr++] = light->color [ 2 ] * 0.2;
clr[index_clr++] = 1;
for ( i = 0; i < 3; i++ )
{
vtx [ i ] = light->origin [ i ] - vpn [ i ] * rad;
}
for ( i = 16; i >= 0; i-- )
{
clr[index_clr++] = 0;
clr[index_clr++] = 0;
clr[index_clr++] = 0;
clr[index_clr++] = 1;
a = i / 16.0 * M_PI * 2;
for ( j = 0; j < 3; j++ )
{
vtx[index_vtx++] = light->origin [ j ] + vright [ j ] * cos( a ) * rad
+ vup [ j ] * sin( a ) * rad;
}
}
glVertexPointer( 3, GL_FLOAT, 0, vtx );
glColorPointer( 4, GL_FLOAT, 0, clr );
glDrawArrays( GL_TRIANGLE_FAN, 0, 18 );
glDisableClientState( GL_VERTEX_ARRAY );
glDisableClientState( GL_COLOR_ARRAY );
#endif // 0
}
void
GL3_RenderDlights(void)
{
STUB_ONCE("TODO: Implement!");
#if 0
int i;
dlight_t *l;
if (!gl_flashblend->value)
{
return;
}
/* because the count hasn't advanced yet for this frame */
r_dlightframecount = r_framecount + 1;
glDepthMask(0);
glDisable(GL_TEXTURE_2D);
glShadeModel(GL_SMOOTH);
glEnable(GL_BLEND);
glBlendFunc(GL_ONE, GL_ONE);
l = r_newrefdef.dlights;
for (i = 0; i < r_newrefdef.num_dlights; i++, l++)
{
RenderDlight(l);
}
glColor4f(1, 1, 1, 1);
glDisable(GL_BLEND);
glEnable(GL_TEXTURE_2D);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glDepthMask(1);
#endif // 0
}
void
GL3_MarkLights(dlight_t *light, int bit, mnode_t *node)
{
cplane_t *splitplane;
float dist;
msurface_t *surf;
int i;
int sidebit;
if (node->contents != -1)
{
return;
}
splitplane = node->plane;
dist = DotProduct(light->origin, splitplane->normal) - splitplane->dist;
if (dist > light->intensity - DLIGHT_CUTOFF)
{
GL3_MarkLights(light, bit, node->children[0]);
return;
}
if (dist < -light->intensity + DLIGHT_CUTOFF)
{
GL3_MarkLights(light, bit, node->children[1]);
return;
}
/* mark the polygons */
surf = gl3_worldmodel->surfaces + node->firstsurface;
for (i = 0; i < node->numsurfaces; i++, surf++)
{
dist = DotProduct(light->origin, surf->plane->normal) - surf->plane->dist;
if (dist >= 0)
{
sidebit = 0;
}
else
{
sidebit = SURF_PLANEBACK;
}
if ((surf->flags & SURF_PLANEBACK) != sidebit)
{
continue;
}
if (surf->dlightframe != r_dlightframecount)
{
surf->dlightbits = 0;
surf->dlightframe = r_dlightframecount;
}
surf->dlightbits |= bit;
}
GL3_MarkLights(light, bit, node->children[0]);
GL3_MarkLights(light, bit, node->children[1]);
}
void
GL3_PushDlights(void)
{
int i;
dlight_t *l;
if (gl_flashblend->value)
{
return;
}
/* because the count hasn't advanced yet for this frame */
r_dlightframecount = gl3_framecount + 1;
l = gl3_newrefdef.dlights;
for (i = 0; i < gl3_newrefdef.num_dlights; i++, l++)
{
GL3_MarkLights(l, 1 << i, gl3_worldmodel->nodes);
}
}
static int
RecursiveLightPoint(mnode_t *node, vec3_t start, vec3_t end)
{
float front, back, frac;
int side;
cplane_t *plane;
vec3_t mid;
msurface_t *surf;
int s, t, ds, dt;
int i;
mtexinfo_t *tex;
byte *lightmap;
int maps;
int r;
if (node->contents != -1)
{
return -1; /* didn't hit anything */
}
/* calculate mid point */
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 RecursiveLightPoint(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 = RecursiveLightPoint(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 = gl3_worldmodel->surfaces + node->firstsurface;
for (i = 0; i < node->numsurfaces; i++, surf++)
{
if (surf->flags & (SURF_DRAWTURB | SURF_DRAWSKY))
{
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;
VectorCopy(vec3_origin, pointcolor);
if (lightmap)
{
vec3_t scale;
lightmap += 3 * (dt * ((surf->extents[0] >> 4) + 1) + ds);
for (maps = 0; maps < MAXLIGHTMAPS && surf->styles[maps] != 255;
maps++)
{
for (i = 0; i < 3; i++)
{
scale[i] = gl_modulate->value *
gl3_newrefdef.lightstyles[surf->styles[maps]].rgb[i];
}
pointcolor[0] += lightmap[0] * scale[0] * (1.0 / 255);
pointcolor[1] += lightmap[1] * scale[1] * (1.0 / 255);
pointcolor[2] += lightmap[2] * scale[2] * (1.0 / 255);
lightmap += 3 * ((surf->extents[0] >> 4) + 1) *
((surf->extents[1] >> 4) + 1);
}
}
return 1;
}
/* go down back side */
return RecursiveLightPoint(node->children[!side], mid, end);
}
void
GL3_LightPoint(vec3_t p, vec3_t color)
{
vec3_t end;
float r;
int lnum;
dlight_t *dl;
vec3_t dist;
float add;
if (!gl3_worldmodel->lightdata)
{
color[0] = color[1] = color[2] = 1.0;
return;
}
end[0] = p[0];
end[1] = p[1];
end[2] = p[2] - 2048;
r = RecursiveLightPoint(gl3_worldmodel->nodes, p, end);
if (r == -1)
{
VectorCopy(vec3_origin, color);
}
else
{
VectorCopy(pointcolor, color);
}
/* add dynamic lights */
dl = gl3_newrefdef.dlights;
for (lnum = 0; lnum < gl3_newrefdef.num_dlights; lnum++, dl++)
{
VectorSubtract(currententity->origin,
dl->origin, dist);
add = dl->intensity - VectorLength(dist);
add *= (1.0 / 256);
if (add > 0)
{
VectorMA(color, add, dl->color, color);
}
}
VectorScale(color, gl_modulate->value, color);
}
static void
AddDynamicLights(msurface_t *surf)
{
int lnum;
int sd, td;
float fdist, frad, fminlight;
vec3_t impact, local;
int s, t;
int i;
int smax, tmax;
mtexinfo_t *tex;
dlight_t *dl;
float *pfBL;
float fsacc, ftacc;
smax = (surf->extents[0] >> 4) + 1;
tmax = (surf->extents[1] >> 4) + 1;
tex = surf->texinfo;
for (lnum = 0; lnum < gl3_newrefdef.num_dlights; lnum++)
{
if (!(surf->dlightbits & (1 << lnum)))
{
continue; /* not lit by this light */
}
dl = &gl3_newrefdef.dlights[lnum];
frad = dl->intensity;
fdist = DotProduct(dl->origin, surf->plane->normal) -
surf->plane->dist;
frad -= fabs(fdist);
/* rad is now the highest intensity on the plane */
fminlight = DLIGHT_CUTOFF;
if (frad < fminlight)
{
continue;
}
fminlight = frad - fminlight;
for (i = 0; i < 3; i++)
{
impact[i] = dl->origin[i] -
surf->plane->normal[i] * fdist;
}
local[0] = DotProduct(impact,
tex->vecs[0]) + tex->vecs[0][3] - surf->texturemins[0];
local[1] = DotProduct(impact,
tex->vecs[1]) + tex->vecs[1][3] - surf->texturemins[1];
pfBL = s_blocklights;
for (t = 0, ftacc = 0; t < tmax; t++, ftacc += 16)
{
td = local[1] - ftacc;
if (td < 0)
{
td = -td;
}
for (s = 0, fsacc = 0; s < smax; s++, fsacc += 16, pfBL += 3)
{
sd = Q_ftol(local[0] - fsacc);
if (sd < 0)
{
sd = -sd;
}
if (sd > td)
{
fdist = sd + (td >> 1);
}
else
{
fdist = td + (sd >> 1);
}
if (fdist < fminlight)
{
pfBL[0] += (frad - fdist) * dl->color[0];
pfBL[1] += (frad - fdist) * dl->color[1];
pfBL[2] += (frad - fdist) * dl->color[2];
}
}
}
}
}
void
GL3_SetCacheState(msurface_t *surf)
{
int maps;
for (maps = 0; maps < MAXLIGHTMAPS && surf->styles[maps] != 255; maps++)
{
surf->cached_light[maps] =
gl3_newrefdef.lightstyles[surf->styles[maps]].white;
}
}
/*
* Combine and scale multiple lightmaps into the floating format in blocklights
*/
void
GL3_BuildLightMap(msurface_t *surf, byte *dest, int stride)
{
int smax, tmax;
int r, g, b, a, max;
int i, j, size;
byte *lightmap;
float scale[4];
int nummaps;
float *bl;
if (surf->texinfo->flags &
(SURF_SKY | SURF_TRANS33 | SURF_TRANS66 | SURF_WARP))
{
ri.Sys_Error(ERR_DROP, "R_BuildLightMap called for non-lit surface");
}
smax = (surf->extents[0] >> 4) + 1;
tmax = (surf->extents[1] >> 4) + 1;
size = smax * tmax;
if (size > (sizeof(s_blocklights) >> 4))
{
ri.Sys_Error(ERR_DROP, "Bad s_blocklights size");
}
/* set to full bright if no light data */
if (!surf->samples)
{
for (i = 0; i < size * 3; i++)
{
s_blocklights[i] = 255;
}
goto store;
}
/* count the # of maps */
for (nummaps = 0; nummaps < MAXLIGHTMAPS && surf->styles[nummaps] != 255;
nummaps++)
{
}
lightmap = surf->samples;
/* add all the lightmaps */
if (nummaps == 1)
{
int maps;
for (maps = 0; maps < MAXLIGHTMAPS && surf->styles[maps] != 255; maps++)
{
bl = s_blocklights;
for (i = 0; i < 3; i++)
{
scale[i] = gl_modulate->value *
gl3_newrefdef.lightstyles[surf->styles[maps]].rgb[i];
}
if ((scale[0] == 1.0F) &&
(scale[1] == 1.0F) &&
(scale[2] == 1.0F))
{
for (i = 0; i < size; i++, bl += 3)
{
bl[0] = lightmap[i * 3 + 0];
bl[1] = lightmap[i * 3 + 1];
bl[2] = lightmap[i * 3 + 2];
}
}
else
{
for (i = 0; i < size; i++, bl += 3)
{
bl[0] = lightmap[i * 3 + 0] * scale[0];
bl[1] = lightmap[i * 3 + 1] * scale[1];
bl[2] = lightmap[i * 3 + 2] * scale[2];
}
}
lightmap += size * 3; /* skip to next lightmap */
}
}
else
{
int maps;
memset(s_blocklights, 0, sizeof(s_blocklights[0]) * size * 3);
for (maps = 0; maps < MAXLIGHTMAPS && surf->styles[maps] != 255; maps++)
{
bl = s_blocklights;
for (i = 0; i < 3; i++)
{
scale[i] = gl_modulate->value *
gl3_newrefdef.lightstyles[surf->styles[maps]].rgb[i];
}
if ((scale[0] == 1.0F) &&
(scale[1] == 1.0F) &&
(scale[2] == 1.0F))
{
for (i = 0; i < size; i++, bl += 3)
{
bl[0] += lightmap[i * 3 + 0];
bl[1] += lightmap[i * 3 + 1];
bl[2] += lightmap[i * 3 + 2];
}
}
else
{
for (i = 0; i < size; i++, bl += 3)
{
bl[0] += lightmap[i * 3 + 0] * scale[0];
bl[1] += lightmap[i * 3 + 1] * scale[1];
bl[2] += lightmap[i * 3 + 2] * scale[2];
}
}
lightmap += size * 3; /* skip to next lightmap */
}
}
/* add all the dynamic lights */
if (surf->dlightframe == gl3_framecount)
{
AddDynamicLights(surf);
}
store:
stride -= (smax << 2);
bl = s_blocklights;
for (i = 0; i < tmax; i++, dest += stride)
{
for (j = 0; j < smax; j++)
{
r = Q_ftol(bl[0]);
g = Q_ftol(bl[1]);
b = Q_ftol(bl[2]);
/* catch negative lights */
if (r < 0)
{
r = 0;
}
if (g < 0)
{
g = 0;
}
if (b < 0)
{
b = 0;
}
/* determine the brightest of the three color components */
if (r > g)
{
max = r;
}
else
{
max = g;
}
if (b > max)
{
max = b;
}
/* alpha is ONLY used for the mono lightmap case. For this
reason we set it to the brightest of the color components
so that things don't get too dim. */
a = max;
/* rescale all the color components if the
intensity of the greatest channel exceeds
1.0 */
if (max > 255)
{
float t = 255.0F / max;
r = r * t;
g = g * t;
b = b * t;
a = a * t;
}
dest[0] = r;
dest[1] = g;
dest[2] = b;
dest[3] = a;
bl += 3;
dest += 4;
}
}
}

View file

@ -0,0 +1,297 @@
/*
* Copyright (C) 1997-2001 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.
*
* =======================================================================
*
* Lightmap handling
*
* =======================================================================
*/
#include "header/local.h"
#define TEXNUM_LIGHTMAPS 1024
extern gl3lightmapstate_t gl3_lms;
void
GL3_LM_InitBlock(void)
{
memset(gl3_lms.allocated, 0, sizeof(gl3_lms.allocated));
}
void
GL3_LM_UploadBlock(qboolean dynamic)
{
STUB_ONCE("TODO: Implement!");
#if 0
int texture;
int height = 0;
if (dynamic)
{
texture = 0;
}
else
{
texture = gl3_lms.current_lightmap_texture;
}
GL3_Bind(gl3state.lightmap_textures + texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
if (dynamic)
{
int i;
for (i = 0; i < BLOCK_WIDTH; i++)
{
if (gl3_lms.allocated[i] > height)
{
height = gl3_lms.allocated[i];
}
}
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, BLOCK_WIDTH,
height, GL_LIGHTMAP_FORMAT, GL_UNSIGNED_BYTE,
gl3_lms.lightmap_buffer);
}
else
{
gl3_lms.internal_format = GL_LIGHTMAP_FORMAT;
glTexImage2D(GL_TEXTURE_2D, 0, gl3_lms.internal_format,
BLOCK_WIDTH, BLOCK_HEIGHT, 0, GL_LIGHTMAP_FORMAT,
GL_UNSIGNED_BYTE, gl3_lms.lightmap_buffer);
if (++gl3_lms.current_lightmap_texture == MAX_LIGHTMAPS)
{
ri.Sys_Error(ERR_DROP,
"LM_UploadBlock() - MAX_LIGHTMAPS exceeded\n");
}
}
#endif // 0
}
/*
* returns a texture number and the position inside it
*/
qboolean
GL3_LM_AllocBlock(int w, int h, int *x, int *y)
{
int i, j;
int best, best2;
best = BLOCK_HEIGHT;
for (i = 0; i < BLOCK_WIDTH - w; i++)
{
best2 = 0;
for (j = 0; j < w; j++)
{
if (gl3_lms.allocated[i + j] >= best)
{
break;
}
if (gl3_lms.allocated[i + j] > best2)
{
best2 = gl3_lms.allocated[i + j];
}
}
if (j == w)
{
/* this is a valid spot */
*x = i;
*y = best = best2;
}
}
if (best + h > BLOCK_HEIGHT)
{
return false;
}
for (i = 0; i < w; i++)
{
gl3_lms.allocated[*x + i] = best + h;
}
return true;
}
void
GL3_LM_BuildPolygonFromSurface(msurface_t *fa)
{
int i, lindex, lnumverts;
medge_t *pedges, *r_pedge;
float *vec;
float s, t;
glpoly_t *poly;
vec3_t total;
/* reconstruct the polygon */
pedges = currentmodel->edges;
lnumverts = fa->numedges;
VectorClear(total);
/* draw texture */
poly = Hunk_Alloc(sizeof(glpoly_t) +
(lnumverts - 4) * VERTEXSIZE * sizeof(float));
poly->next = fa->polys;
poly->flags = fa->flags;
fa->polys = poly;
poly->numverts = lnumverts;
for (i = 0; i < lnumverts; i++)
{
lindex = currentmodel->surfedges[fa->firstedge + i];
if (lindex > 0)
{
r_pedge = &pedges[lindex];
vec = currentmodel->vertexes[r_pedge->v[0]].position;
}
else
{
r_pedge = &pedges[-lindex];
vec = currentmodel->vertexes[r_pedge->v[1]].position;
}
s = DotProduct(vec, fa->texinfo->vecs[0]) + fa->texinfo->vecs[0][3];
s /= fa->texinfo->image->width;
t = DotProduct(vec, fa->texinfo->vecs[1]) + fa->texinfo->vecs[1][3];
t /= fa->texinfo->image->height;
VectorAdd(total, vec, total);
VectorCopy(vec, poly->verts[i]);
poly->verts[i][3] = s;
poly->verts[i][4] = t;
/* lightmap texture coordinates */
s = DotProduct(vec, fa->texinfo->vecs[0]) + fa->texinfo->vecs[0][3];
s -= fa->texturemins[0];
s += fa->light_s * 16;
s += 8;
s /= BLOCK_WIDTH * 16; /* fa->texinfo->texture->width; */
t = DotProduct(vec, fa->texinfo->vecs[1]) + fa->texinfo->vecs[1][3];
t -= fa->texturemins[1];
t += fa->light_t * 16;
t += 8;
t /= BLOCK_HEIGHT * 16; /* fa->texinfo->texture->height; */
poly->verts[i][5] = s;
poly->verts[i][6] = t;
}
poly->numverts = lnumverts;
}
void
GL3_LM_CreateSurfaceLightmap(msurface_t *surf)
{
int smax, tmax;
byte *base;
if (surf->flags & (SURF_DRAWSKY | SURF_DRAWTURB))
{
return;
}
smax = (surf->extents[0] >> 4) + 1;
tmax = (surf->extents[1] >> 4) + 1;
if (!GL3_LM_AllocBlock(smax, tmax, &surf->light_s, &surf->light_t))
{
GL3_LM_UploadBlock(false);
GL3_LM_InitBlock();
if (!GL3_LM_AllocBlock(smax, tmax, &surf->light_s, &surf->light_t))
{
ri.Sys_Error(ERR_FATAL, "Consecutive calls to LM_AllocBlock(%d,%d) failed\n",
smax, tmax);
}
}
surf->lightmaptexturenum = gl3_lms.current_lightmap_texture;
base = gl3_lms.lightmap_buffer;
base += (surf->light_t * BLOCK_WIDTH + surf->light_s) * LIGHTMAP_BYTES;
GL3_SetCacheState(surf);
GL3_BuildLightMap(surf, base, BLOCK_WIDTH * LIGHTMAP_BYTES);
}
void
GL3_LM_BeginBuildingLightmaps(gl3model_t *m)
{
static lightstyle_t lightstyles[MAX_LIGHTSTYLES];
int i;
unsigned dummy[128 * 128];
memset(gl3_lms.allocated, 0, sizeof(gl3_lms.allocated));
gl3_framecount = 1; /* no dlightcache */
/* setup the base lightstyles so the lightmaps
won't have to be regenerated the first time
they're seen */
for (i = 0; i < MAX_LIGHTSTYLES; i++)
{
lightstyles[i].rgb[0] = 1;
lightstyles[i].rgb[1] = 1;
lightstyles[i].rgb[2] = 1;
lightstyles[i].white = 3;
}
gl3_newrefdef.lightstyles = lightstyles;
STUB_ONCE("TODO: IMPLEMENT!");
#if 0
if (!gl_state.lightmap_textures)
{
gl3state.lightmap_textures = TEXNUM_LIGHTMAPS;
}
gl3_lms.current_lightmap_texture = 1;
gl3_lms.internal_format = GL_LIGHTMAP_FORMAT;
/* initialize the dynamic lightmap texture */
GL3_Bind(gl_state.lightmap_textures + 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, gl3_lms.internal_format,
BLOCK_WIDTH, BLOCK_HEIGHT, 0, GL_LIGHTMAP_FORMAT,
GL_UNSIGNED_BYTE, dummy);
#endif // 0
}
void
GL3_LM_EndBuildingLightmaps(void)
{
GL3_LM_UploadBlock(false);
}

View file

@ -45,6 +45,24 @@ unsigned gl3_rawpalette[256];
refdef_t gl3_newrefdef;
viddef_t vid;
gl3model_t *gl3_worldmodel;
gl3model_t *currentmodel;
entity_t *currententity;
float gl3depthmin=0.0f, gl3depthmax=1.0f;
cplane_t frustum[4];
/* view origin */
vec3_t vup;
vec3_t vpn;
vec3_t vright;
vec3_t gl3_origin;
int gl3_visframecount; /* bumped when going to a new PVS */
int gl3_framecount; /* used for dlight push checking */
int c_brush_polys, c_alias_polys;
int gl3_viewcluster, gl3_viewcluster2, gl3_oldviewcluster, gl3_oldviewcluster2;
@ -57,15 +75,48 @@ cvar_t *gl_customwidth;
cvar_t *gl_customheight;
cvar_t *vid_gamma;
cvar_t *gl_anisotropic;
cvar_t *gl_texturemode;
cvar_t *gl_drawbuffer;
cvar_t *gl_clear;
cvar_t *gl_lefthand;
cvar_t *gl_farsee;
cvar_t *intensity;
cvar_t *gl_lightlevel;
cvar_t *gl_overbrightbits;
cvar_t *gl_norefresh;
cvar_t *gl_nolerp_list;
cvar_t *gl_nobind;
cvar_t *gl_lockpvs;
cvar_t *gl_novis;
cvar_t *gl_cull;
cvar_t *gl_zfix;
cvar_t *gl_fullbright;
cvar_t *gl_flashblend;
cvar_t *gl_modulate;
cvar_t *gl_lightmap;
cvar_t *gl_shadows; // TODO: do we really need 2 cvars for shadows here?
cvar_t *gl_stencilshadow;
cvar_t *gl3_debugcontext;
void
GL3_RotateForEntity(entity_t *e)
{
STUB_ONCE("TODO: Implement for OpenGL3!");
#if 0
glTranslatef(e->origin[0], e->origin[1], e->origin[2]);
glRotatef(e->angles[1], 0, 0, 1);
glRotatef(-e->angles[0], 0, 1, 0);
glRotatef(-e->angles[2], 1, 0, 0);
#endif // 0
}
static void
GL3_Strings(void)
{
@ -88,6 +139,10 @@ GL3_Strings(void)
static void
GL3_Register(void)
{
gl_lefthand = ri.Cvar_Get("hand", "0", CVAR_USERINFO | CVAR_ARCHIVE);
gl_farsee = ri.Cvar_Get("gl_farsee", "0", CVAR_LATCH | CVAR_ARCHIVE);
gl_drawbuffer = ri.Cvar_Get("gl_drawbuffer", "GL_BACK", 0);
gl_swapinterval = ri.Cvar_Get("gl_swapinterval", "1", CVAR_ARCHIVE);
gl_msaa_samples = ri.Cvar_Get ( "gl_msaa_samples", "0", CVAR_ARCHIVE );
gl_retexturing = ri.Cvar_Get("gl_retexturing", "1", CVAR_ARCHIVE);
@ -97,27 +152,44 @@ GL3_Register(void)
gl_customheight = ri.Cvar_Get("gl_customheight", "768", CVAR_ARCHIVE);
gl_norefresh = ri.Cvar_Get("gl_norefresh", "0", 0);
gl_fullbright = ri.Cvar_Get("gl_fullbright", "0", 0);
/* don't bilerp characters and crosshairs */
gl_nolerp_list = ri.Cvar_Get("gl_nolerp_list", "pics/conchars.pcx pics/ch1.pcx pics/ch2.pcx pics/ch3.pcx", 0);
gl_nobind = ri.Cvar_Get("gl_nobind", "0", 0);
gl_texturemode = ri.Cvar_Get("gl_texturemode", "GL_LINEAR_MIPMAP_NEAREST", CVAR_ARCHIVE);
gl_anisotropic = ri.Cvar_Get("gl_anisotropic", "0", CVAR_ARCHIVE);
vid_fullscreen = ri.Cvar_Get("vid_fullscreen", "0", CVAR_ARCHIVE);
vid_gamma = ri.Cvar_Get("vid_gamma", "1.0", CVAR_ARCHIVE);
intensity = ri.Cvar_Get("intensity", "1.0", CVAR_ARCHIVE);
gl_lightlevel = ri.Cvar_Get("gl_lightlevel", "0", 0);
gl_overbrightbits = ri.Cvar_Get("gl_overbrightbits", "0", CVAR_ARCHIVE);
gl_lightmap = ri.Cvar_Get("gl_lightmap", "0", 0);
gl_shadows = ri.Cvar_Get("gl_shadows", "0", CVAR_ARCHIVE);
gl_stencilshadow = ri.Cvar_Get("gl_stencilshadow", "0", CVAR_ARCHIVE);
gl_flashblend = ri.Cvar_Get("gl_flashblend", "0", 0);
gl_modulate = ri.Cvar_Get("gl_modulate", "1", CVAR_ARCHIVE);
gl_zfix = ri.Cvar_Get("gl_zfix", "0", 0);
gl_clear = ri.Cvar_Get("gl_clear", "0", 0);
gl_cull = ri.Cvar_Get("gl_cull", "1", 0);
gl_lockpvs = ri.Cvar_Get("gl_lockpvs", "0", 0);
gl_novis = ri.Cvar_Get("gl_novis", "0", 0);
#if 0 // TODO!
gl_lefthand = ri.Cvar_Get("hand", "0", CVAR_USERINFO | CVAR_ARCHIVE);
gl_farsee = ri.Cvar_Get("gl_farsee", "0", CVAR_LATCH | CVAR_ARCHIVE);
//gl_lefthand = ri.Cvar_Get("hand", "0", CVAR_USERINFO | CVAR_ARCHIVE);
//gl_farsee = ri.Cvar_Get("gl_farsee", "0", CVAR_LATCH | CVAR_ARCHIVE);
//gl_norefresh = ri.Cvar_Get("gl_norefresh", "0", 0);
gl_fullbright = ri.Cvar_Get("gl_fullbright", "0", 0);
//gl_fullbright = ri.Cvar_Get("gl_fullbright", "0", 0);
gl_drawentities = ri.Cvar_Get("gl_drawentities", "1", 0);
gl_drawworld = ri.Cvar_Get("gl_drawworld", "1", 0);
gl_novis = ri.Cvar_Get("gl_novis", "0", 0);
gl_lerpmodels = ri.Cvar_Get("gl_lerpmodels", "1", 0);
//gl_novis = ri.Cvar_Get("gl_novis", "0", 0);
//gl_lerpmodels = ri.Cvar_Get("gl_lerpmodels", "1", 0); NOTE: screw this, it looks horrible without
gl_speeds = ri.Cvar_Get("gl_speeds", "0", 0);
gl_lightlevel = ri.Cvar_Get("gl_lightlevel", "0", 0);
@ -130,34 +202,34 @@ GL3_Register(void)
gl_particle_att_b = ri.Cvar_Get("gl_particle_att_b", "0.0", CVAR_ARCHIVE);
gl_particle_att_c = ri.Cvar_Get("gl_particle_att_c", "0.01", CVAR_ARCHIVE);
gl_modulate = ri.Cvar_Get("gl_modulate", "1", CVAR_ARCHIVE);
//gl_modulate = ri.Cvar_Get("gl_modulate", "1", CVAR_ARCHIVE);
//gl_mode = ri.Cvar_Get("gl_mode", "4", CVAR_ARCHIVE);
gl_lightmap = ri.Cvar_Get("gl_lightmap", "0", 0);
gl_shadows = ri.Cvar_Get("gl_shadows", "0", CVAR_ARCHIVE);
gl_stencilshadow = ri.Cvar_Get("gl_stencilshadow", "0", CVAR_ARCHIVE);
//gl_lightmap = ri.Cvar_Get("gl_lightmap", "0", 0);
//gl_shadows = ri.Cvar_Get("gl_shadows", "0", CVAR_ARCHIVE);
//gl_stencilshadow = ri.Cvar_Get("gl_stencilshadow", "0", CVAR_ARCHIVE);
gl_dynamic = ri.Cvar_Get("gl_dynamic", "1", 0);
//gl_nobind = ri.Cvar_Get("gl_nobind", "0", 0);
gl_round_down = ri.Cvar_Get("gl_round_down", "1", 0);
gl_picmip = ri.Cvar_Get("gl_picmip", "0", 0);
gl_showtris = ri.Cvar_Get("gl_showtris", "0", 0);
gl_ztrick = ri.Cvar_Get("gl_ztrick", "0", 0);
gl_zfix = ri.Cvar_Get("gl_zfix", "0", 0);
//gl_ztrick = ri.Cvar_Get("gl_ztrick", "0", 0); NOTE: dump this.
//gl_zfix = ri.Cvar_Get("gl_zfix", "0", 0);
gl_finish = ri.Cvar_Get("gl_finish", "0", CVAR_ARCHIVE);
gl_clear = ri.Cvar_Get("gl_clear", "0", 0);
gl_cull = ri.Cvar_Get("gl_cull", "1", 0);
// gl_cull = ri.Cvar_Get("gl_cull", "1", 0);
gl_polyblend = ri.Cvar_Get("gl_polyblend", "1", 0);
gl_flashblend = ri.Cvar_Get("gl_flashblend", "0", 0);
//gl_flashblend = ri.Cvar_Get("gl_flashblend", "0", 0);
gl_texturemode = ri.Cvar_Get("gl_texturemode", "GL_LINEAR_MIPMAP_NEAREST", CVAR_ARCHIVE);
//gl_texturemode = ri.Cvar_Get("gl_texturemode", "GL_LINEAR_MIPMAP_NEAREST", CVAR_ARCHIVE);
gl_texturealphamode = ri.Cvar_Get("gl_texturealphamode", "default", CVAR_ARCHIVE);
gl_texturesolidmode = ri.Cvar_Get("gl_texturesolidmode", "default", CVAR_ARCHIVE);
//gl_anisotropic = ri.Cvar_Get("gl_anisotropic", "0", CVAR_ARCHIVE);
gl_lockpvs = ri.Cvar_Get("gl_lockpvs", "0", 0);
//gl_lockpvs = ri.Cvar_Get("gl_lockpvs", "0", 0);
gl_palettedtexture = ri.Cvar_Get("gl_palettedtexture", "0", CVAR_ARCHIVE);
//gl_palettedtexture = ri.Cvar_Get("gl_palettedtexture", "0", CVAR_ARCHIVE); NOPE.
gl_pointparameters = ri.Cvar_Get("gl_pointparameters", "1", CVAR_ARCHIVE);
gl_drawbuffer = ri.Cvar_Get("gl_drawbuffer", "GL_BACK", 0);
//gl_drawbuffer = ri.Cvar_Get("gl_drawbuffer", "GL_BACK", 0);
//gl_swapinterval = ri.Cvar_Get("gl_swapinterval", "1", CVAR_ARCHIVE);
gl_saturatelighting = ri.Cvar_Get("gl_saturatelighting", "0", 0);
@ -285,13 +357,12 @@ GL3_SetMode(void)
static qboolean
GL3_Init(void)
{
/* TODO!
int j;
extern float r_turbsin[256];
extern float gl3_turbsin[256];
for (j = 0; j < 256; j++)
{
r_turbsin[j] *= 0.5;
}*/
gl3_turbsin[j] *= 0.5;
}
Swap_Init(); // FIXME: for fucks sake, this doesn't have to be done at runtime!
@ -430,23 +501,125 @@ GL3_Shutdown(void)
GL3_ShutdownWindow(false);
}
static void
GL3_DrawEntitiesOnList(void)
{
STUB_ONCE("TODO: Implement!");
#if 0
int i;
/*
if (!gl_drawentities->value)
{
return;
}
*/
/* draw non-transparent first */
for (i = 0; i < gl3_newrefdef.num_entities; i++)
{
currententity = &gl3_newrefdef.entities[i];
if (currententity->flags & RF_TRANSLUCENT)
{
continue; /* solid */
}
if (currententity->flags & RF_BEAM)
{
R_DrawBeam(currententity);
}
else
{
currentmodel = currententity->model;
if (!currentmodel)
{
R_DrawNullModel();
continue;
}
switch (currentmodel->type)
{
case mod_alias:
GL3_DrawAliasModel(currententity);
break;
case mod_brush:
R_DrawBrushModel(currententity);
break;
case mod_sprite:
R_DrawSpriteModel(currententity);
break;
default:
ri.Sys_Error(ERR_DROP, "Bad modeltype");
break;
}
}
}
/* draw transparent entities
we could sort these if it ever
becomes a problem... */
glDepthMask(0);
for (i = 0; i < gl3_newrefdef.num_entities; i++)
{
currententity = &gl3_newrefdef.entities[i];
if (!(currententity->flags & RF_TRANSLUCENT))
{
continue; /* solid */
}
if (currententity->flags & RF_BEAM)
{
R_DrawBeam(currententity);
}
else
{
currentmodel = currententity->model;
if (!currentmodel)
{
R_DrawNullModel();
continue;
}
switch (currentmodel->type)
{
case mod_alias:
R_DrawAliasModel(currententity);
break;
case mod_brush:
R_DrawBrushModel(currententity);
break;
case mod_sprite:
R_DrawSpriteModel(currententity);
break;
default:
ri.Sys_Error(ERR_DROP, "Bad modeltype");
break;
}
}
}
glDepthMask(1); /* back to writing */
#endif // 0
}
static void
GL3_SetGL2D(void)
{
int x, w, y, h;
int x = 0;
int w = vid.width;
int y = 0;
int h = vid.height;
#if 0 // TODO: stereo
/* set 2D virtual screen size */
qboolean drawing_left_eye = gl_state.camera_separation < 0;
qboolean stereo_split_tb = ((gl_state.stereo_mode == STEREO_SPLIT_VERTICAL) && gl_state.camera_separation);
qboolean stereo_split_lr = ((gl_state.stereo_mode == STEREO_SPLIT_HORIZONTAL) && gl_state.camera_separation);
#endif // 0
x = 0;
w = vid.width;
y = 0;
h = vid.height;
#if 0 // TODO: stereo
if(stereo_split_lr) {
w = w / 2;
x = drawing_left_eye ? 0 : w;
@ -467,23 +640,14 @@ GL3_SetGL2D(void)
glUseProgram(gl3state.si2D.shaderProgram);
glUniformMatrix4fv(gl3state.si2D.uniTransMatrix , 1, GL_FALSE, transMatr.Elements[0]);
// FIXME: change to GL3 code!
#if 0
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, vid.width, vid.height, 0, -99999, 99999);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
#endif // 0
glDisable(GL_DEPTH_TEST);
glDisable(GL_CULL_FACE);
glDisable(GL_BLEND);
// glColor4f(1, 1, 1, 1);
// glColor4f(1, 1, 1, 1); // FIXME: change to GL3 code!
}
/*
* r_newrefdef must be set before the first call
* gl3_newrefdef must be set before the first call
*/
static void
GL3_RenderView(refdef_t *fd)
@ -638,7 +802,7 @@ GL3_RenderView(refdef_t *fd)
R_DrawEntitiesOnList();
R_RenderDlights();
GL3_RenderDlights();
R_DrawParticles();
@ -707,7 +871,7 @@ GL3_SetLightLevel(void)
#if 0 // TODO!
/* save off light value for server to look at */
R_LightPoint(r_newrefdef.vieworg, shadelight);
R_LightPoint(gl3_newrefdef.vieworg, shadelight);
/* pick the greatest component, which should be the
* same as the mono value returned by software */
@ -736,6 +900,7 @@ GL3_SetLightLevel(void)
#endif // 0
}
static void
GL3_RenderFrame(refdef_t *fd)
{
@ -744,27 +909,68 @@ GL3_RenderFrame(refdef_t *fd)
GL3_SetGL2D();
}
static void
GL3_Clear(void)
{
// Check whether the stencil buffer needs clearing, and do so if need be.
GLbitfield stencilFlags = 0;
#if 0 // TODO: stereo stuff
if (gl3state.stereo_mode >= STEREO_MODE_ROW_INTERLEAVED && gl_state.stereo_mode <= STEREO_MODE_PIXEL_INTERLEAVED) {
glClearStencil(0);
stencilFlags |= GL_STENCIL_BUFFER_BIT;
}
#endif // 0
if (gl_clear->value)
{
glClear(GL_COLOR_BUFFER_BIT | stencilFlags | GL_DEPTH_BUFFER_BIT);
}
else
{
glClear(GL_DEPTH_BUFFER_BIT | stencilFlags);
}
gl3depthmin = 0;
gl3depthmax = 1;
glDepthFunc(GL_LEQUAL);
glDepthRange(gl3depthmin, gl3depthmax);
if (gl_zfix->value)
{
if (gl3depthmax > gl3depthmin)
{
glPolygonOffset(0.05, 1);
}
else
{
glPolygonOffset(-0.05, -1);
}
}
/* stencilbuffer shadows */
if (gl_shadows->value && have_stencil && gl_stencilshadow->value)
{
glClearStencil(1);
glClear(GL_STENCIL_BUFFER_BIT);
}
glClear(GL_COLOR_BUFFER_BIT); // TODO: I added this and the next line - keep?
glClearColor(0.5, 0.5, 1, 0.5);
}
void
GL3_BeginFrame(float camera_separation)
{
STUB_ONCE("TODO: Implement!");
/*
glClearColor(0, 0, 0, 0); // FIXME: not sure this should stay
glClear(GL_COLOR_BUFFER_BIT);
glClearColor(1, 0, 0.5, 0.5);
GL3_SetGL2D();
if (vid_gamma->modified || intensity->modified)
{
vid_gamma->modified = false;
intensity->modified = false;
GL3_SetGammaAndIntensity();
}
#if 0
gl_state.camera_separation = camera_separation;
*/
/* change modes if necessary */
if (gl_mode->modified)
@ -772,6 +978,8 @@ GL3_BeginFrame(float camera_separation)
vid_fullscreen->modified = true;
}
#if 0 // TODO: stereo stuff
gl_state.camera_separation = camera_separation;
// force a vid_restart if gl_stereo has been modified.
if ( gl_state.stereo_mode != gl_stereo->value ) {
// If we've gone from one mode to another with the same special buffer requirements there's no need to restart.
@ -781,20 +989,17 @@ GL3_BeginFrame(float camera_separation)
else
{
R_Printf(PRINT_ALL, "stereo supermode changed, restarting video!\n");
cvar_t *ref;
ref = ri.Cvar_Get("vid_fullscreen", "0", CVAR_ARCHIVE);
ref->modified = true;
vid_fullscreen->modified = true;
}
}
#endif // 0
if (vid_gamma->modified)
if (vid_gamma->modified || intensity->modified)
{
vid_gamma->modified = false;
intensity->modified = false;
if (gl_state.hwgamma)
{
UpdateHardwareGamma();
}
GL3_SetGammaAndIntensity();
}
// Clamp overbrightbits
@ -814,44 +1019,15 @@ GL3_BeginFrame(float camera_separation)
/* go into 2D mode */
int x, w, y, h;
qboolean drawing_left_eye = gl_state.camera_separation < 0;
qboolean stereo_split_tb = ((gl_state.stereo_mode == STEREO_SPLIT_VERTICAL) && gl_state.camera_separation);
qboolean stereo_split_lr = ((gl_state.stereo_mode == STEREO_SPLIT_HORIZONTAL) && gl_state.camera_separation);
x = 0;
w = vid.width;
y = 0;
h = vid.height;
if(stereo_split_lr) {
w = w / 2;
x = drawing_left_eye ? 0 : w;
}
if(stereo_split_tb) {
h = h / 2;
y = drawing_left_eye ? h : 0;
}
glViewport(x, y, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, vid.width, vid.height, 0, -99999, 99999);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glDisable(GL_DEPTH_TEST);
glDisable(GL_CULL_FACE);
glDisable(GL_BLEND);
glEnable(GL_ALPHA_TEST);
glColor4f(1, 1, 1, 1);
GL3_SetGL2D();
/* draw buffer stuff */
if (gl_drawbuffer->modified)
{
gl_drawbuffer->modified = false;
if ((gl_state.camera_separation == 0) || gl_state.stereo_mode != STEREO_MODE_OPENGL)
// TODO: stereo stuff
//if ((gl3state.camera_separation == 0) || gl3state.stereo_mode != STEREO_MODE_OPENGL)
{
if (Q_stricmp(gl_drawbuffer->string, "GL_FRONT") == 0)
{
@ -865,13 +1041,15 @@ GL3_BeginFrame(float camera_separation)
}
/* texturemode stuff */
if (gl_texturemode->modified || (gl_config.anisotropic && gl_anisotropic->modified))
if (gl_texturemode->modified || (gl3config.anisotropic && gl_anisotropic->modified))
{
R_TextureMode(gl_texturemode->string);
GL3_TextureMode(gl_texturemode->string);
gl_texturemode->modified = false;
gl_anisotropic->modified = false;
}
STUB_ONCE("TODO: texture-alpha/solid-mode stuff??")
#if 0
if (gl_texturealphamode->modified)
{
R_TextureAlphaMode(gl_texturealphamode->string);
@ -883,10 +1061,10 @@ GL3_BeginFrame(float camera_separation)
R_TextureSolidMode(gl_texturesolidmode->string);
gl_texturesolidmode->modified = false;
}
#endif // 0
/* clear screen if desired */
R_Clear();
#endif // 0
GL3_Clear();
}
static void

View file

@ -0,0 +1,163 @@
/*
* Copyright (C) 1997-2001 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.
*
* =======================================================================
*
* MD2 file format
*
* =======================================================================
*/
#include "header/local.h"
void
GL3_LoadMD2(gl3model_t *mod, void *buffer)
{
int i, j;
dmdl_t *pinmodel, *pheader;
dstvert_t *pinst, *poutst;
dtriangle_t *pintri, *pouttri;
daliasframe_t *pinframe, *poutframe;
int *pincmd, *poutcmd;
int version;
pinmodel = (dmdl_t *)buffer;
version = LittleLong(pinmodel->version);
if (version != ALIAS_VERSION)
{
ri.Sys_Error(ERR_DROP, "%s has wrong version number (%i should be %i)",
mod->name, version, ALIAS_VERSION);
}
pheader = Hunk_Alloc(LittleLong(pinmodel->ofs_end));
/* byte swap the header fields and sanity check */
for (i = 0; i < sizeof(dmdl_t) / 4; i++)
{
((int *)pheader)[i] = LittleLong(((int *)buffer)[i]);
}
if (pheader->skinheight > MAX_LBM_HEIGHT)
{
ri.Sys_Error(ERR_DROP, "model %s has a skin taller than %d", mod->name,
MAX_LBM_HEIGHT);
}
if (pheader->num_xyz <= 0)
{
ri.Sys_Error(ERR_DROP, "model %s has no vertices", mod->name);
}
if (pheader->num_xyz > MAX_VERTS)
{
ri.Sys_Error(ERR_DROP, "model %s has too many vertices", mod->name);
}
if (pheader->num_st <= 0)
{
ri.Sys_Error(ERR_DROP, "model %s has no st vertices", mod->name);
}
if (pheader->num_tris <= 0)
{
ri.Sys_Error(ERR_DROP, "model %s has no triangles", mod->name);
}
if (pheader->num_frames <= 0)
{
ri.Sys_Error(ERR_DROP, "model %s has no frames", mod->name);
}
/* load base s and t vertices (not used in gl version) */
pinst = (dstvert_t *)((byte *)pinmodel + pheader->ofs_st);
poutst = (dstvert_t *)((byte *)pheader + pheader->ofs_st);
for (i = 0; i < pheader->num_st; i++)
{
poutst[i].s = LittleShort(pinst[i].s);
poutst[i].t = LittleShort(pinst[i].t);
}
/* load triangle lists */
pintri = (dtriangle_t *)((byte *)pinmodel + pheader->ofs_tris);
pouttri = (dtriangle_t *)((byte *)pheader + pheader->ofs_tris);
for (i = 0; i < pheader->num_tris; i++)
{
for (j = 0; j < 3; j++)
{
pouttri[i].index_xyz[j] = LittleShort(pintri[i].index_xyz[j]);
pouttri[i].index_st[j] = LittleShort(pintri[i].index_st[j]);
}
}
/* load the frames */
for (i = 0; i < pheader->num_frames; i++)
{
pinframe = (daliasframe_t *)((byte *)pinmodel
+ pheader->ofs_frames + i * pheader->framesize);
poutframe = (daliasframe_t *)((byte *)pheader
+ pheader->ofs_frames + i * pheader->framesize);
memcpy(poutframe->name, pinframe->name, sizeof(poutframe->name));
for (j = 0; j < 3; j++)
{
poutframe->scale[j] = LittleFloat(pinframe->scale[j]);
poutframe->translate[j] = LittleFloat(pinframe->translate[j]);
}
/* verts are all 8 bit, so no swapping needed */
memcpy(poutframe->verts, pinframe->verts,
pheader->num_xyz * sizeof(dtrivertx_t));
}
mod->type = mod_alias;
/* load the glcmds */
pincmd = (int *)((byte *)pinmodel + pheader->ofs_glcmds);
poutcmd = (int *)((byte *)pheader + pheader->ofs_glcmds);
for (i = 0; i < pheader->num_glcmds; i++)
{
poutcmd[i] = LittleLong(pincmd[i]);
}
/* register all skins */
memcpy((char *)pheader + pheader->ofs_skins,
(char *)pinmodel + pheader->ofs_skins,
pheader->num_skins * MAX_SKINNAME);
for (i = 0; i < pheader->num_skins; i++)
{
mod->skins[i] = GL3_FindImage(
(char *)pheader + pheader->ofs_skins + i * MAX_SKINNAME,
it_skin);
}
mod->mins[0] = -32;
mod->mins[1] = -32;
mod->mins[2] = -32;
mod->maxs[0] = 32;
mod->maxs[1] = 32;
mod->maxs[2] = 32;
}

View file

@ -0,0 +1,817 @@
/*
* Copyright (C) 1997-2001 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.
*
* =======================================================================
*
* Mesh handling
*
* =======================================================================
*/
#include "header/local.h"
#define NUMVERTEXNORMALS 162
#define SHADEDOT_QUANT 16
static float r_avertexnormals[NUMVERTEXNORMALS][3] = {
#include "../constants/anorms.h"
};
/* precalculated dot products for quantized angles */
static float r_avertexnormal_dots[SHADEDOT_QUANT][256] =
#include "../constants/anormtab.h"
;
typedef float vec4_t[4];
static vec4_t s_lerped[MAX_VERTS];
vec3_t shadevector;
float shadelight[3];
float *shadedots = r_avertexnormal_dots[0];
extern vec3_t lightspot;
extern qboolean have_stencil;
static void
LerpVerts(int nverts, dtrivertx_t *v, dtrivertx_t *ov,
dtrivertx_t *verts, float *lerp, float move[3],
float frontv[3], float backv[3])
{
int i;
if (currententity->flags &
(RF_SHELL_RED | RF_SHELL_GREEN |
RF_SHELL_BLUE | RF_SHELL_DOUBLE |
RF_SHELL_HALF_DAM))
{
for (i = 0; i < nverts; i++, v++, ov++, lerp += 4)
{
float *normal = r_avertexnormals[verts[i].lightnormalindex];
lerp[0] = move[0] + ov->v[0] * backv[0] + v->v[0] * frontv[0] +
normal[0] * POWERSUIT_SCALE;
lerp[1] = move[1] + ov->v[1] * backv[1] + v->v[1] * frontv[1] +
normal[1] * POWERSUIT_SCALE;
lerp[2] = move[2] + ov->v[2] * backv[2] + v->v[2] * frontv[2] +
normal[2] * POWERSUIT_SCALE;
}
}
else
{
for (i = 0; i < nverts; i++, v++, ov++, lerp += 4)
{
lerp[0] = move[0] + ov->v[0] * backv[0] + v->v[0] * frontv[0];
lerp[1] = move[1] + ov->v[1] * backv[1] + v->v[1] * frontv[1];
lerp[2] = move[2] + ov->v[2] * backv[2] + v->v[2] * frontv[2];
}
}
}
/*
* Interpolates between two frames and origins
*/
static void
DrawAliasFrameLerp(dmdl_t *paliashdr, float backlerp)
{
unsigned short total;
GLenum type;
float l;
daliasframe_t *frame, *oldframe;
dtrivertx_t *v, *ov, *verts;
int *order;
int count;
float frontlerp;
float alpha;
vec3_t move, delta, vectors[3];
vec3_t frontv, backv;
int i;
int index_xyz;
float *lerp;
frame = (daliasframe_t *)((byte *)paliashdr + paliashdr->ofs_frames
+ currententity->frame * paliashdr->framesize);
verts = v = frame->verts;
oldframe = (daliasframe_t *)((byte *)paliashdr + paliashdr->ofs_frames
+ currententity->oldframe * paliashdr->framesize);
ov = oldframe->verts;
order = (int *)((byte *)paliashdr + paliashdr->ofs_glcmds);
if (currententity->flags & RF_TRANSLUCENT)
{
alpha = currententity->alpha;
}
else
{
alpha = 1.0;
}
if (currententity->flags &
(RF_SHELL_RED | RF_SHELL_GREEN | RF_SHELL_BLUE | RF_SHELL_DOUBLE |
RF_SHELL_HALF_DAM))
{
//glDisable(GL_TEXTURE_2D);
STUB_ONCE("TODO: OpenGL: use color-only shader!");
}
frontlerp = 1.0 - backlerp;
/* move should be the delta back to the previous frame * backlerp */
VectorSubtract(currententity->oldorigin, currententity->origin, delta);
AngleVectors(currententity->angles, vectors[0], vectors[1], vectors[2]);
move[0] = DotProduct(delta, vectors[0]); /* forward */
move[1] = -DotProduct(delta, vectors[1]); /* left */
move[2] = DotProduct(delta, vectors[2]); /* up */
VectorAdd(move, oldframe->translate, move);
for (i = 0; i < 3; i++)
{
move[i] = backlerp * move[i] + frontlerp * frame->translate[i];
}
for (i = 0; i < 3; i++)
{
frontv[i] = frontlerp * frame->scale[i];
backv[i] = backlerp * oldframe->scale[i];
}
lerp = s_lerped[0];
LerpVerts(paliashdr->num_xyz, v, ov, verts, lerp, move, frontv, backv);
while (1)
{
/* get the vertex count and primitive type */
count = *order++;
if (!count)
{
break; /* done */
}
if (count < 0)
{
count = -count;
type = GL_TRIANGLE_FAN;
}
else
{
type = GL_TRIANGLE_STRIP;
}
total = count;
GLfloat vtx[3*total];
GLfloat tex[2*total];
GLfloat clr[4 * total];
unsigned int index_vtx = 0;
unsigned int index_tex = 0;
unsigned int index_clr = 0;
if (currententity->flags &
(RF_SHELL_RED | RF_SHELL_GREEN | RF_SHELL_BLUE))
{
do
{
index_xyz = order[2];
order += 3;
clr[index_clr++] = shadelight[0];
clr[index_clr++] = shadelight[1];
clr[index_clr++] = shadelight[2];
clr[index_clr++] = alpha;
vtx[index_vtx++] = s_lerped[index_xyz][0];
vtx[index_vtx++] = s_lerped[index_xyz][1];
vtx[index_vtx++] = s_lerped[index_xyz][2];
}
while (--count);
}
else
{
do
{
/* texture coordinates come from the draw list */
tex[index_tex++] = ((float *) order)[0];
tex[index_tex++] = ((float *) order)[1];
index_xyz = order[2];
order += 3;
/* normals and vertexes come from the frame list */
l = shadedots[verts[index_xyz].lightnormalindex];
clr[index_clr++] = l * shadelight[0];
clr[index_clr++] = l * shadelight[1];
clr[index_clr++] = l * shadelight[2];
clr[index_clr++] = alpha;
vtx[index_vtx++] = s_lerped[index_xyz][0];
vtx[index_vtx++] = s_lerped[index_xyz][1];
vtx[index_vtx++] = s_lerped[index_xyz][2];
}
while (--count);
}
STUB_ONCE("TODO: OpenGL!");
#if 0
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, vtx);
glTexCoordPointer(2, GL_FLOAT, 0, tex);
glColorPointer(4, GL_FLOAT, 0, clr);
glDrawArrays(type, 0, total);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
#endif // 0
}
if (currententity->flags &
(RF_SHELL_RED | RF_SHELL_GREEN | RF_SHELL_BLUE |
RF_SHELL_DOUBLE | RF_SHELL_HALF_DAM))
{
STUB_ONCE("TODO: OpenGL: use textured shader!");
//glEnable(GL_TEXTURE_2D);
}
}
static void
DrawAliasShadow(dmdl_t *paliashdr, int posenum)
{
unsigned short total;
GLenum type;
int *order;
vec3_t point;
float height = 0, lheight;
int count;
lheight = currententity->origin[2] - lightspot[2];
order = (int *)((byte *)paliashdr + paliashdr->ofs_glcmds);
height = -lheight + 0.1f;
/* stencilbuffer shadows */
STUB_ONCE("TODO: OpenGL: stencil shadows!");
#if 0
if (have_stencil && gl_stencilshadow->value)
{
glEnable(GL_STENCIL_TEST);
glStencilFunc(GL_EQUAL, 1, 2);
glStencilOp(GL_KEEP, GL_KEEP, GL_INCR);
}
#endif // 0
while (1)
{
/* get the vertex count and primitive type */
count = *order++;
if (!count)
{
break; /* done */
}
if (count < 0)
{
count = -count;
type = GL_TRIANGLE_FAN;
}
else
{
type = GL_TRIANGLE_STRIP;
}
total = count;
GLfloat vtx[3*total];
unsigned int index_vtx = 0;
do
{
/* normals and vertexes come from the frame list */
memcpy(point, s_lerped[order[2]], sizeof(point));
point[0] -= shadevector[0] * (point[2] + lheight);
point[1] -= shadevector[1] * (point[2] + lheight);
point[2] = height;
vtx[index_vtx++] = point [ 0 ];
vtx[index_vtx++] = point [ 1 ];
vtx[index_vtx++] = point [ 2 ];
order += 3;
}
while (--count);
STUB_ONCE("TODO: OpenGL!");
#if 0
glEnableClientState( GL_VERTEX_ARRAY );
glVertexPointer( 3, GL_FLOAT, 0, vtx );
glDrawArrays( type, 0, total );
glDisableClientState( GL_VERTEX_ARRAY );
#endif // 0
}
/* stencilbuffer shadows */
if (have_stencil && gl_stencilshadow->value)
{
STUB_ONCE("TODO: OpenGL: stencil shadows!");
//glDisable(GL_STENCIL_TEST);
}
}
static qboolean
CullAliasModel(vec3_t bbox[8], entity_t *e)
{
int i;
vec3_t mins, maxs;
dmdl_t *paliashdr;
vec3_t vectors[3];
vec3_t thismins, oldmins, thismaxs, oldmaxs;
daliasframe_t *pframe, *poldframe;
vec3_t angles;
paliashdr = (dmdl_t *)currentmodel->extradata;
if ((e->frame >= paliashdr->num_frames) || (e->frame < 0))
{
R_Printf(PRINT_DEVELOPER, "R_CullAliasModel %s: no such frame %d\n",
currentmodel->name, e->frame);
e->frame = 0;
}
if ((e->oldframe >= paliashdr->num_frames) || (e->oldframe < 0))
{
R_Printf(PRINT_DEVELOPER, "R_CullAliasModel %s: no such oldframe %d\n",
currentmodel->name, e->oldframe);
e->oldframe = 0;
}
pframe = (daliasframe_t *)((byte *)paliashdr + paliashdr->ofs_frames +
e->frame * paliashdr->framesize);
poldframe = (daliasframe_t *)((byte *)paliashdr + paliashdr->ofs_frames +
e->oldframe * paliashdr->framesize);
/* compute axially aligned mins and maxs */
if (pframe == poldframe)
{
for (i = 0; i < 3; i++)
{
mins[i] = pframe->translate[i];
maxs[i] = mins[i] + pframe->scale[i] * 255;
}
}
else
{
for (i = 0; i < 3; i++)
{
thismins[i] = pframe->translate[i];
thismaxs[i] = thismins[i] + pframe->scale[i] * 255;
oldmins[i] = poldframe->translate[i];
oldmaxs[i] = oldmins[i] + poldframe->scale[i] * 255;
if (thismins[i] < oldmins[i])
{
mins[i] = thismins[i];
}
else
{
mins[i] = oldmins[i];
}
if (thismaxs[i] > oldmaxs[i])
{
maxs[i] = thismaxs[i];
}
else
{
maxs[i] = oldmaxs[i];
}
}
}
/* compute a full bounding box */
for (i = 0; i < 8; i++)
{
vec3_t tmp;
if (i & 1)
{
tmp[0] = mins[0];
}
else
{
tmp[0] = maxs[0];
}
if (i & 2)
{
tmp[1] = mins[1];
}
else
{
tmp[1] = maxs[1];
}
if (i & 4)
{
tmp[2] = mins[2];
}
else
{
tmp[2] = maxs[2];
}
VectorCopy(tmp, bbox[i]);
}
/* rotate the bounding box */
VectorCopy(e->angles, angles);
angles[YAW] = -angles[YAW];
AngleVectors(angles, vectors[0], vectors[1], vectors[2]);
for (i = 0; i < 8; i++)
{
vec3_t tmp;
VectorCopy(bbox[i], tmp);
bbox[i][0] = DotProduct(vectors[0], tmp);
bbox[i][1] = -DotProduct(vectors[1], tmp);
bbox[i][2] = DotProduct(vectors[2], tmp);
VectorAdd(e->origin, bbox[i], bbox[i]);
}
int p, f, aggregatemask = ~0;
for (p = 0; p < 8; p++)
{
int mask = 0;
for (f = 0; f < 4; f++)
{
float dp = DotProduct(frustum[f].normal, bbox[p]);
if ((dp - frustum[f].dist) < 0)
{
mask |= (1 << f);
}
}
aggregatemask &= mask;
}
if (aggregatemask)
{
return true;
}
return false;
}
void
GL3_DrawAliasModel(entity_t *e)
{
int i;
dmdl_t *paliashdr;
float an;
vec3_t bbox[8];
gl3image_t *skin;
if (!(e->flags & RF_WEAPONMODEL))
{
if (CullAliasModel(bbox, e))
{
return;
}
}
if (e->flags & RF_WEAPONMODEL)
{
if (gl_lefthand->value == 2)
{
return;
}
}
paliashdr = (dmdl_t *)currentmodel->extradata;
/* get lighting information */
if (currententity->flags &
(RF_SHELL_HALF_DAM | RF_SHELL_GREEN | RF_SHELL_RED |
RF_SHELL_BLUE | RF_SHELL_DOUBLE))
{
VectorClear(shadelight);
if (currententity->flags & RF_SHELL_HALF_DAM)
{
shadelight[0] = 0.56;
shadelight[1] = 0.59;
shadelight[2] = 0.45;
}
if (currententity->flags & RF_SHELL_DOUBLE)
{
shadelight[0] = 0.9;
shadelight[1] = 0.7;
}
if (currententity->flags & RF_SHELL_RED)
{
shadelight[0] = 1.0;
}
if (currententity->flags & RF_SHELL_GREEN)
{
shadelight[1] = 1.0;
}
if (currententity->flags & RF_SHELL_BLUE)
{
shadelight[2] = 1.0;
}
}
else if (currententity->flags & RF_FULLBRIGHT)
{
for (i = 0; i < 3; i++)
{
shadelight[i] = 1.0;
}
}
else
{
GL3_LightPoint(currententity->origin, shadelight);
/* player lighting hack for communication back to server */
if (currententity->flags & RF_WEAPONMODEL)
{
/* pick the greatest component, which should be
the same as the mono value returned by software */
if (shadelight[0] > shadelight[1])
{
if (shadelight[0] > shadelight[2])
{
gl_lightlevel->value = 150 * shadelight[0];
}
else
{
gl_lightlevel->value = 150 * shadelight[2];
}
}
else
{
if (shadelight[1] > shadelight[2])
{
gl_lightlevel->value = 150 * shadelight[1];
}
else
{
gl_lightlevel->value = 150 * shadelight[2];
}
}
}
}
if (currententity->flags & RF_MINLIGHT)
{
for (i = 0; i < 3; i++)
{
if (shadelight[i] > 0.1)
{
break;
}
}
if (i == 3)
{
shadelight[0] = 0.1;
shadelight[1] = 0.1;
shadelight[2] = 0.1;
}
}
if (currententity->flags & RF_GLOW)
{
/* bonus items will pulse with time */
float scale;
float min;
scale = 0.1 * sin(gl3_newrefdef.time * 7);
for (i = 0; i < 3; i++)
{
min = shadelight[i] * 0.8;
shadelight[i] += scale;
if (shadelight[i] < min)
{
shadelight[i] = min;
}
}
}
// Apply gl_overbrightbits to the mesh. If we don't do this they will appear slightly dimmer relative to walls.
if (gl_overbrightbits->value)
{
for (i = 0; i < 3; ++i)
{
shadelight[i] *= gl_overbrightbits->value;
}
}
/* ir goggles color override */
if ((gl3_newrefdef.rdflags & RDF_IRGOGGLES) && (currententity->flags & RF_IR_VISIBLE))
{
shadelight[0] = 1.0;
shadelight[1] = 0.0;
shadelight[2] = 0.0;
}
shadedots = r_avertexnormal_dots[((int)(currententity->angles[1] *
(SHADEDOT_QUANT / 360.0))) & (SHADEDOT_QUANT - 1)];
an = currententity->angles[1] / 180 * M_PI;
shadevector[0] = cos(-an);
shadevector[1] = sin(-an);
shadevector[2] = 1;
VectorNormalize(shadevector);
/* locate the proper data */
c_alias_polys += paliashdr->num_tris;
STUB_ONCE("TODO: OpenGL3 stuff!");
#if 0
/* draw all the triangles */
if (currententity->flags & RF_DEPTHHACK)
{
/* hack the depth range to prevent view model from poking into walls */
glDepthRange(gl3depthmin, gl3depthmin + 0.3 * (gl3depthmax - gl3depthmin));
}
if ((currententity->flags & RF_WEAPONMODEL) && (gl_lefthand->value == 1.0F))
{
extern void R_MYgluPerspective(GLdouble fovy, GLdouble aspect,
GLdouble zNear, GLdouble zFar);
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glScalef(-1, 1, 1);
R_MYgluPerspective(gl3_newrefdef.fov_y,
(float)gl3_newrefdef.width / gl3_newrefdef.height,
4, 4096);
glMatrixMode(GL_MODELVIEW);
glCullFace(GL_BACK);
}
glPushMatrix();
e->angles[PITCH] = -e->angles[PITCH];
GL3_RotateForEntity(e);
e->angles[PITCH] = -e->angles[PITCH];
#endif // 0
/* select skin */
if (currententity->skin)
{
skin = currententity->skin; /* custom player skin */
}
else
{
if (currententity->skinnum >= MAX_MD2SKINS)
{
skin = currentmodel->skins[0];
}
else
{
skin = currentmodel->skins[currententity->skinnum];
if (!skin)
{
skin = currentmodel->skins[0];
}
}
}
if (!skin)
{
skin = gl3_notexture; /* fallback... */
}
GL3_Bind(skin->texnum);
STUB_ONCE("TODO: OpenGL3 stuff!");
#if 0
/* draw it */
glShadeModel(GL_SMOOTH);
R_TexEnv(GL_MODULATE);
if (currententity->flags & RF_TRANSLUCENT)
{
glEnable(GL_BLEND);
}
#endif // 0
if ((currententity->frame >= paliashdr->num_frames) ||
(currententity->frame < 0))
{
R_Printf(PRINT_DEVELOPER, "R_DrawAliasModel %s: no such frame %d\n",
currentmodel->name, currententity->frame);
currententity->frame = 0;
currententity->oldframe = 0;
}
if ((currententity->oldframe >= paliashdr->num_frames) ||
(currententity->oldframe < 0))
{
R_Printf(PRINT_DEVELOPER, "R_DrawAliasModel %s: no such oldframe %d\n",
currentmodel->name, currententity->oldframe);
currententity->frame = 0;
currententity->oldframe = 0;
}
/* Fuck this, gl_lerpmodels 0 looks horrible anyway
if (!gl_lerpmodels->value)
{
currententity->backlerp = 0;
}
*/
DrawAliasFrameLerp(paliashdr, currententity->backlerp);
STUB_ONCE("TODO: even more OpenGL3 stuff!");
#if 0
R_TexEnv(GL_REPLACE);
glShadeModel(GL_FLAT);
glPopMatrix();
if ((currententity->flags & RF_WEAPONMODEL) && (gl_lefthand->value == 1.0F))
{
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glCullFace(GL_FRONT);
}
if (currententity->flags & RF_TRANSLUCENT)
{
glDisable(GL_BLEND);
}
if (currententity->flags & RF_DEPTHHACK)
{
glDepthRange(gldepthmin, gldepthmax);
}
if (gl_shadows->value &&
!(currententity->flags & (RF_TRANSLUCENT | RF_WEAPONMODEL | RF_NOSHADOW)))
{
glPushMatrix();
/* don't rotate shadows on ungodly axes */
glTranslatef(e->origin[0], e->origin[1], e->origin[2]);
glRotatef(e->angles[1], 0, 0, 1);
glDisable(GL_TEXTURE_2D);
glEnable(GL_BLEND);
glColor4f(0, 0, 0, 0.5f);
DrawAliasShadow(paliashdr, currententity->frame);
glEnable(GL_TEXTURE_2D);
glDisable(GL_BLEND);
glPopMatrix();
}
glColor4f(1, 1, 1, 1);
#endif // 0
}

View file

@ -29,17 +29,79 @@
enum { MAX_MOD_KNOWN = 512 };
int registration_sequence;
static gl3model_t *loadmodel;
static byte mod_novis[MAX_MAP_LEAFS / 8];
gl3model_t mod_known[MAX_MOD_KNOWN];
int mod_numknown;
static int mod_numknown;
int registration_sequence;
static byte *mod_base;
/* the inline * models from the current map are kept seperate */
gl3model_t mod_inline[MAX_MOD_KNOWN];
static byte *
Mod_DecompressVis(byte *in, gl3model_t *model)
{
static byte decompressed[MAX_MAP_LEAFS / 8];
int c;
byte *out;
int row;
row = (model->vis->numclusters + 7) >> 3;
out = decompressed;
if (!in)
{
/* no vis info, so make all visible */
while (row)
{
*out++ = 0xff;
row--;
}
return decompressed;
}
do
{
if (*in)
{
*out++ = *in++;
continue;
}
c = in[1];
in += 2;
while (c)
{
*out++ = 0;
c--;
}
}
while (out - decompressed < row);
return decompressed;
}
byte*
GL3_Mod_ClusterPVS(int cluster, gl3model_t *model)
{
if ((cluster == -1) || !model->vis)
{
return mod_novis;
}
return Mod_DecompressVis((byte *)model->vis +
model->vis->bitofs[cluster][DVIS_PVS],
model);
}
void
GL3_Mod_Modellist_f(void)
{
#if 0 // TODO!
int i;
model_t *mod;
gl3model_t *mod;
int total;
total = 0;
@ -57,16 +119,687 @@ GL3_Mod_Modellist_f(void)
}
R_Printf(PRINT_ALL, "Total resident: %i\n", total);
#endif
}
void
GL3_Mod_Init(void)
{
STUB("TODO: Implement!");
// memset(mod_novis, 0xff, sizeof(mod_novis));
memset(mod_novis, 0xff, sizeof(mod_novis));
}
static void
Mod_LoadLighting(lump_t *l)
{
if (!l->filelen)
{
loadmodel->lightdata = NULL;
return;
}
loadmodel->lightdata = Hunk_Alloc(l->filelen);
memcpy(loadmodel->lightdata, mod_base + l->fileofs, l->filelen);
}
static void
Mod_LoadVisibility(lump_t *l)
{
int i;
if (!l->filelen)
{
loadmodel->vis = NULL;
return;
}
loadmodel->vis = Hunk_Alloc(l->filelen);
memcpy(loadmodel->vis, mod_base + l->fileofs, l->filelen);
loadmodel->vis->numclusters = LittleLong(loadmodel->vis->numclusters);
for (i = 0; i < loadmodel->vis->numclusters; i++)
{
loadmodel->vis->bitofs[i][0] = LittleLong(loadmodel->vis->bitofs[i][0]);
loadmodel->vis->bitofs[i][1] = LittleLong(loadmodel->vis->bitofs[i][1]);
}
}
static void
Mod_LoadVertexes(lump_t *l)
{
dvertex_t *in;
mvertex_t *out;
int i, count;
in = (void *)(mod_base + l->fileofs);
if (l->filelen % sizeof(*in))
{
ri.Sys_Error(ERR_DROP, "MOD_LoadBmodel: funny lump size in %s",
loadmodel->name);
}
count = l->filelen / sizeof(*in);
out = Hunk_Alloc(count * sizeof(*out));
loadmodel->vertexes = out;
loadmodel->numvertexes = count;
for (i = 0; i < count; i++, in++, out++)
{
out->position[0] = LittleFloat(in->point[0]);
out->position[1] = LittleFloat(in->point[1]);
out->position[2] = LittleFloat(in->point[2]);
}
}
static float
Mod_RadiusFromBounds(vec3_t mins, vec3_t maxs)
{
int i;
vec3_t corner;
for (i = 0; i < 3; i++)
{
corner[i] = fabs(mins[i]) > fabs(maxs[i]) ? fabs(mins[i]) : fabs(maxs[i]);
}
return VectorLength(corner);
}
static void
Mod_LoadSubmodels(lump_t *l)
{
dmodel_t *in;
mmodel_t *out;
int i, j, count;
in = (void *)(mod_base + l->fileofs);
if (l->filelen % sizeof(*in))
{
ri.Sys_Error(ERR_DROP, "MOD_LoadBmodel: funny lump size in %s",
loadmodel->name);
}
count = l->filelen / sizeof(*in);
out = Hunk_Alloc(count * sizeof(*out));
loadmodel->submodels = out;
loadmodel->numsubmodels = count;
for (i = 0; i < count; i++, in++, out++)
{
for (j = 0; j < 3; j++)
{
/* spread the mins / maxs by a pixel */
out->mins[j] = LittleFloat(in->mins[j]) - 1;
out->maxs[j] = LittleFloat(in->maxs[j]) + 1;
out->origin[j] = LittleFloat(in->origin[j]);
}
out->radius = Mod_RadiusFromBounds(out->mins, out->maxs);
out->headnode = LittleLong(in->headnode);
out->firstface = LittleLong(in->firstface);
out->numfaces = LittleLong(in->numfaces);
}
}
static void
Mod_LoadEdges(lump_t *l)
{
dedge_t *in;
medge_t *out;
int i, count;
in = (void *)(mod_base + l->fileofs);
if (l->filelen % sizeof(*in))
{
ri.Sys_Error(ERR_DROP, "MOD_LoadBmodel: funny lump size in %s",
loadmodel->name);
}
count = l->filelen / sizeof(*in);
out = Hunk_Alloc((count + 1) * sizeof(*out));
loadmodel->edges = out;
loadmodel->numedges = count;
for (i = 0; i < count; i++, in++, out++)
{
out->v[0] = (unsigned short)LittleShort(in->v[0]);
out->v[1] = (unsigned short)LittleShort(in->v[1]);
}
}
static void
Mod_LoadTexinfo(lump_t *l)
{
texinfo_t *in;
mtexinfo_t *out, *step;
int i, j, count;
char name[MAX_QPATH];
int next;
in = (void *)(mod_base + l->fileofs);
if (l->filelen % sizeof(*in))
{
ri.Sys_Error(ERR_DROP, "MOD_LoadBmodel: funny lump size in %s",
loadmodel->name);
}
count = l->filelen / sizeof(*in);
out = Hunk_Alloc(count * sizeof(*out));
loadmodel->texinfo = out;
loadmodel->numtexinfo = count;
for (i = 0; i < count; i++, in++, out++)
{
for (j = 0; j < 4; j++)
{
out->vecs[0][j] = LittleFloat(in->vecs[0][j]);
out->vecs[1][j] = LittleFloat(in->vecs[1][j]);
}
out->flags = LittleLong(in->flags);
next = LittleLong(in->nexttexinfo);
if (next > 0)
{
out->next = loadmodel->texinfo + next;
}
else
{
out->next = NULL;
}
Com_sprintf(name, sizeof(name), "textures/%s.wal", in->texture);
out->image = GL3_FindImage(name, it_wall);
if (!out->image)
{
R_Printf(PRINT_ALL, "Couldn't load %s\n", name);
out->image = gl3_notexture;
}
}
/* count animation frames */
for (i = 0; i < count; i++)
{
out = &loadmodel->texinfo[i];
out->numframes = 1;
for (step = out->next; step && step != out; step = step->next)
{
out->numframes++;
}
}
}
/*
* Fills in s->texturemins[] and s->extents[]
*/
static void
Mod_CalcSurfaceExtents(msurface_t *s)
{
float mins[2], maxs[2], val;
int i, j, e;
mvertex_t *v;
mtexinfo_t *tex;
int bmins[2], bmaxs[2];
mins[0] = mins[1] = 999999;
maxs[0] = maxs[1] = -99999;
tex = s->texinfo;
for (i = 0; i < s->numedges; i++)
{
e = loadmodel->surfedges[s->firstedge + i];
if (e >= 0)
{
v = &loadmodel->vertexes[loadmodel->edges[e].v[0]];
}
else
{
v = &loadmodel->vertexes[loadmodel->edges[-e].v[1]];
}
for (j = 0; j < 2; j++)
{
val = v->position[0] * tex->vecs[j][0] +
v->position[1] * tex->vecs[j][1] +
v->position[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++)
{
bmins[i] = floor(mins[i] / 16);
bmaxs[i] = ceil(maxs[i] / 16);
s->texturemins[i] = bmins[i] * 16;
s->extents[i] = (bmaxs[i] - bmins[i]) * 16;
}
}
extern void
GL3_SubdivideSurface(msurface_t *fa, gl3model_t* loadmodel);
static void
Mod_LoadFaces(lump_t *l)
{
dface_t *in;
msurface_t *out;
int i, count, surfnum;
int planenum, side;
int ti;
in = (void *)(mod_base + l->fileofs);
if (l->filelen % sizeof(*in))
{
ri.Sys_Error(ERR_DROP, "MOD_LoadBmodel: funny lump size in %s",
loadmodel->name);
}
count = l->filelen / sizeof(*in);
out = Hunk_Alloc(count * sizeof(*out));
loadmodel->surfaces = out;
loadmodel->numsurfaces = count;
currentmodel = loadmodel;
GL3_LM_BeginBuildingLightmaps(loadmodel);
for (surfnum = 0; surfnum < count; surfnum++, in++, out++)
{
out->firstedge = LittleLong(in->firstedge);
out->numedges = LittleShort(in->numedges);
out->flags = 0;
out->polys = NULL;
planenum = LittleShort(in->planenum);
side = LittleShort(in->side);
if (side)
{
out->flags |= SURF_PLANEBACK;
}
out->plane = loadmodel->planes + planenum;
ti = LittleShort(in->texinfo);
if ((ti < 0) || (ti >= loadmodel->numtexinfo))
{
ri.Sys_Error(ERR_DROP, "MOD_LoadBmodel: bad texinfo number");
}
out->texinfo = loadmodel->texinfo + ti;
Mod_CalcSurfaceExtents(out);
/* lighting info */
for (i = 0; i < MAXLIGHTMAPS; i++)
{
out->styles[i] = in->styles[i];
}
i = LittleLong(in->lightofs);
if (i == -1)
{
out->samples = NULL;
}
else
{
out->samples = loadmodel->lightdata + i;
}
/* set the drawing flags */
if (out->texinfo->flags & SURF_WARP)
{
out->flags |= SURF_DRAWTURB;
for (i = 0; i < 2; i++)
{
out->extents[i] = 16384;
out->texturemins[i] = -8192;
}
GL3_SubdivideSurface(out, loadmodel); /* cut up polygon for warps */
}
/* create lightmaps and polygons */
if (!(out->texinfo->flags &
(SURF_SKY | SURF_TRANS33 | SURF_TRANS66 | SURF_WARP)))
{
GL3_LM_CreateSurfaceLightmap(out);
}
if (!(out->texinfo->flags & SURF_WARP))
{
GL3_LM_BuildPolygonFromSurface(out);
}
}
GL3_LM_EndBuildingLightmaps();
}
static void
Mod_SetParent(mnode_t *node, mnode_t *parent)
{
node->parent = parent;
if (node->contents != -1)
{
return;
}
Mod_SetParent(node->children[0], node);
Mod_SetParent(node->children[1], node);
}
static void
Mod_LoadNodes(lump_t *l)
{
int i, j, count, p;
dnode_t *in;
mnode_t *out;
in = (void *)(mod_base + l->fileofs);
if (l->filelen % sizeof(*in))
{
ri.Sys_Error(ERR_DROP, "MOD_LoadBmodel: funny lump size in %s",
loadmodel->name);
}
count = l->filelen / sizeof(*in);
out = Hunk_Alloc(count * sizeof(*out));
loadmodel->nodes = out;
loadmodel->numnodes = count;
for (i = 0; i < count; i++, in++, out++)
{
for (j = 0; j < 3; j++)
{
out->minmaxs[j] = LittleShort(in->mins[j]);
out->minmaxs[3 + j] = LittleShort(in->maxs[j]);
}
p = LittleLong(in->planenum);
out->plane = loadmodel->planes + p;
out->firstsurface = LittleShort(in->firstface);
out->numsurfaces = LittleShort(in->numfaces);
out->contents = -1; /* differentiate from leafs */
for (j = 0; j < 2; j++)
{
p = LittleLong(in->children[j]);
if (p >= 0)
{
out->children[j] = loadmodel->nodes + p;
}
else
{
out->children[j] = (mnode_t *)(loadmodel->leafs + (-1 - p));
}
}
}
Mod_SetParent(loadmodel->nodes, NULL); /* sets nodes and leafs */
}
static void
Mod_LoadLeafs(lump_t *l)
{
dleaf_t *in;
mleaf_t *out;
int i, j, count, p;
in = (void *)(mod_base + l->fileofs);
if (l->filelen % sizeof(*in))
{
ri.Sys_Error(ERR_DROP, "MOD_LoadBmodel: funny lump size in %s",
loadmodel->name);
}
count = l->filelen / sizeof(*in);
out = Hunk_Alloc(count * sizeof(*out));
loadmodel->leafs = out;
loadmodel->numleafs = count;
for (i = 0; i < count; i++, in++, out++)
{
for (j = 0; j < 3; j++)
{
out->minmaxs[j] = LittleShort(in->mins[j]);
out->minmaxs[3 + j] = LittleShort(in->maxs[j]);
}
p = LittleLong(in->contents);
out->contents = p;
out->cluster = LittleShort(in->cluster);
out->area = LittleShort(in->area);
out->firstmarksurface = loadmodel->marksurfaces +
LittleShort(in->firstleafface);
out->nummarksurfaces = LittleShort(in->numleaffaces);
}
}
static void
Mod_LoadMarksurfaces(lump_t *l)
{
int i, j, count;
short *in;
msurface_t **out;
in = (void *)(mod_base + l->fileofs);
if (l->filelen % sizeof(*in))
{
ri.Sys_Error(ERR_DROP, "MOD_LoadBmodel: funny lump size in %s",
loadmodel->name);
}
count = l->filelen / sizeof(*in);
out = Hunk_Alloc(count * sizeof(*out));
loadmodel->marksurfaces = out;
loadmodel->nummarksurfaces = count;
for (i = 0; i < count; i++)
{
j = LittleShort(in[i]);
if ((j < 0) || (j >= loadmodel->numsurfaces))
{
ri.Sys_Error(ERR_DROP, "Mod_ParseMarksurfaces: bad surface number");
}
out[i] = loadmodel->surfaces + j;
}
}
static void
Mod_LoadSurfedges(lump_t *l)
{
int i, count;
int *in, *out;
in = (void *)(mod_base + l->fileofs);
if (l->filelen % sizeof(*in))
{
ri.Sys_Error(ERR_DROP, "MOD_LoadBmodel: funny lump size in %s",
loadmodel->name);
}
count = l->filelen / sizeof(*in);
if ((count < 1) || (count >= MAX_MAP_SURFEDGES))
{
ri.Sys_Error(ERR_DROP, "MOD_LoadBmodel: bad surfedges count in %s: %i",
loadmodel->name, count);
}
out = Hunk_Alloc(count * sizeof(*out));
loadmodel->surfedges = out;
loadmodel->numsurfedges = count;
for (i = 0; i < count; i++)
{
out[i] = LittleLong(in[i]);
}
}
static void
Mod_LoadPlanes(lump_t *l)
{
int i, j;
cplane_t *out;
dplane_t *in;
int count;
int bits;
in = (void *)(mod_base + l->fileofs);
if (l->filelen % sizeof(*in))
{
ri.Sys_Error(ERR_DROP, "MOD_LoadBmodel: funny lump size in %s",
loadmodel->name);
}
count = l->filelen / sizeof(*in);
out = Hunk_Alloc(count * 2 * sizeof(*out));
loadmodel->planes = out;
loadmodel->numplanes = count;
for (i = 0; i < count; i++, in++, out++)
{
bits = 0;
for (j = 0; j < 3; j++)
{
out->normal[j] = LittleFloat(in->normal[j]);
if (out->normal[j] < 0)
{
bits |= 1 << j;
}
}
out->dist = LittleFloat(in->dist);
out->type = LittleLong(in->type);
out->signbits = bits;
}
}
static void
Mod_LoadBrushModel(gl3model_t *mod, void *buffer)
{
int i;
dheader_t *header;
mmodel_t *bm;
loadmodel->type = mod_brush;
if (loadmodel != mod_known)
{
ri.Sys_Error(ERR_DROP, "Loaded a brush model after the world");
}
header = (dheader_t *)buffer;
i = LittleLong(header->version);
if (i != BSPVERSION)
{
ri.Sys_Error(ERR_DROP, "Mod_LoadBrushModel: %s has wrong version number (%i should be %i)",
mod->name, i, BSPVERSION);
}
/* swap all the lumps */
mod_base = (byte *)header;
for (i = 0; i < sizeof(dheader_t) / 4; i++)
{
((int *)header)[i] = LittleLong(((int *)header)[i]);
}
/* load into heap */
Mod_LoadVertexes(&header->lumps[LUMP_VERTEXES]);
Mod_LoadEdges(&header->lumps[LUMP_EDGES]);
Mod_LoadSurfedges(&header->lumps[LUMP_SURFEDGES]);
Mod_LoadLighting(&header->lumps[LUMP_LIGHTING]);
Mod_LoadPlanes(&header->lumps[LUMP_PLANES]);
Mod_LoadTexinfo(&header->lumps[LUMP_TEXINFO]);
Mod_LoadFaces(&header->lumps[LUMP_FACES]);
Mod_LoadMarksurfaces(&header->lumps[LUMP_LEAFFACES]);
Mod_LoadVisibility(&header->lumps[LUMP_VISIBILITY]);
Mod_LoadLeafs(&header->lumps[LUMP_LEAFS]);
Mod_LoadNodes(&header->lumps[LUMP_NODES]);
Mod_LoadSubmodels(&header->lumps[LUMP_MODELS]);
mod->numframes = 2; /* regular and alternate animation */
/* set up the submodels */
for (i = 0; i < mod->numsubmodels; i++)
{
gl3model_t *starmod;
bm = &mod->submodels[i];
starmod = &mod_inline[i];
*starmod = *loadmodel;
starmod->firstmodelsurface = bm->firstface;
starmod->nummodelsurfaces = bm->numfaces;
starmod->firstnode = bm->headnode;
if (starmod->firstnode >= loadmodel->numnodes)
{
ri.Sys_Error(ERR_DROP, "Inline model %i has bad firstnode", i);
}
VectorCopy(bm->maxs, starmod->maxs);
VectorCopy(bm->mins, starmod->mins);
starmod->radius = bm->radius;
if (i == 0)
{
*loadmodel = *starmod;
}
starmod->numleafs = bm->visleafs;
}
}
static void
Mod_Free(gl3model_t *mod)
@ -89,6 +822,119 @@ GL3_Mod_FreeAll(void)
}
}
extern void GL3_LoadMD2(gl3model_t *mod, void *buffer);
extern void GL3_LoadSP2(gl3model_t *mod, void *buffer, int modfilelen);
/*
* Loads in a model for the given name
*/
static gl3model_t *
Mod_ForName(char *name, qboolean crash)
{
gl3model_t *mod;
unsigned *buf;
int i;
if (!name[0])
{
ri.Sys_Error(ERR_DROP, "Mod_ForName: NULL name");
}
/* inline models are grabbed only from worldmodel */
if (name[0] == '*')
{
i = (int)strtol(name + 1, (char **)NULL, 10);
if ((i < 1) || !gl3_worldmodel || (i >= gl3_worldmodel->numsubmodels))
{
ri.Sys_Error(ERR_DROP, "bad inline model number");
}
return &mod_inline[i];
}
/* search the currently loaded models */
for (i = 0, mod = mod_known; i < mod_numknown; i++, mod++)
{
if (!mod->name[0])
{
continue;
}
if (!strcmp(mod->name, name))
{
return mod;
}
}
/* find a free model slot spot */
for (i = 0, mod = mod_known; i < mod_numknown; i++, mod++)
{
if (!mod->name[0])
{
break; /* free spot */
}
}
if (i == mod_numknown)
{
if (mod_numknown == MAX_MOD_KNOWN)
{
ri.Sys_Error(ERR_DROP, "mod_numknown == MAX_MOD_KNOWN");
}
mod_numknown++;
}
strcpy(mod->name, name);
/* load the file */
int modfilelen = ri.FS_LoadFile(mod->name, (void **)&buf);
if (!buf)
{
if (crash)
{
ri.Sys_Error(ERR_DROP, "Mod_NumForName: %s not found", mod->name);
}
memset(mod->name, 0, sizeof(mod->name));
return NULL;
}
loadmodel = mod;
/* call the apropriate loader */
switch (LittleLong(*(unsigned *)buf))
{
case IDALIASHEADER:
loadmodel->extradata = Hunk_Begin(0x200000);
GL3_LoadMD2(mod, buf);
break;
case IDSPRITEHEADER:
loadmodel->extradata = Hunk_Begin(0x10000);
GL3_LoadSP2(mod, buf, modfilelen);
break;
case IDBSPHEADER:
loadmodel->extradata = Hunk_Begin(0x1000000);
Mod_LoadBrushModel(mod, buf);
break;
default:
ri.Sys_Error(ERR_DROP,
"Mod_NumForName: unknown fileid for %s",
mod->name);
break;
}
loadmodel->extradatasize = Hunk_End();
ri.FS_FreeFile(buf);
return mod;
}
/*
* Specifies the model that will be used as the world
@ -114,20 +960,15 @@ GL3_BeginRegistration(char *model)
Mod_Free(&mod_known[0]);
}
STUB_ONCE("TODO: Implement Mod_ForName()!");
#if 0 // TODO!
r_worldmodel = Mod_ForName(fullname, true);
#endif // 0
gl3_worldmodel = Mod_ForName(fullname, true);
gl3_viewcluster = -1;
}
struct model_s *
GL3_RegisterModel(char *name)
{
STUB_ONCE("TODO: Implement!");
return NULL;
#if 0
model_t *mod;
gl3model_t *mod;
int i;
dsprite_t *sprout;
dmdl_t *pheader;
@ -145,7 +986,7 @@ GL3_RegisterModel(char *name)
for (i = 0; i < sprout->numframes; i++)
{
mod->skins[i] = R_FindImage(sprout->frames[i].name, it_sprite);
mod->skins[i] = GL3_FindImage(sprout->frames[i].name, it_sprite);
}
}
else if (mod->type == mod_alias)
@ -154,8 +995,7 @@ GL3_RegisterModel(char *name)
for (i = 0; i < pheader->num_skins; i++)
{
mod->skins[i] = R_FindImage((char *)pheader + pheader->ofs_skins +
i * MAX_SKINNAME, it_skin);
mod->skins[i] = GL3_FindImage((char *)pheader + pheader->ofs_skins + i * MAX_SKINNAME, it_skin);
}
mod->numframes = pheader->num_frames;
@ -164,14 +1004,12 @@ GL3_RegisterModel(char *name)
{
for (i = 0; i < mod->numtexinfo; i++)
{
mod->texinfo[i].image->registration_sequence =
registration_sequence;
mod->texinfo[i].image->registration_sequence = registration_sequence;
}
}
}
return mod;
#endif // 0
}
void

View file

@ -71,8 +71,8 @@ int GL3_PrepareForWindow(void)
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);
// SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); // TODO
int contextFlags = 0; // SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG TODO
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
int contextFlags = SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG;
if(gl3_debugcontext && gl3_debugcontext->value)
{
contextFlags |= SDL_GL_CONTEXT_DEBUG_FLAG;

View file

@ -31,40 +31,6 @@
#define eprintf(...) R_Printf(PRINT_ALL, __VA_ARGS__)
#if 0
static const char* vertexSrc = MULTILINE_STRING(#version 150\n
in vec2 position;
// I renamed color to inColor and Color to passColor for more clarity
in vec3 inColor;
// same for texcoord -> inTexCoord, Textcoord -> passTexCoord
in vec2 inTexCoord;
out vec3 passColor;
out vec2 passTexCoord;
void main() {
passColor = inColor;
passTexCoord = inTexCoord;
gl_Position = vec4(position, 0.0, 1.0);
}
);
static const char* fragmentSrc = MULTILINE_STRING(#version 150\n
in vec3 passColor; // I renamed color to passColor (it's from the vertex shader above)
in vec2 passTexCoord; // same for Texcoord -> passTexCoord
out vec4 outColor;
uniform sampler2D tex;
void main()
{
outColor = texture(tex, passTexCoord) * vec4(passColor, 1.0);
//outColor = texture(tex, passTexCoord);
//outColor = vec4(passColor, 1.0);
}
);
#endif // 0
static GLuint
CompileShader(GLenum shaderType, const char* shaderSrc)
{
@ -209,7 +175,10 @@ static const char* fragmentSrc2D = MULTILINE_STRING(#version 150\n
void main()
{
vec4 texel = texture(tex, passTexCoord);
if(texel.a < 0.666)
// the gl1 renderer used glAlphaFunc(GL_GREATER, 0.666);
// and glEnable(GL_ALPHA_TEST); for 2D rendering
// this should do the same
if(texel.a <= 0.666)
discard;
// apply gamma correction and intensity

View file

@ -0,0 +1,67 @@
/*
* Copyright (C) 1997-2001 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.
*
* =======================================================================
*
* .sp2 sprites
*
* =======================================================================
*/
#include "header/local.h"
void
GL3_LoadSP2(gl3model_t *mod, void *buffer, int modfilelen)
{
dsprite_t *sprin, *sprout;
int i;
sprin = (dsprite_t *)buffer;
sprout = Hunk_Alloc(modfilelen);
sprout->ident = LittleLong(sprin->ident);
sprout->version = LittleLong(sprin->version);
sprout->numframes = LittleLong(sprin->numframes);
if (sprout->version != SPRITE_VERSION)
{
ri.Sys_Error(ERR_DROP, "%s has wrong version number (%i should be %i)",
mod->name, sprout->version, SPRITE_VERSION);
}
if (sprout->numframes > MAX_MD2SKINS)
{
ri.Sys_Error(ERR_DROP, "%s has too many frames (%i > %i)",
mod->name, sprout->numframes, MAX_MD2SKINS);
}
/* byte swap everything */
for (i = 0; i < sprout->numframes; i++)
{
sprout->frames[i].width = LittleLong(sprin->frames[i].width);
sprout->frames[i].height = LittleLong(sprin->frames[i].height);
sprout->frames[i].origin_x = LittleLong(sprin->frames[i].origin_x);
sprout->frames[i].origin_y = LittleLong(sprin->frames[i].origin_y);
memcpy(sprout->frames[i].name, sprin->frames[i].name, MAX_SKINNAME);
mod->skins[i] = GL3_FindImage(sprout->frames[i].name, it_sprite);
}
mod->type = mod_sprite;
}

File diff suppressed because it is too large Load diff

View file

@ -27,14 +27,318 @@
#include "header/local.h"
// TODO: can we get rid of this?
float gl3_turbsin[] = {
#include "../constants/warpsin.h"
};
static void
R_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;
}
}
}
}
static const float SUBDIVIDE_SIZE = 64.0f;
static void
R_SubdividePolygon(int numverts, float *verts, msurface_t *warpface)
{
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;
vec3_t total;
float total_s, total_t;
if (numverts > 60)
{
ri.Sys_Error(ERR_DROP, "numverts = %i", numverts);
}
R_BoundPoly(numverts, verts, mins, maxs);
for (i = 0; i < 3; i++)
{
m = (mins[i] + maxs[i]) * 0.5;
m = SUBDIVIDE_SIZE * floor(m / SUBDIVIDE_SIZE + 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++;
}
}
R_SubdividePolygon(f, front[0], warpface);
R_SubdividePolygon(b, back[0], warpface);
return;
}
/* add a point in the center to help keep warp valid */
poly = Hunk_Alloc(sizeof(glpoly_t) + ((numverts - 4) + 2) * VERTEXSIZE * sizeof(float));
poly->next = warpface->polys;
warpface->polys = poly;
poly->numverts = numverts + 2;
VectorClear(total);
total_s = 0;
total_t = 0;
for (i = 0; i < numverts; i++, verts += 3)
{
VectorCopy(verts, poly->verts[i + 1]);
s = DotProduct(verts, warpface->texinfo->vecs[0]);
t = DotProduct(verts, warpface->texinfo->vecs[1]);
total_s += s;
total_t += t;
VectorAdd(total, verts, total);
poly->verts[i + 1][3] = s;
poly->verts[i + 1][4] = t;
}
VectorScale(total, (1.0 / numverts), poly->verts[0]);
poly->verts[0][3] = total_s / numverts;
poly->verts[0][4] = total_t / numverts;
/* copy first vertex to last */
memcpy(poly->verts[i + 1], poly->verts[1], sizeof(poly->verts[0]));
}
/*
* Breaks a polygon up along axial 64 unit
* boundaries so that turbulent and sky warps
* can be done reasonably.
*/
void
GL3_SubdivideSurface(msurface_t *fa, gl3model_t* loadmodel)
{
vec3_t verts[64];
int numverts;
int i;
int lindex;
float *vec;
/* 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++;
}
R_SubdividePolygon(numverts, verts[0], fa);
}
/*
* Does a water warp on the pre-fragmented glpoly_t chain
*/
void
GL3_EmitWaterPolys(msurface_t *fa)
{
glpoly_t *p, *bp;
float *v;
int i;
float s, t, os, ot;
float scroll;
float rdt = gl3_newrefdef.time;
static const float TURBSCALE = (256.0 / (2 * M_PI));
if (fa->texinfo->flags & SURF_FLOWING)
{
scroll = -64 * ((gl3_newrefdef.time * 0.5) - (int)(gl3_newrefdef.time * 0.5));
}
else
{
scroll = 0;
}
for (bp = fa->polys; bp; bp = bp->next)
{
p = bp;
GLfloat tex[2*p->numverts];
unsigned int index_tex = 0;
for ( i = 0, v = p->verts [ 0 ]; i < p->numverts; i++, v += VERTEXSIZE )
{
os = v [ 3 ];
ot = v [ 4 ];
s = os + gl3_turbsin [ (int) ( ( ot * 0.125 + gl3_newrefdef.time ) * TURBSCALE ) & 255 ];
s += scroll;
tex[index_tex++] = s * ( 1.0 / 64 );
t = ot + gl3_turbsin [ (int) ( ( os * 0.125 + rdt ) * TURBSCALE ) & 255 ];
tex[index_tex++] = t * ( 1.0 / 64 );
}
v = p->verts [ 0 ];
STUB_ONCE("TODO: Implement OpenGL3 part!");
#if 0
glEnableClientState( GL_VERTEX_ARRAY );
glEnableClientState( GL_TEXTURE_COORD_ARRAY );
glVertexPointer( 3, GL_FLOAT, VERTEXSIZE*sizeof(GLfloat), v );
glTexCoordPointer( 2, GL_FLOAT, 0, tex );
glDrawArrays( GL_TRIANGLE_FAN, 0, p->numverts );
glDisableClientState( GL_VERTEX_ARRAY );
glDisableClientState( GL_TEXTURE_COORD_ARRAY );
#endif // 0
}
}
// ########### below: Sky-specific stuff ##########
#define ON_EPSILON 0.1 /* point on plane side epsilon */
enum { MAX_CLIP_VERTS = 64 };
static const int skytexorder[6] = {0, 2, 1, 3, 4, 5};
static GLfloat vtx_sky[12];
static GLfloat tex_sky[8];
static unsigned int index_vtx = 0;
static unsigned int index_tex = 0;
static float skymins[2][6], skymaxs[2][6];
static float sky_min, sky_max;
static float skyrotate;
static vec3_t skyaxis;
static gl3image_t* sky_images[6];
static float sky_min, sky_max;
/* 3dstudio environment map names */
static const char* suf[6] = {"rt", "bk", "lf", "ft", "up", "dn"};
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;
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 */
};
int vec_to_st[6][3] = {
{-2, 3, 1},
{2, 3, -1},
{1, 3, 2},
{-1, 3, -2},
{-2, -1, 3},
{-2, 1, -3}
};
void
GL3_SetSky(char *name, float rotate, vec3_t axis)
{
@ -64,3 +368,397 @@ GL3_SetSky(char *name, float rotate, vec3_t axis)
sky_max = 511.0 / 512;
}
}
static void
DrawSkyPolygon(int nump, vec3_t vecs)
{
int i, j;
vec3_t v, av;
float s, t, dv;
int axis;
float *vp;
c_sky++;
/* 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;
}
}
}
static 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)
{
ri.Sys_Error(ERR_DROP, "R_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);
}
void
GL3_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], gl3_origin, verts[i]);
}
ClipSkyPolygon(p->numverts, verts[0], 0);
}
}
void
GL3_ClearSkyBox(void)
{
int i;
for (i = 0; i < 6; i++)
{
skymins[0][i] = skymins[1][i] = 9999;
skymaxs[0][i] = skymaxs[1][i] = -9999;
}
}
static void
MakeSkyVec(float s, float t, int axis)
{
vec3_t v, b;
int j, k;
if (gl_farsee->value == 0)
{
b[0] = s * 2300;
b[1] = t * 2300;
b[2] = 2300;
}
else
{
b[0] = s * 4096;
b[1] = t * 4096;
b[2] = 4096;
}
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];
}
}
/* avoid bilerp seam */
s = (s + 1) * 0.5;
t = (t + 1) * 0.5;
if (s < sky_min)
{
s = sky_min;
}
else if (s > sky_max)
{
s = sky_max;
}
if (t < sky_min)
{
t = sky_min;
}
else if (t > sky_max)
{
t = sky_max;
}
t = 1.0 - t;
tex_sky[index_tex++] = s;
tex_sky[index_tex++] = t;
vtx_sky[index_vtx++] = v[ 0 ];
vtx_sky[index_vtx++] = v[ 1 ];
vtx_sky[index_vtx++] = v[ 2 ];
}
void
GL3_DrawSkyBox(void)
{
int i;
if (skyrotate)
{ /* check for no sky at all */
for (i = 0; i < 6; i++)
{
if ((skymins[0][i] < skymaxs[0][i]) &&
(skymins[1][i] < skymaxs[1][i]))
{
break;
}
}
if (i == 6)
{
return; /* nothing visible */
}
}
STUB_ONCE("TODO: Implement OpenGL3 stuff");
#if 0
glPushMatrix();
glTranslatef(gl3_origin[0], gl3_origin[1], gl3_origin[2]);
glRotatef(gl3_newrefdef.time * skyrotate, skyaxis[0], skyaxis[1], skyaxis[2]);
for (i = 0; i < 6; i++)
{
if (skyrotate)
{
skymins[0][i] = -1;
skymins[1][i] = -1;
skymaxs[0][i] = 1;
skymaxs[1][i] = 1;
}
if ((skymins[0][i] >= skymaxs[0][i]) ||
(skymins[1][i] >= skymaxs[1][i]))
{
continue;
}
GL3_Bind(sky_images[skytexorder[i]]->texnum);
glEnableClientState( GL_VERTEX_ARRAY );
glEnableClientState( GL_TEXTURE_COORD_ARRAY );
index_vtx = 0;
index_tex = 0;
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 );
glVertexPointer( 3, GL_FLOAT, 0, vtx_sky );
glTexCoordPointer( 2, GL_FLOAT, 0, tex_sky );
glDrawArrays( GL_TRIANGLE_FAN, 0, 4 );
glDisableClientState( GL_VERTEX_ARRAY );
glDisableClientState( GL_TEXTURE_COORD_ARRAY );
}
glPopMatrix();
#endif // 0
}

View file

@ -116,7 +116,7 @@ typedef struct
unsigned char *d_16to8table;
int lightmap_textures;
//int lightmap_textures;
//int currenttextures[2];
GLuint currenttexture;
@ -140,8 +140,15 @@ extern gl3state_t gl3state;
extern viddef_t vid;
extern refdef_t gl3_newrefdef;
extern int gl3_visframecount; /* bumped when going to a new PVS */
extern int gl3_framecount; /* used for dlight push checking */
extern int gl3_viewcluster, gl3_viewcluster2, gl3_oldviewcluster, gl3_oldviewcluster2;
extern int c_brush_polys, c_alias_polys;
/* NOTE: struct image_s* is what re.RegisterSkin() etc return so no gl3image_s!
* (I think the client only passes the pointer around and doesn't know the
* definition of this struct, so this being different from struct image_s
@ -169,13 +176,49 @@ enum {MAX_GL3TEXTURES = 1024};
// include this down here so it can use gl3image_t
#include "model.h"
enum {
BLOCK_WIDTH = 128,
BLOCK_HEIGHT = 128,
LIGHTMAP_BYTES = 4,
MAX_LIGHTMAPS = 128
};
typedef struct
{
int internal_format;
int current_lightmap_texture;
msurface_t *lightmap_surfaces[MAX_LIGHTMAPS];
int allocated[BLOCK_WIDTH];
/* the lightmap texture data needs to be kept in
main memory so texsubimage can update properly */
byte lightmap_buffer[4 * BLOCK_WIDTH * BLOCK_HEIGHT];
} gl3lightmapstate_t;
extern gl3model_t *gl3_worldmodel;
extern gl3model_t *currentmodel;
extern entity_t *currententity;
extern float gl3depthmin, gl3depthmax;
extern cplane_t frustum[4];
vec3_t gl3_origin;
extern gl3image_t *gl3_notexture; /* use for bad textures */
extern gl3image_t *gl3_particletexture; /* little dot for particles */
extern int gl_filter_min;
extern int gl_filter_max;
extern qboolean GL3_CullBox(vec3_t mins, vec3_t maxs);
extern void GL3_RotateForEntity(entity_t *e);
// gl3_sdl.c
extern qboolean have_stencil;
extern int GL3_PrepareForWindow(void);
extern int GL3_InitContext(void* win);
extern void GL3_EndFrame(void);
@ -194,6 +237,7 @@ extern void GL3_BeginRegistration(char *model);
extern struct model_s * GL3_RegisterModel(char *name);
extern void GL3_EndRegistration(void);
extern void GL3_Mod_Modellist_f(void);
extern byte* GL3_Mod_ClusterPVS(int cluster, gl3model_t *model);
// gl3_draw.c
extern void GL3_Draw_InitLocal(void);
@ -221,8 +265,43 @@ extern void GL3_ShutdownImages(void);
extern void GL3_FreeUnusedImages(void);
extern void GL3_ImageList_f(void);
// gl3_light.c
extern void GL3_RenderDlights(void);
extern void GL3_MarkLights(dlight_t *light, int bit, mnode_t *node);
extern void GL3_PushDlights(void);
extern void GL3_LightPoint(vec3_t p, vec3_t color);
extern void GL3_SetCacheState(msurface_t *surf);
extern void GL3_BuildLightMap(msurface_t *surf, byte *dest, int stride);
// gl3_lightmap.c
#define GL_LIGHTMAP_FORMAT GL_RGBA
extern void GL3_LM_InitBlock(void);
extern void GL3_LM_UploadBlock(qboolean dynamic);
extern qboolean GL3_LM_AllocBlock(int w, int h, int *x, int *y);
extern void GL3_LM_BuildPolygonFromSurface(msurface_t *fa);
extern void GL3_LM_CreateSurfaceLightmap(msurface_t *surf);
extern void GL3_LM_BeginBuildingLightmaps(gl3model_t *m);
extern void GL3_LM_EndBuildingLightmaps(void);
// gl3_warp.c
extern void GL3_EmitWaterPolys(msurface_t *fa);
extern void GL3_SubdivideSurface(msurface_t *fa, gl3model_t* loadmodel);
extern void GL3_SetSky(char *name, float rotate, vec3_t axis);
extern void GL3_DrawSkyBox(void);
extern void GL3_ClearSkyBox(void);
extern void GL3_AddSkySurface(msurface_t *fa);
// gl3_surf.c
extern void GL3_DrawGLPoly(glpoly_t *p);
extern void GL3_DrawGLFlowingPoly(msurface_t *fa);
extern void GL3_DrawTriangleOutlines(void);
extern void GL3_DrawAlphaSurfaces(void);
extern void GL3_DrawBrushModel(entity_t *e);
extern void GL3_DrawWorld(void);
extern void GL3_MarkLeaves(void);
// gl3_shaders.c
@ -242,11 +321,29 @@ extern cvar_t *gl_customheight;
extern cvar_t *gl_nolerp_list;
extern cvar_t *gl_nobind;
extern cvar_t *gl_lockpvs;
extern cvar_t *gl_novis;
extern cvar_t *gl_cull;
extern cvar_t *gl_zfix;
extern cvar_t *gl_fullbright;
extern cvar_t *gl_norefresh;
extern cvar_t *gl_lefthand;
extern cvar_t *gl_farsee;
extern cvar_t *vid_gamma;
extern cvar_t *intensity;
extern cvar_t *gl_anisotropic;
extern cvar_t *gl_lightlevel;
extern cvar_t *gl_overbrightbits;
extern cvar_t *gl_flashblend;
extern cvar_t *gl_modulate;
extern cvar_t *gl_stencilshadow;
extern cvar_t *gl3_debugcontext;
#endif /* SRC_CLIENT_REFRESH_GL3_HEADER_LOCAL_H_ */

View file

@ -56,6 +56,8 @@ typedef enum
mod_alias
} modtype_t;
#define MAX_LBM_HEIGHT 480
extern void R_Printf(int level, const char* msg, ...) __attribute__ ((format (printf, 2, 3)));
extern void LoadPCX(char *origname, byte **pic, byte **palette, int *width, int *height);