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 *lit_filebase;
extern uint8_t *lux_filebase; extern uint8_t *lux_filebase;
extern int facestyles;
extern int oversample; extern int oversample;
extern int write_litfile; extern int write_litfile;
extern int write_luxfile; extern int write_luxfile;

View File

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

View File

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

View File

@ -61,7 +61,6 @@ const char * light_t::classname() const {
static std::vector<std::pair<std::string, int>> lightstyleForTargetname; static std::vector<std::pair<std::string, int>> lightstyleForTargetname;
#define MAX_SWITCHABLE_STYLES 64
static entdict_t &WorldEnt() 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 // generate a new style number and return it
const int newStylenum = cfg.compilerstyle_start.intValue() + lightstyleForTargetname.size(); const int newStylenum = cfg.compilerstyle_start.intValue() + lightstyleForTargetname.size();
if (newStylenum >= (facestyles?INVALID_LIGHTSTYLE:INVALID_LIGHTSTYLE_OLD))
// check if full {
if (newStylenum >= MAX_SWITCHABLE_STYLES) { if (!facestyles)
Error("%s: Too many unique light targetnames (max=%d)\n", __func__, MAX_SWITCHABLE_STYLES); 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 lightstyleForTargetname.emplace_back(targetname, newStylenum); //mxd. https://clang.llvm.org/extra/clang-tidy/checks/modernize-use-emplace.html
if (verbose_log) { if (verbose_log) {
@ -375,8 +375,8 @@ CheckEntityFields(const globalconfig_t &cfg, light_t *entity)
entity->light.setFloatValue(entity->light.floatValue() / entity->samples.intValue()); entity->light.setFloatValue(entity->light.floatValue() / entity->samples.intValue());
} }
if (entity->style.intValue() < 0 || entity->style.intValue() > 254) { if (entity->style.intValue() < 0 || entity->style.intValue() > INVALID_LIGHTSTYLE) {
Error("Bad light style %i (must be 0-254)", entity->style.intValue()); 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); free(bsp->dentdata);
/* FIXME - why are we printing this here? */ /* FIXME - why are we printing this here? */
logprint("%i switchable light styles (%d max)\n", logprint("%i switchable light styles\n",
static_cast<int>(lightstyleForTargetname.size()), static_cast<int>(lightstyleForTargetname.size()));
MAX_SWITCHABLE_STYLES - cfg.compilerstyle_start.intValue());
bsp->entdatasize = entdata.size() + 1; // +1 for a null byte at the end bsp->entdatasize = entdata.size() + 1; // +1 for a null byte at the end
bsp->dentdata = (char *) calloc(bsp->entdatasize, 1); 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 *> shadowworldonlylist;
std::vector<const modelinfo_t *> switchableshadowlist; std::vector<const modelinfo_t *> switchableshadowlist;
int facestyles = 0; //max styles per face - uses bspx stuff.
int oversample = 1; int oversample = 1;
int write_litfile = 0; /* 0 for none, 1 for .lit, 2 for bspx, 3 for both */ 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 */ 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) else if (scaledonly)
{ {
f->lightofs = -1; f->lightofs = -1;
f->styles[0] = 255; f->styles[0] = INVALID_LIGHTSTYLE_OLD;
LightFace(bsp, f, faces_sup + facenum, cfg_static); LightFace(bsp, f, faces_sup + facenum, cfg_static);
} }
else if (faces_sup[facenum].lmscale == face_modelinfo->lightmapscale) else if (faces_sup[facenum].lmscale == face_modelinfo->lightmapscale)
{ {
LightFace(bsp, f, nullptr, cfg_static); LightFace(bsp, f, faces_sup + facenum, cfg_static);
faces_sup[facenum].lightofs = f->lightofs; f->lightofs = faces_sup[facenum].lightofs;
for (int i = 0; i < MAXLIGHTMAPS; i++) for (int i = 0; i < MAXLIGHTMAPS; i++)
faces_sup[facenum].styles[i] = f->styles[i]; f->styles[i] = faces_sup[facenum].styles[i];
} }
else else
{ {
@ -418,10 +419,8 @@ LightWorld(bspdata_t *bspdata, qboolean forcedscale)
BSPX_AddLump(bspdata, "LMSHIFT", NULL, 0); BSPX_AddLump(bspdata, "LMSHIFT", NULL, 0);
const unsigned char *lmshift_lump = (const unsigned char *)BSPX_GetLump(bspdata, "LMSHIFT", NULL); const unsigned char *lmshift_lump = (const unsigned char *)BSPX_GetLump(bspdata, "LMSHIFT", NULL);
if (!lmshift_lump && write_litfile != ~0) if (lmshift_lump || (write_litfile&2) || (write_luxfile&2) || facestyles)
faces_sup = NULL; //no scales, no lit2 { //we have scales/bspx/lit2 output. yay...
else
{ //we have scales or lit2 output. yay...
faces_sup = (facesup_t *)malloc(sizeof(*faces_sup) * bsp->numfaces); faces_sup = (facesup_t *)malloc(sizeof(*faces_sup) * bsp->numfaces);
memset(faces_sup, 0, sizeof(*faces_sup) * bsp->numfaces); memset(faces_sup, 0, sizeof(*faces_sup) * bsp->numfaces);
if (lmshift_lump) if (lmshift_lump)
@ -435,6 +434,10 @@ LightWorld(bspdata_t *bspdata, qboolean forcedscale)
faces_sup[i].lmscale = modelinfo.at(0)->lightmapscale; faces_sup[i].lmscale = modelinfo.at(0)->lightmapscale;
} }
} }
else
faces_sup = NULL; //no scales, no lit2, no -bspx
if (!facestyles)
facestyles = 4;
CalcualateVertexNormals(bsp); CalcualateVertexNormals(bsp);
@ -484,20 +487,69 @@ LightWorld(bspdata_t *bspdata, qboolean forcedscale)
} }
logprint("lightdatasize: %i\n", bsp->lightdatasize); logprint("lightdatasize: %i\n", bsp->lightdatasize);
if (faces_sup) { //kill this stuff if it lingered from a previous light compile
uint8_t *styles = (uint8_t *)malloc(sizeof(*styles)*4*bsp->numfaces); BSPX_AddLump(bspdata, "LMSTYLE16", NULL, 0);
int32_t *offsets = (int32_t *)malloc(sizeof(*offsets)*bsp->numfaces); 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++) { for (int i = 0; i < bsp->numfaces; i++) {
offsets[i] = faces_sup[i].lightofs; if (bsp->dfaces[i].lightofs != faces_sup[i].lightofs)
for (int j = 0; j < MAXLIGHTMAPS; j++) needoffsets = true;
styles[i*4+j] = faces_sup[i].styles[j]; 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" " -bspxlit writes rgb data into the bsp itself\n"
" -bspx writes both rgb and directions 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" " -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("\n");
printf("Overridable worldspawn keys:\n"); printf("Overridable worldspawn keys:\n");
@ -997,6 +1050,11 @@ light_main(int argc, const char **argv)
} else if (!strcmp(argv[i], "-bspx")) { } else if (!strcmp(argv[i], "-bspx")) {
write_litfile |= 2; write_litfile |= 2;
write_luxfile |= 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")) { } else if (!strcmp(argv[i], "-novanilla")) {
scaledonly = true; scaledonly = true;
} else if ( !strcmp( argv[ i ], "-radlights" ) ) { } 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 // no exact match, check for an unsaved one
for (auto &lm : *lightmaps) { for (auto &lm : *lightmaps) {
if (lm.style == 255) { if (lm.style == INVALID_LIGHTSTYLE) {
Lightmap_AllocOrClear(&lm, lightsurf); Lightmap_AllocOrClear(&lm, lightsurf);
return &lm; 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) // add a new one to the vector (invalidates existing lightmap_t pointers)
lightmap_t newLightmap {}; lightmap_t newLightmap {};
newLightmap.style = 255; newLightmap.style = INVALID_LIGHTSTYLE;
Lightmap_AllocOrClear(&newLightmap, lightsurf); Lightmap_AllocOrClear(&newLightmap, lightsurf);
lightmaps->push_back(newLightmap); lightmaps->push_back(newLightmap);
@ -919,7 +919,7 @@ static void
Lightmap_ClearAll(lightmapdict_t *lightmaps) Lightmap_ClearAll(lightmapdict_t *lightmaps)
{ {
for (auto &lm : *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_Save(lightmapdict_t *lightmaps, const lightsurf_t *lightsurf,
lightmap_t *lightmap, const int style) lightmap_t *lightmap, const int style)
{ {
if (lightmap->style == 255) { if (lightmap->style == INVALID_LIGHTSTYLE) {
lightmap->style = style; lightmap->style = style;
} }
} }
@ -3072,13 +3072,25 @@ WriteLightmaps(const mbsp_t *bsp, bsp2_dface_t *face, facesup_t *facesup, const
return; 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 // intermediate collection for sorting lightmaps
std::vector<std::pair<float, const lightmap_t *>> sortable; std::vector<std::pair<float, const lightmap_t *>> sortable;
for (const lightmap_t &lightmap : *lightmaps) { for (const lightmap_t &lightmap : *lightmaps) {
// skip un-saved lightmaps // skip un-saved lightmaps
if (lightmap.style == 255) if (lightmap.style == INVALID_LIGHTSTYLE)
continue; 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 // 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) 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; std::vector<const lightmap_t *> sorted;
for (const auto &pair : sortable) { for (const auto &pair : sortable) {
if (sorted.size() == MAXLIGHTMAPS) { if (sorted.size() == maxfstyles) {
logprint("WARNING: Too many light styles on a face\n" logprint("WARNING: Too many light styles on a face\n"
" lightmap point near (%s)\n", " lightmap point near (%s)\n",
VecStr(lightsurf->points[0]).c_str()); 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 */ /* final number of lightmaps */
const int numstyles = static_cast<int>(sorted.size()); 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) */ /* update face info (either core data or supplementary stuff) */
if (facesup) 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++) { for (mapnum = 0; mapnum < numstyles; mapnum++) {
facesup->styles[mapnum] = sorted.at(mapnum)->style; facesup->styles[mapnum] = sorted.at(mapnum)->style;
} }
for (; mapnum < MAXLIGHTMAPS; mapnum++) { for (; mapnum < MAXLIGHTMAPSSUP; mapnum++) {
facesup->styles[mapnum] = 255; facesup->styles[mapnum] = INVALID_LIGHTSTYLE;
} }
facesup->lmscale = lightsurf->lightmapscale; 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; face->styles[mapnum] = sorted.at(mapnum)->style;
} }
for (; mapnum < MAXLIGHTMAPS; mapnum++) { 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) if (facesup)
{ {
facesup->lightofs = -1; facesup->lightofs = -1;
for (int i = 0; i < MAXLIGHTMAPS; i++) for (int i = 0; i < MAXLIGHTMAPSSUP; i++)
facesup->styles[i] = 255; facesup->styles[i] = INVALID_LIGHTSTYLE;
} }
else else
{ {
face->lightofs = -1; face->lightofs = -1;
for (int i = 0; i < MAXLIGHTMAPS; i++) for (int i = 0; i < MAXLIGHTMAPS; i++)
face->styles[i] = 255; face->styles[i] = INVALID_LIGHTSTYLE_OLD;
} }
} }