Implement sector groups

This commit is contained in:
RaveYard 2022-10-30 13:47:10 +01:00
parent cb9416269e
commit 0a9c2cf131
5 changed files with 95 additions and 25 deletions

View file

@ -70,6 +70,8 @@ struct IntSideDef
inline int GetSampleDistanceBottom() const { return sampleDistanceBottom ? sampleDistanceBottom : sampleDistance; }
TArray<UDMFKey> props;
inline int GetSectorGroup() const;
};
struct MapLineDef
@ -107,6 +109,8 @@ struct IntLineDef
TArray<int> ids;
IntSector *frontsector = nullptr, *backsector = nullptr;
inline int GetSectorGroup() const;
};
struct MapSector
@ -158,6 +162,8 @@ struct IntSector
TArray<IntLineDef*> lines;
TArray<IntLineDef*> portals;
int group = 0;
// Utility functions
inline const char* GetTextureName(int plane) const { return plane != PLANE_FLOOR ? data.ceilingpic : data.floorpic; }
@ -173,6 +179,16 @@ struct IntSector
}
};
inline int IntLineDef::GetSectorGroup() const
{
return frontsector ? frontsector->group : (backsector ? backsector->group : 0);
}
inline int IntSideDef::GetSectorGroup() const
{
return line ? line->GetSectorGroup() : 0;
}
struct MapSubsector
{
uint16_t numlines;
@ -329,7 +345,9 @@ struct ThingLight
IntSector *sector;
MapSubsectorEx *ssect;
// Portal related functionality
vec3 relativePosition = vec3(0);
int sectorGroup = 0;
// Portal aware position
vec3 LightRelativeOrigin() const

View file

@ -691,6 +691,41 @@ void FLevel::PostLoadInitialization()
}
}
}
// Discover islands of sectors
{
int groupId = 0;
std::vector<IntSector*> candidates;
for (auto& sector : Sectors)
{
if (!sector.group)
{
sector.group = ++groupId;
candidates.push_back(&sector);
while (!candidates.empty())
{
auto* sector = candidates[candidates.size() - 1];
candidates.pop_back();
for (const auto& line : sector->lines)
{
if (line->frontsector && !line->frontsector->group)
{
line->frontsector->group = groupId;
candidates.push_back(line->frontsector);
}
if (line->backsector && !line->backsector->group)
{
line->backsector->group = groupId;
candidates.push_back(line->backsector);
}
}
}
}
}
}
}
void FProcessor::BuildNodes()

View file

@ -290,6 +290,7 @@ void FLevel::CreateLights()
thingLight.sector = GetSectorFromSubSector(thingLight.ssect);
thingLight.origin.x = x;
thingLight.origin.y = y;
thingLight.sectorGroup = thingLight.sector->group;
ThingLights.Push(thingLight);
}

View file

