Initial port of BSPX lights

0eeb410ce0
This commit is contained in:
Shpoike 2023-10-04 23:17:22 +03:00 committed by Denis Pauk
parent f2393a2e34
commit a87c9a0cd8
3 changed files with 280 additions and 4 deletions

View file

@ -670,8 +670,15 @@ R_DrawAliasModel(entity_t *currententity, const model_t *currentmodel)
} }
} }
else else
{
if (r_worldmodel->grid)
{
BSPX_LightGridValue(r_worldmodel->grid, currententity->origin, shadelight);
}
else
{ {
R_LightPoint(currententity, currententity->origin, shadelight); R_LightPoint(currententity, currententity->origin, shadelight);
}
/* player lighting hack for communication back to server */ /* player lighting hack for communication back to server */
if (currententity->flags & RF_WEAPONMODEL) if (currententity->flags & RF_WEAPONMODEL)

View file

@ -915,6 +915,9 @@ Mod_LoadBrushModel(model_t *mod, const void *buffer, int modfilelen)
((int *)header)[i] = LittleLong(((int *)header)[i]); ((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 // calculate the needed hunksize from the lumps
int hunkSize = 0; int hunkSize = 0;
hunkSize += Mod_CalcLumpHunkSize(&header->lumps[LUMP_VERTEXES], sizeof(dvertex_t), sizeof(mvertex_t), 0); hunkSize += Mod_CalcLumpHunkSize(&header->lumps[LUMP_VERTEXES], sizeof(dvertex_t), sizeof(mvertex_t), 0);
@ -955,12 +958,23 @@ Mod_LoadBrushModel(model_t *mod, const void *buffer, int modfilelen)
} }
hunkSize += Mod_CalcLumpHunkSize(&header->lumps[LUMP_MODELS], sizeof(dmodel_t), sizeof(model_t), 0); hunkSize += Mod_CalcLumpHunkSize(&header->lumps[LUMP_MODELS], sizeof(dmodel_t), sizeof(model_t), 0);
{
int lightgridsize = 0;
/* Get size of octree on disk, need to recheck real size */
if (Mod_LoadBSPXFindLump(bspx_header, "LIGHTGRID_OCTREE", &lightgridsize, mod_base))
{
hunkSize += lightgridsize * 4;
}
}
mod->extradata = Hunk_Begin(hunkSize); mod->extradata = Hunk_Begin(hunkSize);
mod->type = mod_brush; mod->type = mod_brush;
if (bspx_header)
/* check for BSPX extensions */ {
bspx_header = Mod_LoadBSPX(modfilelen, (byte*)header); mod->grid = BSPX_LightGridLoad(bspx_header, mod_base);
}
/* load into heap */ /* load into heap */
Mod_LoadVertexes(mod->name, &mod->vertexes, &mod->numvertexes, mod_base, Mod_LoadVertexes(mod->name, &mod->vertexes, &mod->numvertexes, mod_base,
@ -1258,3 +1272,220 @@ RI_EndRegistration(void)
R_FreeUnusedImages(); 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,6 +29,41 @@
#include "../../ref_model.h" #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 */ /* Whole model */
typedef struct model_s typedef struct model_s
@ -97,6 +132,9 @@ typedef struct model_s
// submodules // submodules
vec3_t origin; // for sounds or lights vec3_t origin; // for sounds or lights
/* octree */
bspxlightgrid_t *grid;
} model_t; } model_t;
void Mod_Init(void); void Mod_Init(void);