Skip to content

Commit

Permalink
Removed legacy switchable lightstyles limit (requires updated engines…
Browse files Browse the repository at this point in the history
… 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.
  • Loading branch information
Shpoike committed Sep 10, 2019
1 parent 0460165 commit ee37f63
Show file tree
Hide file tree
Showing 7 changed files with 125 additions and 50 deletions.
2 changes: 1 addition & 1 deletion include/light/entities.hh
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@

#define DEFAULTLIGHTLEVEL 300.0f
#define LIGHT_TARGETS_START 32
#define MAX_LIGHT_TARGETS 32
//#define MAX_LIGHT_TARGETS (((facestyles?INVALID_LIGHTSTYLE:INVALID_LIGHTSTYLE_OLD)-1)-LIGHT_TARGETS_START)

using entdict_t = std::map<std::string, std::string>;

Expand Down
1 change: 1 addition & 0 deletions include/light/light.hh
Original file line number Diff line number Diff line change
Expand Up @@ -386,6 +386,7 @@ extern byte *filebase;
extern byte *lit_filebase;
extern byte *lux_filebase;

extern int facestyles;
extern int oversample;
extern int write_litfile;
extern int write_luxfile;
Expand Down
7 changes: 5 additions & 2 deletions include/light/litfile.hh
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
3 changes: 2 additions & 1 deletion include/qbsp/bspfile.hh
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,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;
Expand Down
25 changes: 13 additions & 12 deletions light/entities.cc
Original file line number Diff line number Diff line change
Expand Up @@ -60,10 +60,10 @@ const char * light_t::classname() const {

static std::vector<std::pair<std::string, int>> lightstyleForTargetname;

static bool IsSwitchableLightstyle(int style) {
/*static bool IsSwitchableLightstyle(int style) {
return style >= LIGHT_TARGETS_START
&& style < (LIGHT_TARGETS_START + MAX_LIGHT_TARGETS);
}
}*/

static entdict_t &WorldEnt()
{
Expand Down Expand Up @@ -99,13 +99,15 @@ LightStyleForTargetname(const std::string &targetname)
}
}

// check if full
if (lightstyleForTargetname.size() == MAX_LIGHT_TARGETS) {
Error("%s: Too many unique light targetnames\n", __func__);
}

// generate a new style number and return it
const int newStylenum = LIGHT_TARGETS_START + lightstyleForTargetname.size();
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-LIGHT_TARGETS_START);
else
Error("%s: Too many unique light targetnames (reached max of %i)\n", __func__, newStylenum-LIGHT_TARGETS_START);
}
lightstyleForTargetname.emplace_back(targetname, newStylenum); //mxd. https://clang.llvm.org/extra/clang-tidy/checks/modernize-use-emplace.html

if (verbose_log) {
Expand Down Expand Up @@ -376,8 +378,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);
}
}

Expand Down Expand Up @@ -1365,9 +1367,8 @@ WriteEntitiesToString(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_LIGHT_TARGETS);
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);
Expand Down
100 changes: 79 additions & 21 deletions light/light.cc
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,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 */
Expand Down Expand Up @@ -255,15 +256,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
{
Expand Down Expand Up @@ -396,10 +397,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)
Expand All @@ -413,6 +412,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);

Expand Down Expand Up @@ -447,20 +450,69 @@ LightWorld(bspdata_t *bspdata, qboolean forcedscale)
bsp->lightdatasize = file_p - filebase;
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);
}
}

Expand Down Expand Up @@ -773,7 +825,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"
" -light filename.rad loads a <surfacename> <r> <g> <b> <intensity> file\n");
" -light 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");
Expand Down Expand Up @@ -960,6 +1013,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 ], "-light" ) ) {
Expand Down
37 changes: 24 additions & 13 deletions light/ltface.cc
Original file line number Diff line number Diff line change
Expand Up @@ -895,15 +895,15 @@ 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;
}
}

// 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);

Expand All @@ -914,7 +914,7 @@ static void
Lightmap_ClearAll(lightmapdict_t *lightmaps)
{
for (auto &lm : *lightmaps) {
lm.style = 255;
lm.style = INVALID_LIGHTSTYLE;
}
}

Expand All @@ -928,7 +928,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;
}
}
Expand Down Expand Up @@ -2956,13 +2956,24 @@ static void
WriteLightmaps(const mbsp_t *bsp, bsp2_dface_t *face, facesup_t *facesup, const lightsurf_t *lightsurf,
const lightmapdict_t *lightmaps)
{
int maxstyles = facesup?MAXLIGHTMAPSSUP:MAXLIGHTMAPS;
if (maxstyles > facestyles)
maxstyles = 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)
Expand All @@ -2981,7 +2992,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() == maxstyles) {
logprint("WARNING: Too many light styles on a face\n"
" lightmap point near (%s)\n",
VecStr(lightsurf->points[0]).c_str());
Expand All @@ -2993,7 +3004,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)
Expand All @@ -3004,8 +3015,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;
}
Expand All @@ -3016,7 +3027,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;
}
}

Expand Down Expand Up @@ -3161,14 +3172,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;
}

/* don't bother with degenerate faces */
Expand Down

0 comments on commit ee37f63

Please sign in to comment.