light: wip -world_units_per_luxel and DECOUPLED_LM BSPX lump
This commit is contained in:
parent
8b524cf324
commit
ca0efbf3d3
|
|
@ -96,6 +96,33 @@ static json serialize_bspxbrushlist(const std::vector<uint8_t> &lump)
|
|||
return j;
|
||||
}
|
||||
|
||||
static json serialize_bspx_decoupled_lm(const std::vector<uint8_t> &lump)
|
||||
{
|
||||
json j = json::array();
|
||||
|
||||
imemstream p(lump.data(), lump.size(), std::ios_base::in | std::ios_base::binary);
|
||||
|
||||
p >> endianness<std::endian::little>;
|
||||
|
||||
while (true) {
|
||||
bspx_decoupled_lm_perface src_face;
|
||||
p >= src_face;
|
||||
|
||||
if (!p) {
|
||||
break;
|
||||
}
|
||||
|
||||
json &model = j.insert(j.end(), json::object()).value();
|
||||
model["lmwidth"] = src_face.lmwidth;
|
||||
model["lmheight"] = src_face.lmheight;
|
||||
model["offset"] = src_face.offset;
|
||||
model["world_to_lm_space"] =
|
||||
json::array({src_face.world_to_lm_space.row(0), src_face.world_to_lm_space.row(1)});
|
||||
}
|
||||
|
||||
return j;
|
||||
}
|
||||
|
||||
/**
|
||||
* The MIT License (MIT)
|
||||
* Copyright (c) 2016 tomykaira
|
||||
|
|
@ -191,8 +218,15 @@ static std::string serialize_image(const std::optional<img::texture> &texture_op
|
|||
|
||||
#include "common/bsputils.hh"
|
||||
|
||||
static faceextents_t get_face_extents(const mbsp_t &bsp, const bspxentries_t &bspx, const mface_t &face, bool use_bspx)
|
||||
static faceextents_t get_face_extents(const mbsp_t &bsp, const bspxentries_t &bspx,
|
||||
const std::vector<bspx_decoupled_lm_perface> &bspx_decoupled, const mface_t &face, bool use_bspx,
|
||||
bool use_decoupled)
|
||||
{
|
||||
if (use_decoupled) {
|
||||
ptrdiff_t face_idx = &face - bsp.dfaces.data();
|
||||
auto &bspx = bspx_decoupled[face_idx];
|
||||
return {face, bsp, bspx.lmwidth, bspx.lmheight, bspx.world_to_lm_space};
|
||||
}
|
||||
if (!use_bspx) {
|
||||
return {face, bsp, 16.0};
|
||||
}
|
||||
|
|
@ -201,7 +235,7 @@ static faceextents_t get_face_extents(const mbsp_t &bsp, const bspxentries_t &bs
|
|||
(float)nth_bit(reinterpret_cast<const char *>(bspx.at("LMSHIFT").data())[&face - bsp.dfaces.data()])};
|
||||
}
|
||||
|
||||
static void export_obj_and_lightmaps(const mbsp_t &bsp, const bspxentries_t &bspx, bool use_bspx, fs::path obj_path, fs::path lightmaps_path)
|
||||
static void export_obj_and_lightmaps(const mbsp_t &bsp, const bspxentries_t &bspx, bool use_bspx, bool use_decoupled, fs::path obj_path, fs::path lightmaps_path)
|
||||
{
|
||||
struct face_rect
|
||||
{
|
||||
|
|
@ -235,18 +269,38 @@ static void export_obj_and_lightmaps(const mbsp_t &bsp, const bspxentries_t &bsp
|
|||
bspx_lmoffset >> endianness<std::endian::little>;
|
||||
}
|
||||
|
||||
std::vector<bspx_decoupled_lm_perface> bspx_decoupled;
|
||||
if (use_decoupled && (bspx.find("DECOUPLED_LM") != bspx.end())) {
|
||||
bspx_decoupled.resize(bsp.dfaces.size());
|
||||
|
||||
imemstream stream(nullptr, 0);
|
||||
|
||||
auto &decoupled_lm = bspx.at("DECOUPLED_LM");
|
||||
stream = imemstream(decoupled_lm.data(), decoupled_lm.size());
|
||||
stream >> endianness<std::endian::little>;
|
||||
|
||||
for (size_t i = 0; i < bsp.dfaces.size(); ++i) {
|
||||
stream >= bspx_decoupled[i];
|
||||
}
|
||||
} else {
|
||||
use_decoupled = false;
|
||||
}
|
||||
|
||||
// make rectangles
|
||||
for (auto &face : bsp.dfaces) {
|
||||
const ptrdiff_t face_idx = (&face - bsp.dfaces.data());
|
||||
int32_t faceofs;
|
||||
|
||||
if (!use_bspx) {
|
||||
if (use_decoupled) {
|
||||
faceofs = bspx_decoupled[face_idx].offset;
|
||||
} else if (!use_bspx) {
|
||||
faceofs = face.lightofs;
|
||||
} else {
|
||||
bspx_lmoffset.seekg((&face - bsp.dfaces.data()) * sizeof(int32_t));
|
||||
bspx_lmoffset.seekg(face_idx * sizeof(int32_t));
|
||||
bspx_lmoffset >= faceofs;
|
||||
}
|
||||
|
||||
rectangles.emplace_back(face_rect{&face, get_face_extents(bsp, bspx, face, use_bspx), faceofs});
|
||||
rectangles.emplace_back(face_rect{&face, get_face_extents(bsp, bspx, bspx_decoupled, face, use_bspx, use_decoupled), faceofs});
|
||||
}
|
||||
|
||||
if (!rectangles.size()) {
|
||||
|
|
@ -684,6 +738,8 @@ void serialize_bsp(const bspdata_t &bspdata, const mbsp_t &bsp, const fs::path &
|
|||
|
||||
if (lump.first == "BRUSHLIST") {
|
||||
entry["models"] = serialize_bspxbrushlist(lump.second);
|
||||
} else if (lump.first == "DECOUPLED_LM") {
|
||||
entry["faces"] = serialize_bspx_decoupled_lm(lump.second);
|
||||
} else {
|
||||
// unhandled BSPX lump, just write the raw data
|
||||
entry["lumpdata"] = hex_string(lump.second.data(), lump.second.size());
|
||||
|
|
@ -705,7 +761,7 @@ void serialize_bsp(const bspdata_t &bspdata, const mbsp_t &bsp, const fs::path &
|
|||
}
|
||||
}
|
||||
#endif
|
||||
export_obj_and_lightmaps(bsp, bspdata.bspx.entries, false, fs::path(name).replace_extension(".geometry.obj"), fs::path(name).replace_extension(".lm.png"));
|
||||
export_obj_and_lightmaps(bsp, bspdata.bspx.entries, false, true, fs::path(name).replace_extension(".geometry.obj"), fs::path(name).replace_extension(".lm.png"));
|
||||
|
||||
std::ofstream(name, std::fstream::out | std::fstream::trunc) << std::setw(4) << j;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -745,6 +745,107 @@ faceextents_t::faceextents_t(const mface_t &face, const mbsp_t &bsp, float light
|
|||
worldToLMMatrix = TexCoordToLMMatrix * worldToTexCoordMatrix;
|
||||
}
|
||||
|
||||
faceextents_t::faceextents_t(const mface_t &face, const mbsp_t &bsp, uint16_t lmwidth, uint16_t lmheight, texvecf world_to_lm_space) {
|
||||
if (lmwidth > 0 && lmheight > 0) {
|
||||
lm_extents = {lmwidth - 1, lmheight - 1};
|
||||
}
|
||||
|
||||
worldToTexCoordMatrix = WorldToTexSpace(&bsp, &face);
|
||||
texCoordToWorldMatrix = TexSpaceToWorld(&bsp, &face);
|
||||
|
||||
worldToLMMatrix.set_row(0, world_to_lm_space.row(0));
|
||||
worldToLMMatrix.set_row(1, world_to_lm_space.row(1));
|
||||
worldToLMMatrix.set_row(2, {0, 0, 1, 0});
|
||||
worldToLMMatrix.set_row(3, {0, 0, 0, 1});
|
||||
|
||||
lmToWorldMatrix = qv::inverse(worldToLMMatrix);
|
||||
|
||||
// bounds
|
||||
for (int i = 0; i < face.numedges; i++) {
|
||||
const qvec3f &worldpoint = Face_PointAtIndex(&bsp, &face, i);
|
||||
bounds += worldpoint;
|
||||
}
|
||||
|
||||
// calculate a bounding sphere for the face
|
||||
qvec3d radius = (bounds.maxs() - bounds.mins()) * 0.5;
|
||||
|
||||
origin = bounds.mins() + radius;
|
||||
this->radius = qv::length(radius);
|
||||
}
|
||||
|
||||
faceextents_t::faceextents_t(const mface_t &face, const mbsp_t &bsp, world_units_per_luxel_t tag, float world_units_per_luxel)
|
||||
{
|
||||
auto orig_normal = Face_Normal(&bsp, &face);
|
||||
size_t axis = qv::indexOfLargestMagnitudeComponent(orig_normal);
|
||||
|
||||
#if 0
|
||||
if (orig_normal == qvec3f(-1, 0, 0)) {
|
||||
logging::print("-x\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
qvec3f snapped_normal{};
|
||||
if (orig_normal[axis] > 0) {
|
||||
snapped_normal[axis] = 1;
|
||||
} else {
|
||||
snapped_normal[axis] = -1;
|
||||
}
|
||||
|
||||
auto [t, b] = qv::MakeTangentAndBitangentUnnormalized(snapped_normal);
|
||||
t = t * (1/world_units_per_luxel);
|
||||
b = b * (1/world_units_per_luxel);
|
||||
|
||||
qmat<float, 3, 3> world_to_lm;
|
||||
world_to_lm.set_row(0, t);
|
||||
world_to_lm.set_row(1, b);
|
||||
world_to_lm.set_row(2, snapped_normal);
|
||||
|
||||
aabb2f lm_bounds;
|
||||
for (int i = 0; i < face.numedges; i++) {
|
||||
const qvec3f &worldpoint = Face_PointAtIndex(&bsp, &face, i);
|
||||
const qvec2f lmcoord = world_to_lm * worldpoint;
|
||||
lm_bounds += lmcoord;
|
||||
}
|
||||
|
||||
qvec2i lm_mins;
|
||||
for (int i = 0; i < 2; i++) {
|
||||
lm_bounds[0][i] = floor(lm_bounds[0][i]);
|
||||
lm_bounds[1][i] = ceil(lm_bounds[1][i]);
|
||||
lm_mins[i] = static_cast<int>(lm_bounds[0][i]);
|
||||
lm_extents[i] = static_cast<int>(lm_bounds[1][i] - lm_bounds[0][i]);
|
||||
}
|
||||
|
||||
worldToLMMatrix.set_row(0, qvec4f(world_to_lm.row(0), -lm_mins[0]));
|
||||
worldToLMMatrix.set_row(1, qvec4f(world_to_lm.row(1), -lm_mins[1]));
|
||||
worldToLMMatrix.set_row(2, qvec4f(world_to_lm.row(2), 0));
|
||||
worldToLMMatrix.set_row(3, qvec4f(0, 0, 0, 1));
|
||||
|
||||
lmToWorldMatrix = qv::inverse(worldToLMMatrix);
|
||||
|
||||
// world <-> tex conversions
|
||||
worldToTexCoordMatrix = WorldToTexSpace(&bsp, &face);
|
||||
texCoordToWorldMatrix = TexSpaceToWorld(&bsp, &face);
|
||||
|
||||
// bounds
|
||||
for (int i = 0; i < face.numedges; i++) {
|
||||
const qvec3f &worldpoint = Face_PointAtIndex(&bsp, &face, i);
|
||||
bounds += worldpoint;
|
||||
|
||||
auto lm = worldToLMMatrix * qvec4f(worldpoint, 1.0f);
|
||||
#if 0
|
||||
logging::print("testing world {} -> lm {}\n",
|
||||
worldpoint,
|
||||
lm);
|
||||
#endif
|
||||
}
|
||||
|
||||
// calculate a bounding sphere for the face
|
||||
qvec3d radius = (bounds.maxs() - bounds.mins()) * 0.5;
|
||||
|
||||
origin = bounds.mins() + radius;
|
||||
this->radius = qv::length(radius);
|
||||
}
|
||||
|
||||
int faceextents_t::width() const
|
||||
{
|
||||
return lm_extents[0] + 1;
|
||||
|
|
|
|||
|
|
@ -70,3 +70,15 @@ void bspxbrushes_perbrush::stream_read(std::istream &s)
|
|||
{
|
||||
s >= std::tie(bounds, contents, numfaces);
|
||||
}
|
||||
|
||||
// bspx_decoupled_lm_perface
|
||||
|
||||
void bspx_decoupled_lm_perface::stream_write(std::ostream &s) const
|
||||
{
|
||||
s <= std::tie(lmwidth, lmheight, offset, world_to_lm_space);
|
||||
}
|
||||
|
||||
void bspx_decoupled_lm_perface::stream_read(std::istream &s)
|
||||
{
|
||||
s >= std::tie(lmwidth, lmheight, offset, world_to_lm_space);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -120,16 +120,17 @@ qmat4x4f TexSpaceToWorld(const mbsp_t *bsp, const mface_t *f);
|
|||
* it doesn't affect bsp complexity (actually, can simplify it a little)*/
|
||||
constexpr size_t MAXDIMENSION = 255 + 1;
|
||||
|
||||
struct world_units_per_luxel_t {};
|
||||
|
||||
class faceextents_t
|
||||
{
|
||||
private:
|
||||
public:
|
||||
qvec2i lm_extents;
|
||||
qmat4x4f worldToTexCoordMatrix;
|
||||
qmat4x4f texCoordToWorldMatrix;
|
||||
qmat4x4f lmToWorldMatrix;
|
||||
qmat4x4f worldToLMMatrix;
|
||||
|
||||
public:
|
||||
qvec3d origin;
|
||||
vec_t radius;
|
||||
aabb3d bounds;
|
||||
|
|
@ -137,6 +138,8 @@ public:
|
|||
faceextents_t() = default;
|
||||
|
||||
faceextents_t(const mface_t &face, const mbsp_t &bsp, float lmshift);
|
||||
faceextents_t(const mface_t &face, const mbsp_t &bsp, uint16_t lmwidth, uint16_t lmheight, texvecf world_to_lm_space);
|
||||
faceextents_t(const mface_t &face, const mbsp_t &bsp, world_units_per_luxel_t tag, float world_units_per_luxel);
|
||||
|
||||
int width() const;
|
||||
int height() const;
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@
|
|||
#include <cstdint>
|
||||
#include <common/aabb.hh>
|
||||
#include <memory>
|
||||
#include <common/bspfile.hh>
|
||||
|
||||
/* ========================================================================= */
|
||||
|
||||
|
|
@ -98,4 +99,22 @@ struct bspxfacenormals_header
|
|||
uint32_t bitangent;
|
||||
};
|
||||
|
||||
// DECOUPLED_LM BSPX lump (subject to change!)
|
||||
struct bspx_decoupled_lm_perface
|
||||
{
|
||||
uint16_t lmwidth; // pixels
|
||||
uint16_t lmheight; // pixels
|
||||
// offset into dlightdata lump.
|
||||
// start of numstyles (from face struct) * (lmwidth * lmheight) samples
|
||||
int32_t offset;
|
||||
|
||||
// 2 rows * 4 column matrix, stored in row major order
|
||||
// this is a world -> lightmap space transformation matrix
|
||||
texvecf world_to_lm_space;
|
||||
|
||||
// serialize for streams
|
||||
void stream_write(std::ostream &s) const;
|
||||
void stream_read(std::istream &s);
|
||||
};
|
||||
|
||||
// BSPX data
|
||||
|
|
|
|||
|
|
@ -370,6 +370,7 @@ public:
|
|||
setting_func bspxlux;
|
||||
setting_func bspxonly;
|
||||
setting_func bspx;
|
||||
setting_scalar world_units_per_luxel;
|
||||
setting_bool litonly;
|
||||
setting_bool nolights;
|
||||
setting_int32 facestyles;
|
||||
|
|
|
|||
|
|
@ -52,11 +52,12 @@ std::unordered_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);
|
||||
std::unique_ptr<lightsurf_t> CreateLightmapSurface(const mbsp_t *bsp, const mface_t *face, const facesup_t *facesup,
|
||||
const bspx_decoupled_lm_perface *facesup_decoupled, const settings::worldspawn_keys &cfg);
|
||||
bool Face_IsLightmapped(const mbsp_t *bsp, const mface_t *face);
|
||||
void DirectLightFace(const mbsp_t *bsp, lightsurf_t &lightsurf, const settings::worldspawn_keys &cfg);
|
||||
void IndirectLightFace(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, lightsurf_t *lightsurf,
|
||||
const faceextents_t &extents, const faceextents_t &output_extents);
|
||||
void SaveLightmapSurface(const mbsp_t *bsp, mface_t *face, facesup_t *facesup,
|
||||
bspx_decoupled_lm_perface *facesup_decoupled, lightsurf_t *lightsurf, const faceextents_t &extents,
|
||||
const faceextents_t &output_extents);
|
||||
|
|
|
|||
|
|
@ -63,6 +63,7 @@ std::vector<std::unique_ptr<lightsurf_t>> &LightSurfaces()
|
|||
}
|
||||
|
||||
static std::vector<facesup_t> faces_sup; // lit2/bspx stuff
|
||||
static std::vector<bspx_decoupled_lm_perface> facesup_decoupled_global;
|
||||
|
||||
bool IsOutputtingSupplementaryData()
|
||||
{
|
||||
|
|
@ -296,6 +297,7 @@ light_settings::light_settings()
|
|||
write_luxfile = lightfile::bspx;
|
||||
},
|
||||
&experimental_group, "writes both rgb and directions data into the bsp itself"},
|
||||
world_units_per_luxel{this, "world_units_per_luxel", 0, 0, 1024, &output_group, "enables output of DECOUPLED_LM BSPX lump"},
|
||||
litonly{this, "litonly", false, &output_group, "only write .lit file, don't modify BSP"},
|
||||
nolights{this, "nolights", false, &output_group, "ignore light entities (only sunlight/minlight)"},
|
||||
facestyles{this, "facestyles", 4, &output_group, "max amount of styles per face; requires BSPX lump if > 4"},
|
||||
|
|
@ -619,6 +621,7 @@ static void CreateLightmapSurfaces(mbsp_t *bsp)
|
|||
logging::funcheader();
|
||||
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 facesup_decoupled = facesup_decoupled_global.empty() ? nullptr : &facesup_decoupled_global[i];
|
||||
auto face = &bsp->dfaces[i];
|
||||
|
||||
/* One extra lightmap is allocated to simplify handling overflow */
|
||||
|
|
@ -636,10 +639,14 @@ static void CreateLightmapSurfaces(mbsp_t *bsp)
|
|||
for (size_t i = 0; i < MAXLIGHTMAPS; i++) {
|
||||
face->styles[i] = INVALID_LIGHTSTYLE_OLD;
|
||||
}
|
||||
|
||||
if (facesup_decoupled) {
|
||||
facesup_decoupled->offset = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
light_surfaces[i] = CreateLightmapSurface(bsp, face, facesup, light_options);
|
||||
light_surfaces[i] = CreateLightmapSurface(bsp, face, facesup, facesup_decoupled, light_options);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -658,22 +665,24 @@ static void SaveLightmapSurfaces(mbsp_t *bsp)
|
|||
auto f = &bsp->dfaces[i];
|
||||
const modelinfo_t *face_modelinfo = ModelInfoForFace(bsp, i);
|
||||
|
||||
if (faces_sup.empty()) {
|
||||
SaveLightmapSurface(bsp, f, nullptr, surf.get(), surf->extents, surf->extents);
|
||||
if (!facesup_decoupled_global.empty()) {
|
||||
SaveLightmapSurface(bsp, f, nullptr, &facesup_decoupled_global[i], surf.get(), surf->extents, surf->extents);
|
||||
} else if (faces_sup.empty()) {
|
||||
SaveLightmapSurface(bsp, f, nullptr, nullptr, surf.get(), surf->extents, surf->extents);
|
||||
} else if (light_options.novanilla.value() || faces_sup[i].lmscale == face_modelinfo->lightmapscale) {
|
||||
if (faces_sup[i].lmscale == face_modelinfo->lightmapscale) {
|
||||
f->lightofs = faces_sup[i].lightofs;
|
||||
} else {
|
||||
f->lightofs = -1;
|
||||
}
|
||||
SaveLightmapSurface(bsp, f, &faces_sup[i], surf.get(), surf->extents, surf->extents);
|
||||
SaveLightmapSurface(bsp, f, &faces_sup[i], nullptr, surf.get(), surf->extents, surf->extents);
|
||||
for (int j = 0; j < MAXLIGHTMAPS; j++) {
|
||||
f->styles[j] =
|
||||
faces_sup[i].styles[j] == INVALID_LIGHTSTYLE ? INVALID_LIGHTSTYLE_OLD : faces_sup[i].styles[j];
|
||||
}
|
||||
} else {
|
||||
SaveLightmapSurface(bsp, f, nullptr, surf.get(), surf->extents, surf->vanilla_extents);
|
||||
SaveLightmapSurface(bsp, f, &faces_sup[i], surf.get(), surf->extents, surf->extents);
|
||||
SaveLightmapSurface(bsp, f, nullptr, nullptr, surf.get(), surf->extents, surf->vanilla_extents);
|
||||
SaveLightmapSurface(bsp, f, &faces_sup[i], nullptr, surf.get(), surf->extents, surf->extents);
|
||||
}
|
||||
|
||||
light_surfaces[i].reset();
|
||||
|
|
@ -831,6 +840,12 @@ static void LightWorld(bspdata_t *bspdata, bool forcedscale)
|
|||
}
|
||||
}
|
||||
|
||||
// decoupled lightmaps
|
||||
facesup_decoupled_global.clear();
|
||||
if (light_options.world_units_per_luxel.isChanged()) {
|
||||
facesup_decoupled_global.resize(bsp.dfaces.size());
|
||||
}
|
||||
|
||||
CalculateVertexNormals(&bsp);
|
||||
|
||||
// create lightmap surfaces
|
||||
|
|
@ -896,6 +911,7 @@ static void LightWorld(bspdata_t *bspdata, bool forcedscale)
|
|||
bspdata->bspx.entries.erase("LMSTYLE16");
|
||||
bspdata->bspx.entries.erase("LMSTYLE");
|
||||
bspdata->bspx.entries.erase("LMOFFSET");
|
||||
bspdata->bspx.entries.erase("DECOUPLED_LM");
|
||||
|
||||
if (!faces_sup.empty()) {
|
||||
bool needoffsets = false;
|
||||
|
|
@ -978,6 +994,20 @@ static void LightWorld(bspdata_t *bspdata, bool forcedscale)
|
|||
bspdata->bspx.transfer("LMOFFSET", offsets_mem);
|
||||
}
|
||||
}
|
||||
|
||||
if (!facesup_decoupled_global.empty()) {
|
||||
std::vector<uint8_t> mem(sizeof(bspx_decoupled_lm_perface) * bsp.dfaces.size());
|
||||
|
||||
omemstream stream(mem.data(), mem.size(), std::ios_base::out | std::ios_base::binary);
|
||||
stream << endianness<std::endian::little>;
|
||||
|
||||
for (size_t i = 0; i < bsp.dfaces.size(); i++) {
|
||||
stream <= facesup_decoupled_global[i];
|
||||
}
|
||||
|
||||
logging::print("DECOUPLED_LM BSPX lump written\n");
|
||||
bspdata->bspx.transfer("DECOUPLED_LM", mem);
|
||||
}
|
||||
}
|
||||
|
||||
static void LoadExtendedTexinfoFlags(const fs::path &sourcefilename, const mbsp_t *bsp)
|
||||
|
|
|
|||
|
|
@ -413,8 +413,7 @@ static void CalcPoints(
|
|||
const vec_t us = starts + s * st_step;
|
||||
const vec_t ut = startt + t * st_step;
|
||||
|
||||
point = surf->extents.LMCoordToWorld(qvec2f(us, ut)) +
|
||||
surf->plane.normal; // one unit in front of face
|
||||
point = surf->extents.LMCoordToWorld(qvec2f(us, ut)) + surf->plane.normal; // one unit in front of face
|
||||
|
||||
// do this before correcting the point, so we can wrap around the inside of pipes
|
||||
const bool phongshaded = (surf->curved && cfg.phongallowed.value());
|
||||
|
|
@ -587,7 +586,8 @@ static void CalcPvs(const mbsp_t *bsp, lightsurf_t *lightsurf)
|
|||
}
|
||||
|
||||
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)
|
||||
const mface_t *face, const mbsp_t *bsp, const facesup_t *facesup,
|
||||
const bspx_decoupled_lm_perface *facesup_decoupled)
|
||||
{
|
||||
auto spaceToWorld = TexSpaceToWorld(bsp, face);
|
||||
|
||||
|
|
@ -697,7 +697,12 @@ static std::unique_ptr<lightsurf_t> Lightsurf_Init(const modelinfo_t *modelinfo,
|
|||
lightsurf->tnormal = -qv::normalize(tex->vecs.row(1).xyz());
|
||||
|
||||
/* Set up the surface points */
|
||||
lightsurf->extents = faceextents_t(*face, *bsp, lightsurf->lightmapscale);
|
||||
if (light_options.world_units_per_luxel.isChanged()) {
|
||||
lightsurf->extents = faceextents_t(*face, *bsp, world_units_per_luxel_t{},
|
||||
light_options.world_units_per_luxel.value());
|
||||
} else {
|
||||
lightsurf->extents = faceextents_t(*face, *bsp, lightsurf->lightmapscale);
|
||||
}
|
||||
lightsurf->vanilla_extents = faceextents_t(*face, *bsp, 16.0);
|
||||
|
||||
CalcPoints(modelinfo, modelinfo->offset, lightsurf.get(), bsp, face);
|
||||
|
|
@ -2528,8 +2533,9 @@ static void WriteSingleLightmap(const mbsp_t *bsp, const mface_t *face, const li
|
|||
}
|
||||
}
|
||||
|
||||
void SaveLightmapSurface(const mbsp_t *bsp, mface_t *face, facesup_t *facesup, lightsurf_t *lightsurf,
|
||||
const faceextents_t &extents, const faceextents_t &output_extents)
|
||||
void SaveLightmapSurface(const mbsp_t *bsp, mface_t *face, facesup_t *facesup,
|
||||
bspx_decoupled_lm_perface *facesup_decoupled, lightsurf_t *lightsurf, const faceextents_t &extents,
|
||||
const faceextents_t &output_extents)
|
||||
{
|
||||
lightmapdict_t &lightmaps = lightsurf->lightmapsByStyle;
|
||||
const int actual_width = extents.width();
|
||||
|
|
@ -2693,6 +2699,15 @@ void SaveLightmapSurface(const mbsp_t *bsp, mface_t *face, facesup_t *facesup, l
|
|||
for (; mapnum < MAXLIGHTMAPS; mapnum++) {
|
||||
face->styles[mapnum] = INVALID_LIGHTSTYLE_OLD;
|
||||
}
|
||||
|
||||
if (facesup_decoupled) {
|
||||
facesup_decoupled->lmwidth = output_width;
|
||||
facesup_decoupled->lmheight = output_height;
|
||||
for (size_t i = 0; i < 2; ++i) {
|
||||
facesup_decoupled->world_to_lm_space.set_row(i,
|
||||
output_extents.worldToLMMatrix.row(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!numstyles)
|
||||
|
|
@ -2714,6 +2729,9 @@ void SaveLightmapSurface(const mbsp_t *bsp, mface_t *face, facesup_t *facesup, l
|
|||
facesup->lightofs = lightofs;
|
||||
} else {
|
||||
face->lightofs = lightofs;
|
||||
if (facesup_decoupled) {
|
||||
facesup_decoupled->offset = lightofs;
|
||||
}
|
||||
}
|
||||
|
||||
// sanity check that we don't save a lightmap for a non-lightmapped face
|
||||
|
|
@ -2741,8 +2759,8 @@ void SaveLightmapSurface(const mbsp_t *bsp, mface_t *face, facesup_t *facesup, l
|
|||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<lightsurf_t> CreateLightmapSurface(
|
||||
const mbsp_t *bsp, const mface_t *face, const 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 bspx_decoupled_lm_perface *facesup_decoupled, const settings::worldspawn_keys &cfg)
|
||||
{
|
||||
/* Find the correct model offset */
|
||||
const modelinfo_t *modelinfo = ModelInfoForFace(bsp, Face_GetNum(bsp, face));
|
||||
|
|
@ -2767,7 +2785,7 @@ std::unique_ptr<lightsurf_t> CreateLightmapSurface(
|
|||
if (!Q_strcasecmp(texname, "skip"))
|
||||
return nullptr;
|
||||
|
||||
return Lightsurf_Init(modelinfo, cfg, face, bsp, facesup);
|
||||
return Lightsurf_Init(modelinfo, cfg, face, bsp, facesup, facesup_decoupled);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -21,9 +21,6 @@ static void LoadTestmap(const std::filesystem::path &name, std::vector<std::stri
|
|||
"-path",
|
||||
wal_metadata_path.string()
|
||||
};
|
||||
for (auto &arg : extra_args) {
|
||||
args.push_back(arg);
|
||||
}
|
||||
args.push_back(map_path.string());
|
||||
args.push_back(bsp_path.string());
|
||||
|
||||
|
|
@ -36,9 +33,12 @@ static void LoadTestmap(const std::filesystem::path &name, std::vector<std::stri
|
|||
{
|
||||
std::vector<std::string> light_args{
|
||||
"", // the exe path, which we're ignoring in this case
|
||||
"-extra",
|
||||
bsp_path.string()
|
||||
};
|
||||
for (auto &arg : extra_args) {
|
||||
light_args.push_back(arg);
|
||||
}
|
||||
light_args.push_back(bsp_path.string());
|
||||
|
||||
light_main(light_args);
|
||||
}
|
||||
|
||||
|
|
@ -56,5 +56,5 @@ static void LoadTestmap(const std::filesystem::path &name, std::vector<std::stri
|
|||
}
|
||||
|
||||
TEST_CASE("TestLight") {
|
||||
LoadTestmap("q2_lightmap_custom_scale.map", {});
|
||||
LoadTestmap("q2_lightmap_custom_scale.map", {"-threads", "1", "-extra", "-world_units_per_luxel", "8"});
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue