mirror of
https://github.com/yquake2/yquake2remaster.git
synced 2025-03-27 13:21:26 +00:00
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:
parent
ebbb675cb8
commit
0b35ceabdc
20 changed files with 5120 additions and 174 deletions
17
Makefile
17
Makefile
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
699
src/client/refresh/gl3/gl3_light.c
Normal file
699
src/client/refresh/gl3/gl3_light.c
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
297
src/client/refresh/gl3/gl3_lightmap.c
Normal file
297
src/client/refresh/gl3/gl3_lightmap.c
Normal 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);
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
163
src/client/refresh/gl3/gl3_md2.c
Normal file
163
src/client/refresh/gl3/gl3_md2.c
Normal 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;
|
||||
}
|
||||
|
817
src/client/refresh/gl3/gl3_mesh.c
Normal file
817
src/client/refresh/gl3/gl3_mesh.c
Normal 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
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
67
src/client/refresh/gl3/gl3_sp2.c
Normal file
67
src/client/refresh/gl3/gl3_sp2.c
Normal 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;
|
||||
}
|
||||
|
1124
src/client/refresh/gl3/gl3_surf.c
Normal file
1124
src/client/refresh/gl3/gl3_surf.c
Normal file
File diff suppressed because it is too large
Load diff
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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_ */
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue