mirror of
https://github.com/ZDoom/ZDRay.git
synced 2024-11-28 14:41:57 +00:00
Refactor light propagation
This commit is contained in:
parent
22f24e7993
commit
ea5b1a3cac
3 changed files with 39 additions and 36 deletions
|
@ -178,16 +178,9 @@ void LevelMesh::BuildSmoothingGroups(FLevel& doomMap)
|
|||
printf("Created %d smoothing groups for %d surfaces\n\n", (int)smoothingGroups.size(), (int)surfaces.size());
|
||||
}
|
||||
|
||||
|
||||
#include <set> // hack
|
||||
std::set<Portal, RejectRecursivePortals> touchedPortals;
|
||||
|
||||
int depth = 0;
|
||||
|
||||
void LevelMesh::PropagateLight(FLevel& doomMap, ThingLight *light)
|
||||
{
|
||||
// Because of sectorGroups, this will unlikely get this deep anyway
|
||||
if (depth > 32)
|
||||
if (lightPropagationRecursiveDepth > 32)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
@ -195,17 +188,17 @@ void LevelMesh::PropagateLight(FLevel& doomMap, ThingLight *light)
|
|||
SphereShape sphere;
|
||||
sphere.center = light->LightRelativeOrigin();
|
||||
sphere.radius = light->LightRadius();
|
||||
depth++;
|
||||
std::set<Portal, RejectRecursivePortals> portalsToErase;
|
||||
lightPropagationRecursiveDepth++;
|
||||
std::set<Portal, RecursivePortalComparator> portalsToErase;
|
||||
for (int triangleIndex : TriangleMeshShape::find_all_hits(Collision.get(), &sphere))
|
||||
{
|
||||
Surface* surface = surfaces[MeshSurfaces[triangleIndex]].get();
|
||||
// Reject any surface which isn't physically connected to the sector group in which the light resided
|
||||
|
||||
// skip any surface which isn't physically connected to the sector group in which the light resides
|
||||
if (light->sectorGroup == surface->sectorGroup)
|
||||
{
|
||||
if (surface->portalIndex >= 0)
|
||||
{
|
||||
|
||||
auto portal = portals[surface->portalIndex].get();
|
||||
|
||||
if (touchedPortals.insert(*portal).second)
|
||||
|
@ -240,7 +233,8 @@ void LevelMesh::PropagateLight(FLevel& doomMap, ThingLight *light)
|
|||
{
|
||||
touchedPortals.erase(portal);
|
||||
}
|
||||
depth--;
|
||||
|
||||
lightPropagationRecursiveDepth--;
|
||||
}
|
||||
|
||||
void LevelMesh::BuildLightLists(FLevel& doomMap)
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include <string>
|
||||
#include <cstring>
|
||||
#include <map>
|
||||
#include <set>
|
||||
|
||||
#include "framework/tarray.h"
|
||||
#include "framework/halffloat.h"
|
||||
|
@ -154,9 +155,14 @@ public:
|
|||
std::unique_ptr<TriangleMeshShape> Collision;
|
||||
|
||||
private:
|
||||
std::vector<std::unique_ptr<ThingLight>> portalLights; // Portal generated lights
|
||||
// Portal to portals[] index
|
||||
std::map<Portal, int, IdenticalPortalComparator> portalCache;
|
||||
|
||||
// Portal lights
|
||||
std::vector<std::unique_ptr<ThingLight>> portalLights;
|
||||
std::set<Portal, RecursivePortalComparator> touchedPortals;
|
||||
int lightPropagationRecursiveDepth = 0;
|
||||
|
||||
void CreateSubsectorSurfaces(FLevel &doomMap);
|
||||
void CreateCeilingSurface(FLevel &doomMap, MapSubsectorEx *sub, IntSector *sector, int typeIndex, bool is3DFloor);
|
||||
void CreateFloorSurface(FLevel &doomMap, MapSubsectorEx *sub, IntSector *sector, int typeIndex, bool is3DFloor);
|
||||
|
|
|
@ -20,51 +20,54 @@ struct Portal
|
|||
return vec3(v.x, v.y, v.z);
|
||||
}
|
||||
|
||||
// Check if the portal is inverse
|
||||
inline bool IsInversePortal(const Portal& portal) const
|
||||
// Checks only transformation
|
||||
inline bool IsInverseTransformationPortal(const Portal& portal) const
|
||||
{
|
||||
auto diff = portal.TransformPosition(TransformPosition(vec3(0)));
|
||||
return abs(diff.x) < 0.001 && abs(diff.y) < 0.001 && abs(diff.z) < 0.001;
|
||||
}
|
||||
|
||||
// Check if the portal transformation is equal
|
||||
inline bool IsEqualPortal(const Portal& portal) const
|
||||
// Checks only transformation
|
||||
inline bool IsEqualTransformationPortal(const Portal& portal) const
|
||||
{
|
||||
auto diff = portal.TransformPosition(vec3(0)) - TransformPosition(vec3(0));
|
||||
return (abs(diff.x) < 0.001 && abs(diff.y) < 0.001 && abs(diff.z) < 0.001);
|
||||
}
|
||||
|
||||
// Do both portals travel from sector group A to sector group B?
|
||||
inline bool IsTravelingBetweenSameSectorGroups(const Portal& portal) const
|
||||
|
||||
// Checks transformation, source and destiantion sector groups
|
||||
inline bool IsEqualPortal(const Portal& portal) const
|
||||
{
|
||||
return sourceSectorGroup == portal.sourceSectorGroup && targetSectorGroup == portal.targetSectorGroup;
|
||||
return sourceSectorGroup == portal.sourceSectorGroup && targetSectorGroup == portal.targetSectorGroup && IsEqualTransformationPortal(portal);
|
||||
}
|
||||
|
||||
// Checks transformation, source and destiantion sector groups
|
||||
inline bool IsInversePortal(const Portal& portal) const
|
||||
{
|
||||
return sourceSectorGroup == portal.targetSectorGroup && targetSectorGroup == portal.sourceSectorGroup && IsInverseTransformationPortal(portal);
|
||||
}
|
||||
|
||||
inline void DumpInfo()
|
||||
{
|
||||
auto v = TransformPosition(vec3(0));
|
||||
printf("Portal offset: %.3f %.3f %.3f\n\tsource group:\t%d\n\ttarget group:\t%d", v.x, v.y, v.z, sourceSectorGroup, targetSectorGroup);
|
||||
}
|
||||
};
|
||||
|
||||
// for use with std::set to recursively go through portals
|
||||
struct RejectRecursivePortals
|
||||
// for use with std::set to recursively go through portals and skip returning portals
|
||||
struct RecursivePortalComparator
|
||||
{
|
||||
inline bool IsEqual(const Portal& a, const Portal& b) const
|
||||
{
|
||||
return a.IsInversePortal(b) || a.IsEqualPortal(b);
|
||||
}
|
||||
|
||||
bool operator()(const Portal& a, const Portal& b) const
|
||||
{
|
||||
return !IsEqual(a, b) && std::memcmp(&a.transformation, &b.transformation, sizeof(mat4)) < 0;
|
||||
return !a.IsInversePortal(b) && std::memcmp(&a.transformation, &b.transformation, sizeof(mat4)) < 0;
|
||||
}
|
||||
};
|
||||
|
||||
// for use with std::map to reject portals which have equal transformation between equal sector groups
|
||||
// for use with std::map to reject portals which have the same effect for light rays
|
||||
struct IdenticalPortalComparator
|
||||
{
|
||||
inline bool IsEqual(const Portal& a, const Portal& b) const
|
||||
{
|
||||
return a.IsEqualPortal(b) && a.IsTravelingBetweenSameSectorGroups(b);
|
||||
}
|
||||
|
||||
bool operator()(const Portal& a, const Portal& b) const
|
||||
{
|
||||
return !IsEqual(a, b) && std::memcmp(&a.transformation, &b.transformation, sizeof(mat4)) < 0;
|
||||
return !a.IsEqualPortal(b) && std::memcmp(&a.transformation, &b.transformation, sizeof(mat4)) < 0;
|
||||
}
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue