diff --git a/doomsday/client/include/world/map.h b/doomsday/client/include/world/map.h index 0bf9a5a04a..8d2439c1e5 100644 --- a/doomsday/client/include/world/map.h +++ b/doomsday/client/include/world/map.h @@ -39,15 +39,13 @@ # include "Lumobj" #endif +#include +#include +#include #include - #include #include #include -#include -#include -#include -#include class MapDef; class BspLeaf; @@ -136,7 +134,6 @@ class Map typedef QList Sectors; typedef QList Subspaces; - typedef QMultiMap SectorClusters; #ifdef __CLIENT__ typedef QSet PlaneSet; @@ -268,14 +265,20 @@ class Map inline int subspaceCount() const { return subspaces().count(); } /** - * Provides access to the SectorCluster map for efficient traversal. + * Returns the total number of SectorClusters in the map. */ - SectorClusters const &clusters() const; + int clusterCount() const; /** - * Returns the total number of SectorClusters in the map. + * Iterate through the SectorClusters of the map. + * + * @param sector If not @c nullptr, traverse the clusters of this Sector only. */ - inline int clusterCount() const { return clusters().count(); } + LoopResult forAllClusters(Sector *sector, std::function func); + + inline LoopResult forAllClusters(std::function func) { + return forAllClusters(nullptr, func); + } /** * Helper function which returns the relevant side index given a @a lineIndex diff --git a/doomsday/client/src/render/rend_main.cpp b/doomsday/client/src/render/rend_main.cpp index e38505c65e..72d1a1f3c1 100644 --- a/doomsday/client/src/render/rend_main.cpp +++ b/doomsday/client/src/render/rend_main.cpp @@ -4589,11 +4589,9 @@ static void drawTangentVectorsForWallSections(HEdge const *hedge) /** * @todo Use drawTangentVectorsForWallSections() for polyobjs too. */ -static void drawSurfaceTangentVectors(SectorCluster *cluster) +static void drawSurfaceTangentVectors(SectorCluster &cluster) { - if(!cluster) return; - - foreach(ConvexSubspace *subspace, cluster->subspaces()) + for(ConvexSubspace *subspace : cluster.subspaces()) { HEdge const *base = subspace->poly().hedge(); HEdge const *hedge = base; @@ -4602,23 +4600,23 @@ static void drawSurfaceTangentVectors(SectorCluster *cluster) drawTangentVectorsForWallSections(hedge); } while((hedge = &hedge->next()) != base); - foreach(Mesh *mesh, subspace->extraMeshes()) - foreach(HEdge *hedge, mesh->hedges()) + for(Mesh *mesh : subspace->extraMeshes()) + for(HEdge *hedge : mesh->hedges()) { drawTangentVectorsForWallSections(hedge); } - foreach(Polyobj *polyobj, subspace->polyobjs()) - foreach(HEdge *hedge, polyobj->mesh().hedges()) + for(Polyobj *polyobj : subspace->polyobjs()) + for(HEdge *hedge : polyobj->mesh().hedges()) { drawTangentVectorsForWallSections(hedge); } } - int const planeCount = cluster->sector().planeCount(); + int const planeCount = cluster.sector().planeCount(); for(int i = 0; i < planeCount; ++i) { - Plane const &plane = cluster->visPlane(i); + Plane const &plane = cluster.visPlane(i); coord_t height = 0; if(plane.surface().hasSkyMaskedMaterial() && @@ -4631,7 +4629,7 @@ static void drawSurfaceTangentVectors(SectorCluster *cluster) height = plane.heightSmoothed(); } - drawTangentVectorsForSurface(plane.surface(), Vector3d(cluster->center(), height)); + drawTangentVectorsForSurface(plane.surface(), Vector3d(cluster.center(), height)); } } @@ -4644,10 +4642,11 @@ static void drawAllSurfaceTangentVectors(Map &map) glDisable(GL_CULL_FACE); - foreach(SectorCluster *cluster, map.clusters()) + map.forAllClusters([] (SectorCluster &cluster) { drawSurfaceTangentVectors(cluster); - } + return LoopContinue; + }); glEnable(GL_CULL_FACE); } @@ -5054,10 +5053,9 @@ static void drawVertexes(Map &map) #undef MAX_VERTEX_POINT_DIST } -static String labelForCluster(SectorCluster const *cluster) +static String labelForCluster(SectorCluster const &cluster) { - DENG_ASSERT(cluster != 0); - return String("%1").arg(cluster->sector().indexInMap()); + return String::number(cluster.sector().indexInMap()); } /** @@ -5070,10 +5068,9 @@ static void drawSectors(Map &map) if(!devSectorIndices) return; // Draw per-cluster sector labels: - - foreach(SectorCluster *cluster, map.clusters()) + map.forAllClusters([] (SectorCluster &cluster) { - Vector3d const origin(cluster->center(), cluster->visPlane(Sector::Floor).heightSmoothed()); + Vector3d const origin(cluster.center(), cluster.visPlane(Sector::Floor).heightSmoothed()); ddouble const distToEye = (eyeOrigin - origin).length(); if(distToEye < MAX_LABEL_DIST) { @@ -5081,7 +5078,8 @@ static void drawSectors(Map &map) distToEye / (DENG_GAMEVIEW_WIDTH / 2), 1 - distToEye / MAX_LABEL_DIST); } - } + return LoopContinue; + }); #undef MAX_LABEL_DIST } diff --git a/doomsday/client/src/world/map.cpp b/doomsday/client/src/world/map.cpp index 5d03549da9..c16388defb 100644 --- a/doomsday/client/src/world/map.cpp +++ b/doomsday/client/src/world/map.cpp @@ -76,6 +76,7 @@ #include #include #include +#include #include static int bspSplitFactor = 7; // cvar @@ -150,6 +151,8 @@ DENG2_PIMPL(Map) } bsp; Subspaces subspaces; + + typedef QMultiMap SectorClusters; SectorClusters clusters; /// Map entities and element properties (things, line specials, etc...). @@ -573,14 +576,14 @@ DENG2_PIMPL(Map) */ bool buildBspTree() { - DENG2_ASSERT(bsp.tree == 0); + DENG2_ASSERT(bsp.tree == nullptr); DENG2_ASSERT(subspaces.isEmpty()); // It begins... Time begunAt; LOGDEV_MAP_XVERBOSE("Building BSP for \"%s\" with split cost factor %d...") - << (def? def->composeUri() : "(unknown map)") << bspSplitFactor; + << (def? def->composeUri() : "(unknown map)") << bspSplitFactor; // First we'll scan for so-called "one-way window" constructs and mark // them so that the space partitioner can treat them specially. @@ -594,8 +597,8 @@ DENG2_PIMPL(Map) QSet linesToBuildFor = QSet::fromList(lines); // Polyobj lines should be excluded. - foreach(Polyobj *po, polyobjs) - foreach(Line *line, po->lines()) + for(Polyobj *po : polyobjs) + for(Line *line : po->lines()) { linesToBuildFor.remove(line); } @@ -608,7 +611,7 @@ DENG2_PIMPL(Map) // Build a new BSP tree. bsp.tree = partitioner.makeBspTree(linesToBuildFor, mesh); - DENG2_ASSERT(bsp.tree != 0); + DENG2_ASSERT(bsp.tree); LOG_MAP_VERBOSE("BSP built: %s. With %d Segments and %d Vertexes.") << bsp.tree->summary() @@ -629,8 +632,8 @@ DENG2_PIMPL(Map) #endif // Iterative pre-order traversal of the map element tree. - BspTree const *cur = bsp.tree; - BspTree const *prev = 0; + BspTree const *cur = bsp.tree; + BspTree const *prev = nullptr; while(cur) { while(cur) @@ -643,7 +646,7 @@ DENG2_PIMPL(Map) if(!leaf.sectorPtr()) { LOG_MAP_WARNING("BSP leaf %p has degenerate geometry (%d half-edges).") - << &leaf << (leaf.hasSubspace()? leaf.subspace().poly().hedgeCount() : 0); + << &leaf << (leaf.hasSubspace()? leaf.subspace().poly().hedgeCount() : 0); } if(leaf.hasSubspace()) @@ -667,11 +670,11 @@ DENG2_PIMPL(Map) if(discontinuities) { LOG_MAP_WARNING("Face geometry for BSP leaf [%p] at %s in sector %i " - "is not contiguous (%i gaps/overlaps).\n%s") - << &leaf << subspace.poly().center().asText() - << (leaf.sectorPtr()? leaf.sectorPtr()->indexInArchive() : -1) - << discontinuities - << subspace.poly().description(); + "is not contiguous (%i gaps/overlaps).\n%s") + << &leaf << subspace.poly().center().asText() + << (leaf.sectorPtr()? leaf.sectorPtr()->indexInArchive() : -1) + << discontinuities + << subspace.poly().description(); } #endif } @@ -714,7 +717,7 @@ DENG2_PIMPL(Map) // How much time did we spend? LOGDEV_MAP_VERBOSE("BSP built in %.2f seconds") << begunAt.since(); - return bsp.tree != 0; + return bsp.tree != nullptr; } /** @@ -722,8 +725,10 @@ DENG2_PIMPL(Map) */ void buildClusters(Sector §or) { - SectorClusters::iterator it = clusters.find(§or); - while(it != clusters.end() && it.key() == §or) { delete *it; } + for(auto it = clusters.find(§or); it != clusters.end() && it.key() == §or; ) + { + delete *it; + } clusters.remove(§or); typedef QList Subspaces; @@ -735,7 +740,7 @@ DENG2_PIMPL(Map) * starting with a set per subspace and then keep merging these sets until * no more shared edges are found. */ - foreach(ConvexSubspace *subspace, subspaces) + for(ConvexSubspace *subspace : subspaces) { if(subspace->bspLeaf().sectorPtr() == §or) { @@ -755,7 +760,7 @@ DENG2_PIMPL(Map) { if(i == k) continue; - foreach(ConvexSubspace *subspace, subspaceSets[i]) + for(ConvexSubspace *subspace : subspaceSets[i]) { HEdge *baseHEdge = subspace->poly().hedge(); HEdge *hedge = baseHEdge; @@ -792,7 +797,7 @@ DENG2_PIMPL(Map) // Clustering complete. // Build clusters. - foreach(Subspaces const &subspaceSet, subspaceSets) + for(Subspaces const &subspaceSet : subspaceSets) { // Subspace ownership is not given to the cluster. clusters.insert(§or, new SectorCluster(subspaceSet)); @@ -1611,9 +1616,27 @@ Map::Subspaces const &Map::subspaces() const return d->subspaces; } -Map::SectorClusters const &Map::clusters() const +LoopResult Map::forAllClusters(Sector *sector, std::function func) +{ + if(sector) + { + for(auto it = d->clusters.constFind(sector); it != d->clusters.end() && it.key() == sector; ++it) + { + if(auto result = func(**it)) return result; + } + } + + for(SectorCluster *cluster : d->clusters) + { + if(auto result = func(*cluster)) return result; + } + + return LoopContinue; +} + +int Map::clusterCount() const { - return d->clusters; + return d->clusters.count(); } #ifdef __CLIENT__ diff --git a/doomsday/client/src/world/sector.cpp b/doomsday/client/src/world/sector.cpp index 28098f637a..ac38fe32a0 100644 --- a/doomsday/client/src/world/sector.cpp +++ b/doomsday/client/src/world/sector.cpp @@ -104,22 +104,19 @@ DENG2_PIMPL(Sector) aaBox.clear(); bool haveGeometry = false; - Map::SectorClusters const &clusterMap = self.map().clusters(); - Map::SectorClusters::const_iterator i = clusterMap.constFind(thisPublic); - while(i != clusterMap.end() && i.key() == thisPublic) + self.map().forAllClusters(thisPublic, [&] (SectorCluster &cluster) { - SectorCluster *cluster = *i; if(haveGeometry) { - V2d_UniteBox(aaBox.arvec2, cluster->aaBox().arvec2); + V2d_UniteBox(aaBox.arvec2, cluster.aaBox().arvec2); } else { - aaBox = cluster->aaBox(); + aaBox = cluster.aaBox(); haveGeometry = true; } - ++i; - } + return LoopContinue; + }); // The XY origin of our sound emitter can now be updated as the center // point of the sector geometry is now known. @@ -141,13 +138,11 @@ DENG2_PIMPL(Sector) needRoughAreaUpdate = false; roughArea = 0; - Map::SectorClusters const &clusterMap = self.map().clusters(); - Map::SectorClusters::const_iterator i = clusterMap.constFind(thisPublic); - while(i != clusterMap.end() && i.key() == thisPublic) + self.map().forAllClusters(thisPublic, [&] (SectorCluster &cluster) { - roughArea += (*i)->roughArea(); - ++i; - } + roughArea += cluster.roughArea(); + return LoopContinue; + }); } #endif // __CLIENT__