diff --git a/include/common/aabb.hh b/include/common/aabb.hh index c9938036..30372517 100644 --- a/include/common/aabb.hh +++ b/include/common/aabb.hh @@ -194,6 +194,17 @@ public: constexpr value_type size() const { return maxs() - mins(); } + constexpr bool valid() const { + value_type our_size = size(); + + if (our_size[0] < static_cast(0) + || our_size[1] < static_cast(0) + || our_size[2] < static_cast(0)) { + return false; + } + return true; + } + constexpr aabb grow(const value_type &size) const { return {mins() - size, maxs() + size}; } constexpr value_type &operator[](const size_t &index) { return m_corners[index]; } diff --git a/include/light/entities.hh b/include/light/entities.hh index e98ff5f2..3e36d42a 100644 --- a/include/light/entities.hh +++ b/include/light/entities.hh @@ -131,6 +131,7 @@ public: void ResetLightEntities(); std::string TargetnameForLightStyle(int style); std::vector> &GetLights(); +const std::vector &GetEntdicts(); std::vector &GetSuns(); std::vector &GetRadLights(); diff --git a/light/entities.cc b/light/entities.cc index a8e50f02..68ba11ee 100644 --- a/light/entities.cc +++ b/light/entities.cc @@ -29,10 +29,10 @@ #include #include -std::vector> all_lights; -std::vector all_suns; -std::vector entdicts; -std::vector radlights; +static std::vector> all_lights; +static std::vector all_suns; +static std::vector entdicts; +static std::vector radlights; static std::vector> lightstyleForTargetname; static std::vector> surfacelight_templates; static std::ofstream surflights_dump_file; @@ -60,6 +60,11 @@ std::vector> &GetLights() return all_lights; } +const std::vector &GetEntdicts() +{ + return entdicts; +} + std::vector &GetSuns() { return all_suns; diff --git a/light/lightgrid.cc b/light/lightgrid.cc index 8482afea..291fe4cc 100644 --- a/light/lightgrid.cc +++ b/light/lightgrid.cc @@ -51,6 +51,30 @@ static std::vector StringToVector(const std::string &str) return result; } +static aabb3f LightGridBounds(const mbsp_t &bsp) +{ + aabb3f result; + + // see if `_lightgrid_hint` entities are in use + for (auto &entity : GetEntdicts()) { + if (entity.get_int("_lightgrid_hint")) { + qvec3d point{}; + entity.get_vector("origin", point); + result += point; + } + } + + if (result.valid()) { + auto size = result.size(); + if (size[0] > 0 && size[1] > 0 && size[2] > 0) { + return result; + } + } + + result = Model_BoundsOfFaces(bsp, bsp.dmodels[0]); + return result; +} + void LightGrid(bspdata_t *bspdata) { if (!light_options.lightgrid.value()) @@ -60,9 +84,9 @@ void LightGrid(bspdata_t *bspdata) auto &bsp = std::get(bspdata->bsp); - auto faces_size = Model_BoundsOfFaces(bsp, bsp.dmodels[0]); - const qvec3f grid_maxs = faces_size.maxs(); - const qvec3f grid_mins = faces_size.mins(); + const auto grid_bounds = LightGridBounds(bsp); + const qvec3f grid_maxs = grid_bounds.maxs(); + const qvec3f grid_mins = grid_bounds.mins(); const qvec3f world_size = grid_maxs - grid_mins; // number of grid points on each axis diff --git a/qbsp/outside.cc b/qbsp/outside.cc index 129d3f6a..e0a07b57 100644 --- a/qbsp/outside.cc +++ b/qbsp/outside.cc @@ -306,6 +306,18 @@ static void WriteLeafVolumes(const std::vector &leakline, std::strin WriteBspBrushMap(filename_suffix, volumes_to_write); } +/** + * Is this entity allowed to be in the void without causing a leak? + */ +static bool IsNofillEntity(const entdict_t &edict) +{ + if (edict.get_int("_nofill")) + return true; + if (edict.get_int("_lightgrid_hint")) + return true; + return false; +} + /* ================== FindOccupiedLeafs @@ -323,7 +335,7 @@ static void MarkOccupiedClusters(node_t *headnode) continue; // skip nofill entities - if (entity.epairs.has("_nofill") && entity.epairs.get_int("_nofill")) { + if (IsNofillEntity(entity.epairs)) { continue; }