Removed legacy switchable lightstyles limit (requires updated engines when exceeded). Added -facestyles argument that allows for >4 styles per face, as well as potentially increasing style indexes to 16bit for far far more switchable styles.

This commit is contained in:
Shpoike 2019-09-10 15:49:38 +01:00
parent 2ff31d012e
commit 96cd23761c
6 changed files with 122 additions and 48 deletions

View File

@ -400,6 +400,7 @@ extern uint8_t *filebase;
extern uint8_t *lit_filebase;
extern uint8_t *lux_filebase;
extern int facestyles;
extern int oversample;
extern int write_litfile;
extern int write_luxfile;

View File

@ -36,10 +36,13 @@ typedef struct litheader_s {
} litheader_t;
/* internal representation for bspx/lit2 */
#define MAXLIGHTMAPSSUP 16
#define INVALID_LIGHTSTYLE 0xffffu
#define INVALID_LIGHTSTYLE_OLD 0xffu
typedef struct {
float lmscale;
uint8_t styles[MAXLIGHTMAPS]; /* scaled styles */
int32_t lightofs; /* scaled lighting */
uint16_t styles[MAXLIGHTMAPSSUP]; /* scaled styles */
int32_t lightofs; /* scaled lighting */
unsigned short extent[2];
} facesup_t;

View File