@ -147,7 +147,6 @@ LevelMesh::LevelMesh(FLevel &doomMap, int sampleDistance, int textureSize)
Collision = std::make_unique<TriangleMeshShape>(MeshVertices.Data(), MeshVertices.Size(), MeshElements.Data(), MeshElements.Size());
printf("Building light list...\n\n");
BuildLightLists(doomMap);
/*
std::map<int, int> lightStats;
@ -166,7 +165,8 @@ int depth = 0;
void LevelMesh::PropagateLight(FLevel& doomMap, ThingLight *light)
{
if (depth > 4)
// Because of sectorGroups, this will unlikely get this deep anyway
if (depth > 32)
{
return;
}
@ -180,35 +180,43 @@ void LevelMesh::PropagateLight(FLevel& doomMap, ThingLight *light)
{
Surface* surface = surfaces[MeshSurfaces[triangleIndex]].get();
if (surface->portalIndex >= 0)
auto surfaceSectorGroup = surface->type == ST_CEILING || surface->type == ST_FLOOR ?
doomMap.GetSectorFromSubSector(&doomMap.GLSubsectors[surface->typeIndex])->group : (doomMap.Sides[surface->typeIndex].GetSectorGroup());
// Reject any surface which isn't physically connected to the sector group in which the light resided
if (light->sectorGroup == surfaceSectorGroup)
{
auto portal = portals[surface->portalIndex].get();
if (surface->portalIndex >= 0)
{
if (touchedPortals.insert(*portal).second)
{
auto fakeLight = std::make_unique<ThingLight>(*light);
auto portal = portals[surface->portalIndex].get();
fakeLight->relativePosition = portal->TransformPosition(light->LightRelativeOrigin());
if (touchedPortals.insert(*portal).second)
{
auto fakeLight = std::make_unique<ThingLight>(*light);
PropagateLight(doomMap, fakeLight.get());
portalsToErase.insert(*portal);
portalLights.push_back(std::move(fakeLight));
fakeLight->relativePosition = portal->TransformPosition(light->LightRelativeOrigin());
fakeLight->sectorGroup = portal->targetSectorGroup;
PropagateLight(doomMap, fakeLight.get());
portalsToErase.insert(*portal);
portalLights.push_back(std::move(fakeLight));
}
}
}
// Add light to the list if it isn't already there
bool found = false;
for (ThingLight* light2 : surface->LightList)
{
if (light2 == light)
// Add light to the list if it isn't already there
bool found = false;
for (ThingLight* light2 : surface->LightList)
{
found = true;
break;
if (light2 == light)
{
found = true;
break;
}
}
if (!found)
surface->LightList.push_back(light);
}
if (!found)
surface->LightList.push_back(light);
}
for (auto& portal : portalsToErase)
@ -220,10 +228,13 @@ void LevelMesh::PropagateLight(FLevel& doomMap, ThingLight *light)
void LevelMesh::BuildLightLists(FLevel& doomMap)
{
for (ThingLight& light : map->ThingLights)
for (unsigned i = 0; i < map->ThingLights.Size(); ++i)
{
PropagateLight(doomMap, &light);
printf("Building light lists: %u / %u\r", i, map->ThingLights.Size());
PropagateLight(doomMap, &map->ThingLights[i]);
}
printf("Building light lists: %u / %u\n", map->ThingLights.Size(), map->ThingLights.Size());
}
// Determines a lightmap block in which to map to the lightmap texture.
@ -548,6 +559,8 @@ int LevelMesh::CreateLinePortal(FLevel& doomMap, const IntLineDef& srcLine, cons
// printf("Portal translation: %.3f %.3f %.3f\n", translation.x, translation.y, translation.z);
portal->transformation = mat4::translate(translation);
portal->sourceSectorGroup = srcLine.GetSectorGroup();
portal->targetSectorGroup = dstLine.GetSectorGroup();
}
portals.push_back(std::move(portal));
@ -632,6 +645,8 @@ int LevelMesh::CreatePlanePortal(FLevel& doomMap, const IntLineDef& srcLine, con
// printf("Portal translation: %.3f %.3f %.3f\n", translation.x, translation.y, translation.z);
portal->transformation = mat4::translate(translation);
portal->sourceSectorGroup = srcLine.GetSectorGroup();
portal->targetSectorGroup = dstLine.GetSectorGroup();
}
portals.push_back(std::move(portal));

View file

@ -63,6 +63,8 @@ enum SurfaceType
struct Portal
{
mat4 transformation = mat4::identity();
int sourceSectorGroup = 0;
int targetSectorGroup = 0;
inline vec3 TransformPosition(const vec3& pos) const
{
@ -99,7 +101,6 @@ struct RejectRecursivePortals
{
bool operator()(const Portal& a, const Portal& b) const
{
static_assert(sizeof(Portal) == sizeof(float) * 4 * 4);
return !(a.IsInversePortal(b) || a.IsEqualPortal(b)) && std::memcmp(&a.transformation, &b.transformation, sizeof(mat4)) < 0;
}
};