Merge branch 'brushbsp' of https://github.com/ericwa/ericw-tools into brushbsp
This commit is contained in:
commit
2452d5edda
|
|
@ -538,6 +538,8 @@ extern std::vector<uint8_t> filebase;
|
|||
extern std::vector<uint8_t> lit_filebase;
|
||||
extern std::vector<uint8_t> lux_filebase;
|
||||
|
||||
std::vector<std::unique_ptr<lightsurf_t>> &LightSurfaces();
|
||||
|
||||
extern std::vector<surfflags_t> extended_texinfo_flags;
|
||||
|
||||
bool Leaf_HasSky(const mbsp_t *bsp, const mleaf_t *leaf);
|
||||
|
|
|
|||
|
|
@ -81,8 +81,13 @@ std::map<int, qvec3f> GetDirectLighting(
|
|||
void SetupDirt(settings::worldspawn_keys &cfg);
|
||||
float DirtAtPoint(const settings::worldspawn_keys &cfg, raystream_intersection_t *rs, const qvec3d &point,
|
||||
const qvec3d &normal, const modelinfo_t *selfshadow);
|
||||
std::unique_ptr<lightsurf_t> CreateLightmapSurface(const mbsp_t *bsp, const mface_t *face, const facesup_t *facesup, const settings::worldspawn_keys &cfg);
|
||||
bool Face_IsLightmapped(const mbsp_t *bsp, const mface_t *face);
|
||||
void LightFace(const mbsp_t *bsp, mface_t *face, facesup_t *facesup, const settings::worldspawn_keys &cfg);
|
||||
void LightFace(const mbsp_t *bsp, lightsurf_t &lightsurf, const settings::worldspawn_keys &cfg);
|
||||
void FinishLightmapSurface(
|
||||
const mbsp_t *bsp, lightsurf_t *lightsurf);
|
||||
void SaveLightmapSurface(
|
||||
const mbsp_t *bsp, mface_t *face, facesup_t *facesup, const lightsurf_t *lightsurf);
|
||||
|
||||
inline qmat4x4f TexSpaceToWorld(const mbsp_t *bsp, const mface_t *f)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -46,6 +46,5 @@ struct surfacelight_t
|
|||
};
|
||||
|
||||
const std::vector<surfacelight_t> &SurfaceLights();
|
||||
int TotalSurfacelightPoints();
|
||||
const std::vector<int> &SurfaceLightsForFaceNum(int facenum);
|
||||
void MakeRadiositySurfaceLights(const settings::worldspawn_keys &cfg, const mbsp_t *bsp);
|
||||
|
|
|
|||
|
|
@ -45,9 +45,9 @@
|
|||
using namespace std;
|
||||
using namespace polylib;
|
||||
|
||||
mutex radlights_lock;
|
||||
static std::vector<bouncelight_t> radlights;
|
||||
std::map<int, std::vector<int>> radlightsByFacenum;
|
||||
mutex bouncelights_lock;
|
||||
static std::vector<bouncelight_t> bouncelights;
|
||||
std::map<int, std::vector<int>> bouncelightsByFacenum;
|
||||
|
||||
class patch_t
|
||||
{
|
||||
|
|
@ -149,22 +149,22 @@ static void AddBounceLight(const qvec3d &pos, const std::map<int, qvec3f> &color
|
|||
l.bounds = EstimateVisibleBoundsAtPoint(pos);
|
||||
}
|
||||
|
||||
unique_lock<mutex> lck{radlights_lock};
|
||||
radlights.push_back(l);
|
||||
unique_lock<mutex> lck{bouncelights_lock};
|
||||
bouncelights.push_back(l);
|
||||
|
||||
const int lastBounceLightIndex = static_cast<int>(radlights.size()) - 1;
|
||||
radlightsByFacenum[Face_GetNum(bsp, face)].push_back(lastBounceLightIndex);
|
||||
const int lastBounceLightIndex = static_cast<int>(bouncelights.size()) - 1;
|
||||
bouncelightsByFacenum[Face_GetNum(bsp, face)].push_back(lastBounceLightIndex);
|
||||
}
|
||||
|
||||
const std::vector<bouncelight_t> &BounceLights()
|
||||
{
|
||||
return radlights;
|
||||
return bouncelights;
|
||||
}
|
||||
|
||||
const std::vector<int> &BounceLightsForFaceNum(int facenum)
|
||||
{
|
||||
const auto &vec = radlightsByFacenum.find(facenum);
|
||||
if (vec != radlightsByFacenum.end()) {
|
||||
const auto &vec = bouncelightsByFacenum.find(facenum);
|
||||
if (vec != bouncelightsByFacenum.end()) {
|
||||
return vec->second;
|
||||
}
|
||||
|
||||
|
|
@ -172,12 +172,6 @@ const std::vector<int> &BounceLightsForFaceNum(int facenum)
|
|||
return empty;
|
||||
}
|
||||
|
||||
struct make_bounce_lights_args_t
|
||||
{
|
||||
const mbsp_t *bsp;
|
||||
const settings::worldspawn_keys &cfg;
|
||||
};
|
||||
|
||||
static void MakeBounceLightsThread(const settings::worldspawn_keys &cfg, const mbsp_t *bsp, const mface_t &face)
|
||||
{
|
||||
if (!Face_ShouldBounce(bsp, &face)) {
|
||||
|
|
@ -263,5 +257,5 @@ void MakeBounceLights(const settings::worldspawn_keys &cfg, const mbsp_t *bsp)
|
|||
MakeBounceLightsThread(cfg, bsp, face);
|
||||
});
|
||||
|
||||
logging::print("{} bounce lights created\n", radlights.size());
|
||||
logging::print("{} bounce lights created\n", bouncelights.size());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@
|
|||
std::vector<std::unique_ptr<light_t>> all_lights;
|
||||
std::vector<sun_t> all_suns;
|
||||
std::vector<entdict_t> entdicts;
|
||||
static std::vector<entdict_t> radlights;
|
||||
std::vector<entdict_t> radlights;
|
||||
|
||||
const std::vector<std::unique_ptr<light_t>> &GetLights()
|
||||
{
|
||||
|
|
@ -978,15 +978,15 @@ inline qvec3d UniformPointOnSphere(vec_t u1, vec_t u2)
|
|||
|
||||
aabb3d EstimateVisibleBoundsAtPoint(const qvec3d &point)
|
||||
{
|
||||
const int N = 32;
|
||||
const int N2 = N * N;
|
||||
constexpr size_t N = 32;
|
||||
constexpr size_t N2 = N * N;
|
||||
|
||||
raystream_intersection_t rs{N2};
|
||||
|
||||
aabb3d bounds = point;
|
||||
|
||||
for (int x = 0; x < N; x++) {
|
||||
for (int y = 0; y < N; y++) {
|
||||
for (size_t x = 0; x < N; x++) {
|
||||
for (size_t y = 0; y < N; y++) {
|
||||
const vec_t u1 = static_cast<vec_t>(x) / static_cast<vec_t>(N - 1);
|
||||
const vec_t u2 = static_cast<vec_t>(y) / static_cast<vec_t>(N - 1);
|
||||
|
||||
|
|
@ -1030,10 +1030,6 @@ inline void EstimateLightAABB(const std::unique_ptr<light_t> &light)
|
|||
|
||||
void EstimateLightVisibility(void)
|
||||
{
|
||||
if (options.visapprox.value() != visapprox_t::RAYS) {
|
||||
return;
|
||||
}
|
||||
|
||||
logging::print("--- EstimateLightVisibility ---\n");
|
||||
|
||||
logging::parallel_for_each(all_lights, EstimateLightAABB);
|
||||
|
|
@ -1059,8 +1055,9 @@ void SetupLights(const settings::worldspawn_keys &cfg, const mbsp_t *bsp)
|
|||
SetupSuns(cfg);
|
||||
SetupSkyDomes(cfg);
|
||||
FixLightsOnFaces(bsp);
|
||||
EstimateLightVisibility();
|
||||
if (options.visapprox.value() == visapprox_t::VIS) {
|
||||
if (options.visapprox.value() == visapprox_t::RAYS) {
|
||||
EstimateLightVisibility();
|
||||
} else if (options.visapprox.value() == visapprox_t::VIS) {
|
||||
SetupLightLeafnums(bsp);
|
||||
}
|
||||
|
||||
|
|
|
|||
129
light/light.cc
129
light/light.cc
|
|
@ -55,10 +55,16 @@
|
|||
#include <common/qvec.hh>
|
||||
#include <common/json.hh>
|
||||
|
||||
using namespace std;
|
||||
|
||||
bool dirt_in_use = false;
|
||||
|
||||
// intermediate representation of lightmap surfaces
|
||||
static std::vector<std::unique_ptr<lightsurf_t>> light_surfaces;
|
||||
|
||||
std::vector<std::unique_ptr<lightsurf_t>> &LightSurfaces()
|
||||
{
|
||||
return light_surfaces;
|
||||
}
|
||||
|
||||
static std::vector<facesup_t> faces_sup; // lit2/bspx stuff
|
||||
|
||||
/// start of lightmap data
|
||||
|
|
@ -302,40 +308,70 @@ const img::texture *Face_Texture(const mbsp_t *bsp, const mface_t *face)
|
|||
return img::find(name);
|
||||
}
|
||||
|
||||
static void LightThread(const mbsp_t *bsp, size_t facenum)
|
||||
static void CreateLightmapSurfaces(mbsp_t *bsp)
|
||||
{
|
||||
#if defined(HAVE_EMBREE) && defined (__SSE2__)
|
||||
_MM_SET_FLUSH_ZERO_MODE(_MM_FLUSH_ZERO_ON);
|
||||
// _MM_SET_DENORMALS_ZERO_MODE(_MM_DENORMALS_ZERO_ON);
|
||||
#endif
|
||||
light_surfaces.resize(bsp->dfaces.size());
|
||||
logging::print("--- CreateLightmapSurfaces ---\n");
|
||||
logging::parallel_for(static_cast<size_t>(0), bsp->dfaces.size(), [&bsp](size_t i) {
|
||||
auto facesup = faces_sup.empty() ? nullptr : &faces_sup[i];
|
||||
auto face = &bsp->dfaces[i];
|
||||
|
||||
mface_t *f = BSP_GetFace(const_cast<mbsp_t *>(bsp), facenum);
|
||||
/* One extra lightmap is allocated to simplify handling overflow */
|
||||
if (!options.litonly.value()) {
|
||||
// if litonly is set we need to preserve the existing lightofs
|
||||
|
||||
/* Find the correct model offset */
|
||||
const modelinfo_t *face_modelinfo = ModelInfoForFace(bsp, facenum);
|
||||
if (face_modelinfo == NULL) {
|
||||
// ericw -- silenced this warning becasue is causes spam when "skip" faces are used
|
||||
// logging::print("warning: no model has face {}\n", facenum);
|
||||
return;
|
||||
}
|
||||
|
||||
if (faces_sup.empty()) {
|
||||
LightFace(bsp, f, nullptr, options);
|
||||
} else if (options.novanilla.value()) {
|
||||
f->lightofs = -1;
|
||||
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, &faces_sup[facenum], options);
|
||||
f->lightofs = faces_sup[facenum].lightofs;
|
||||
for (int i = 0; i < MAXLIGHTMAPS; i++) {
|
||||
f->styles[i] = faces_sup[facenum].styles[i];
|
||||
/* some surfaces don't need lightmaps */
|
||||
if (facesup) {
|
||||
facesup->lightofs = -1;
|
||||
for (size_t i = 0; i < MAXLIGHTMAPSSUP; i++) {
|
||||
facesup->styles[i] = INVALID_LIGHTSTYLE;
|
||||
}
|
||||
} else {
|
||||
face->lightofs = -1;
|
||||
for (size_t i = 0; i < MAXLIGHTMAPS; i++) {
|
||||
face->styles[i] = INVALID_LIGHTSTYLE_OLD;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
LightFace(bsp, f, nullptr, options);
|
||||
LightFace(bsp, f, &faces_sup[facenum], options);
|
||||
}
|
||||
|
||||
light_surfaces[i] = std::move(CreateLightmapSurface(bsp, face, facesup, options));
|
||||
});
|
||||
}
|
||||
|
||||
static void SaveLightmapSurfaces(mbsp_t *bsp)
|
||||
{
|
||||
logging::print("--- SaveLightmapSurfaces ---\n");
|
||||
logging::parallel_for(static_cast<size_t>(0), bsp->dfaces.size(), [&bsp](size_t i) {
|
||||
auto &surf = light_surfaces[i];
|
||||
|
||||
if (!surf) {
|
||||
return;
|
||||
}
|
||||
|
||||
FinishLightmapSurface(bsp, surf.get());
|
||||
|
||||
auto f = &bsp->dfaces[i];
|
||||
const modelinfo_t *face_modelinfo = ModelInfoForFace(bsp, i);
|
||||
|
||||
if (faces_sup.empty()) {
|
||||
SaveLightmapSurface(bsp, f, nullptr, surf.get());
|
||||
} else if (options.novanilla.value()) {
|
||||
f->lightofs = -1;
|
||||
f->styles[0] = INVALID_LIGHTSTYLE_OLD;
|
||||
SaveLightmapSurface(bsp, f, &faces_sup[i], surf.get());
|
||||
} else if (faces_sup[i].lmscale == face_modelinfo->lightmapscale) {
|
||||
SaveLightmapSurface(bsp, f, &faces_sup[i], surf.get());
|
||||
f->lightofs = faces_sup[i].lightofs;
|
||||
for (int i = 0; i < MAXLIGHTMAPS; i++) {
|
||||
f->styles[i] = faces_sup[i].styles[i];
|
||||
}
|
||||
} else {
|
||||
SaveLightmapSurface(bsp, f, nullptr, surf.get());
|
||||
SaveLightmapSurface(bsp, f, &faces_sup[i], surf.get());
|
||||
}
|
||||
|
||||
light_surfaces[i].reset();
|
||||
});
|
||||
}
|
||||
|
||||
static void FindModelInfo(const mbsp_t *bsp)
|
||||
|
|
@ -429,6 +465,7 @@ static void LightWorld(bspdata_t *bspdata, bool forcedscale)
|
|||
|
||||
mbsp_t &bsp = std::get<mbsp_t>(bspdata->bsp);
|
||||
|
||||
light_surfaces.clear();
|
||||
filebase.clear();
|
||||
lit_filebase.clear();
|
||||
lux_filebase.clear();
|
||||
|
|
@ -448,8 +485,9 @@ static void LightWorld(bspdata_t *bspdata, bool forcedscale)
|
|||
lux_file_p = 0;
|
||||
lux_file_end = (MAX_MAP_LIGHTING * 3);
|
||||
|
||||
if (forcedscale)
|
||||
if (forcedscale) {
|
||||
bspdata->bspx.entries.erase("LMSHIFT");
|
||||
}
|
||||
|
||||
auto lmshift_lump = bspdata->bspx.entries.find("LMSHIFT");
|
||||
|
||||
|
|
@ -471,6 +509,9 @@ static void LightWorld(bspdata_t *bspdata, bool forcedscale)
|
|||
|
||||
CalculateVertexNormals(&bsp);
|
||||
|
||||
// create lightmap surfaces
|
||||
CreateLightmapSurfaces(&bsp);
|
||||
|
||||
const bool isQuake2map = bsp.loadversion->game->id == GAME_QUAKE_II; // mxd
|
||||
const bool bouncerequired =
|
||||
options.bounce.value() && (options.debugmode == debugmodes::none || options.debugmode == debugmodes::bounce ||
|
||||
|
|
@ -484,16 +525,6 @@ static void LightWorld(bspdata_t *bspdata, bool forcedscale)
|
|||
}
|
||||
}
|
||||
|
||||
if (SurfaceLights().size()) {
|
||||
logging::print("{} surface lights ({} light points) in use.\n",
|
||||
SurfaceLights().size(), TotalSurfacelightPoints());
|
||||
}
|
||||
|
||||
if (BounceLights().size()) { // mxd. Print some extra stats...
|
||||
logging::print("{} bounce lights in use.\n",
|
||||
BounceLights().size());
|
||||
}
|
||||
|
||||
#if 0
|
||||
lightbatchthread_info_t info;
|
||||
info.all_batches = MakeLightingBatches(bsp);
|
||||
|
|
@ -503,10 +534,18 @@ static void LightWorld(bspdata_t *bspdata, bool forcedscale)
|
|||
#else
|
||||
logging::print("--- LightThread ---\n"); // mxd
|
||||
logging::parallel_for(static_cast<size_t>(0), bsp.dfaces.size(), [&bsp](size_t i) {
|
||||
LightThread(&bsp, i);
|
||||
if (light_surfaces[i]) {
|
||||
#if defined(HAVE_EMBREE) && defined (__SSE2__)
|
||||
_MM_SET_FLUSH_ZERO_MODE(_MM_FLUSH_ZERO_ON);
|
||||
#endif
|
||||
|
||||
LightFace(&bsp, *light_surfaces[i].get(), options);
|
||||
}
|
||||
});
|
||||
#endif
|
||||
|
||||
SaveLightmapSurfaces(&bsp);
|
||||
|
||||
logging::print("Lighting Completed.\n\n");
|
||||
|
||||
// Transfer greyscale lightmap (or color lightmap for Q2/HL) to the bsp and update lightdatasize
|
||||
|
|
@ -712,8 +751,8 @@ static void ExportObj(const fs::path &filename, const mbsp_t *bsp)
|
|||
}
|
||||
|
||||
// obj
|
||||
static vector<vector<const mleaf_t *>> faceleafs;
|
||||
static vector<bool> leafhassky;
|
||||
static std::vector<std::vector<const mleaf_t *>> faceleafs;
|
||||
static std::vector<bool> leafhassky;
|
||||
|
||||
// index some stuff from the bsp
|
||||
static void BuildPvsIndex(const mbsp_t *bsp)
|
||||
|
|
|
|||
131
light/ltface.cc
131
light/ltface.cc
|
|
@ -860,19 +860,32 @@ static void CalcPvs(const mbsp_t *bsp, lightsurf_t *lightsurf)
|
|||
}
|
||||
}
|
||||
|
||||
static bool Lightsurf_Init(
|
||||
const modelinfo_t *modelinfo, const mface_t *face, const mbsp_t *bsp, lightsurf_t *lightsurf, facesup_t *facesup)
|
||||
static std::unique_ptr<lightsurf_t> Lightsurf_Init(
|
||||
const modelinfo_t *modelinfo, const settings::worldspawn_keys &cfg, const mface_t *face, const mbsp_t *bsp, const facesup_t *facesup)
|
||||
{
|
||||
/*FIXME: memset can be slow on large datasets*/
|
||||
// memset(lightsurf, 0, sizeof(*lightsurf));
|
||||
auto spaceToWorld = TexSpaceToWorld(bsp, face);
|
||||
|
||||
/* Check for invalid texture axes */
|
||||
if (std::isnan(spaceToWorld.at(0, 0))) {
|
||||
logging::print("Bad texture axes on face:\n");
|
||||
PrintFaceInfo(face, bsp);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto lightsurf = std::make_unique<lightsurf_t>();
|
||||
lightsurf->cfg = &cfg;
|
||||
lightsurf->modelinfo = modelinfo;
|
||||
lightsurf->bsp = bsp;
|
||||
lightsurf->face = face;
|
||||
|
||||
/* if liquid doesn't have the TEX_SPECIAL flag set, the map was qbsp'ed with
|
||||
* lit water in mind. In that case receive light from both top and bottom.
|
||||
* (lit will only be rendered in compatible engines, but degrades gracefully.)
|
||||
*/
|
||||
lightsurf->twosided = Face_IsTranslucent(bsp, face);
|
||||
|
||||
if (facesup)
|
||||
lightsurf->lightmapscale = facesup->lmscale;
|
||||
else
|
||||
lightsurf->lightmapscale = modelinfo->lightmapscale;
|
||||
// pick the larger of the two scales
|
||||
lightsurf->lightmapscale = (facesup && facesup->lmscale > modelinfo->lightmapscale) ? facesup->lmscale : modelinfo->lightmapscale;
|
||||
|
||||
const surfflags_t &extended_flags = extended_texinfo_flags[face->texinfo];
|
||||
lightsurf->curved = extended_flags.phong_angle != 0;
|
||||
|
|
@ -934,24 +947,17 @@ static bool Lightsurf_Init(
|
|||
}
|
||||
|
||||
/* Set up the texorg for coordinate transformation */
|
||||
lightsurf->texorg.texSpaceToWorld = TexSpaceToWorld(bsp, face);
|
||||
lightsurf->texorg.texSpaceToWorld = spaceToWorld;
|
||||
lightsurf->texorg.texinfo = &bsp->texinfo[face->texinfo];
|
||||
lightsurf->texorg.planedist = plane.dist;
|
||||
|
||||
/* Check for invalid texture axes */
|
||||
if (std::isnan(lightsurf->texorg.texSpaceToWorld.at(0, 0))) {
|
||||
logging::print("Bad texture axes on face:\n");
|
||||
PrintFaceInfo(face, bsp);
|
||||
return false;
|
||||
}
|
||||
|
||||
const mtexinfo_t *tex = &bsp->texinfo[face->texinfo];
|
||||
lightsurf->snormal = qv::normalize(tex->vecs.row(0).xyz());
|
||||
lightsurf->tnormal = -qv::normalize(tex->vecs.row(1).xyz());
|
||||
|
||||
/* Set up the surface points */
|
||||
CalcFaceExtents(face, bsp, lightsurf);
|
||||
CalcPoints(modelinfo, modelinfo->offset, lightsurf, bsp, face);
|
||||
CalcFaceExtents(face, bsp, lightsurf.get());
|
||||
CalcPoints(modelinfo, modelinfo->offset, lightsurf.get(), bsp, face);
|
||||
|
||||
/* Correct the plane for the model offset (must be done last,
|
||||
calculation of face extents / points needs the uncorrected plane) */
|
||||
|
|
@ -970,10 +976,10 @@ static bool Lightsurf_Init(
|
|||
|
||||
/* Setup vis data */
|
||||
if (options.visapprox.value() == visapprox_t::VIS) {
|
||||
CalcPvs(bsp, lightsurf);
|
||||
CalcPvs(bsp, lightsurf.get());
|
||||
}
|
||||
|
||||
return true;
|
||||
return lightsurf;
|
||||
}
|
||||
|
||||
static void Lightmap_AllocOrClear(lightmap_t *lightmap, const lightsurf_t *lightsurf)
|
||||
|
|
@ -2691,11 +2697,11 @@ static void LightFace_CalculateDirt(lightsurf_t *lightsurf)
|
|||
|
||||
// clamps negative values. applies gamma and rangescale. clamps values over 255
|
||||
// N.B. we want to do this before smoothing / downscaling, so huge values don't mess up the averaging.
|
||||
static void LightFace_ScaleAndClamp(const lightsurf_t *lightsurf, lightmapdict_t *lightmaps)
|
||||
inline void LightFace_ScaleAndClamp(lightsurf_t *lightsurf)
|
||||
{
|
||||
const settings::worldspawn_keys &cfg = *lightsurf->cfg;
|
||||
|
||||
for (lightmap_t &lightmap : *lightmaps) {
|
||||
for (lightmap_t &lightmap : lightsurf->lightmapsByStyle) {
|
||||
for (int i = 0; i < lightsurf->points.size(); i++) {
|
||||
qvec3d &color = lightmap.samples[i].color;
|
||||
|
||||
|
|
@ -2718,6 +2724,13 @@ static void LightFace_ScaleAndClamp(const lightsurf_t *lightsurf, lightmapdict_t
|
|||
}
|
||||
}
|
||||
|
||||
void FinishLightmapSurface(
|
||||
const mbsp_t *bsp, lightsurf_t *lightsurf)
|
||||
{
|
||||
/* Apply gamma, rangescale, and clamp */
|
||||
LightFace_ScaleAndClamp(lightsurf);
|
||||
}
|
||||
|
||||
static float Lightmap_AvgBrightness(const lightmap_t *lm, const lightsurf_t *lightsurf)
|
||||
{
|
||||
float avgb = 0;
|
||||
|
|
@ -3105,9 +3118,10 @@ bool Face_IsLightmapped(const mbsp_t *bsp, const mface_t *face)
|
|||
static void WriteSingleLightmap(const mbsp_t *bsp, const mface_t *face, const lightsurf_t *lightsurf,
|
||||
const lightmap_t *lm, const int actual_width, const int actual_height, uint8_t *out, uint8_t *lit, uint8_t *lux);
|
||||
|
||||
static void WriteLightmaps(
|
||||
const mbsp_t *bsp, mface_t *face, facesup_t *facesup, const lightsurf_t *lightsurf, const lightmapdict_t *lightmaps)
|
||||
void SaveLightmapSurface(
|
||||
const mbsp_t *bsp, mface_t *face, facesup_t *facesup, const lightsurf_t *lightsurf)
|
||||
{
|
||||
const lightmapdict_t &lightmaps = lightsurf->lightmapsByStyle;
|
||||
const int actual_width = lightsurf->texsize[0] + 1;
|
||||
const int actual_height = lightsurf->texsize[1] + 1;
|
||||
|
||||
|
|
@ -3132,7 +3146,7 @@ static void WriteLightmaps(
|
|||
}
|
||||
|
||||
// see if we have computed lighting for this style
|
||||
for (const lightmap_t &lm : *lightmaps) {
|
||||
for (const lightmap_t &lm : lightmaps) {
|
||||
if (lm.style == style) {
|
||||
WriteSingleLightmap(bsp, face, lightsurf, &lm, actual_width, actual_height, out, lit, lux);
|
||||
break;
|
||||
|
|
@ -3157,7 +3171,7 @@ static void WriteLightmaps(
|
|||
// intermediate collection for sorting lightmaps
|
||||
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
|
||||
if (lightmap.style == INVALID_LIGHTSTYLE)
|
||||
continue;
|
||||
|
|
@ -3347,69 +3361,44 @@ static void WriteSingleLightmap(const mbsp_t *bsp, const mface_t *face, const li
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* ============
|
||||
* LightFace
|
||||
* ============
|
||||
*/
|
||||
void LightFace(const mbsp_t *bsp, mface_t *face, facesup_t *facesup, const settings::worldspawn_keys &cfg)
|
||||
std::unique_ptr<lightsurf_t> CreateLightmapSurface(const mbsp_t *bsp, const mface_t *face, const facesup_t *facesup, const settings::worldspawn_keys &cfg)
|
||||
{
|
||||
/* Find the correct model offset */
|
||||
const modelinfo_t *modelinfo = ModelInfoForFace(bsp, Face_GetNum(bsp, face));
|
||||
if (modelinfo == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* One extra lightmap is allocated to simplify handling overflow */
|
||||
|
||||
if (!options.litonly.value()) {
|
||||
// if litonly is set we need to preserve the existing lightofs
|
||||
|
||||
/* some surfaces don't need lightmaps */
|
||||
if (facesup) {
|
||||
facesup->lightofs = -1;
|
||||
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] = INVALID_LIGHTSTYLE_OLD;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/* don't bother with degenerate faces */
|
||||
if (face->numedges < 3)
|
||||
return;
|
||||
return nullptr;
|
||||
|
||||
if (!Face_IsLightmapped(bsp, face))
|
||||
return;
|
||||
return nullptr;
|
||||
|
||||
const char *texname = Face_TextureName(bsp, face);
|
||||
|
||||
/* don't save lightmaps for "trigger" texture */
|
||||
if (!Q_strcasecmp(texname, "trigger"))
|
||||
return;
|
||||
return nullptr;
|
||||
|
||||
/* don't save lightmaps for "skip" texture */
|
||||
if (!Q_strcasecmp(texname, "skip"))
|
||||
return;
|
||||
return nullptr;
|
||||
|
||||
/* all good, this face is going to be lightmapped. */
|
||||
lightsurf_t lightsurf{};
|
||||
lightsurf.cfg = &cfg;
|
||||
return Lightsurf_Init(modelinfo, cfg, face, bsp, facesup);
|
||||
}
|
||||
|
||||
/* if liquid doesn't have the TEX_SPECIAL flag set, the map was qbsp'ed with
|
||||
* lit water in mind. In that case receive light from both top and bottom.
|
||||
* (lit will only be rendered in compatible engines, but degrades gracefully.)
|
||||
*/
|
||||
if (Face_IsTranslucent(bsp, face)) {
|
||||
lightsurf.twosided = true;
|
||||
}
|
||||
/*
|
||||
* ============
|
||||
* LightFace
|
||||
* ============
|
||||
*/
|
||||
void LightFace(const mbsp_t *bsp, lightsurf_t &lightsurf, const settings::worldspawn_keys &cfg)
|
||||
{
|
||||
auto face = lightsurf.face;
|
||||
const modelinfo_t *modelinfo = ModelInfoForFace(bsp, Face_GetNum(bsp, face));
|
||||
|
||||
if (!Lightsurf_Init(modelinfo, face, bsp, &lightsurf, facesup)) {
|
||||
/* invalid texture axes */
|
||||
return;
|
||||
}
|
||||
lightmapdict_t *lightmaps = &lightsurf.lightmapsByStyle;
|
||||
|
||||
/* calculate dirt (ambient occlusion) but don't use it yet */
|
||||
|
|
@ -3450,7 +3439,6 @@ void LightFace(const mbsp_t *bsp, mface_t *face, facesup_t *facesup, const setti
|
|||
}
|
||||
|
||||
/* minlight - Use Q2 surface light, or the greater of global or model minlight. */
|
||||
// FIXME: _surface 2 support
|
||||
const mtexinfo_t *texinfo = Face_Texinfo(bsp, face); // mxd. Surface lights...
|
||||
if (texinfo != nullptr && texinfo->value > 0 && (texinfo->flags.native & Q2_SURF_LIGHT)) {
|
||||
LightFace_Min(bsp, face, Face_LookupTextureColor(bsp, face), texinfo->value * 2.0f, &lightsurf,
|
||||
|
|
@ -3501,9 +3489,4 @@ void LightFace(const mbsp_t *bsp, mface_t *face, facesup_t *facesup, const setti
|
|||
|
||||
if (options.debugmode == debugmodes::debugneighbours)
|
||||
LightFace_DebugNeighbours(&lightsurf, lightmaps);
|
||||
|
||||
/* Apply gamma, rangescale, and clamp */
|
||||
LightFace_ScaleAndClamp(&lightsurf, lightmaps);
|
||||
|
||||
WriteLightmaps(bsp, face, facesup, &lightsurf, lightmaps);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ using namespace polylib;
|
|||
mutex surfacelights_lock;
|
||||
std::vector<surfacelight_t> surfacelights;
|
||||
std::map<int, std::vector<int>> surfacelightsByFacenum;
|
||||
int total_surflight_points = 0;
|
||||
size_t total_surflight_points = 0;
|
||||
|
||||
static void MakeSurfaceLight(const mbsp_t *bsp, const settings::worldspawn_keys &cfg, const mface_t *face, std::optional<qvec3f> texture_color, bool is_directional, bool is_sky, int32_t style, int32_t light_value)
|
||||
{
|
||||
|
|
@ -175,11 +175,6 @@ const std::vector<surfacelight_t> &SurfaceLights()
|
|||
return surfacelights;
|
||||
}
|
||||
|
||||
int TotalSurfacelightPoints()
|
||||
{
|
||||
return total_surflight_points;
|
||||
}
|
||||
|
||||
// No surflight_debug (yet?), so unused...
|
||||
const std::vector<int> &SurfaceLightsForFaceNum(int facenum)
|
||||
{
|
||||
|
|
@ -197,4 +192,9 @@ MakeRadiositySurfaceLights(const settings::worldspawn_keys &cfg, const mbsp_t *b
|
|||
logging::print("--- MakeRadiositySurfaceLights ---\n");
|
||||
|
||||
logging::parallel_for(static_cast<size_t>(0), bsp->dfaces.size(), [&](size_t i) { MakeSurfaceLightsThread(bsp, cfg, i); });
|
||||
|
||||
if (surfacelights.size()) {
|
||||
logging::print("{} surface lights ({} light points) in use.\n",
|
||||
surfacelights.size(), total_surflight_points);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue