fix crash in light from bounce lighting storage
move bounce lights to a forwardly linked list fix minlight affecting style 0 for switchables
This commit is contained in:
parent
7810875860
commit
3ee28fc416
|
|
@ -27,6 +27,7 @@
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
#include <common/qvec.hh>
|
#include <common/qvec.hh>
|
||||||
|
#include <forward_list>
|
||||||
|
|
||||||
struct bouncelight_t
|
struct bouncelight_t
|
||||||
{
|
{
|
||||||
|
|
@ -47,7 +48,7 @@ struct bouncelight_t
|
||||||
|
|
||||||
// public functions
|
// public functions
|
||||||
|
|
||||||
const std::vector<bouncelight_t> &BounceLights();
|
const std::forward_list<bouncelight_t> &BounceLights();
|
||||||
const std::vector<int> &BounceLightsForFaceNum(int facenum);
|
const std::vector<std::reference_wrapper<bouncelight_t>> &BounceLightsForFaceNum(int facenum);
|
||||||
void MakeBounceLights(const settings::worldspawn_keys &cfg, const mbsp_t *bsp);
|
void MakeBounceLights(const settings::worldspawn_keys &cfg, const mbsp_t *bsp);
|
||||||
qvec3b Face_LookupTextureColor(const mbsp_t *bsp, const mface_t *face); // mxd
|
qvec3b Face_LookupTextureColor(const mbsp_t *bsp, const mface_t *face); // mxd
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ See file, 'COPYING', for details.
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <tuple>
|
||||||
|
|
||||||
struct surfacelight_t
|
struct surfacelight_t
|
||||||
{
|
{
|
||||||
|
|
@ -46,6 +47,6 @@ struct surfacelight_t
|
||||||
};
|
};
|
||||||
|
|
||||||
std::vector<surfacelight_t> &GetSurfaceLights();
|
std::vector<surfacelight_t> &GetSurfaceLights();
|
||||||
std::optional<int32_t> IsSurfaceLitFace(const mbsp_t *bsp, const mface_t *face);
|
std::optional<std::tuple<int32_t, int32_t>> IsSurfaceLitFace(const mbsp_t *bsp, const mface_t *face);
|
||||||
const std::vector<int> &SurfaceLightsForFaceNum(int facenum);
|
const std::vector<int> &SurfaceLightsForFaceNum(int facenum);
|
||||||
void MakeRadiositySurfaceLights(const settings::worldspawn_keys &cfg, const mbsp_t *bsp);
|
void MakeRadiositySurfaceLights(const settings::worldspawn_keys &cfg, const mbsp_t *bsp);
|
||||||
|
|
|
||||||
|
|
@ -47,8 +47,9 @@ using namespace std;
|
||||||
using namespace polylib;
|
using namespace polylib;
|
||||||
|
|
||||||
mutex bouncelights_lock;
|
mutex bouncelights_lock;
|
||||||
static std::vector<bouncelight_t> bouncelights;
|
static std::forward_list<bouncelight_t> bouncelights;
|
||||||
std::unordered_map<int, std::vector<int>> bouncelightsByFacenum;
|
static size_t lastBounceLightIndex;
|
||||||
|
static std::unordered_map<size_t, std::vector<std::reference_wrapper<bouncelight_t>>> bouncelightsByFacenum;
|
||||||
|
|
||||||
static bool Face_ShouldBounce(const mbsp_t *bsp, const mface_t *face)
|
static bool Face_ShouldBounce(const mbsp_t *bsp, const mface_t *face)
|
||||||
{
|
{
|
||||||
|
|
@ -94,15 +95,14 @@ qvec3b Face_LookupTextureColor(const mbsp_t *bsp, const mface_t *face)
|
||||||
inline bouncelight_t &CreateBounceLight(const mface_t *face, const mbsp_t *bsp)
|
inline bouncelight_t &CreateBounceLight(const mface_t *face, const mbsp_t *bsp)
|
||||||
{
|
{
|
||||||
unique_lock<mutex> lck{bouncelights_lock};
|
unique_lock<mutex> lck{bouncelights_lock};
|
||||||
bouncelight_t &l = bouncelights.emplace_back();
|
bouncelight_t &l = bouncelights.emplace_front();
|
||||||
|
|
||||||
const int lastBounceLightIndex = static_cast<int>(bouncelights.size()) - 1;
|
bouncelightsByFacenum[Face_GetNum(bsp, face)].push_back(l);
|
||||||
bouncelightsByFacenum[Face_GetNum(bsp, face)].push_back(lastBounceLightIndex);
|
|
||||||
|
|
||||||
return l;
|
return l;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void AddBounceLight(const qvec3d &pos, const std::unordered_map<int, qvec3d> &colorByStyle,
|
static void AddBounceLight(const qvec3d &pos, std::unordered_map<int, qvec3d> &&colorByStyle,
|
||||||
const qvec3d &surfnormal, vec_t area, const mface_t *face, const mbsp_t *bsp)
|
const qvec3d &surfnormal, vec_t area, const mface_t *face, const mbsp_t *bsp)
|
||||||
{
|
{
|
||||||
for (const auto &styleColor : colorByStyle) {
|
for (const auto &styleColor : colorByStyle) {
|
||||||
|
|
@ -118,15 +118,11 @@ static void AddBounceLight(const qvec3d &pos, const std::unordered_map<int, qvec
|
||||||
l.pos = pos;
|
l.pos = pos;
|
||||||
l.colorByStyle = colorByStyle;
|
l.colorByStyle = colorByStyle;
|
||||||
|
|
||||||
qvec3f componentwiseMaxColor{};
|
for (const auto &styleColor : l.colorByStyle) {
|
||||||
for (const auto &styleColor : colorByStyle) {
|
|
||||||
for (int i = 0; i < 3; i++) {
|
for (int i = 0; i < 3; i++) {
|
||||||
if (styleColor.second[i] > componentwiseMaxColor[i]) {
|
l.componentwiseMaxColor[i] = max(l.componentwiseMaxColor[i], styleColor.second[i]);
|
||||||
componentwiseMaxColor[i] = styleColor.second[i];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
l.componentwiseMaxColor = componentwiseMaxColor;
|
|
||||||
l.surfnormal = surfnormal;
|
l.surfnormal = surfnormal;
|
||||||
l.area = area;
|
l.area = area;
|
||||||
|
|
||||||
|
|
@ -137,19 +133,19 @@ static void AddBounceLight(const qvec3d &pos, const std::unordered_map<int, qvec
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::vector<bouncelight_t> &BounceLights()
|
const std::forward_list<bouncelight_t> &BounceLights()
|
||||||
{
|
{
|
||||||
return bouncelights;
|
return bouncelights;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::vector<int> &BounceLightsForFaceNum(int facenum)
|
const std::vector<std::reference_wrapper<bouncelight_t>> &BounceLightsForFaceNum(int facenum)
|
||||||
{
|
{
|
||||||
const auto &vec = bouncelightsByFacenum.find(facenum);
|
const auto &vec = bouncelightsByFacenum.find(facenum);
|
||||||
if (vec != bouncelightsByFacenum.end()) {
|
if (vec != bouncelightsByFacenum.end()) {
|
||||||
return vec->second;
|
return vec->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::vector<int> empty;
|
static std::vector<std::reference_wrapper<bouncelight_t>> empty;
|
||||||
return empty;
|
return empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -215,7 +211,7 @@ static void MakeBounceLightsThread(const settings::worldspawn_keys &cfg, const m
|
||||||
emitcolors[styleColor.first] = styleColor.second * blendedcolor;
|
emitcolors[styleColor.first] = styleColor.second * blendedcolor;
|
||||||
}
|
}
|
||||||
|
|
||||||
AddBounceLight(facemidpoint, emitcolors, faceplane.normal, area, &face, bsp);
|
AddBounceLight(facemidpoint, std::move(emitcolors), faceplane.normal, area, &face, bsp);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MakeBounceLights(const settings::worldspawn_keys &cfg, const mbsp_t *bsp)
|
void MakeBounceLights(const settings::worldspawn_keys &cfg, const mbsp_t *bsp)
|
||||||
|
|
@ -224,5 +220,5 @@ void MakeBounceLights(const settings::worldspawn_keys &cfg, const mbsp_t *bsp)
|
||||||
|
|
||||||
logging::parallel_for_each(bsp->dfaces, [&](const mface_t &face) { MakeBounceLightsThread(cfg, bsp, face); });
|
logging::parallel_for_each(bsp->dfaces, [&](const mface_t &face) { MakeBounceLightsThread(cfg, bsp, face); });
|
||||||
|
|
||||||
logging::print("{} bounce lights created\n", bouncelights.size());
|
logging::print("{} bounce lights created\n", lastBounceLightIndex);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1389,7 +1389,7 @@ static void LightFace_Sky(const sun_t *sun, lightsurf_t *lightsurf, lightmapdict
|
||||||
* ============
|
* ============
|
||||||
*/
|
*/
|
||||||
static void LightFace_Min(const mbsp_t *bsp, const mface_t *face, const qvec3d &color, vec_t light,
|
static void LightFace_Min(const mbsp_t *bsp, const mface_t *face, const qvec3d &color, vec_t light,
|
||||||
lightsurf_t *lightsurf, lightmapdict_t *lightmaps)
|
lightsurf_t *lightsurf, lightmapdict_t *lightmaps, int32_t style)
|
||||||
{
|
{
|
||||||
const settings::worldspawn_keys &cfg = *lightsurf->cfg;
|
const settings::worldspawn_keys &cfg = *lightsurf->cfg;
|
||||||
const modelinfo_t *modelinfo = lightsurf->modelinfo;
|
const modelinfo_t *modelinfo = lightsurf->modelinfo;
|
||||||
|
|
@ -1399,8 +1399,8 @@ static void LightFace_Min(const mbsp_t *bsp, const mface_t *face, const qvec3d &
|
||||||
return; /* this face is excluded from minlight */
|
return; /* this face is excluded from minlight */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Find a style 0 lightmap */
|
/* Find the lightmap */
|
||||||
lightmap_t *lightmap = Lightmap_ForStyle(lightmaps, 0, lightsurf);
|
lightmap_t *lightmap = Lightmap_ForStyle(lightmaps, style, lightsurf);
|
||||||
|
|
||||||
bool hit = false;
|
bool hit = false;
|
||||||
for (int i = 0; i < lightsurf->points.size(); i++) {
|
for (int i = 0; i < lightsurf->points.size(); i++) {
|
||||||
|
|
@ -1423,7 +1423,19 @@ static void LightFace_Min(const mbsp_t *bsp, const mface_t *face, const qvec3d &
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hit) {
|
if (hit) {
|
||||||
Lightmap_Save(lightmaps, lightsurf, lightmap, 0);
|
Lightmap_Save(lightmaps, lightsurf, lightmap, style);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void LightFace_LocalMin(const mbsp_t *bsp, const mface_t *face,
|
||||||
|
lightsurf_t *lightsurf, lightmapdict_t *lightmaps)
|
||||||
|
{
|
||||||
|
const settings::worldspawn_keys &cfg = *lightsurf->cfg;
|
||||||
|
const modelinfo_t *modelinfo = lightsurf->modelinfo;
|
||||||
|
|
||||||
|
const surfflags_t &extended_flags = extended_texinfo_flags[face->texinfo];
|
||||||
|
if (extended_flags.no_minlight) {
|
||||||
|
return; /* this face is excluded from minlight */
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: Refactor this?
|
// FIXME: Refactor this?
|
||||||
|
|
@ -1446,9 +1458,9 @@ static void LightFace_Min(const mbsp_t *bsp, const mface_t *face, const qvec3d &
|
||||||
raystream_occlusion_t &rs = lightsurf->occlusion_stream;
|
raystream_occlusion_t &rs = lightsurf->occlusion_stream;
|
||||||
rs.clearPushedRays();
|
rs.clearPushedRays();
|
||||||
|
|
||||||
lightmap = Lightmap_ForStyle(lightmaps, entity->style.value(), lightsurf);
|
lightmap_t *lightmap = Lightmap_ForStyle(lightmaps, entity->style.value(), lightsurf);
|
||||||
|
|
||||||
hit = false;
|
bool hit = false;
|
||||||
for (int i = 0; i < lightsurf->points.size(); i++) {
|
for (int i = 0; i < lightsurf->points.size(); i++) {
|
||||||
if (lightsurf->occluded[i])
|
if (lightsurf->occluded[i])
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -1547,16 +1559,15 @@ static void LightFace_BounceLightsDebug(const lightsurf_t *lightsurf, lightmapdi
|
||||||
// reset all lightmaps to black (lazily)
|
// reset all lightmaps to black (lazily)
|
||||||
Lightmap_ClearAll(lightmaps);
|
Lightmap_ClearAll(lightmaps);
|
||||||
|
|
||||||
const std::vector<int> &vpls = BounceLightsForFaceNum(Face_GetNum(lightsurf->bsp, lightsurf->face));
|
const std::vector<std::reference_wrapper<bouncelight_t>> &vpls = BounceLightsForFaceNum(Face_GetNum(lightsurf->bsp, lightsurf->face));
|
||||||
const std::vector<bouncelight_t> &all_vpls = BounceLights();
|
|
||||||
|
|
||||||
/* Overwrite each point with the emitted color... */
|
/* Overwrite each point with the emitted color... */
|
||||||
for (int i = 0; i < lightsurf->points.size(); i++) {
|
for (int i = 0; i < lightsurf->points.size(); i++) {
|
||||||
if (lightsurf->occluded[i])
|
if (lightsurf->occluded[i])
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
for (const auto &vplnum : vpls) {
|
for (const auto &vpl_ref : vpls) {
|
||||||
const bouncelight_t &vpl = all_vpls[vplnum];
|
auto &vpl = vpl_ref.get();
|
||||||
|
|
||||||
// check for point in polygon (note: could be on the edge of more than one)
|
// check for point in polygon (note: could be on the edge of more than one)
|
||||||
if (!GLM_EdgePlanes_PointInside(vpl.poly_edgeplanes, lightsurf->points[i]))
|
if (!GLM_EdgePlanes_PointInside(vpl.poly_edgeplanes, lightsurf->points[i]))
|
||||||
|
|
@ -2966,7 +2977,7 @@ void DirectLightFace(const mbsp_t *bsp, lightsurf_t &lightsurf, const settings::
|
||||||
float minlight = 0;
|
float minlight = 0;
|
||||||
qvec3d minlight_color;
|
qvec3d minlight_color;
|
||||||
|
|
||||||
/* minlight - use the greater of global or model minlight, or Q2 surface emission */
|
// first, check for global minlight; this only affects style 0
|
||||||
if (lightsurf.minlight > cfg.minlight.value()) {
|
if (lightsurf.minlight > cfg.minlight.value()) {
|
||||||
minlight = lightsurf.minlight;
|
minlight = lightsurf.minlight;
|
||||||
minlight_color = lightsurf.minlight_color;
|
minlight_color = lightsurf.minlight_color;
|
||||||
|
|
@ -2975,17 +2986,18 @@ void DirectLightFace(const mbsp_t *bsp, lightsurf_t &lightsurf, const settings::
|
||||||
minlight_color = cfg.minlight_color.value();
|
minlight_color = cfg.minlight_color.value();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!minlight) {
|
if (minlight) {
|
||||||
if (auto value = IsSurfaceLitFace(bsp, face)) {
|
LightFace_Min(bsp, face, minlight_color, minlight, &lightsurf, lightmaps, 0);
|
||||||
minlight = *value * 64.0f;
|
|
||||||
minlight_color = Face_LookupTextureColor(bsp, face);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (minlight) {
|
if (auto value = IsSurfaceLitFace(bsp, face)) {
|
||||||
LightFace_Min(bsp, face, minlight_color, minlight, &lightsurf, lightmaps);
|
minlight = std::get<0>(value.value()) * 64.0f;
|
||||||
|
minlight_color = Face_LookupTextureColor(bsp, face);
|
||||||
|
LightFace_Min(bsp, face, minlight_color, minlight, &lightsurf, lightmaps, std::get<1>(value.value()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LightFace_LocalMin(bsp, face, &lightsurf, lightmaps);
|
||||||
|
|
||||||
/* negative lights */
|
/* negative lights */
|
||||||
if (!(modelinfo->lightignore.value() || extended_flags.light_ignore)) {
|
if (!(modelinfo->lightignore.value() || extended_flags.light_ignore)) {
|
||||||
for (const auto &entity : GetLights()) {
|
for (const auto &entity : GetLights()) {
|
||||||
|
|
|
||||||
|
|
@ -141,20 +141,20 @@ static void MakeSurfaceLight(const mbsp_t *bsp, const settings::worldspawn_keys
|
||||||
surfacelightsByFacenum[Face_GetNum(bsp, face)].push_back(index);
|
surfacelightsByFacenum[Face_GetNum(bsp, face)].push_back(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<int32_t> IsSurfaceLitFace(const mbsp_t *bsp, const mface_t *face)
|
std::optional<std::tuple<int32_t, int32_t>> IsSurfaceLitFace(const mbsp_t *bsp, const mface_t *face)
|
||||||
{
|
{
|
||||||
if (bsp->loadversion->game->id == GAME_QUAKE_II) {
|
if (bsp->loadversion->game->id == GAME_QUAKE_II) {
|
||||||
// first, check if it's a Q2 surface
|
// first, check if it's a Q2 surface
|
||||||
const mtexinfo_t *info = Face_Texinfo(bsp, face);
|
const mtexinfo_t *info = Face_Texinfo(bsp, face);
|
||||||
|
|
||||||
if (info != nullptr && (info->flags.native & Q2_SURF_LIGHT) && info->value > 0) {
|
if (info != nullptr && (info->flags.native & Q2_SURF_LIGHT) && info->value > 0) {
|
||||||
return info->value;
|
return std::make_tuple(info->value, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const auto &surflight : GetSurfaceLightTemplates()) {
|
for (const auto &surflight : GetSurfaceLightTemplates()) {
|
||||||
if (FaceMatchesSurfaceLightTemplate(bsp, face, *surflight, SURFLIGHT_RAD)) {
|
if (FaceMatchesSurfaceLightTemplate(bsp, face, *surflight, SURFLIGHT_RAD)) {
|
||||||
return surflight->light.value();
|
return std::make_tuple(surflight->light.value(), surflight->style.value());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -435,7 +435,10 @@ void MakeTreePortals(tree_t *tree)
|
||||||
portalstats_t stats{};
|
portalstats_t stats{};
|
||||||
|
|
||||||
MakeHeadnodePortals(tree);
|
MakeHeadnodePortals(tree);
|
||||||
|
|
||||||
MakeTreePortals_r(tree, tree->headnode.get(), stats);
|
MakeTreePortals_r(tree, tree->headnode.get(), stats);
|
||||||
|
|
||||||
|
logging::print(logging::flag::STAT, " {:8} tiny portals\n", stats.c_tinyportals);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void AssertNoPortals_r(node_t *node)
|
static void AssertNoPortals_r(node_t *node)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue