Move BSPX lighting code to shared code

This commit is contained in:
Denis Pauk 2023-10-05 19:24:15 +03:00
parent 4a3dbb22d9
commit 21ceb16de4
10 changed files with 725 additions and 633 deletions

View file

@ -997,6 +997,7 @@ REFGL1_OBJS_ := \
src/client/refresh/gl1/gl1_surf.o \
src/client/refresh/gl1/gl1_warp.o \
src/client/refresh/gl1/gl1_sdl.o \
src/client/refresh/files/light.o \
src/client/refresh/files/surf.o \
src/client/refresh/files/models.o \
src/client/refresh/files/pcx.o \
@ -1030,6 +1031,7 @@ REFGL3_OBJS_ := \
src/client/refresh/gl3/gl3_surf.o \
src/client/refresh/gl3/gl3_warp.o \
src/client/refresh/gl3/gl3_shaders.o \
src/client/refresh/files/light.o \
src/client/refresh/files/surf.o \
src/client/refresh/files/models.o \
src/client/refresh/files/pcx.o \
@ -1069,6 +1071,7 @@ REFGL4_OBJS_ := \
src/client/refresh/gl4/gl4_surf.o \
src/client/refresh/gl4/gl4_warp.o \
src/client/refresh/gl4/gl4_shaders.o \
src/client/refresh/files/light.o \
src/client/refresh/files/surf.o \
src/client/refresh/files/models.o \
src/client/refresh/files/pcx.o \
@ -1109,6 +1112,7 @@ REFSOFT_OBJS_ := \
src/client/refresh/soft/sw_scan.o \
src/client/refresh/soft/sw_sprite.o \
src/client/refresh/soft/sw_surf.o \
src/client/refresh/files/light.o \
src/client/refresh/files/surf.o \
src/client/refresh/files/models.o \
src/client/refresh/files/pcx.o \
@ -1149,6 +1153,7 @@ REFVK_OBJS_ := \
src/client/refresh/vk/vk_warp.o \
src/client/refresh/vk/vk_util.o \
src/client/refresh/vk/volk/volk.o \
src/client/refresh/files/light.o \
src/client/refresh/files/surf.o \
src/client/refresh/files/models.o \
src/client/refresh/files/pcx.o \

View file

@ -0,0 +1,94 @@
/*
* 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.
*
* =======================================================================
*
* Light logic
*
* =======================================================================
*/
#include "../ref_shared.h"
static int
BSPX_LightGridSingleValue(const bspxlightgrid_t *grid, const lightstyle_t *lightstyles, int x, int y, int z, vec3_t res_diffuse)
{
int i;
unsigned int node;
struct bspxlgsamp_s *samp;
node = grid->rootnode;
while (!(node & LGNODE_LEAF))
{
struct bspxlgnode_s *n;
if (node & LGNODE_MISSING)
return 0; //failure
n = grid->nodes + node;
node = n->child[
((x>=n->mid[0])<<2)|
((y>=n->mid[1])<<1)|
((z>=n->mid[2])<<0)];
}
{
struct bspxlgleaf_s *leaf = &grid->leafs[node & ~LGNODE_LEAF];
x -= leaf->mins[0];
y -= leaf->mins[1];
z -= leaf->mins[2];
if (x >= leaf->size[0] ||
y >= leaf->size[1] ||
z >= leaf->size[2])
return 0; //sample we're after is out of bounds...
i = x + leaf->size[0]*(y + leaf->size[1]*z);
samp = leaf->rgbvalues + i;
//no hdr support
for (i = 0; i < 4; i++)
{
if (samp->map[i].style == ((byte)(~0u)))
break; //no more
res_diffuse[0] += samp->map[i].rgb[0] * lightstyles[samp->map[i].style].rgb[0] / 255.0;
res_diffuse[1] += samp->map[i].rgb[1] * lightstyles[samp->map[i].style].rgb[1] / 255.0;
res_diffuse[2] += samp->map[i].rgb[2] * lightstyles[samp->map[i].style].rgb[2] / 255.0;
}
}
return 1;
}
void
BSPX_LightGridValue(const bspxlightgrid_t *grid, const lightstyle_t *lightstyles, const vec3_t point, vec3_t res_diffuse)
{
int tile[3];
int i;
int s;
VectorSet(res_diffuse, 0, 0, 0); //assume worst
for (i = 0; i < 3; i++)
tile[i] = (point[i] - grid->mins[i]) * grid->gridscale[i];
for (i = 0, s = 0; i < 8; i++)
s += BSPX_LightGridSingleValue(grid, lightstyles,
tile[0]+!!(i&1),
tile[1]+!!(i&2),
tile[2]+!!(i&4), res_diffuse);
VectorScale(res_diffuse, 1.0/s, res_diffuse); //average the successful ones
}

View file

@ -2054,3 +2054,154 @@ Mod_LoadBSPX(int filesize, const byte *mod_base)
// success
return xheader;
}
/* Need to clean */
struct rctx_s {
const byte *data;
int ofs, size;
};
static byte ReadByte(struct rctx_s *ctx)
{
if (ctx->ofs >= ctx->size)
{
ctx->ofs++;
return 0;
}
return ctx->data[ctx->ofs++];
}
static int ReadInt(struct rctx_s *ctx)
{
int r = (int)ReadByte(ctx)<<0;
r|= (int)ReadByte(ctx)<<8;
r|= (int)ReadByte(ctx)<<16;
r|= (int)ReadByte(ctx)<<24;
return r;
}
static float ReadFloat(struct rctx_s *ctx)
{
union {float f; int i;} u;
u.i = ReadInt(ctx);
return u.f;
}
bspxlightgrid_t*
BSPX_LightGridLoad(const bspx_header_t *bspx_header, const byte *mod_base)
{
vec3_t step, mins;
int size[3];
bspxlightgrid_t *grid;
unsigned int numstyles, numnodes, numleafs, rootnode;
unsigned int nodestart, leafsamps = 0, i, j, k, s;
struct bspxlgsamp_s *samp;
struct rctx_s ctx = {0};
ctx.data = Mod_LoadBSPXFindLump(bspx_header, "LIGHTGRID_OCTREE", &ctx.size, mod_base);
if (!ctx.data)
{
return NULL;
}
for (j = 0; j < 3; j++)
step[j] = ReadFloat(&ctx);
for (j = 0; j < 3; j++)
size[j] = ReadInt(&ctx);
for (j = 0; j < 3; j++)
mins[j] = ReadFloat(&ctx);
numstyles = ReadByte(&ctx); //urgh, misaligned the entire thing
rootnode = ReadInt(&ctx);
numnodes = ReadInt(&ctx);
nodestart = ctx.ofs;
ctx.ofs += (3+8)*4*numnodes;
numleafs = ReadInt(&ctx);
for (i = 0; i < numleafs; i++)
{
unsigned int lsz[3];
ctx.ofs += 3*4;
for (j = 0; j < 3; j++)
lsz[j] = ReadInt(&ctx);
j = lsz[0]*lsz[1]*lsz[2];
leafsamps += j;
while (j --> 0)
{ //this loop is annonying, memcpy dreams...
s = ReadByte(&ctx);
if (s == 255)
continue;
ctx.ofs += s*4;
}
}
grid = Hunk_Alloc(sizeof(*grid) + sizeof(*grid->leafs)*numleafs + sizeof(*grid->nodes)*numnodes + sizeof(struct bspxlgsamp_s)*leafsamps);
memset(grid, 0xcc, sizeof(*grid) + sizeof(*grid->leafs)*numleafs + sizeof(*grid->nodes)*numnodes + sizeof(struct bspxlgsamp_s)*leafsamps);
grid->leafs = (void*)(grid+1);
grid->nodes = (void*)(grid->leafs + numleafs);
samp = (void*)(grid->nodes+numnodes);
for (j = 0; j < 3; j++)
grid->gridscale[j] = 1/step[j]; //prefer it as a multiply
VectorCopy(mins, grid->mins);
VectorCopy(size, grid->count);
grid->numnodes = numnodes;
grid->numleafs = numleafs;
grid->rootnode = rootnode;
(void)numstyles;
//rewind to the nodes. *sigh*
ctx.ofs = nodestart;
for (i = 0; i < numnodes; i++)
{
for (j = 0; j < 3; j++)
grid->nodes[i].mid[j] = ReadInt(&ctx);
for (j = 0; j < 8; j++)
grid->nodes[i].child[j] = ReadInt(&ctx);
}
ctx.ofs += 4;
for (i = 0; i < numleafs; i++)
{
for (j = 0; j < 3; j++)
grid->leafs[i].mins[j] = ReadInt(&ctx);
for (j = 0; j < 3; j++)
grid->leafs[i].size[j] = ReadInt(&ctx);
grid->leafs[i].rgbvalues = samp;
j = grid->leafs[i].size[0]*grid->leafs[i].size[1]*grid->leafs[i].size[2];
while (j --> 0)
{
s = ReadByte(&ctx);
if (s == 0xff)
memset(samp, 0xff, sizeof(*samp));
else
{
for (k = 0; k < s; k++)
{
if (k >= 4)
ReadInt(&ctx);
else
{
samp->map[k].style = ReadByte(&ctx);
samp->map[k].rgb[0] = ReadByte(&ctx);
samp->map[k].rgb[1] = ReadByte(&ctx);
samp->map[k].rgb[2] = ReadByte(&ctx);
}
}
for (; k < 4; k++)
{
samp->map[k].style = (byte)~0u;
samp->map[k].rgb[0] =
samp->map[k].rgb[1] =
samp->map[k].rgb[2] = 0;
}
}
samp++;
}
}
if (ctx.ofs != ctx.size)
grid = NULL;
return grid;
}

View file

@ -29,12 +29,12 @@
#define NUMVERTEXNORMALS 162
#define SHADEDOT_QUANT 16
float r_avertexnormals[NUMVERTEXNORMALS][3] = {
static float r_avertexnormals[NUMVERTEXNORMALS][3] = {
#include "../constants/anorms.h"
};
/* precalculated dot products for quantized angles */
float r_avertexnormal_dots[SHADEDOT_QUANT][256] = {
static float r_avertexnormal_dots[SHADEDOT_QUANT][256] = {
#include "../constants/anormtab.h"
};
@ -376,9 +376,9 @@ R_DrawAliasShadowCommand(entity_t *currententity, int *order, int *order_end,
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 ];
vtx[index_vtx++] = point[0];
vtx[index_vtx++] = point[1];
vtx[index_vtx++] = point[2];
order += 3;
}
@ -673,7 +673,8 @@ R_DrawAliasModel(entity_t *currententity, const model_t *currentmodel)
{
if (r_worldmodel->grid)
{
BSPX_LightGridValue(r_worldmodel->grid, currententity->origin, shadelight);
BSPX_LightGridValue(r_worldmodel->grid, r_newrefdef.lightstyles,
currententity->origin, shadelight);
}
else
{
@ -732,12 +733,13 @@ R_DrawAliasModel(entity_t *currententity, const model_t *currentmodel)
{
/* bonus items will pulse with time */
float scale;
float min;
scale = 0.1 * sin(r_newrefdef.time * 7);
for (i = 0; i < 3; i++)
{
float min;
min = shadelight[i] * 0.8;
shadelight[i] += scale;
@ -951,4 +953,3 @@ R_DrawAliasModel(entity_t *currententity, const model_t *currentmodel)
glColor4f(1, 1, 1, 1);
}

View file

@ -30,7 +30,7 @@ static YQ2_ALIGNAS_TYPE(int) byte mod_novis[MAX_MAP_LEAFS / 8];
#define MAX_MOD_KNOWN 512
static model_t mod_known[MAX_MOD_KNOWN];
static int mod_numknown;
static int mod_numknown = 0;
static int mod_max = 0;
int registration_sequence;
@ -1161,7 +1161,7 @@ Mod_ForName(const char *name, model_t *parent_model, qboolean crash)
return mod;
}
void
static void
Mod_Free(model_t *mod)
{
Hunk_Free(mod->extradata);
@ -1272,220 +1272,3 @@ RI_EndRegistration(void)
R_FreeUnusedImages();
}
/* Need to clean */
struct rctx_s {
const byte *data;
int ofs, size;
};
static byte ReadByte(struct rctx_s *ctx)
{
if (ctx->ofs >= ctx->size)
{
ctx->ofs++;
return 0;
}
return ctx->data[ctx->ofs++];
}
static int ReadInt(struct rctx_s *ctx)
{
int r = (int)ReadByte(ctx)<<0;
r|= (int)ReadByte(ctx)<<8;
r|= (int)ReadByte(ctx)<<16;
r|= (int)ReadByte(ctx)<<24;
return r;
}
static float ReadFloat(struct rctx_s *ctx)
{
union {float f; int i;} u;
u.i = ReadInt(ctx);
return u.f;
}
bspxlightgrid_t*
BSPX_LightGridLoad(const bspx_header_t *bspx_header, const byte *mod_base)
{
vec3_t step, mins;
int size[3];
bspxlightgrid_t *grid;
unsigned int numstyles, numnodes, numleafs, rootnode;
unsigned int nodestart, leafsamps = 0, i, j, k, s;
struct bspxlgsamp_s *samp;
struct rctx_s ctx = {0};
ctx.data = Mod_LoadBSPXFindLump(bspx_header, "LIGHTGRID_OCTREE", &ctx.size, mod_base);
if (!ctx.data)
{
return NULL;
}
for (j = 0; j < 3; j++)
step[j] = ReadFloat(&ctx);
for (j = 0; j < 3; j++)
size[j] = ReadInt(&ctx);
for (j = 0; j < 3; j++)
mins[j] = ReadFloat(&ctx);
numstyles = ReadByte(&ctx); //urgh, misaligned the entire thing
rootnode = ReadInt(&ctx);
numnodes = ReadInt(&ctx);
nodestart = ctx.ofs;
ctx.ofs += (3+8)*4*numnodes;
numleafs = ReadInt(&ctx);
for (i = 0; i < numleafs; i++)
{
unsigned int lsz[3];
ctx.ofs += 3*4;
for (j = 0; j < 3; j++)
lsz[j] = ReadInt(&ctx);
j = lsz[0]*lsz[1]*lsz[2];
leafsamps += j;
while (j --> 0)
{ //this loop is annonying, memcpy dreams...
s = ReadByte(&ctx);
if (s == 255)
continue;
ctx.ofs += s*4;
}
}
grid = Hunk_Alloc(sizeof(*grid) + sizeof(*grid->leafs)*numleafs + sizeof(*grid->nodes)*numnodes + sizeof(struct bspxlgsamp_s)*leafsamps);
memset(grid, 0xcc, sizeof(*grid) + sizeof(*grid->leafs)*numleafs + sizeof(*grid->nodes)*numnodes + sizeof(struct bspxlgsamp_s)*leafsamps);
grid->leafs = (void*)(grid+1);
grid->nodes = (void*)(grid->leafs + numleafs);
samp = (void*)(grid->nodes+numnodes);
for (j = 0; j < 3; j++)
grid->gridscale[j] = 1/step[j]; //prefer it as a multiply
VectorCopy(mins, grid->mins);
VectorCopy(size, grid->count);
grid->numnodes = numnodes;
grid->numleafs = numleafs;
grid->rootnode = rootnode;
(void)numstyles;
//rewind to the nodes. *sigh*
ctx.ofs = nodestart;
for (i = 0; i < numnodes; i++)
{
for (j = 0; j < 3; j++)
grid->nodes[i].mid[j] = ReadInt(&ctx);
for (j = 0; j < 8; j++)
grid->nodes[i].child[j] = ReadInt(&ctx);
}
ctx.ofs += 4;
for (i = 0; i < numleafs; i++)
{
for (j = 0; j < 3; j++)
grid->leafs[i].mins[j] = ReadInt(&ctx);
for (j = 0; j < 3; j++)
grid->leafs[i].size[j] = ReadInt(&ctx);
grid->leafs[i].rgbvalues = samp;
j = grid->leafs[i].size[0]*grid->leafs[i].size[1]*grid->leafs[i].size[2];
while (j --> 0)
{
s = ReadByte(&ctx);
if (s == 0xff)
memset(samp, 0xff, sizeof(*samp));
else
{
for (k = 0; k < s; k++)
{
if (k >= 4)
ReadInt(&ctx);
else
{
samp->map[k].style = ReadByte(&ctx);
samp->map[k].rgb[0] = ReadByte(&ctx);
samp->map[k].rgb[1] = ReadByte(&ctx);
samp->map[k].rgb[2] = ReadByte(&ctx);
}
}
for (; k < 4; k++)
{
samp->map[k].style = (byte)~0u;
samp->map[k].rgb[0] =
samp->map[k].rgb[1] =
samp->map[k].rgb[2] = 0;
}
}
samp++;
}
}
if (ctx.ofs != ctx.size)
grid = NULL;
return grid;
}
static int
BSPX_LightGridSingleValue(bspxlightgrid_t *grid, int x, int y, int z, vec3_t res_diffuse)
{
int i;
unsigned int node;
struct bspxlgsamp_s *samp;
node = grid->rootnode;
while (!(node & LGNODE_LEAF))
{
struct bspxlgnode_s *n;
if (node & LGNODE_MISSING)
return 0; //failure
n = grid->nodes + node;
node = n->child[
((x>=n->mid[0])<<2)|
((y>=n->mid[1])<<1)|
((z>=n->mid[2])<<0)];
}
{
struct bspxlgleaf_s *leaf = &grid->leafs[node & ~LGNODE_LEAF];
x -= leaf->mins[0];
y -= leaf->mins[1];
z -= leaf->mins[2];
if (x >= leaf->size[0] ||
y >= leaf->size[1] ||
z >= leaf->size[2])
return 0; //sample we're after is out of bounds...
i = x + leaf->size[0]*(y + leaf->size[1]*z);
samp = leaf->rgbvalues + i;
//no hdr support
for (i = 0; i < 4; i++)
{
if (samp->map[i].style == ((byte)(~0u)))
break; //no more
res_diffuse[0] += samp->map[i].rgb[0] * r_newrefdef.lightstyles[samp->map[i].style].rgb[0] / 255.0;
res_diffuse[1] += samp->map[i].rgb[1] * r_newrefdef.lightstyles[samp->map[i].style].rgb[1] / 255.0;
res_diffuse[2] += samp->map[i].rgb[2] * r_newrefdef.lightstyles[samp->map[i].style].rgb[2] / 255.0;
}
}
return 1;
}
void
BSPX_LightGridValue(bspxlightgrid_t *grid, const vec3_t point, vec3_t res_diffuse)
{
int tile[3];
int i;
int s;
VectorSet(res_diffuse, 0, 0, 0); //assume worst
for (i = 0; i < 3; i++)
tile[i] = (point[i] - grid->mins[i]) * grid->gridscale[i];
for (i = 0, s = 0; i < 8; i++)
s += BSPX_LightGridSingleValue(grid, tile[0]+!!(i&1),
tile[1]+!!(i&2),
tile[2]+!!(i&4), res_diffuse);
VectorScale(res_diffuse, 1.0/s, res_diffuse); //average the successful ones
}

View file

@ -29,41 +29,6 @@
#include "../../ref_model.h"
typedef struct
{
vec3_t gridscale;
unsigned int count[3];
vec3_t mins;
unsigned int styles;
unsigned int rootnode;
unsigned int numnodes;
struct bspxlgnode_s
{ //this uses an octtree to trim samples.
int mid[3];
unsigned int child[8];
#define LGNODE_LEAF (1u<<31)
#define LGNODE_MISSING (1u<<30)
} *nodes;
unsigned int numleafs;
struct bspxlgleaf_s
{
int mins[3];
int size[3];
struct bspxlgsamp_s
{
struct
{
byte style;
byte rgb[3];
} map[4];
} *rgbvalues;
} *leafs;
} bspxlightgrid_t;
bspxlightgrid_t* BSPX_LightGridLoad(const bspx_header_t *bspx_header, const byte *mod_base);
void BSPX_LightGridValue(bspxlightgrid_t *grid, const vec3_t point, vec3_t res_diffuse);
/* Whole model */
typedef struct model_s
@ -149,6 +114,5 @@ int Hunk_End(void);
void Hunk_Free(void *base);
void Mod_FreeAll(void);
void Mod_Free(model_t *mod);
#endif

View file

@ -179,6 +179,50 @@ typedef struct mleaf_s
int key; /* BSP sequence number for leaf's contents */
} mleaf_t;
/* BSPX Light octtree */
#define LGNODE_LEAF (1u<<31)
#define LGNODE_MISSING (1u<<30)
/* this uses an octtree to trim samples. */
typedef struct bspxlgnode_s
{
int mid[3];
unsigned int child[8];
} bspxlgnode_t;
typedef struct bspxlglightstyle_s
{
byte style;
byte rgb[3];
} bspxlglightstyle_t;
typedef struct bspxlgsamp_s
{
bspxlglightstyle_t map[4];
} bspxlgsamp_t;
typedef struct bspxlgleaf_s
{
int mins[3];
int size[3];
bspxlgsamp_t *rgbvalues;
} bspxlgleaf_t;
typedef struct
{
vec3_t gridscale;
unsigned int count[3];
vec3_t mins;
unsigned int styles;
unsigned int rootnode;
unsigned int numnodes;
bspxlgnode_t *nodes;
unsigned int numleafs;
bspxlgleaf_t *leafs;
} bspxlightgrid_t;
/* Shared models func */
typedef struct image_s* (*findimage_t)(const char *name, imagetype_t type);
extern void *Mod_LoadAliasModel (const char *mod_name, const void *buffer, int modfilelen,
@ -237,4 +281,9 @@ extern void R_SetFrustum(vec3_t vup, vec3_t vpn, vec3_t vright, vec3_t r_origin,
float fov_x, float fov_y, cplane_t *frustum);
extern void R_BoundPoly(int numverts, float *verts, vec3_t mins, vec3_t maxs);
/* Lights logic */
extern bspxlightgrid_t *BSPX_LightGridLoad(const bspx_header_t *bspx_header, const byte *mod_base);
extern void BSPX_LightGridValue(const bspxlightgrid_t *grid, const lightstyle_t *lightstyles,
const vec3_t point, vec3_t res_diffuse);
#endif /* SRC_CLIENT_REFRESH_REF_SHARED_H_ */

View file

@ -54,91 +54,86 @@ BRUSH MODELS
typedef struct model_s
{
char name[MAX_QPATH];
char name[MAX_QPATH];
int registration_sequence;
int registration_sequence;
modtype_t type;
int numframes;
modtype_t type;
int numframes;
int flags;
int flags;
//
// volume occupied by the model graphics
//
vec3_t mins, maxs;
float radius;
/* volume occupied by the model graphics */
vec3_t mins, maxs;
float radius;
//
// solid volume for clipping
//
qboolean clipbox;
vec3_t clipmins, clipmaxs;
/* solid volume for clipping */
qboolean clipbox;
vec3_t clipmins, clipmaxs;
//
// brush model
//
int firstmodelsurface, nummodelsurfaces;
int lightmap; // only for submodels
/* brush model */
int firstmodelsurface, nummodelsurfaces;
int lightmap; /* only for submodels */
int numsubmodels;
struct model_s *submodels;
int numsubmodels;
struct model_s *submodels;
int numplanes;
cplane_t *planes;
int numplanes;
cplane_t *planes;
int numleafs; // number of visible leafs, not counting 0
mleaf_t *leafs;
int numleafs; /* number of visible leafs, not counting 0 */
mleaf_t *leafs;
int numvertexes;
mvertex_t *vertexes;
int numvertexes;
mvertex_t *vertexes;
int numedges;
medge_t *edges;
int numedges;
medge_t *edges;
int numnodes;
int firstnode;
mnode_t *nodes;
int numnodes;
int firstnode;
mnode_t *nodes;
int numtexinfo;
mtexinfo_t *texinfo;
int numtexinfo;
mtexinfo_t *texinfo;
int numsurfaces;
msurface_t *surfaces;
int numsurfaces;
msurface_t *surfaces;
int numsurfedges;
int *surfedges;
int numsurfedges;
int *surfedges;
int nummarksurfaces;
msurface_t **marksurfaces;
int nummarksurfaces;
msurface_t **marksurfaces;
dvis_t *vis;
dvis_t *vis;
byte *lightdata;
byte *lightdata;
// for alias models and skins
image_t *skins[MAX_MD2SKINS];
/* for alias models and skins */
image_t *skins[MAX_MD2SKINS];
int extradatasize;
void *extradata;
int extradatasize;
void *extradata;
// submodules
vec3_t origin; // for sounds or lights
/* octree */
bspxlightgrid_t *grid;
} model_t;
//============================================================================
void Mod_Init(void);
const byte *Mod_ClusterPVS(int cluster, const model_t *model);
void Mod_Init (void);
const byte *Mod_ClusterPVS (int cluster, const model_t *model);
void Mod_Modellist_f(void);
void Mod_Modellist_f (void);
void *Hunk_Begin(int maxsize);
void *Hunk_Alloc(int size);
int Hunk_End(void);
void Hunk_Free(void *base);
void *Hunk_Begin (int maxsize);
void *Hunk_Alloc (int size);
int Hunk_End (void);
void Hunk_Free (void *base);
void Mod_FreeAll (void);
void Mod_FreeAll(void);
void Mod_FreeModelsKnown (void);
#endif

View file

@ -20,23 +20,15 @@
*
* =======================================================================
*
* Triangle model functions
* Mesh handling
*
* =======================================================================
*
*/
#include "header/local.h"
/*
=============================================================
ALIAS MODELS
=============================================================
*/
#define NUMVERTEXNORMALS 162
#define NUMVERTEXNORMALS 162
#define SHADEDOT_QUANT 16
static float r_avertexnormals[NUMVERTEXNORMALS][3] = {
#include "../constants/anorms.h"
@ -64,20 +56,18 @@ polyvert_t *verts_buffer = NULL;
lmappolyvert_t *lmappolyverts_buffer = NULL;
static drawinfo_t *drawInfo[2] = {NULL, NULL};
static modelvert *vertList[2] = {NULL, NULL};
static vec4_t *s_lerped = NULL;
static vec3_t *shadowverts = NULL;
static int verts_count = 0;
vec3_t shadevector;
float shadelight[3];
// precalculated dot products for quantized angles
#define SHADEDOT_QUANT 16
/* precalculated dot products for quantized angles */
static float r_avertexnormal_dots[SHADEDOT_QUANT][256] = {
#include "../constants/anormtab.h"
};
float *shadedots = r_avertexnormal_dots[0];
static vec4_t *s_lerped = NULL;
vec3_t shadevector;
float shadelight[3];
float *shadedots = r_avertexnormal_dots[0];
// correction matrix with "hacked depth" for models with RF_DEPTHHACK flag set
static float r_vulkan_correction_dh[16] = {
@ -244,34 +234,39 @@ void Mesh_Free (void)
}
static void Vk_LerpVerts( int nverts, dtrivertx_t *v, dtrivertx_t *ov, dtrivertx_t *verts,
static void
Vk_LerpVerts(int nverts, dtrivertx_t *v, dtrivertx_t *ov, dtrivertx_t *verts,
float *lerp, const float move[3], const float frontv[3], const float backv[3],
entity_t *currententity )
entity_t *currententity)
{
int i;
//PMM -- added RF_SHELL_DOUBLE, RF_SHELL_HALF_DAM
if ( currententity->flags & ( RF_SHELL_RED | RF_SHELL_GREEN | RF_SHELL_BLUE | RF_SHELL_DOUBLE | RF_SHELL_HALF_DAM) )
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 )
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;
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)
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];
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];
}
}
}
static void
@ -298,10 +293,11 @@ Vk_DrawAliasFrameLerpCommands (entity_t *currententity, int *order, int *order_e
while (1)
{
int count;
int count;
// get the vertex count and primitive type
/* get the vertex count and primitive type */
count = *order++;
if (!count || order >= order_end)
{
break; /* done */
@ -325,7 +321,8 @@ Vk_DrawAliasFrameLerpCommands (entity_t *currententity, int *order, int *order_e
drawInfo[pipelineIdx][pipeCounters[pipelineIdx]].vertexCount = count;
maxTriangleFanIdxCnt = max(maxTriangleFanIdxCnt, ((count - 2) * 3));
if (currententity->flags & (RF_SHELL_RED | RF_SHELL_GREEN | RF_SHELL_BLUE))
if (currententity->flags &
(RF_SHELL_RED | RF_SHELL_GREEN | RF_SHELL_BLUE))
{
meshUbo.textured = 0;
do
@ -469,57 +466,61 @@ FIXME: batch lerp all vertexes
=============
*/
static void
Vk_DrawAliasFrameLerp (dmdl_t *paliashdr, float backlerp, image_t *skin,
Vk_DrawAliasFrameLerp(dmdl_t *paliashdr, float backlerp, image_t *skin,
float *modelMatrix, int leftHandOffset, int translucentIdx, entity_t *currententity)
{
daliasframe_t *frame, *oldframe;
dtrivertx_t *v, *ov, *verts;
int *order;
float frontlerp;
float alpha;
vec3_t move, delta, vectors[3];
vec3_t frontv, backv;
int i;
float *lerp;
daliasframe_t *frame, *oldframe;
dtrivertx_t *v, *ov, *verts;
int *order;
float frontlerp;
float alpha;
vec3_t move, delta, vectors[3];
vec3_t frontv, backv;
int i;
float *lerp;
int num_mesh_nodes;
short *mesh_nodes;
frame = (daliasframe_t *)((byte *)paliashdr + paliashdr->ofs_frames
+ currententity->frame * paliashdr->framesize);
+ currententity->frame * paliashdr->framesize);
verts = v = frame->verts;
oldframe = (daliasframe_t *)((byte *)paliashdr + paliashdr->ofs_frames
+ currententity->oldframe * paliashdr->framesize);
+ 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;
}
frontlerp = 1.0 - backlerp;
// move should be the delta back to the previous frame * 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]);
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
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);
VectorAdd(move, oldframe->translate, move);
for (i=0 ; i<3 ; i++)
for (i = 0; i < 3; i++)
{
move[i] = backlerp*move[i] + frontlerp*frame->translate[i];
move[i] = backlerp * move[i] + frontlerp * frame->translate[i];
}
for (i=0 ; i<3 ; i++)
for (i = 0; i < 3; i++)
{
frontv[i] = frontlerp*frame->scale[i];
backv[i] = backlerp*oldframe->scale[i];
frontv[i] = frontlerp * frame->scale[i];
backv[i] = backlerp * oldframe->scale[i];
}
if (Mesh_VertsRealloc(paliashdr->num_xyz))
@ -529,7 +530,7 @@ Vk_DrawAliasFrameLerp (dmdl_t *paliashdr, float backlerp, image_t *skin,
lerp = s_lerped[0];
Vk_LerpVerts( paliashdr->num_xyz, v, ov, verts, lerp, move, frontv, backv, currententity );
Vk_LerpVerts(paliashdr->num_xyz, v, ov, verts, lerp, move, frontv, backv, currententity );
num_mesh_nodes = (paliashdr->ofs_skins - sizeof(dmdl_t)) / sizeof(short) / 2;
mesh_nodes = (short *)((char*)paliashdr + sizeof(dmdl_t));
@ -554,13 +555,8 @@ Vk_DrawAliasFrameLerp (dmdl_t *paliashdr, float backlerp, image_t *skin,
}
}
/*
=============
Vk_DrawAliasShadow
=============
*/
static void Vk_DrawAliasShadow (int *order, int *order_end, int posenum,
static void
Vk_DrawAliasShadow(int *order, int *order_end, int posenum,
float *modelMatrix, entity_t *currententity)
{
vec3_t point;
@ -579,8 +575,7 @@ static void Vk_DrawAliasShadow (int *order, int *order_end, int posenum,
while (1)
{
int i;
int count;
int i, count;
i = 0;
// get the vertex count and primitive type
@ -612,11 +607,11 @@ static void Vk_DrawAliasShadow (int *order, int *order_end, int posenum,
ri.Sys_Error(ERR_FATAL, "%s: can't allocate memory", __func__);
}
// normals and vertexes come from the frame list
memcpy( point, s_lerped[order[2]], sizeof( point ) );
/* 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[0] -= shadevector[0] * (point[2] + lheight);
point[1] -= shadevector[1] * (point[2] + lheight);
point[2] = height;
shadowverts[i][0] = point[0];
@ -625,7 +620,8 @@ static void Vk_DrawAliasShadow (int *order, int *order_end, int posenum,
order += 3;
i++;
} while (--count);
}
while (--count);
if (i > 0)
{
@ -653,142 +649,158 @@ static void Vk_DrawAliasShadow (int *order, int *order_end, int posenum,
}
}
/*
** R_CullAliasModel
*/
static qboolean R_CullAliasModel( vec3_t bbox[8], entity_t *e, model_t *currentmodel )
static qboolean
R_CullAliasModel(vec3_t bbox[8], entity_t *e, model_t *currentmodel )
{
int i;
vec3_t mins, maxs;
dmdl_t *paliashdr;
vec3_t vectors[3];
vec3_t thismins, oldmins, thismaxs, oldmaxs;
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 ) )
if (!paliashdr)
{
R_Printf(PRINT_ALL, "%s %s: no such frame %d\n",
__func__, currentmodel->name, e->frame);
R_Printf(PRINT_ALL, "%s %s: Model is not fully loaded\n",
__func__, currentmodel->name);
return true;
}
if ((e->frame >= paliashdr->num_frames) || (e->frame < 0))
{
R_Printf(PRINT_DEVELOPER, "%s %s: no such frame %d\n",
__func__, currentmodel->name, e->frame);
e->frame = 0;
}
if ( ( e->oldframe >= paliashdr->num_frames ) || ( e->oldframe < 0 ) )
if ((e->oldframe >= paliashdr->num_frames) || (e->oldframe < 0))
{
R_Printf(PRINT_ALL, "%s %s: no such oldframe %d\n",
__func__, currentmodel->name, e->oldframe);
R_Printf(PRINT_DEVELOPER, "%s %s: no such oldframe %d\n",
__func__, currentmodel->name, e->oldframe);
e->oldframe = 0;
}
pframe = ( daliasframe_t * ) ( ( byte * ) paliashdr +
paliashdr->ofs_frames +
e->frame * paliashdr->framesize);
pframe = (daliasframe_t *)((byte *)paliashdr + paliashdr->ofs_frames +
e->frame * paliashdr->framesize);
poldframe = ( daliasframe_t * ) ( ( byte * ) paliashdr +
paliashdr->ofs_frames +
e->oldframe * paliashdr->framesize);
poldframe = (daliasframe_t *)((byte *)paliashdr + paliashdr->ofs_frames +
e->oldframe * paliashdr->framesize);
/*
** compute axially aligned mins and maxs
*/
if ( pframe == poldframe )
/* compute axially aligned mins and maxs */
if (pframe == poldframe)
{
for ( i = 0; i < 3; i++ )
for (i = 0; i < 3; i++)
{
mins[i] = pframe->translate[i];
maxs[i] = mins[i] + pframe->scale[i]*255;
maxs[i] = mins[i] + pframe->scale[i] * 255;
}
}
else
{
for ( i = 0; i < 3; i++ )
for (i = 0; i < 3; i++)
{
thismins[i] = pframe->translate[i];
thismaxs[i] = thismins[i] + pframe->scale[i]*255;
thismaxs[i] = thismins[i] + pframe->scale[i] * 255;
oldmins[i] = poldframe->translate[i];
oldmaxs[i] = oldmins[i] + poldframe->scale[i]*255;
oldmins[i] = poldframe->translate[i];
oldmaxs[i] = oldmins[i] + poldframe->scale[i] * 255;
if ( thismins[i] < oldmins[i] )
if (thismins[i] < oldmins[i])
{
mins[i] = thismins[i];
}
else
{
mins[i] = oldmins[i];
}
if ( thismaxs[i] > oldmaxs[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++ )
/* compute a full bounding box */
for (i = 0; i < 8; i++)
{
vec3_t tmp;
VectorCopy( bbox[i], tmp );
if (i & 1)
{
tmp[0] = mins[0];
}
else
{
tmp[0] = maxs[0];
}
bbox[i][0] = DotProduct( vectors[0], tmp );
bbox[i][1] = -DotProduct( vectors[1], tmp );
bbox[i][2] = DotProduct( vectors[2], tmp );
if (i & 2)
{
tmp[1] = mins[1];
}
else
{
tmp[1] = maxs[1];
}
VectorAdd( e->origin, bbox[i], bbox[i] );
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++ )
for (p = 0; p < 8; p++)
{
int mask = 0;
for ( f = 0; f < 4; f++ )
for (f = 0; f < 4; f++)
{
float dp = DotProduct( frustum[f].normal, bbox[p] );
if ( ( dp - frustum[f].dist ) < 0 )
if ((dp - frustum[f].dist ) < 0)
{
mask |= ( 1 << f );
mask |= (1 << f);
}
}
aggregatemask &= mask;
}
if ( aggregatemask )
if (aggregatemask)
{
return true;
}
@ -797,100 +809,129 @@ static qboolean R_CullAliasModel( vec3_t bbox[8], entity_t *e, model_t *currentm
}
}
/*
=================
R_DrawAliasModel
=================
*/
void R_DrawAliasModel (entity_t *currententity, model_t *currentmodel)
void
R_DrawAliasModel(entity_t *currententity, model_t *currentmodel)
{
int i;
int leftHandOffset = 0;
dmdl_t *paliashdr;
float an;
float prev_viewproj[16];
int i;
int leftHandOffset = 0;
dmdl_t *paliashdr;
float an;
float prev_viewproj[16];
if ( !( currententity->flags & RF_WEAPONMODEL ) )
if (!(currententity->flags & RF_WEAPONMODEL))
{
vec3_t bbox[8];
vec3_t bbox[8];
if ( R_CullAliasModel( bbox, currententity, currentmodel ) )
if (R_CullAliasModel( bbox, currententity, currentmodel))
{
return;
}
}
if ( currententity->flags & RF_WEAPONMODEL )
if (currententity->flags & RF_WEAPONMODEL)
{
if ( r_lefthand->value == 2 )
if (r_lefthand->value == 2)
{
return;
}
}
paliashdr = (dmdl_t *)currentmodel->extradata;
//
// get lighting information
//
// PMM - rewrote, reordered to handle new shells & mixing
// PMM - 3.20 code .. replaced with original way of doing it to keep mod authors happy
//
if ( currententity->flags & ( RF_SHELL_HALF_DAM | RF_SHELL_GREEN | RF_SHELL_RED | RF_SHELL_BLUE | RF_SHELL_DOUBLE ) )
/* get lighting information */
if (currententity->flags &
(RF_SHELL_HALF_DAM | RF_SHELL_GREEN | RF_SHELL_RED |
RF_SHELL_BLUE | RF_SHELL_DOUBLE))
{
VectorClear (shadelight);
VectorClear(shadelight);
if (currententity->flags & RF_SHELL_HALF_DAM)
{
shadelight[0] = 0.56;
shadelight[1] = 0.59;
shadelight[2] = 0.45;
shadelight[0] = 0.56;
shadelight[1] = 0.59;
shadelight[2] = 0.45;
}
if ( currententity->flags & RF_SHELL_DOUBLE )
if (currententity->flags & RF_SHELL_DOUBLE)
{
shadelight[0] = 0.9;
shadelight[1] = 0.7;
}
if ( currententity->flags & RF_SHELL_RED )
if (currententity->flags & RF_SHELL_RED)
{
shadelight[0] = 1.0;
if ( currententity->flags & RF_SHELL_GREEN )
}
if (currententity->flags & RF_SHELL_GREEN)
{
shadelight[1] = 1.0;
if ( currententity->flags & RF_SHELL_BLUE )
}
if (currententity->flags & RF_SHELL_BLUE)
{
shadelight[2] = 1.0;
}
}
else if ( currententity->flags & RF_FULLBRIGHT )
else if (currententity->flags & RF_FULLBRIGHT)
{
for (i=0 ; i<3 ; i++)
for (i = 0; i < 3; i++)
{
shadelight[i] = 1.0;
}
}
else
{
R_LightPoint(currententity->origin, shadelight, currententity);
// player lighting hack for communication back to server
// big hack!
if ( currententity->flags & RF_WEAPONMODEL )
if (r_worldmodel->grid)
{
// pick the greatest component, which should be the same
// as the mono value returned by software
BSPX_LightGridValue(r_worldmodel->grid, r_newrefdef.lightstyles,
currententity->origin, shadelight);
}
else
{
R_LightPoint(currententity->origin, shadelight, currententity);
}
/* 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])
r_lightlevel->value = 150*shadelight[0];
{
r_lightlevel->value = 150 * shadelight[0];
}
else
r_lightlevel->value = 150*shadelight[2];
{
r_lightlevel->value = 150 * shadelight[2];
}
}
else
{
if (shadelight[1] > shadelight[2])
r_lightlevel->value = 150*shadelight[1];
{
r_lightlevel->value = 150 * shadelight[1];
}
else
r_lightlevel->value = 150*shadelight[2];
{
r_lightlevel->value = 150 * shadelight[2];
}
}
}
}
if ( currententity->flags & RF_MINLIGHT )
if (currententity->flags & RF_MINLIGHT)
{
for (i=0 ; i<3 ; i++)
for (i = 0; i < 3; i++)
{
if (shadelight[i] > 0.1)
{
break;
}
}
if (i == 3)
{
shadelight[0] = 0.1;
@ -899,50 +940,49 @@ void R_DrawAliasModel (entity_t *currententity, model_t *currentmodel)
}
}
if ( currententity->flags & RF_GLOW )
{ // bonus items will pulse with time
float scale;
if (currententity->flags & RF_GLOW)
{
/* bonus items will pulse with time */
float scale;
scale = 0.1 * sin(r_newrefdef.time*7);
for (i=0 ; i<3 ; i++)
scale = 0.1 * sin(r_newrefdef.time * 7);
for (i = 0; i < 3; i++)
{
float min;
min = shadelight[i] * 0.8;
shadelight[i] += scale;
if (shadelight[i] < min)
{
shadelight[i] = min;
}
}
}
// =================
// PGM ir goggles color override
if ( r_newrefdef.rdflags & RDF_IRGOGGLES && currententity->flags & RF_IR_VISIBLE)
/* ir goggles color override */
if (r_newrefdef.rdflags & RDF_IRGOGGLES && currententity->flags &
RF_IR_VISIBLE)
{
shadelight[0] = 1.0;
shadelight[1] = 0.0;
shadelight[2] = 0.0;
}
// PGM
// =================
shadedots = r_avertexnormal_dots[((int)(currententity->angles[1] * (SHADEDOT_QUANT / 360.0))) & (SHADEDOT_QUANT - 1)];
shadedots = r_avertexnormal_dots[((int)(currententity->angles[1] *
(SHADEDOT_QUANT / 360.0))) & (SHADEDOT_QUANT - 1)];
an = currententity->angles[1]/180*M_PI;
an = currententity->angles[1] / 180 * M_PI;
shadevector[0] = cos(-an);
shadevector[1] = sin(-an);
shadevector[2] = 1;
VectorNormalize (shadevector);
//
// locate the proper data
//
VectorNormalize(shadevector);
/* locate the proper data */
c_alias_polys += paliashdr->num_tris;
//
// draw all the triangles
//
/* draw all the triangles */
if (currententity->flags & RF_DEPTHHACK || r_newrefdef.rdflags & RDF_NOWORLDMODEL) { // hack the depth range to prevent view model from poking into walls
float r_proj_aspect = (float)r_newrefdef.width / r_newrefdef.height;
float r_proj_fovy = r_newrefdef.fov_y;

View file

@ -23,19 +23,18 @@
* Model loading and caching. Includes the .bsp file format
*
* =======================================================================
*
*/
#include "header/local.h"
YQ2_ALIGNAS_TYPE(int) static byte mod_novis[MAX_MAP_LEAFS/8];
static YQ2_ALIGNAS_TYPE(int) byte mod_novis[MAX_MAP_LEAFS / 8];
#define MAX_MOD_KNOWN 512
static model_t *models_known;
static int mod_numknown = 0;
static int mod_loaded = 0;
static int mod_max = 0;
static int models_known_max = 0;
#define MAX_MOD_KNOWN 512
static model_t *models_known;
static int mod_numknown = 0;
static int mod_max = 0;
static int mod_loaded = 0;
static int models_known_max = 0;
int registration_sequence;
@ -160,7 +159,7 @@ Mod_LoadSubmodels(model_t *loadmodel, const byte *mod_base, const lump_t *l)
* Fills in s->texturemins[] and s->extents[]
*/
static void
CalcSurfaceExtents(model_t *loadmodel, msurface_t *s)
Mod_CalcSurfaceExtents(model_t *loadmodel, msurface_t *s)
{
float mins[2], maxs[2], val;
int i;
@ -510,7 +509,7 @@ Mod_LoadFaces(model_t *loadmodel, const byte *mod_base, const lump_t *l,
out->lmvlen[0] = 1.0f;
out->lmvlen[1] = 1.0f;
CalcSurfaceExtents(loadmodel, out);
Mod_CalcSurfaceExtents(loadmodel, out);
lightofs = in->lightofs;
}
@ -633,7 +632,7 @@ Mod_LoadQFaces(model_t *loadmodel, const byte *mod_base, const lump_t *l,
out->lmvlen[0] = 1.0f;
out->lmvlen[1] = 1.0f;
CalcSurfaceExtents(loadmodel, out);
Mod_CalcSurfaceExtents(loadmodel, out);
lightofs = in->lightofs;
}
@ -900,6 +899,9 @@ Mod_LoadBrushModel(model_t *mod, const void *buffer, int modfilelen)
((int *)header)[i] = LittleLong(((int *)header)[i]);
}
/* check for BSPX extensions */
bspx_header = Mod_LoadBSPX(modfilelen, (byte*)header);
// calculate the needed hunksize from the lumps
int hunkSize = 0;
hunkSize += calcLumpHunkSize(&header->lumps[LUMP_VERTEXES], sizeof(dvertex_t), sizeof(mvertex_t));
@ -943,8 +945,10 @@ Mod_LoadBrushModel(model_t *mod, const void *buffer, int modfilelen)
mod->extradata = Hunk_Begin(hunkSize);
mod->type = mod_brush;
/* check for BSPX extensions */
bspx_header = Mod_LoadBSPX(modfilelen, (byte*)header);
if (bspx_header)
{
mod->grid = BSPX_LightGridLoad(bspx_header, mod_base);
}
/* load into heap */
Mod_LoadVertexes(mod->name, &mod->vertexes, &mod->numvertexes, mod_base,
@ -996,69 +1000,73 @@ Mod_LoadBrushModel(model_t *mod, const void *buffer, int modfilelen)
mod->numframes = 2; /* regular and alternate animation */
}
//=============================================================================
/*
==================
Mod_ForName
Loads in a model for the given name
==================
*/
* Loads in a model for the given name
*/
static model_t *
Mod_ForName (const char *name, model_t *parent_model, qboolean crash)
Mod_ForName(const char *name, model_t *parent_model, qboolean crash)
{
model_t *mod;
void *buf;
int i, modfilelen;
model_t *mod;
void *buf;
int i, modfilelen;
if (!name[0])
{
ri.Sys_Error(ERR_DROP, "%s: NULL name", __func__);
}
//
// inline models are grabbed only from worldmodel
//
/* inline models are grabbed only from worldmodel */
if (name[0] == '*' && parent_model)
{
i = atoi(name+1);
i = (int)strtol(name + 1, (char **)NULL, 10);
if (i < 1 || i >= parent_model->numsubmodels)
ri.Sys_Error (ERR_DROP, "bad inline model number");
{
ri.Sys_Error(ERR_DROP, "%s: bad inline model number",
__func__);
}
return &parent_model->submodels[i];
}
//
// search the currently loaded models
//
for (i=0 , mod=models_known ; i<mod_numknown ; i++, mod++)
/* search the currently loaded models */
for (i = 0, mod = models_known; i < mod_numknown; i++, mod++)
{
if (!mod->name[0])
{
continue;
if (!strcmp (mod->name, name) )
}
if (!strcmp(mod->name, name))
{
return mod;
}
}
//
// find a free model slot spot
//
for (i=0 , mod=models_known ; i<mod_numknown ; i++, mod++)
/* find a free model slot spot */
for (i = 0, mod = models_known; i < mod_numknown; i++, mod++)
{
if (!mod->name[0])
break; // free spot
{
break; /* free spot */
}
}
if (i == mod_numknown)
{
if (mod_numknown == models_known_max)
{
ri.Sys_Error(ERR_DROP, "%s: mod_numknown == models_known_max", __func__);
}
mod_numknown++;
}
strcpy (mod->name, name);
//
// load the file
//
strcpy(mod->name, name);
/* load the file */
modfilelen = Mod_LoadFile (mod->name, &buf);
if (!buf)
{
if (crash)
@ -1071,7 +1079,8 @@ Mod_ForName (const char *name, model_t *parent_model, qboolean crash)
{
R_Printf(PRINT_ALL, "%s: Can't load %s\n", __func__, mod->name);
}
memset (mod->name, 0, sizeof(mod->name));
memset(mod->name, 0, sizeof(mod->name));
return NULL;
}
@ -1086,59 +1095,58 @@ Mod_ForName (const char *name, model_t *parent_model, qboolean crash)
// fill it in
//
// call the apropriate loader
/* call the apropriate loader */
switch (LittleLong(*(unsigned *)buf))
{
case DKMHEADER:
/* fall through */
case RAVENFMHEADER:
/* fall through */
case IDALIASHEADER:
/* fall through */
case IDMDLHEADER:
{
mod->extradata = Mod_LoadAliasModel(mod->name, buf, modfilelen,
mod->mins, mod->maxs,
(struct image_s **)mod->skins, (findimage_t)Vk_FindImage,
&(mod->type));
if (!mod->extradata)
case DKMHEADER:
/* fall through */
case RAVENFMHEADER:
/* fall through */
case IDALIASHEADER:
/* fall through */
case IDMDLHEADER:
{
ri.Sys_Error(ERR_DROP, "%s: Failed to load %s",
__func__, mod->name);
}
};
break;
mod->extradata = Mod_LoadAliasModel(mod->name, buf, modfilelen,
mod->mins, mod->maxs,
(struct image_s **)mod->skins, (findimage_t)Vk_FindImage,
&(mod->type));
if (!mod->extradata)
{
ri.Sys_Error(ERR_DROP, "%s: Failed to load %s",
__func__, mod->name);
}
};
break;
case IDSPRITEHEADER:
{
mod->extradata = Mod_LoadSP2(mod->name, buf, modfilelen,
(struct image_s **)mod->skins, (findimage_t)Vk_FindImage,
&(mod->type));
if (!mod->extradata)
case IDSPRITEHEADER:
{
ri.Sys_Error(ERR_DROP, "%s: Failed to load %s",
__func__, mod->name);
mod->extradata = Mod_LoadSP2(mod->name, buf, modfilelen,
(struct image_s **)mod->skins, (findimage_t)Vk_FindImage,
&(mod->type));
if (!mod->extradata)
{
ri.Sys_Error(ERR_DROP, "%s: Failed to load %s",
__func__, mod->name);
}
}
}
break;
break;
case IDBSPHEADER:
/* fall through */
case QBSPHEADER:
Mod_LoadBrushModel(mod, buf, modfilelen);
break;
case IDBSPHEADER:
/* fall through */
case QBSPHEADER:
Mod_LoadBrushModel(mod, buf, modfilelen);
break;
default:
ri.Sys_Error(ERR_DROP, "%s: unknown fileid for %s",
__func__, mod->name);
break;
default:
ri.Sys_Error(ERR_DROP, "%s: unknown fileid for %s",
__func__, mod->name);
break;
}
mod->radius = Mod_RadiusFromBounds(mod->mins, mod->maxs);
if (mod->extradata)
{
mod->extradatasize = Hunk_End ();
mod->extradatasize = Hunk_End();
}
else
{
@ -1165,8 +1173,8 @@ Mod_Free(model_t *mod)
R_Printf(PRINT_ALL, "%s: Unload %s[%d]\n", __func__, mod->name, mod_loaded);
}
Hunk_Free (mod->extradata);
memset (mod, 0, sizeof(*mod));
Hunk_Free(mod->extradata);
memset(mod, 0, sizeof(*mod));
mod_loaded --;
if (mod_loaded < 0)
{
@ -1175,19 +1183,21 @@ Mod_Free(model_t *mod)
}
void
Mod_FreeAll (void)
Mod_FreeAll(void)
{
int i;
int i;
for (i=0 ; i<mod_numknown ; i++)
for (i = 0; i < mod_numknown; i++)
{
if (models_known[i].extradatasize)
Mod_Free (&models_known[i]);
{
Mod_Free(&models_known[i]);
}
}
}
void
Mod_FreeModelsKnown (void)
Mod_FreeModelsKnown(void)
{
free(models_known);
models_known = NULL;
@ -1197,7 +1207,7 @@ Mod_FreeModelsKnown (void)
* Specifies the model that will be used as the world
*/
void
RE_BeginRegistration (const char *model)
RE_BeginRegistration(const char *model)
{
char fullname[MAX_QPATH];
cvar_t *flushmap;
@ -1321,10 +1331,10 @@ Mod_Modellist_f (void)
}
void
RE_EndRegistration (void)
RE_EndRegistration(void)
{
int i;
model_t *mod;
int i;
model_t *mod;
if (Mod_HasFreeSpace() && Vk_ImageHasFreeSpace())
{
@ -1346,5 +1356,5 @@ RE_EndRegistration (void)
}
}
Vk_FreeUnusedImages ();
Vk_FreeUnusedImages();
}