552 lines
20 KiB
C++
552 lines
20 KiB
C++
/* Copyright (C) 1996-1997 Id Software, Inc.
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
|
|
See file, 'COPYING', for details.
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <common/cmdlib.hh>
|
|
#include <common/mathlib.hh>
|
|
#include <common/bspfile.hh>
|
|
#include <common/log.hh>
|
|
#include <common/threads.hh>
|
|
#include <common/polylib.hh>
|
|
#include <common/imglib.hh>
|
|
#include <common/settings.hh>
|
|
#include <common/bitflags.hh>
|
|
|
|
#include <light/litfile.hh>
|
|
#include <light/trace.hh>
|
|
|
|
#include <vector>
|
|
#include <map>
|
|
#include <set>
|
|
#include <string>
|
|
#include <cassert>
|
|
#include <limits>
|
|
#include <sstream>
|
|
|
|
#include <common/qvec.hh>
|
|
#include <common/bsputils.hh>
|
|
|
|
constexpr vec_t ON_EPSILON = 0.1;
|
|
constexpr vec_t ANGLE_EPSILON = 0.001;
|
|
constexpr vec_t EQUAL_EPSILON = 0.001;
|
|
|
|
// FIXME: use maximum dimension of level
|
|
constexpr vec_t MAX_SKY_DIST = 1000000;
|
|
|
|
struct lightsample_t
|
|
{
|
|
qvec3d color, direction;
|
|
};
|
|
|
|
// CHECK: isn't average a bad algorithm for color brightness?
|
|
template<typename T>
|
|
constexpr float LightSample_Brightness(const T &color)
|
|
{
|
|
return ((color[0] + color[1] + color[2]) / 3.0);
|
|
}
|
|
|
|
/**
|
|
* A directional light, emitted from "sky*" textured faces.
|
|
*/
|
|
class sun_t
|
|
{
|
|
public:
|
|
qvec3d sunvec;
|
|
vec_t sunlight;
|
|
qvec3d sunlight_color;
|
|
bool dirt;
|
|
float anglescale;
|
|
int style;
|
|
std::string suntexture;
|
|
const img::texture *suntexture_value;
|
|
};
|
|
|
|
struct texorg_t
|
|
{
|
|
qmat4x4f texSpaceToWorld;
|
|
const mtexinfo_t *texinfo;
|
|
vec_t planedist;
|
|
};
|
|
|
|
class modelinfo_t;
|
|
namespace settings
|
|
{
|
|
class worldspawn_keys;
|
|
};
|
|
|
|
class lightmap_t
|
|
{
|
|
public:
|
|
int style;
|
|
std::vector<lightsample_t> samples;
|
|
};
|
|
|
|
using lightmapdict_t = std::vector<lightmap_t>;
|
|
|
|
struct lightsurf_t
|
|
{
|
|
const settings::worldspawn_keys *cfg;
|
|
const modelinfo_t *modelinfo;
|
|
const mbsp_t *bsp;
|
|
const mface_t *face;
|
|
/* these take precedence the values in modelinfo */
|
|
vec_t minlight;
|
|
qvec3d minlight_color;
|
|
bool nodirt, minlightMottle;
|
|
|
|
qplane3d plane;
|
|
qvec3d snormal;
|
|
qvec3d tnormal;
|
|
|
|
/* 16 in vanilla. engines will hate you if this is not power-of-two-and-at-least-one */
|
|
float lightmapscale;
|
|
bool curved; /*normals are interpolated for smooth lighting*/
|
|
|
|
faceextents_t extents, vanilla_extents;
|
|
qvec3d midpoint;
|
|
|
|
std::vector<qvec3d> points;
|
|
std::vector<qvec3d> normals;
|
|
std::vector<bool> occluded;
|
|
std::vector<int> realfacenums;
|
|
|
|
/*
|
|
raw ambient occlusion amount per sample point, 0-1, where 1 is
|
|
fully occluded. dirtgain/dirtscale are not applied yet
|
|
*/
|
|
std::vector<float> occlusion;
|
|
|
|
/*
|
|
pvs for the entire light surface. generated by ORing together
|
|
the pvs at each of the sample points
|
|
*/
|
|
std::vector<uint8_t> pvs;
|
|
|
|
// for radiosity
|
|
qvec3d radiosity;
|
|
qvec3d texturecolor;
|
|
|
|
/* stuff used by CalcPoint */
|
|
texorg_t texorg;
|
|
int width, height;
|
|
|
|
/* for lit water. receive light from either front or back. */
|
|
bool twosided;
|
|
|
|
// ray batch stuff
|
|
raystream_occlusion_t occlusion_stream;
|
|
raystream_intersection_t intersection_stream;
|
|
|
|
lightmapdict_t lightmapsByStyle;
|
|
};
|
|
|
|
/* debug */
|
|
|
|
enum class debugmodes
|
|
{
|
|
none = 0,
|
|
phong,
|
|
phong_obj,
|
|
dirt,
|
|
bounce,
|
|
bouncelights,
|
|
debugoccluded,
|
|
debugneighbours,
|
|
phong_tangents,
|
|
phong_bitangents
|
|
};
|
|
|
|
enum class lightfile
|
|
{
|
|
none = 0,
|
|
external = 1,
|
|
bspx = 2,
|
|
both = external | bspx,
|
|
lit2 = 4
|
|
};
|
|
|
|
/* tracelist is a std::vector of pointers to modelinfo_t to use for LOS tests */
|
|
extern std::vector<const modelinfo_t *> tracelist;
|
|
extern std::vector<const modelinfo_t *> selfshadowlist;
|
|
extern std::vector<const modelinfo_t *> shadowworldonlylist;
|
|
extern std::vector<const modelinfo_t *> switchableshadowlist;
|
|
|
|
extern int numDirtVectors;
|
|
|
|
// other flags
|
|
|
|
extern bool dirt_in_use; // should any dirtmapping take place? set in SetupDirt
|
|
|
|
constexpr qvec3d vec3_white{255};
|
|
|
|
extern int dump_facenum;
|
|
extern int dump_vertnum;
|
|
|
|
class modelinfo_t : public settings::setting_container
|
|
{
|
|
static constexpr vec_t DEFAULT_PHONG_ANGLE = 89.0;
|
|
|
|
public:
|
|
const mbsp_t *bsp;
|
|
const dmodelh2_t *model;
|
|
float lightmapscale;
|
|
qvec3d offset{};
|
|
|
|
settings::setting_scalar minlight{this, "minlight", 0};
|
|
settings::setting_bool minlightMottle{this, "minlightMottle", false};
|
|
settings::setting_scalar shadow{this, "shadow", 0};
|
|
settings::setting_scalar shadowself{this, {"shadowself", "selfshadow"}, 0};
|
|
settings::setting_scalar shadowworldonly{this, "shadowworldonly", 0};
|
|
settings::setting_scalar switchableshadow{this, "switchableshadow", 0};
|
|
settings::setting_int32 switchshadstyle{this, "switchshadstyle", 0};
|
|
settings::setting_scalar dirt{this, "dirt", 0};
|
|
settings::setting_scalar phong{this, "phong", 0};
|
|
settings::setting_scalar phong_angle{this, "phong_angle", 0};
|
|
settings::setting_scalar alpha{this, "alpha", 1.0};
|
|
settings::setting_color minlight_color{this, {"minlight_color", "mincolor"}, 255.0, 255.0, 255.0};
|
|
settings::setting_bool lightignore{this, "lightignore", false};
|
|
|
|
float getResolvedPhongAngle() const
|
|
{
|
|
const float s = phong_angle.value();
|
|
if (s != 0) {
|
|
return s;
|
|
}
|
|
if (phong.value() > 0) {
|
|
return DEFAULT_PHONG_ANGLE;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
bool isWorld() const { return &bsp->dmodels[0] == model; }
|
|
|
|
modelinfo_t(const mbsp_t *b, const dmodelh2_t *m, float lmscale) : bsp{b}, model{m}, lightmapscale{lmscale} { }
|
|
};
|
|
|
|
enum class visapprox_t
|
|
{
|
|
NONE,
|
|
AUTO,
|
|
VIS,
|
|
RAYS
|
|
};
|
|
|
|
//
|
|
// worldspawn keys / command-line settings
|
|
//
|
|
|
|
enum
|
|
{
|
|
// Q1-style surface light copies
|
|
SURFLIGHT_Q1 = 0,
|
|
// Q2/Q3-style radiosity
|
|
SURFLIGHT_RAD = 1
|
|
};
|
|
|
|
namespace settings
|
|
{
|
|
extern setting_group worldspawn_group;
|
|
|
|
class worldspawn_keys : public virtual setting_container
|
|
{
|
|
public:
|
|
setting_scalar scaledist{this, "dist", 1.0, 0.0, 100.0, &worldspawn_group};
|
|
setting_scalar rangescale{this, "range", 0.5, 0.0, 100.0, &worldspawn_group};
|
|
setting_scalar global_anglescale{this, {"anglescale", "anglesense"}, 0.5, 0.0, 1.0, &worldspawn_group};
|
|
setting_scalar lightmapgamma{this, "gamma", 1.0, 0.0, 100.0, &worldspawn_group};
|
|
setting_bool addminlight{this, "addmin", false, &worldspawn_group};
|
|
setting_scalar minlight{this, {"light", "minlight"}, 0, &worldspawn_group};
|
|
setting_color minlight_color{this, {"minlight_color", "mincolor"}, 255.0, 255.0, 255.0, &worldspawn_group};
|
|
setting_bool spotlightautofalloff{this, "spotlightautofalloff", false, &worldspawn_group}; // mxd
|
|
setting_int32 compilerstyle_start{
|
|
this, "compilerstyle_start", 32, &worldspawn_group}; // start index for switchable light styles, default 32
|
|
setting_int32 compilerstyle_max{
|
|
this, "compilerstyle_max", 64, &worldspawn_group}; // max index for switchable light styles, default 64
|
|
|
|
/* dirt */
|
|
setting_bool globalDirt{this, {"dirt", "dirty"}, false,
|
|
&worldspawn_group}; // apply dirt to all lights (unless they override it) + sunlight + minlight?
|
|
setting_scalar dirtMode{this, "dirtmode", 0.0f, &worldspawn_group};
|
|
setting_scalar dirtDepth{this, "dirtdepth", 128.0, 1.0, std::numeric_limits<vec_t>::infinity(), &worldspawn_group};
|
|
setting_scalar dirtScale{this, "dirtscale", 1.0, 0.0, 100.0, &worldspawn_group};
|
|
setting_scalar dirtGain{this, "dirtgain", 1.0, 0.0, 100.0, &worldspawn_group};
|
|
setting_scalar dirtAngle{this, "dirtangle", 88.0, 1.0, 90.0, &worldspawn_group};
|
|
setting_bool minlightDirt{this, "minlight_dirt", false, &worldspawn_group}; // apply dirt to minlight?
|
|
|
|
/* phong */
|
|
setting_bool phongallowed{this, "phong", true, &worldspawn_group};
|
|
setting_scalar phongangle{this, "phong_angle", 0, &worldspawn_group};
|
|
|
|
/* bounce */
|
|
setting_bool bounce{this, "bounce", false, &worldspawn_group};
|
|
setting_bool bouncestyled{this, "bouncestyled", false, &worldspawn_group};
|
|
setting_scalar bouncescale{this, "bouncescale", 1.0, 0.0, 100.0, &worldspawn_group};
|
|
setting_scalar bouncecolorscale{this, "bouncecolorscale", 0.0, 0.0, 1.0, &worldspawn_group};
|
|
|
|
/* Q2 surface lights (mxd) */
|
|
setting_scalar surflightscale{this, "surflightscale", 1.0, &worldspawn_group};
|
|
setting_scalar surflightsubdivision{this, {"surflightsubdivision", "choplight"}, 16.0, 1.0, 8192.0,
|
|
&worldspawn_group}; // "choplight" - arghrad3 name
|
|
|
|
/* sunlight */
|
|
/* sun_light, sun_color, sun_angle for http://www.bspquakeeditor.com/arghrad/ compatibility */
|
|
setting_scalar sunlight{this, {"sunlight", "sun_light"}, 0.0, &worldspawn_group}; /* main sun */
|
|
setting_color sunlight_color{this, {"sunlight_color", "sun_color"}, 255.0, 255.0, 255.0, &worldspawn_group};
|
|
setting_scalar sun2{this, "sun2", 0.0, &worldspawn_group}; /* second sun */
|
|
setting_color sun2_color{this, "sun2_color", 255.0, 255.0, 255.0, &worldspawn_group};
|
|
setting_scalar sunlight2{this, "sunlight2", 0.0, &worldspawn_group}; /* top sky dome */
|
|
setting_color sunlight2_color{this, {"sunlight2_color", "sunlight_color2"}, 255.0, 255.0, 255.0, &worldspawn_group};
|
|
setting_scalar sunlight3{this, "sunlight3", 0.0, &worldspawn_group}; /* bottom sky dome */
|
|
setting_color sunlight3_color{this, {"sunlight3_color", "sunlight_color3"}, 255.0, 255.0, 255.0, &worldspawn_group};
|
|
setting_scalar sunlight_dirt{this, "sunlight_dirt", 0.0, &worldspawn_group};
|
|
setting_scalar sunlight2_dirt{this, "sunlight2_dirt", 0.0, &worldspawn_group};
|
|
setting_mangle sunvec{this, {"sunlight_mangle", "sun_mangle", "sun_angle"}, 0.0, -90.0, 0.0,
|
|
&worldspawn_group}; /* defaults to straight down */
|
|
setting_mangle sun2vec{this, "sun2_mangle", 0.0, -90.0, 0.0, &worldspawn_group}; /* defaults to straight down */
|
|
setting_scalar sun_deviance{this, "sunlight_penumbra", 0.0, 0.0, 180.0, &worldspawn_group};
|
|
setting_vec3 sky_surface{
|
|
this, {"sky_surface", "sun_surface"}, 0, 0, 0, &worldspawn_group} /* arghrad surface lights on sky faces */;
|
|
setting_int32 surflight_radiosity{this, "surflight_radiosity", SURFLIGHT_Q1, &worldspawn_group,
|
|
"whether to use Q1-style surface subdivision (0) or Q2-style surface radiosity"};
|
|
};
|
|
|
|
extern setting_group output_group;
|
|
extern setting_group debug_group;
|
|
extern setting_group postprocessing_group;
|
|
extern setting_group experimental_group;
|
|
|
|
class light_settings : public common_settings, public worldspawn_keys
|
|
{
|
|
public:
|
|
// slight modification to setting_numeric that supports
|
|
// a default value if a non-number is supplied after parsing
|
|
class setting_soft : public setting_int32
|
|
{
|
|
public:
|
|
using setting_int32::setting_int32;
|
|
|
|
bool parse(const std::string &settingName, parser_base_t &parser, source source) override
|
|
{
|
|
if (!parser.parse_token(PARSE_PEEK)) {
|
|
return false;
|
|
}
|
|
|
|
try {
|
|
int32_t f = static_cast<int32_t>(std::stoull(parser.token));
|
|
|
|
setValue(f, source);
|
|
|
|
parser.parse_token();
|
|
|
|
return true;
|
|
} catch (std::exception &) {
|
|
// if we didn't provide a (valid) number, then
|
|
// assume it's meant to be the default of -1
|
|
setValue(-1, source);
|
|
return true;
|
|
}
|
|
}
|
|
|
|
std::string format() const override { return "[n]"; }
|
|
};
|
|
|
|
class setting_extra : public setting_value<int32_t>
|
|
{
|
|
public:
|
|
using setting_value::setting_value;
|
|
|
|
bool parse(const std::string &settingName, parser_base_t &parser, source source) override
|
|
{
|
|
if (settingName.back() == '4') {
|
|
setValue(4, source);
|
|
} else {
|
|
setValue(2, source);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
std::string stringValue() const override { return std::to_string(_value); };
|
|
|
|
std::string format() const override { return ""; };
|
|
};
|
|
|
|
setting_bool surflight_dump{this, "surflight_dump", false, &debug_group, "dump surface lights to a .map file"};
|
|
setting_scalar surflight_subdivide{
|
|
this, "surflight_subdivide", 128.0, 1.0, 2048.0, &performance_group, "surface light subdivision size"};
|
|
setting_bool onlyents{this, "onlyents", false, &output_group, "only update entities"};
|
|
setting_bool write_normals{
|
|
this, "wrnormals", false, &output_group, "output normals, tangents and bitangents in a BSPX lump"};
|
|
setting_bool novanilla{
|
|
this, "novanilla", false, &experimental_group, "implies -bspxlit; don't write vanilla lighting"};
|
|
setting_scalar gate{this, "gate", EQUAL_EPSILON, &performance_group, "cutoff lights at this brightness level"};
|
|
setting_int32 sunsamples{
|
|
this, "sunsamples", 64, 8, 2048, &performance_group, "set samples for _sunlight2, default 64"};
|
|
setting_bool arghradcompat{
|
|
this, "arghradcompat", false, &output_group, "enable compatibility for Arghrad-specific keys"};
|
|
setting_bool nolighting{this, "nolighting", false, &output_group, "don't output main world lighting (Q2RTX)"};
|
|
setting_vec3 debugface{this, "debugface", std::numeric_limits<vec_t>::quiet_NaN(),
|
|
std::numeric_limits<vec_t>::quiet_NaN(), std::numeric_limits<vec_t>::quiet_NaN(), &debug_group, ""};
|
|
setting_vec3 debugvert{this, "debugvert", std::numeric_limits<vec_t>::quiet_NaN(),
|
|
std::numeric_limits<vec_t>::quiet_NaN(), std::numeric_limits<vec_t>::quiet_NaN(), &debug_group, ""};
|
|
setting_bool highlightseams{this, "highlightseams", false, &debug_group, ""};
|
|
setting_soft soft{this, "soft", 0, -1, std::numeric_limits<int32_t>::max(), &postprocessing_group,
|
|
"blurs the lightmap. specify n to blur radius in samples, otherwise auto"};
|
|
setting_set radlights{this, "radlights", "\"filename.rad\"", &experimental_group,
|
|
"loads a <surfacename> <r> <g> <b> <intensity> file"};
|
|
setting_int32 lightmap_scale{
|
|
this, "lightmap_scale", 0, &experimental_group, "force change lightmap scale; vanilla engines only allow 16"};
|
|
setting_extra extra{
|
|
this, {"extra", "extra4"}, 1, &performance_group, "supersampling; 2x2 (extra) or 4x4 (extra4) respectively"};
|
|
setting_enum<visapprox_t> visapprox{this, "visapprox", visapprox_t::AUTO,
|
|
{{"auto", visapprox_t::AUTO}, {"none", visapprox_t::NONE}, {"vis", visapprox_t::VIS},
|
|
{"rays", visapprox_t::RAYS}},
|
|
&debug_group,
|
|
"change approximate visibility algorithm. auto = choose default based on format. vis = use BSP vis data (slow but precise). rays = use sphere culling with fired rays (fast but may miss faces)"};
|
|
setting_func lit{
|
|
this, "lit", [&](source) { write_litfile |= lightfile::external; }, &output_group, "write .lit file"};
|
|
setting_func lit2{
|
|
this, "lit2", [&](source) { write_litfile = lightfile::lit2; }, &experimental_group, "write .lit2 file"};
|
|
setting_func bspxlit{this, "bspxlit", [&](source) { write_litfile |= lightfile::bspx; }, &experimental_group,
|
|
"writes rgb data into the bsp itself"};
|
|
setting_func lux{
|
|
this, "lux", [&](source) { write_luxfile |= lightfile::external; }, &experimental_group, "write .lux file"};
|
|
setting_func bspxlux{this, "bspxlux", [&](source) { write_luxfile |= lightfile::bspx; }, &experimental_group,
|
|
"writes lux data into the bsp itself"};
|
|
setting_func bspxonly{this, "bspxonly",
|
|
[&](source source) {
|
|
write_litfile = lightfile::bspx;
|
|
write_luxfile = lightfile::bspx;
|
|
novanilla.setValue(true, source);
|
|
},
|
|
&experimental_group, "writes both rgb and directions data *only* into the bsp itself"};
|
|
setting_func bspx{this, "bspx",
|
|
[&](source source) {
|
|
write_litfile = lightfile::bspx;
|
|
write_luxfile = lightfile::bspx;
|
|
},
|
|
&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 if > 4"};
|
|
setting_bool exportobj{this, "exportobj", false, &output_group, "export an .OBJ for inspection"};
|
|
setting_int32 lmshift{this, "lmshift", 4, &output_group,
|
|
"force a specified lmshift to be applied to the entire map; this is useful if you want to re-light a map with higher quality BSPX lighting without the sources. Will add the LMSHIFT lump to the BSP."};
|
|
|
|
inline void CheckNoDebugModeSet()
|
|
{
|
|
if (debugmode != debugmodes::none) {
|
|
Error("Only one debug mode is allowed at a time");
|
|
}
|
|
}
|
|
|
|
setting_func dirtdebug{this, {"dirtdebug", "debugdirt"},
|
|
[&](source) {
|
|
CheckNoDebugModeSet();
|
|
debugmode = debugmodes::dirt;
|
|
},
|
|
&debug_group, "only save the AO values to the lightmap"};
|
|
|
|
setting_func bouncedebug{this, "bouncedebug",
|
|
[&](source) {
|
|
CheckNoDebugModeSet();
|
|
debugmode = debugmodes::bounce;
|
|
},
|
|
&debug_group, "only save bounced lighting to the lightmap"};
|
|
|
|
setting_func bouncelightsdebug{this, "bouncelightsdebug",
|
|
[&](source) {
|
|
CheckNoDebugModeSet();
|
|
debugmode = debugmodes::bouncelights;
|
|
},
|
|
&debug_group, "only save bounced emitters lighting to the lightmap"};
|
|
|
|
setting_func phongdebug{this, "phongdebug",
|
|
[&](source) {
|
|
CheckNoDebugModeSet();
|
|
debugmode = debugmodes::phong;
|
|
},
|
|
&debug_group, "only save phong normals to the lightmap"};
|
|
|
|
setting_func phongdebug_obj{this, "phongdebug_obj",
|
|
[&](source) {
|
|
CheckNoDebugModeSet();
|
|
debugmode = debugmodes::phong_obj;
|
|
},
|
|
&debug_group, "save map as .obj with phonged normals"};
|
|
|
|
setting_func debugoccluded{this, "debugoccluded",
|
|
[&](source) {
|
|
CheckNoDebugModeSet();
|
|
debugmode = debugmodes::debugoccluded;
|
|
},
|
|
&debug_group, "save light occlusion data to lightmap"};
|
|
|
|
setting_func debugneighbours{this, "debugneighbours",
|
|
[&](source) {
|
|
CheckNoDebugModeSet();
|
|
debugmode = debugmodes::debugneighbours;
|
|
},
|
|
&debug_group, "save neighboring faces data to lightmap (requires -debugface)"};
|
|
|
|
fs::path sourceMap;
|
|
|
|
bitflags<lightfile> write_litfile = lightfile::none;
|
|
bitflags<lightfile> write_luxfile = lightfile::none;
|
|
debugmodes debugmode = debugmodes::none;
|
|
|
|
void setParameters(int argc, const char **argv) override
|
|
{
|
|
common_settings::setParameters(argc, argv);
|
|
programDescription = "light compiles lightmap data for BSPs\n\n";
|
|
remainderName = "mapname.bsp";
|
|
}
|
|
|
|
void initialize(int argc, const char **argv) override;
|
|
void postinitialize(int argc, const char **argv) override;
|
|
};
|
|
}; // namespace settings
|
|
|
|
extern settings::light_settings light_options;
|
|
|
|
extern std::vector<uint8_t> filebase;
|
|
extern std::vector<uint8_t> lit_filebase;
|
|
extern std::vector<uint8_t> lux_filebase;
|
|
|
|
bool IsOutputtingSupplementaryData();
|
|
|
|
std::vector<std::unique_ptr<lightsurf_t>> &LightSurfaces();
|
|
|
|
extern std::vector<surfflags_t> extended_texinfo_flags;
|
|
|
|
// public functions
|
|
|
|
void FixupGlobalSettings(void);
|
|
void GetFileSpace(uint8_t **lightdata, uint8_t **colordata, uint8_t **deluxdata, int size);
|
|
void GetFileSpace_PreserveOffsetInBsp(uint8_t **lightdata, uint8_t **colordata, uint8_t **deluxdata, int lightofs);
|
|
const modelinfo_t *ModelInfoForModel(const mbsp_t *bsp, int modelnum);
|
|
/**
|
|
* returns nullptr for "skip" faces
|
|
*/
|
|
const modelinfo_t *ModelInfoForFace(const mbsp_t *bsp, int facenum);
|
|
const img::texture *Face_Texture(const mbsp_t *bsp, const mface_t *face);
|
|
int light_main(int argc, const char **argv);
|