cherry pick commit 96cd23761c from @Shpoike
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:
parent
827d382d5a
commit
210d994445
|
|
@ -399,6 +399,7 @@ struct mtexinfo_t
|
|||
};
|
||||
|
||||
constexpr size_t MAXLIGHTMAPS = 4;
|
||||
constexpr uint16_t INVALID_LIGHTSTYLE_OLD = 0xffu;
|
||||
|
||||
struct mface_t
|
||||
{
|
||||
|
|
|
|||
|
|
@ -76,7 +76,7 @@ public:
|
|||
{{"linear", LF_LINEAR}, {"inverse", LF_INVERSE}, {"inverse2", LF_INVERSE2}, {"infinite", LF_INFINITE}, {"localmin", LF_LOCALMIN}, {"inverse2a", LF_INVERSE2A}}};
|
||||
settings::setting_scalar spotangle{this, "angle", 40.0};
|
||||
settings::setting_scalar spotangle2{this, "softangle", 0.0};
|
||||
settings::setting_numeric<int32_t> style{this, "style", 0, 0, 254};
|
||||
settings::setting_numeric<int32_t> style{this, "style", 0, 0, INVALID_LIGHTSTYLE - 1};
|
||||
settings::setting_scalar anglescale{this, {"anglesense", "anglescale"}, -1.0}; // fallback to worldspawn
|
||||
settings::setting_scalar dirtscale{this, "dirtscale", 0.0};
|
||||
settings::setting_scalar dirtgain{this, "dirtgain", 0};
|
||||
|
|
|
|||
|
|
@ -450,6 +450,7 @@ public:
|
|||
&experimental_group, "writes both rgb and directions data into the bsp itself"};
|
||||
setting_bool litonly{this, "litonly", false, &output_group, "only write .lit file, don't modify BSP"};
|
||||
setting_bool nolights{this, "nolights", false, &output_group, "ignore light entities (only sunlight/minlight)"};
|
||||
setting_int32 facestyles{this, "facestyles", 4, &output_group, "max amount of styles per face; requires BSPX lump"};
|
||||
|
||||
inline void CheckNoDebugModeSet()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -41,13 +41,16 @@ struct litheader_t
|
|||
} v2;
|
||||
};
|
||||
|
||||
constexpr size_t MAXLIGHTMAPSSUP = 16;
|
||||
constexpr uint16_t INVALID_LIGHTSTYLE = 0xffffu;
|
||||
|
||||
/* internal representation for bspx/lit2 */
|
||||
struct facesup_t
|
||||
{
|
||||
float lmscale;
|
||||
uint8_t styles[MAXLIGHTMAPS]; /* scaled styles */
|
||||
uint16_t styles[MAXLIGHTMAPSSUP]; /* scaled styles */
|
||||
int32_t lightofs; /* scaled lighting */
|
||||
unsigned short extent[2];
|
||||
uint16_t extent[2];
|
||||
};
|
||||
|
||||
void WriteLitFile(const mbsp_t *bsp, facesup_t *facesup, const fs::path &filename, int version);
|
||||
|
|
|
|||
|
|
@ -168,6 +168,11 @@ void light_settings::postinitialize(int argc, const char **argv)
|
|||
}
|
||||
}
|
||||
|
||||
// upgrade to uint16 if facestyles is specified
|
||||
if (options.facestyles.value() > MAXLIGHTMAPS && !options.compilerstyle_max.isChanged()) {
|
||||
options.compilerstyle_max.setValue(INVALID_LIGHTSTYLE);
|
||||
}
|
||||
|
||||
common_settings::postinitialize(argc, argv);
|
||||
}
|
||||
} // namespace settings
|
||||
|
|
@ -318,13 +323,13 @@ static void LightThread(const mbsp_t *bsp, size_t facenum)
|
|||
LightFace(bsp, f, nullptr, options);
|
||||
else if (options.novanilla.value()) {
|
||||
f->lightofs = -1;
|
||||
f->styles[0] = 255;
|
||||
f->styles[0] = INVALID_LIGHTSTYLE_OLD;
|
||||
LightFace(bsp, f, faces_sup + facenum, options);
|
||||
} else if (faces_sup[facenum].lmscale == face_modelinfo->lightmapscale) {
|
||||
LightFace(bsp, f, nullptr, options);
|
||||
faces_sup[facenum].lightofs = f->lightofs;
|
||||
LightFace(bsp, f, faces_sup + facenum, options);
|
||||
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 {
|
||||
LightFace(bsp, f, nullptr, options);
|
||||
LightFace(bsp, f, faces_sup + facenum, options);
|
||||
|
|
@ -449,7 +454,7 @@ static void LightWorld(bspdata_t *bspdata, bool forcedscale)
|
|||
|
||||
auto lmshift_lump = bspdata->bspx.entries.find("LMSHIFT");
|
||||
|
||||
if (lmshift_lump == bspdata->bspx.entries.end() && options.write_litfile != lightfile::lit2)
|
||||
if (lmshift_lump == bspdata->bspx.entries.end() && options.write_litfile != lightfile::lit2 && options.facestyles.value() <= 4)
|
||||
faces_sup = nullptr; // no scales, no lit2
|
||||
else { // we have scales or lit2 output. yay...
|
||||
faces_sup = new facesup_t[bsp.dfaces.size()]{};
|
||||
|
|
@ -518,23 +523,79 @@ static void LightWorld(bspdata_t *bspdata, bool forcedscale)
|
|||
logging::print("lightdatasize: {}\n", bsp.dlightdata.size());
|
||||
|
||||
// kill this stuff if its somehow found.
|
||||
bspdata->bspx.entries.erase("LMSTYLE16");
|
||||
bspdata->bspx.entries.erase("LMSTYLE");
|
||||
bspdata->bspx.entries.erase("LMOFFSET");
|
||||
|
||||
if (faces_sup) {
|
||||
std::vector<uint8_t> styles(4 * bsp.dfaces.size());
|
||||
bool needoffsets = false;
|
||||
bool needstyles = false;
|
||||
int maxstyle = 0;
|
||||
int stylesperface = 0;
|
||||
|
||||
for (int i = 0; i < bsp.dfaces.size(); i++) {
|
||||
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);
|
||||
|
||||
logging::print("max {} styles per face{}\n", stylesperface, maxstyle >= INVALID_LIGHTSTYLE_OLD ? ", 16bit lightstyles" : "");
|
||||
|
||||
if (needstyles) {
|
||||
if (maxstyle >= INVALID_LIGHTSTYLE_OLD) {
|
||||
/*needs bigger datatype*/
|
||||
std::vector<uint8_t> styles_mem(sizeof(uint16_t) * stylesperface * bsp.dfaces.size());
|
||||
|
||||
omemstream styles(styles_mem.data(), std::ios_base::out | std::ios_base::binary);
|
||||
styles << endianness<std::endian::little>;
|
||||
|
||||
for (size_t i = 0; i < bsp.dfaces.size(); i++) {
|
||||
for (size_t j = 0; j < stylesperface; j++) {
|
||||
styles <= faces_sup[i].styles[j];
|
||||
}
|
||||
}
|
||||
|
||||
bspdata->bspx.transfer("LMSTYLE16", styles_mem);
|
||||
} else {
|
||||
/*original LMSTYLE lump was just for different lmshift info*/
|
||||
std::vector<uint8_t> styles_mem(stylesperface * bsp.dfaces.size());
|
||||
|
||||
for (size_t i = 0, k = 0; i < bsp.dfaces.size(); i++) {
|
||||
for (size_t j = 0; j < stylesperface; j++, k++) {
|
||||
styles_mem[k] = faces_sup[i].styles[j];
|
||||
}
|
||||
}
|
||||
|
||||
bspdata->bspx.transfer("LMSTYLE", styles_mem);
|
||||
}
|
||||
}
|
||||
|
||||
if (needoffsets) {
|
||||
std::vector<uint8_t> offsets_mem(bsp.dfaces.size() * sizeof(int32_t));
|
||||
|
||||
omemstream offsets(offsets_mem.data(), std::ios_base::out | std::ios_base::binary);
|
||||
offsets << endianness<std::endian::little>;
|
||||
for (int i = 0; i < bsp.dfaces.size(); i++) {
|
||||
|
||||
for (size_t i = 0; i < bsp.dfaces.size(); i++) {
|
||||
offsets <= faces_sup[i].lightofs;
|
||||
for (int j = 0; j < MAXLIGHTMAPS; j++)
|
||||
styles[i * 4 + j] = faces_sup[i].styles[j];
|
||||
}
|
||||
bspdata->bspx.transfer("LMSTYLE", styles);
|
||||
|
||||
bspdata->bspx.transfer("LMOFFSET", offsets_mem);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void LoadExtendedTexinfoFlags(const fs::path &sourcefilename, const mbsp_t *bsp)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1014,7 +1014,7 @@ static lightmap_t *Lightmap_ForStyle(lightmapdict_t *lightmaps, const int style,
|
|||
|
||||
// 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;
|
||||
}
|
||||
|
|
@ -1022,7 +1022,7 @@ static lightmap_t *Lightmap_ForStyle(lightmapdict_t *lightmaps, const int style,
|
|||
|
||||
// add a new one to the vector (invalidates existing lightmap_t pointers)
|
||||
lightmap_t &newLightmap = lightmaps->emplace_back();
|
||||
newLightmap.style = 255;
|
||||
newLightmap.style = INVALID_LIGHTSTYLE;
|
||||
Lightmap_AllocOrClear(&newLightmap, lightsurf);
|
||||
return &newLightmap;
|
||||
}
|
||||
|
|
@ -1030,7 +1030,7 @@ static lightmap_t *Lightmap_ForStyle(lightmapdict_t *lightmaps, const int style,
|
|||
static void Lightmap_ClearAll(lightmapdict_t *lightmaps)
|
||||
{
|
||||
for (auto &lm : *lightmaps) {
|
||||
lm.style = 255;
|
||||
lm.style = INVALID_LIGHTSTYLE;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1043,7 +1043,7 @@ static void Lightmap_ClearAll(lightmapdict_t *lightmaps)
|
|||
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;
|
||||
}
|
||||
}
|
||||
|
|
@ -3151,13 +3151,26 @@ static void WriteLightmaps(
|
|||
return;
|
||||
}
|
||||
|
||||
int maxfstyles = facesup ? MAXLIGHTMAPSSUP : MAXLIGHTMAPS;
|
||||
if (maxfstyles > options.facestyles.value()) {
|
||||
maxfstyles = options.facestyles.value(); //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) {
|
||||
logging::print("WARNING: Style {} too high\n"
|
||||
" lightmap point near {}\n",
|
||||
lightmap.style,
|
||||
lightsurf->points[0]);
|
||||
continue;
|
||||
}
|
||||
|
||||
// skip lightmaps where all samples have brightness below 1
|
||||
if (bsp->loadversion->game->id != GAME_QUAKE_II) { // HACK: don't do this on Q2. seems if all styles are 0xff,
|
||||
|
|
@ -3177,7 +3190,7 @@ static void WriteLightmaps(
|
|||
|
||||
std::vector<const lightmap_t *> sorted;
|
||||
for (const auto &pair : sortable) {
|
||||
if (sorted.size() == MAXLIGHTMAPS) {
|
||||
if (sorted.size() == maxfstyles) {
|
||||
logging::print("WARNING: Too many light styles on a face\n"
|
||||
" lightmap point near [{}]\n",
|
||||
lightsurf->points[0]);
|
||||
|
|
@ -3189,7 +3202,7 @@ static void WriteLightmaps(
|
|||
|
||||
/* 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) {
|
||||
|
|
@ -3199,8 +3212,8 @@ static void WriteLightmaps(
|
|||
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;
|
||||
} else {
|
||||
|
|
@ -3209,7 +3222,7 @@ static void WriteLightmaps(
|
|||
face->styles[mapnum] = sorted.at(mapnum)->style;
|
||||
}
|
||||
for (; mapnum < MAXLIGHTMAPS; mapnum++) {
|
||||
face->styles[mapnum] = 255;
|
||||
face->styles[mapnum] = INVALID_LIGHTSTYLE_OLD;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -3376,12 +3389,12 @@ void LightFace(const mbsp_t *bsp, mface_t *face, facesup_t *facesup, const setti
|
|||
/* some surfaces don't need lightmaps */
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -86,7 +86,7 @@ static void MakeSurfaceLightsThread(const mbsp_t *bsp, const settings::worldspaw
|
|||
style = surflight->epairs->get_int("style");
|
||||
|
||||
if (surflight->color.isChanged()) {
|
||||
texture_color = surflight->color.value();
|
||||
texture_color = surflight->color.value() / 255.f;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue