diff --git a/src/level/level.cpp b/src/level/level.cpp index 20f94c9..d3391a4 100644 --- a/src/level/level.cpp +++ b/src/level/level.cpp @@ -692,11 +692,16 @@ void FLevel::PostLoadInitialization() } } - // Discover islands of sectors + // Discover sector groups (graph islands) { int groupId = 0; std::vector candidates; + auto canPass = [&](IntLineDef* line) { + // Further conditions can be added to further split the map into groups + return line->special == 0 || (line->special != Line_SetPortal && line->special != Line_Horizon); + }; + for (auto& sector : Sectors) { if (!sector.group) @@ -711,15 +716,18 @@ void FLevel::PostLoadInitialization() for (const auto& line : sector->lines) { - if (line->frontsector && !line->frontsector->group) + if (canPass(line)) { - line->frontsector->group = groupId; - candidates.push_back(line->frontsector); - } - if (line->backsector && !line->backsector->group) - { - line->backsector->group = groupId; - candidates.push_back(line->backsector); + 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); + } } } } diff --git a/src/lightmap/levelmesh.cpp b/src/lightmap/levelmesh.cpp index df96676..462dfc6 100644 --- a/src/lightmap/levelmesh.cpp +++ b/src/lightmap/levelmesh.cpp @@ -60,6 +60,13 @@ LevelMesh::LevelMesh(FLevel &doomMap, int sampleDistance, int textureSize) printf("Surfaces total: %i\n\n", (int)surfaces.size()); + // Update sector group of the surfacesaa + for (auto& surface : surfaces) + { + surface->sectorGroup = surface->type == ST_CEILING || surface->type == ST_FLOOR ? + doomMap.GetSectorFromSubSector(&doomMap.GLSubsectors[surface->typeIndex])->group : (doomMap.Sides[surface->typeIndex].GetSectorGroup()); + } + printf("Building level mesh...\n\n"); for (size_t i = 0; i < surfaces.size(); i++) @@ -112,37 +119,7 @@ LevelMesh::LevelMesh(FLevel &doomMap, int sampleDistance, int textureSize) } printf("Finding smoothing groups...\n\n"); - - for (size_t i = 0; i < surfaces.size(); i++) - { - // Is this surface in the same plane as an existing smoothing group? - int smoothingGroupIndex = -1; - for (size_t j = 0; j < smoothingGroups.size(); j++) - { - float direction = std::abs(dot(smoothingGroups[j].Normal(), surfaces[i]->plane.Normal())); - if (direction >= 0.9999f && direction <= 1.001f) - { - float dist = std::abs(smoothingGroups[j].Distance(surfaces[i]->plane.Normal() * surfaces[i]->plane.d)); - if (dist <= 0.01f) - { - smoothingGroupIndex = (int)j; - break; - } - } - } - - // Surface is in a new plane. Create a smoothing group for it - if (smoothingGroupIndex == -1) - { - smoothingGroupIndex = smoothingGroups.size(); - smoothingGroups.push_back(surfaces[i]->plane); - } - - surfaces[i]->smoothingGroupIndex = smoothingGroupIndex; - } - - printf("Created %d smoothing groups for %d surfaces\n\n", (int)smoothingGroups.size(), (int)surfaces.size()); - + BuildSmoothingGroups(doomMap); printf("Building collision data...\n\n"); Collision = std::make_unique(MeshVertices.Data(), MeshVertices.Size(), MeshElements.Data(), MeshElements.Size()); @@ -158,6 +135,50 @@ LevelMesh::LevelMesh(FLevel &doomMap, int sampleDistance, int textureSize) */ } +void LevelMesh::BuildSmoothingGroups(FLevel& doomMap) +{ + for (size_t i = 0; i < surfaces.size(); i++) + { + // Is this surface in the same plane as an existing smoothing group? + int smoothingGroupIndex = -1; + + auto surface = surfaces[i].get(); + + for (size_t j = 0; j < smoothingGroups.size(); j++) + { + if (surface->sectorGroup == smoothingGroups[j].sectorGroup) + { + float direction = std::abs(dot(smoothingGroups[j].plane.Normal(), surface->plane.Normal())); + if (direction >= 0.9999f && direction <= 1.001f) + { + float dist = std::abs(smoothingGroups[j].plane.Distance(surface->plane.Normal() * surface->plane.d)); + if (dist <= 0.01f) + { + smoothingGroupIndex = (int)j; + break; + } + } + } + } + + // Surface is in a new plane. Create a smoothing group for it + if (smoothingGroupIndex == -1) + { + smoothingGroupIndex = smoothingGroups.size(); + + SmoothingGroup group; + group.plane = surface->plane; + group.sectorGroup = surface->sectorGroup; + smoothingGroups.push_back(group); + } + + surface->smoothingGroupIndex = smoothingGroupIndex; + } + + printf("Created %d smoothing groups for %d surfaces\n\n", (int)smoothingGroups.size(), (int)surfaces.size()); +} + + #include // hack std::set touchedPortals; @@ -179,12 +200,8 @@ void LevelMesh::PropagateLight(FLevel& doomMap, ThingLight *light) for (int triangleIndex : TriangleMeshShape::find_all_hits(Collision.get(), &sphere)) { Surface* surface = surfaces[MeshSurfaces[triangleIndex]].get(); - - 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) + if (light->sectorGroup == surface->sectorGroup) { if (surface->portalIndex >= 0) { diff --git a/src/lightmap/levelmesh.h b/src/lightmap/levelmesh.h index 4c5b590..8bc6fd6 100644 --- a/src/lightmap/levelmesh.h +++ b/src/lightmap/levelmesh.h @@ -83,6 +83,9 @@ struct Surface // Portal int portalDestinationIndex = -1; // line or sector index int portalIndex = -1; + + // Sector group + int sectorGroup = 0; // Touching light sources std::vector LightList; @@ -114,6 +117,12 @@ struct Surface int smoothingGroupIndex = -1; }; +struct SmoothingGroup +{ + Plane plane = Plane(0, 0, 1, 0); + int sectorGroup = 0; +}; + class LevelMesh { public: @@ -129,7 +138,7 @@ public: std::vector> textures; - std::vector smoothingGroups; + std::vector smoothingGroups; std::vector> portals; @@ -159,6 +168,8 @@ private: void BuildLightLists(FLevel &doomMap); void PropagateLight(FLevel& doomMap, ThingLight* thing); + void BuildSmoothingGroups(FLevel& doomMap); + void BlurSurfaces(); void FinishSurface(RectPacker& packer, Surface* surface);