@ -172,7 +172,8 @@ typedef struct {
uint32_t v[2]; /* vertex numbers */
} bsp2_dedge_t;
#define MAXLIGHTMAPS 4
#define MAXLIGHTMAPS 4
#define INVALID_LIGHTSTYLE_OLD 0xffu /*signifies 'no more lightstyles'*/
typedef struct {
int16_t planenum;
int16_t side;

View File

@ -61,7 +61,6 @@ const char * light_t::classname() const {
static std::vector<std::pair<std::string, int>> lightstyleForTargetname;
#define MAX_SWITCHABLE_STYLES 64
static entdict_t &WorldEnt()
{
@ -99,12 +98,13 @@ LightStyleForTargetname(const globalconfig_t& cfg, const std::string &targetname
// generate a new style number and return it
const int newStylenum = cfg.compilerstyle_start.intValue() + lightstyleForTargetname.size();
// check if full
if (newStylenum >= MAX_SWITCHABLE_STYLES) {
Error("%s: Too many unique light targetnames (max=%d)\n", __func__, MAX_SWITCHABLE_STYLES);
if (newStylenum >= (facestyles?INVALID_LIGHTSTYLE:INVALID_LIGHTSTYLE_OLD))
{
if (!facestyles)
Error("%s: Too many unique light targetnames (reached max of %i)\nTip: Use '-facestyles N' for 16bit lightstyle limits in supporting engines.", __func__, newStylenum-cfg.compilerstyle_start.intValue());
else
Error("%s: Too many unique light targetnames (reached max of %i)\n", __func__, newStylenum-cfg.compilerstyle_start.intValue());
}
lightstyleForTargetname.emplace_back(targetname, newStylenum); //mxd. https://clang.llvm.org/extra/clang-tidy/checks/modernize-use-emplace.html
if (verbose_log) {
@ -375,8 +375,8 @@ CheckEntityFields(const globalconfig_t &cfg, light_t *entity)
entity->light.setFloatValue(entity->light.floatValue() / entity->samples.intValue());
}
if (entity->style.intValue() < 0 || entity->style.intValue() > 254) {
Error("Bad light style %i (must be 0-254)", entity->style.intValue());
if (entity->style.intValue() < 0 || entity->style.intValue() > INVALID_LIGHTSTYLE) {
Error("Bad light style %i (must be 0-%i)", entity->style.intValue(), INVALID_LIGHTSTYLE-1);
}
}
@ -1272,9 +1272,8 @@ WriteEntitiesToString(const globalconfig_t& cfg, mbsp_t *bsp)
free(bsp->dentdata);
/* FIXME - why are we printing this here? */
logprint("%i switchable light styles (%d max)\n",
static_cast<int>(lightstyleForTargetname.size()),
MAX_SWITCHABLE_STYLES - cfg.compilerstyle_start.intValue());
logprint("%i switchable light styles\n",
static_cast<int>(lightstyleForTargetname.size()));
bsp->entdatasize = entdata.size() + 1; // +1 for a null byte at the end
bsp->dentdata = (char *) calloc(bsp->entdatasize, 1);

View File

@ -94,6 +94,7 @@ std::vector<const modelinfo_t *> selfshadowlist;
std::vector<const modelinfo_t *> shadowworldonlylist;
std::vector<const modelinfo_t *> switchableshadowlist;
int facestyles = 0; //max styles per face - uses bspx stuff.
int oversample = 1;
int write_litfile = 0; /* 0 for none, 1 for .lit, 2 for bspx, 3 for both */
int write_luxfile = 0; /* 0 for none, 1 for .lux, 2 for bspx, 3 for both */
@ -281,15 +282,15 @@ LightThread(void *arg)
else if (scaledonly)
{
f->lightofs = -1;
f->styles[0] = 255;
f->styles[0] = INVALID_LIGHTSTYLE_OLD;
LightFace(bsp, f, faces_sup + facenum, cfg_static);
}
else if (faces_sup[facenum].lmscale == face_modelinfo->lightmapscale)
{
LightFace(bsp, f, nullptr, cfg_static);
faces_sup[facenum].lightofs = f->lightofs;
LightFace(bsp, f, faces_sup + facenum, cfg_static);
f->lightofs = faces_sup[facenum].lightofs;
for (int i = 0; i < MAXLIGHTMAPS; i++)
faces_sup[facenum].styles[i] = f->styles[i];
f->styles[i] = faces_sup[facenum].styles[i];
}
else
{
@ -418,10 +419,8 @@ LightWorld(bspdata_t *bspdata, qboolean forcedscale)
BSPX_AddLump(bspdata, "LMSHIFT", NULL, 0);
const unsigned char *lmshift_lump = (const unsigned char *)BSPX_GetLump(bspdata, "LMSHIFT", NULL);
if (!lmshift_lump && write_litfile != ~0)
faces_sup = NULL; //no scales, no lit2
else
{ //we have scales or lit2 output. yay...
if (lmshift_lump || (write_litfile&2) || (write_luxfile&2) || facestyles)
{ //we have scales/bspx/lit2 output. yay...
faces_sup = (facesup_t *)malloc(sizeof(*faces_sup) * bsp->numfaces);
memset(faces_sup, 0, sizeof(*faces_sup) * bsp->numfaces);
if (lmshift_lump)
@ -435,6 +434,10 @@ LightWorld(bspdata_t *bspdata, qboolean forcedscale)
faces_sup[i].lmscale = modelinfo.at(0)->lightmapscale;
}
}
else
faces_sup = NULL; //no scales, no lit2, no -bspx
if (!facestyles)
facestyles = 4;
CalcualateVertexNormals(bsp);
@ -484,20 +487,69 @@ LightWorld(bspdata_t *bspdata, qboolean forcedscale)
}
logprint("lightdatasize: %i\n", bsp->lightdatasize);
if (faces_sup) {
uint8_t *styles = (uint8_t *)malloc(sizeof(*styles)*4*bsp->numfaces);
int32_t *offsets = (int32_t *)malloc(sizeof(*offsets)*bsp->numfaces);
//kill this stuff if it lingered from a previous light compile
BSPX_AddLump(bspdata, "LMSTYLE16", NULL, 0);
BSPX_AddLump(bspdata, "LMSTYLE", NULL, 0);
BSPX_AddLump(bspdata, "LMOFFSET", NULL, 0);
//write out new stuff if we have it.
if (faces_sup)
{
bool needoffsets = false;
bool needstyles = false;
int maxstyle = 0;
int stylesperface = 0;
for (int i = 0; i < bsp->numfaces; i++) {
offsets[i] = faces_sup[i].lightofs;
for (int j = 0; j < MAXLIGHTMAPS; j++)
styles[i*4+j] = faces_sup[i].styles[j];
if (bsp->dfaces[i].lightofs != faces_sup[i].lightofs)
needoffsets = true;
int j = 0;
for (; j < MAXLIGHTMAPSSUP; j++) {
if (faces_sup[i].styles[j] == INVALID_LIGHTSTYLE)
break;
if (bsp->dfaces[i].styles[j] != faces_sup[i].styles[j])
needstyles = true;
if (maxstyle < faces_sup[i].styles[j])
maxstyle = faces_sup[i].styles[j];
}
if (stylesperface < j)
stylesperface = j;
}
needstyles |= (stylesperface>4);
logprint("max %i styles per face%s\n", stylesperface, maxstyle >= INVALID_LIGHTSTYLE_OLD?", 16bit lightstyles":"");
if (needstyles)
{
if (maxstyle >= INVALID_LIGHTSTYLE_OLD/*needs bigger datatype*/) {
/*LMSTYLE16 lump provides for more than 4 styles per surface, as well as more than 255 styles*/
uint16_t *styles = (uint16_t *)malloc(sizeof(*styles)*stylesperface*bsp->numfaces);
for (int i = 0; i < bsp->numfaces; i++) {
for (int j = 0; j < stylesperface; j++)
styles[i*stylesperface+j] = faces_sup[i].styles[j];
}
BSPX_AddLump(bspdata, "LMSTYLE16", styles, sizeof(*styles)*stylesperface*bsp->numfaces);
}
else {
/*original LMSTYLE lump was just for different lmshift info*/
if (stylesperface < 4)
stylesperface = 4; /*better compat*/
uint8_t *styles = (uint8_t *)malloc(sizeof(*styles)*stylesperface*bsp->numfaces);
for (int i = 0; i < bsp->numfaces; i++) {
for (int j = 0; j < stylesperface; j++)
styles[i*stylesperface+j] = faces_sup[i].styles[j];
}
BSPX_AddLump(bspdata, "LMSTYLE", styles, sizeof(*styles)*stylesperface*bsp->numfaces);
}
}
if (needoffsets)
{
int32_t *offsets = (int32_t *)malloc(sizeof(*offsets)*bsp->numfaces);
for (int i = 0; i < bsp->numfaces; i++) {
offsets[i] = faces_sup[i].lightofs;
}
BSPX_AddLump(bspdata, "LMOFFSET", offsets, sizeof(*offsets)*bsp->numfaces);
}
BSPX_AddLump(bspdata, "LMSTYLE", styles, sizeof(*styles)*4*bsp->numfaces);
BSPX_AddLump(bspdata, "LMOFFSET", offsets, sizeof(*offsets)*bsp->numfaces);
} else {
//kill this stuff if its somehow found.
BSPX_AddLump(bspdata, "LMSTYLE", NULL, 0);
BSPX_AddLump(bspdata, "LMOFFSET", NULL, 0);
}
}
@ -810,7 +862,8 @@ static void PrintUsage()
" -bspxlit writes rgb data into the bsp itself\n"
" -bspx writes both rgb and directions data into the bsp itself\n"
" -novanilla implies -bspxlit. don't write vanilla lighting\n"
" -radlights filename.rad loads a <surfacename> <r> <g> <b> <intensity> file\n");
" -radlights filename.rad loads a <surfacename> <r> <g> <b> <intensity> file\n"
" -facestyles n (bspx) overrides the max number of lightstyles per face\n");
printf("\n");
printf("Overridable worldspawn keys:\n");
@ -997,6 +1050,11 @@ light_main(int argc, const char **argv)
} else if (!strcmp(argv[i], "-bspx")) {
write_litfile |= 2;
write_luxfile |= 2;
} else if (!strcmp(argv[i], "-facestyles")) {
if ((i + 1) < argc && isdigit(argv[i + 1][0]))
facestyles = atoi(argv[++i]);
else
facestyles = 0;
} else if (!strcmp(argv[i], "-novanilla")) {
scaledonly = true;
} else if ( !strcmp( argv[ i ], "-radlights" ) ) {

View File

@ -900,7 +900,7 @@ Lightmap_ForStyle(lightmapdict_t *lightmaps, const int style, const lightsurf_t
// no exact match, check for an unsaved one
for (auto &lm : *lightmaps) {
if (lm.style == 255) {
if (lm.style == INVALID_LIGHTSTYLE) {
Lightmap_AllocOrClear(&lm, lightsurf);
return &lm;
}
@ -908,7 +908,7 @@ Lightmap_ForStyle(lightmapdict_t *lightmaps, const int style, const lightsurf_t
// add a new one to the vector (invalidates existing lightmap_t pointers)
lightmap_t newLightmap {};
newLightmap.style = 255;
newLightmap.style = INVALID_LIGHTSTYLE;
Lightmap_AllocOrClear(&newLightmap, lightsurf);
lightmaps->push_back(newLightmap);
@ -919,7 +919,7 @@ static void
Lightmap_ClearAll(lightmapdict_t *lightmaps)
{
for (auto &lm : *lightmaps) {
lm.style = 255;
lm.style = INVALID_LIGHTSTYLE;
}
}
@ -933,7 +933,7 @@ static void
Lightmap_Save(lightmapdict_t *lightmaps, const lightsurf_t *lightsurf,
lightmap_t *lightmap, const int style)
{
if (lightmap->style == 255) {
if (lightmap->style == INVALID_LIGHTSTYLE) {
lightmap->style = style;
}
}
@ -3072,13 +3072,25 @@ WriteLightmaps(const mbsp_t *bsp, bsp2_dface_t *face, facesup_t *facesup, const
return;
}
int maxfstyles = facesup?MAXLIGHTMAPSSUP:MAXLIGHTMAPS;
if (maxfstyles > facestyles)
maxfstyles = facestyles; //truncate it a little
int maxstyle = facesup?INVALID_LIGHTSTYLE:INVALID_LIGHTSTYLE_OLD;
// intermediate collection for sorting lightmaps
std::vector<std::pair<float, const lightmap_t *>> sortable;
for (const lightmap_t &lightmap : *lightmaps) {
// skip un-saved lightmaps
if (lightmap.style == 255)
if (lightmap.style == INVALID_LIGHTSTYLE)
continue;
if (lightmap.style > maxstyle) {
logprint("WARNING: Style %i too high\n"
" lightmap point near (%s)\n",
lightmap.style,
VecStr(lightsurf->points[0]).c_str());
continue;
}
// skip lightmaps where all samples have brightness below 1
if (bsp->loadversion != Q2_BSPVERSION) { // HACK: don't do this on Q2. seems if all styles are 0xff, the face is drawn fullbright instead of black (Q1)
@ -3097,7 +3109,7 @@ WriteLightmaps(const mbsp_t *bsp, bsp2_dface_t *face, facesup_t *facesup, const
std::vector<const lightmap_t *> sorted;
for (const auto &pair : sortable) {
if (sorted.size() == MAXLIGHTMAPS) {
if (sorted.size() == maxfstyles) {
logprint("WARNING: Too many light styles on a face\n"
" lightmap point near (%s)\n",
VecStr(lightsurf->points[0]).c_str());
@ -3109,7 +3121,7 @@ WriteLightmaps(const mbsp_t *bsp, bsp2_dface_t *face, facesup_t *facesup, const
/* final number of lightmaps */
const int numstyles = static_cast<int>(sorted.size());
Q_assert(numstyles <= MAXLIGHTMAPS);
Q_assert(numstyles <= MAXLIGHTMAPSSUP);
/* update face info (either core data or supplementary stuff) */
if (facesup)
@ -3120,8 +3132,8 @@ WriteLightmaps(const mbsp_t *bsp, bsp2_dface_t *face, facesup_t *facesup, const
for (mapnum = 0; mapnum < numstyles; mapnum++) {
facesup->styles[mapnum] = sorted.at(mapnum)->style;
}
for (; mapnum < MAXLIGHTMAPS; mapnum++) {
facesup->styles[mapnum] = 255;
for (; mapnum < MAXLIGHTMAPSSUP; mapnum++) {
facesup->styles[mapnum] = INVALID_LIGHTSTYLE;
}
facesup->lmscale = lightsurf->lightmapscale;
}
@ -3132,7 +3144,7 @@ WriteLightmaps(const mbsp_t *bsp, bsp2_dface_t *face, facesup_t *facesup, const
face->styles[mapnum] = sorted.at(mapnum)->style;
}
for (; mapnum < MAXLIGHTMAPS; mapnum++) {
face->styles[mapnum] = 255;
face->styles[mapnum] = INVALID_LIGHTSTYLE_OLD;
}
}
@ -3297,14 +3309,14 @@ LightFace(const mbsp_t *bsp, bsp2_dface_t *face, facesup_t *facesup, const globa
if (facesup)
{
facesup->lightofs = -1;
for (int i = 0; i < MAXLIGHTMAPS; i++)
facesup->styles[i] = 255;
for (int i = 0; i < MAXLIGHTMAPSSUP; i++)
facesup->styles[i] = INVALID_LIGHTSTYLE;
}
else
{
face->lightofs = -1;
for (int i = 0; i < MAXLIGHTMAPS; i++)
face->styles[i] = 255;
face->styles[i] = INVALID_LIGHTSTYLE_OLD;
}
}