diff --git a/src/gamedata/r_defs.h b/src/gamedata/r_defs.h index 0dca16c30..0aed732e5 100644 --- a/src/gamedata/r_defs.h +++ b/src/gamedata/r_defs.h @@ -786,6 +786,7 @@ struct sector_t int health3dgroup; LightProbeTarget lightProbe; // TODO split individual flats in the sector including 3d floors + int lightmapHeightGroup[2]; // Member functions diff --git a/src/rendering/hwrenderer/doom_levelmesh.cpp b/src/rendering/hwrenderer/doom_levelmesh.cpp index 83a39537f..4b361639e 100644 --- a/src/rendering/hwrenderer/doom_levelmesh.cpp +++ b/src/rendering/hwrenderer/doom_levelmesh.cpp @@ -271,6 +271,7 @@ DoomLevelMesh::DoomLevelMesh(FLevelLocals& doomMap) r_viewpoint.extralight = 0; r_viewpoint.camera = nullptr; + BuildHeightGroups(doomMap); BuildSideVisibilityLists(doomMap); BuildSubsectorVisibilityLists(doomMap); @@ -501,6 +502,62 @@ void DoomLevelMesh::BuildSideVisibilityLists(FLevelLocals& doomMap) } } +void DoomLevelMesh::BuildHeightGroups(FLevelLocals& doomMap) +{ + // Reset groups + for (sector_t& sector : doomMap.sectors) + for (int plane = 0; plane < 2; plane++) + sector.lightmapHeightGroup[plane] = -1; + + // Try to group sector flats into continous planes while taking slopes into account + int nextGroup = 0; + TArray stack; + for (sector_t& sector : doomMap.sectors) + { + for (int plane = 0; plane < 2; plane++) + { + if (sector.lightmapHeightGroup[plane] != -1) + continue; + + int group = nextGroup++; + sector.lightmapHeightGroup[plane] = group; + + stack.Push(§or); + while (stack.Size() != 0) + { + sector_t* cur = stack.Last(); + stack.Pop(); + + for (line_t* line : cur->Lines) + { + if (!line->backsector) + continue; + + auto fs = line->frontsector; + auto bs = line->backsector; + auto& fsplane = fs->GetSecPlane(plane); + auto& bsplane = bs->GetSecPlane(plane); + + if (std::abs(fsplane.ZatPoint(line->v1) - bsplane.ZatPoint(line->v1)) < 16.0 && + std::abs(fsplane.ZatPoint(line->v2) - bsplane.ZatPoint(line->v2)) < 16.0) + { + if (fs == cur && bs->lightmapHeightGroup[plane] == -1) + { + cur->lightmapHeightGroup[plane] = group; + stack.Push(bs); + } + else if (bs == cur && fs->lightmapHeightGroup[plane] == -1) + { + cur->lightmapHeightGroup[plane] = group; + stack.Push(fs); + } + } + } + } + } + } +} + void DoomLevelMesh::BuildSubsectorVisibilityLists(FLevelLocals& doomMap) { TArray stack; @@ -2099,8 +2156,13 @@ void DoomLevelMesh::GetVisibleSurfaces(LightmapTile* tile, TArray& outSurfa } else if (tile->Binding.Type == ST_CEILING || tile->Binding.Type == ST_FLOOR) { + int heightGroup = level.subsectors[tile->Binding.TypeIndex].sector->lightmapHeightGroup[ST_FLOOR - tile->Binding.Type]; for (int subsectorIndex : VisibleSubsectors[tile->Binding.TypeIndex]) { + int heightGroup2 = level.subsectors[subsectorIndex].sector->lightmapHeightGroup[ST_FLOOR - tile->Binding.Type]; + if (heightGroup != heightGroup2) + continue; + int surf = SubsectorSurfaces[subsectorIndex]; while (surf != -1) { diff --git a/src/rendering/hwrenderer/doom_levelmesh.h b/src/rendering/hwrenderer/doom_levelmesh.h index b1ae4bc5e..6fe993616 100644 --- a/src/rendering/hwrenderer/doom_levelmesh.h +++ b/src/rendering/hwrenderer/doom_levelmesh.h @@ -257,6 +257,7 @@ private: void BuildSideVisibilityLists(FLevelLocals& doomMap); void BuildSubsectorVisibilityLists(FLevelLocals& doomMap); + void BuildHeightGroups(FLevelLocals& doomMap); DoomSurfaceInfo* GetDoomSurface(const SurfaceAllocInfo& sinfo) {