mirror of
https://github.com/ZDoom/ZDRay.git
synced 2024-11-25 05:11:20 +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());
|
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)
|
void LevelMesh::PropagateLight(FLevel& doomMap, ThingLight *light)
|
||||||
{
|
{
|
||||||
// Because of sectorGroups, this will unlikely get this deep anyway
|
if (lightPropagationRecursiveDepth > 32)
|
||||||
if (depth > 32)
|
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -195,17 +188,17 @@ void LevelMesh::PropagateLight(FLevel& doomMap, ThingLight *light)
|
||||||
SphereShape sphere;
|
SphereShape sphere;
|
||||||
sphere.center = light->LightRelativeOrigin();
|
sphere.center = light->LightRelativeOrigin();
|
||||||
sphere.radius = light->LightRadius();
|
sphere.radius = light->LightRadius();
|
||||||
depth++;
|
lightPropagationRecursiveDepth++;
|
||||||
std::set<Portal, RejectRecursivePortals> portalsToErase;
|
std::set<Portal, RecursivePortalComparator> portalsToErase;
|
||||||
for (int triangleIndex : TriangleMeshShape::find_all_hits(Collision.get(), &sphere))
|
for (int triangleIndex : TriangleMeshShape::find_all_hits(Collision.get(), &sphere))
|
||||||
{
|
{
|
||||||
Surface* surface = surfaces[MeshSurfaces[triangleIndex]].get();
|
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 (light->sectorGroup == surface->sectorGroup)
|
||||||
{
|
{
|
||||||
if (surface->portalIndex >= 0)
|
if (surface->portalIndex >= 0)
|
||||||
{
|
{
|
||||||
|
|
||||||
auto portal = portals[surface->portalIndex].get();
|
auto portal = portals[surface->portalIndex].get();
|
||||||
|
|
||||||
if (touchedPortals.insert(*portal).second)
|
if (touchedPortals.insert(*portal).second)
|
||||||
|
@ -240,7 +233,8 @@ void LevelMesh::PropagateLight(FLevel& doomMap, ThingLight *light)
|
||||||
{
|
{
|
||||||
touchedPortals.erase(portal);
|
touchedPortals.erase(portal);
|
||||||
}
|
}
|
||||||
depth--;
|
|
||||||
|
lightPropagationRecursiveDepth--;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LevelMesh::BuildLightLists(FLevel& doomMap)
|
void LevelMesh::BuildLightLists(FLevel& doomMap)
|
||||||
|
|
|
@ -32,6 +32,7 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <set>
|
||||||
|
|
||||||
#include "framework/tarray.h"
|
#include "framework/tarray.h"
|
||||||
#include "framework/halffloat.h"
|
#include "framework/halffloat.h"
|
||||||
|
@ -154,9 +155,14 @@ public:
|
||||||
std::unique_ptr<TriangleMeshShape> Collision;
|
std::unique_ptr<TriangleMeshShape> Collision;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<std::unique_ptr<ThingLight>> portalLights; // Portal generated lights
|
// Portal to portals[] index
|
||||||
std::map<Portal, int, IdenticalPortalComparator> portalCache;
|
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 CreateSubsectorSurfaces(FLevel &doomMap);
|
||||||
void CreateCeilingSurface(FLevel &doomMap, MapSubsectorEx *sub, IntSector *sector, int typeIndex, bool is3DFloor);
|
void CreateCeilingSurface(FLevel &doomMap, MapSubsectorEx *sub, IntSector *sector, int typeIndex, bool is3DFloor);
|
||||||
void CreateFloorSurface(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);
|
return vec3(v.x, v.y, v.z);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if the portal is inverse
|
// Checks only transformation
|
||||||
inline bool IsInversePortal(const Portal& portal) const
|
inline bool IsInverseTransformationPortal(const Portal& portal) const
|
||||||
{
|
{
|
||||||
auto diff = portal.TransformPosition(TransformPosition(vec3(0)));
|
auto diff = portal.TransformPosition(TransformPosition(vec3(0)));
|
||||||
return abs(diff.x) < 0.001 && abs(diff.y) < 0.001 && abs(diff.z) < 0.001;
|
return abs(diff.x) < 0.001 && abs(diff.y) < 0.001 && abs(diff.z) < 0.001;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if the portal transformation is equal
|
// Checks only transformation
|
||||||
inline bool IsEqualPortal(const Portal& portal) const
|
inline bool IsEqualTransformationPortal(const Portal& portal) const
|
||||||
{
|
{
|
||||||
auto diff = portal.TransformPosition(vec3(0)) - TransformPosition(vec3(0));
|
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);
|
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
|
// for use with std::set to recursively go through portals and skip returning portals
|
||||||
struct RejectRecursivePortals
|
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
|
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
|
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
|
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