mirror of
https://github.com/nzp-team/fteqw.git
synced 2024-11-26 05:41:52 +00:00
Support for ericw-tools' lightgrid stuff.
This commit is contained in:
parent
e907f6adf0
commit
0eeb410ce0
3 changed files with 249 additions and 12 deletions
|
@ -1334,18 +1334,6 @@ static void Mod_LoadModelWorker (void *ctx, void *data, size_t a, size_t b)
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
#ifdef MAP_PROC
|
||||
if (!strcmp(com_token, "CM")) //doom3 map.
|
||||
{
|
||||
TRACE(("Mod_LoadModel: doom3 CM\n"));
|
||||
if (!D3_LoadMap_CollisionMap (mod, (char*)buf))
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
*/
|
||||
|
||||
TRACE(("Mod_LoadModel: Loaded\n"));
|
||||
|
||||
BZ_Free(buf);
|
||||
|
@ -1635,6 +1623,11 @@ void Mod_LoadLighting (model_t *loadmodel, bspx_header_t *bspx, qbyte *mod_base,
|
|||
#endif
|
||||
|
||||
extern cvar_t gl_overbright;
|
||||
|
||||
#ifdef HAVE_CLIENT
|
||||
BSPX_LightGridLoad(loadmodel, bspx, mod_base);
|
||||
#endif
|
||||
|
||||
loadmodel->lightmaps.fmt = LM_L8;
|
||||
|
||||
//q3 maps have built in 4-fold overbright.
|
||||
|
|
|
@ -600,6 +600,7 @@ void Q1BSP_LoadBrushes(struct model_s *model, bspx_header_t *bspx, void *mod_bas
|
|||
void Q1BSP_Init(void);
|
||||
void Q1BSP_GenerateShadowMesh(struct model_s *model, struct dlight_s *dl, const qbyte *lightvis, qbyte *litvis, void (*callback)(msurface_t *surf));
|
||||
|
||||
void BSPX_LightGridLoad(struct model_s *model, bspx_header_t *bspx, qbyte *mod_base); //for q1 or q2 models.
|
||||
void BSPX_LoadEnvmaps(struct model_s *mod, bspx_header_t *bspx, void *mod_base);
|
||||
void *BSPX_FindLump(bspx_header_t *bspxheader, void *mod_base, char *lumpname, int *lumpsize);
|
||||
bspx_header_t *BSPX_Setup(struct model_s *mod, char *filebase, size_t filelen, lump_t *lumps, size_t numlumps);
|
||||
|
|
|
@ -2925,6 +2925,246 @@ static float *GLRecursiveLightPoint3C (model_t *mod, mnode_t *node, const vec3_t
|
|||
|
||||
#endif
|
||||
|
||||
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
|
||||
{
|
||||
qbyte style;
|
||||
qbyte rgb[3];
|
||||
} map[4];
|
||||
} *rgbvalues;
|
||||
} *leafs;
|
||||
} bspxlightgrid_t;
|
||||
struct rctx_s {qbyte *data; int ofs, size;};
|
||||
static qbyte 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;
|
||||
}
|
||||
void BSPX_LightGridLoad(model_t *model, bspx_header_t *bspx, qbyte *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 = BSPX_FindLump(bspx, mod_base, "LIGHTGRID_OCTREE", &ctx.size);
|
||||
model->lightgrid = NULL;
|
||||
if (!ctx.data)
|
||||
return;
|
||||
|
||||
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 = ZG_Malloc(&model->memgroup, 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 = (qbyte)~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;
|
||||
|
||||
model->lightgrid = (void*)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;
|
||||
float lev;
|
||||
|
||||
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 == ((qbyte)(~0u)))
|
||||
break; //no more
|
||||
lev = d_lightstylevalue[samp->map[i].style]*(1/255.0);
|
||||
res_diffuse[0] += samp->map[i].rgb[0] * lev * cl_lightstyle[samp->map[i].style].colours[0];
|
||||
res_diffuse[1] += samp->map[i].rgb[1] * lev * cl_lightstyle[samp->map[i].style].colours[1];
|
||||
res_diffuse[2] += samp->map[i].rgb[2] * lev * cl_lightstyle[samp->map[i].style].colours[2];
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
static void BSPX_LightGridValue(void *lightgridinfo, const vec3_t point, vec3_t res_diffuse, vec3_t res_ambient, vec3_t res_dir)
|
||||
{
|
||||
bspxlightgrid_t *grid = lightgridinfo;
|
||||
int tile[3];
|
||||
int i;
|
||||
int s;
|
||||
|
||||
VectorSet(res_diffuse, 0, 0, 0); //assume worst
|
||||
VectorSet(res_ambient, 0, 0, 0); //assume worst
|
||||
VectorSet(res_dir, 1, 0, 1); //super lame
|
||||
|
||||
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
|
||||
VectorScale(res_diffuse, 0.5, res_ambient); //and fix up ambients.
|
||||
}
|
||||
|
||||
void GLQ1BSP_LightPointValues(model_t *model, const vec3_t point, vec3_t res_diffuse, vec3_t res_ambient, vec3_t res_dir)
|
||||
{
|
||||
vec3_t end;
|
||||
|
@ -2952,6 +3192,9 @@ void GLQ1BSP_LightPointValues(model_t *model, const vec3_t point, vec3_t res_dif
|
|||
return;
|
||||
}
|
||||
|
||||
if (model->lightgrid)
|
||||
return BSPX_LightGridValue(model->lightgrid, point, res_diffuse, res_ambient, res_dir);
|
||||
|
||||
end[0] = point[0];
|
||||
end[1] = point[1];
|
||||
end[2] = point[2] - mod_lightpoint_distance.value;
|
||||
|
|
Loading…
Reference in a new issue