From 6d3c9b38ba3ba089dda6abb5c9e2e4705f0e502b Mon Sep 17 00:00:00 2001 From: Rafael Stahl Date: Fri, 18 Dec 2015 14:33:44 +0100 Subject: [PATCH] add rcScopedTimer to fix timers not being stopped on all paths and to prevent it in the future. --- Recast/Include/Recast.h | 18 ++- Recast/Source/Recast.cpp | 4 +- Recast/Source/RecastArea.cpp | 21 +--- Recast/Source/RecastContour.cpp | 4 +- Recast/Source/RecastFilter.cpp | 14 +-- Recast/Source/RecastLayers.cpp | 7 +- Recast/Source/RecastMesh.cpp | 8 +- Recast/Source/RecastMeshDetail.cpp | 8 +- Recast/Source/RecastRasterization.cpp | 16 +-- Recast/Source/RecastRegion.cpp | 154 ++++++++++++-------------- 10 files changed, 110 insertions(+), 144 deletions(-) diff --git a/Recast/Include/Recast.h b/Recast/Include/Recast.h index 797d69d..0705033 100644 --- a/Recast/Include/Recast.h +++ b/Recast/Include/Recast.h @@ -127,7 +127,7 @@ public: inline void resetTimers() { if (m_timerEnabled) doResetTimers(); } /// Starts the specified performance timer. - /// @param label The category of timer. + /// @param label The category of the timer. inline void startTimer(const rcTimerLabel label) { if (m_timerEnabled) doStartTimer(label); } /// Stops the specified performance timer. @@ -173,6 +173,22 @@ protected: bool m_timerEnabled; }; +/// A helper to first start a timer and then stop it when this helper goes out of scope. +/// @see rcContext +class rcScopedTimer +{ +public: + /// Constructs an instance and starts the timer. + /// @param[in] ctx The context to use. + /// @param[in] label The category of the timer. + inline rcScopedTimer(rcContext* ctx, const rcTimerLabel label) : m_ctx(ctx), m_label(label) { m_ctx->startTimer(m_label); } + inline ~rcScopedTimer() { m_ctx->stopTimer(m_label); } + +private: + rcContext* const m_ctx; + const rcTimerLabel m_label; +}; + /// Specifies a configuration to use when performing Recast builds. /// @ingroup recast struct rcConfig diff --git a/Recast/Source/Recast.cpp b/Recast/Source/Recast.cpp index 59d9960..46bc8b7 100644 --- a/Recast/Source/Recast.cpp +++ b/Recast/Source/Recast.cpp @@ -329,7 +329,7 @@ bool rcBuildCompactHeightfield(rcContext* ctx, const int walkableHeight, const i { rcAssert(ctx); - ctx->startTimer(RC_TIMER_BUILD_COMPACTHEIGHTFIELD); + rcScopedTimer timer(ctx, RC_TIMER_BUILD_COMPACTHEIGHTFIELD); const int w = hf.width; const int h = hf.height; @@ -456,8 +456,6 @@ bool rcBuildCompactHeightfield(rcContext* ctx, const int walkableHeight, const i ctx->log(RC_LOG_ERROR, "rcBuildCompactHeightfield: Heightfield has too many layers %d (max: %d)", tooHighNeighbour, MAX_LAYERS); } - - ctx->stopTimer(RC_TIMER_BUILD_COMPACTHEIGHTFIELD); return true; } diff --git a/Recast/Source/RecastArea.cpp b/Recast/Source/RecastArea.cpp index 1a338cd..97139cf 100644 --- a/Recast/Source/RecastArea.cpp +++ b/Recast/Source/RecastArea.cpp @@ -41,7 +41,7 @@ bool rcErodeWalkableArea(rcContext* ctx, int radius, rcCompactHeightfield& chf) const int w = chf.width; const int h = chf.height; - ctx->startTimer(RC_TIMER_ERODE_AREA); + rcScopedTimer timer(ctx, RC_TIMER_ERODE_AREA); unsigned char* dist = (unsigned char*)rcAlloc(sizeof(unsigned char)*chf.spanCount, RC_ALLOC_TEMP); if (!dist) @@ -215,8 +215,6 @@ bool rcErodeWalkableArea(rcContext* ctx, int radius, rcCompactHeightfield& chf) rcFree(dist); - ctx->stopTimer(RC_TIMER_ERODE_AREA); - return true; } @@ -245,7 +243,7 @@ bool rcMedianFilterWalkableArea(rcContext* ctx, rcCompactHeightfield& chf) const int w = chf.width; const int h = chf.height; - ctx->startTimer(RC_TIMER_MEDIAN_AREA); + rcScopedTimer timer(ctx, RC_TIMER_MEDIAN_AREA); unsigned char* areas = (unsigned char*)rcAlloc(sizeof(unsigned char)*chf.spanCount, RC_ALLOC_TEMP); if (!areas) @@ -306,8 +304,6 @@ bool rcMedianFilterWalkableArea(rcContext* ctx, rcCompactHeightfield& chf) memcpy(chf.areas, areas, sizeof(unsigned char)*chf.spanCount); rcFree(areas); - - ctx->stopTimer(RC_TIMER_MEDIAN_AREA); return true; } @@ -322,7 +318,7 @@ void rcMarkBoxArea(rcContext* ctx, const float* bmin, const float* bmax, unsigne { rcAssert(ctx); - ctx->startTimer(RC_TIMER_MARK_BOX_AREA); + rcScopedTimer timer(ctx, RC_TIMER_MARK_BOX_AREA); int minx = (int)((bmin[0]-chf.bmin[0])/chf.cs); int miny = (int)((bmin[1]-chf.bmin[1])/chf.ch); @@ -357,9 +353,6 @@ void rcMarkBoxArea(rcContext* ctx, const float* bmin, const float* bmax, unsigne } } } - - ctx->stopTimer(RC_TIMER_MARK_BOX_AREA); - } @@ -391,7 +384,7 @@ void rcMarkConvexPolyArea(rcContext* ctx, const float* verts, const int nverts, { rcAssert(ctx); - ctx->startTimer(RC_TIMER_MARK_CONVEXPOLY_AREA); + rcScopedTimer timer(ctx, RC_TIMER_MARK_CONVEXPOLY_AREA); float bmin[3], bmax[3]; rcVcopy(bmin, verts); @@ -448,8 +441,6 @@ void rcMarkConvexPolyArea(rcContext* ctx, const float* verts, const int nverts, } } } - - ctx->stopTimer(RC_TIMER_MARK_CONVEXPOLY_AREA); } int rcOffsetPoly(const float* verts, const int nverts, const float offset, @@ -541,7 +532,7 @@ void rcMarkCylinderArea(rcContext* ctx, const float* pos, { rcAssert(ctx); - ctx->startTimer(RC_TIMER_MARK_CYLINDER_AREA); + rcScopedTimer timer(ctx, RC_TIMER_MARK_CYLINDER_AREA); float bmin[3], bmax[3]; bmin[0] = pos[0] - r; @@ -597,6 +588,4 @@ void rcMarkCylinderArea(rcContext* ctx, const float* pos, } } } - - ctx->stopTimer(RC_TIMER_MARK_CYLINDER_AREA); } diff --git a/Recast/Source/RecastContour.cpp b/Recast/Source/RecastContour.cpp index a7be669..8c5cd9e 100644 --- a/Recast/Source/RecastContour.cpp +++ b/Recast/Source/RecastContour.cpp @@ -831,7 +831,7 @@ bool rcBuildContours(rcContext* ctx, rcCompactHeightfield& chf, const int h = chf.height; const int borderSize = chf.borderSize; - ctx->startTimer(RC_TIMER_BUILD_CONTOURS); + rcScopedTimer timer(ctx, RC_TIMER_BUILD_CONTOURS); rcVcopy(cset.bmin, chf.bmin); rcVcopy(cset.bmax, chf.bmax); @@ -1100,7 +1100,5 @@ bool rcBuildContours(rcContext* ctx, rcCompactHeightfield& chf, } - ctx->stopTimer(RC_TIMER_BUILD_CONTOURS); - return true; } diff --git a/Recast/Source/RecastFilter.cpp b/Recast/Source/RecastFilter.cpp index bf985c3..e17105b 100644 --- a/Recast/Source/RecastFilter.cpp +++ b/Recast/Source/RecastFilter.cpp @@ -37,7 +37,7 @@ void rcFilterLowHangingWalkableObstacles(rcContext* ctx, const int walkableClimb { rcAssert(ctx); - ctx->startTimer(RC_TIMER_FILTER_LOW_OBSTACLES); + rcScopedTimer timer(ctx, RC_TIMER_FILTER_LOW_OBSTACLES); const int w = solid.width; const int h = solid.height; @@ -67,8 +67,6 @@ void rcFilterLowHangingWalkableObstacles(rcContext* ctx, const int walkableClimb } } } - - ctx->stopTimer(RC_TIMER_FILTER_LOW_OBSTACLES); } /// @par @@ -86,7 +84,7 @@ void rcFilterLedgeSpans(rcContext* ctx, const int walkableHeight, const int walk { rcAssert(ctx); - ctx->startTimer(RC_TIMER_FILTER_BORDER); + rcScopedTimer timer(ctx, RC_TIMER_FILTER_BORDER); const int w = solid.width; const int h = solid.height; @@ -167,9 +165,7 @@ void rcFilterLedgeSpans(rcContext* ctx, const int walkableHeight, const int walk } } } - - ctx->stopTimer(RC_TIMER_FILTER_BORDER); -} +} /// @par /// @@ -181,7 +177,7 @@ void rcFilterWalkableLowHeightSpans(rcContext* ctx, int walkableHeight, rcHeight { rcAssert(ctx); - ctx->startTimer(RC_TIMER_FILTER_WALKABLE); + rcScopedTimer timer(ctx, RC_TIMER_FILTER_WALKABLE); const int w = solid.width; const int h = solid.height; @@ -202,6 +198,4 @@ void rcFilterWalkableLowHeightSpans(rcContext* ctx, int walkableHeight, rcHeight } } } - - ctx->stopTimer(RC_TIMER_FILTER_WALKABLE); } diff --git a/Recast/Source/RecastLayers.cpp b/Recast/Source/RecastLayers.cpp index 41458c1..b9b416b 100644 --- a/Recast/Source/RecastLayers.cpp +++ b/Recast/Source/RecastLayers.cpp @@ -87,7 +87,7 @@ bool rcBuildHeightfieldLayers(rcContext* ctx, rcCompactHeightfield& chf, { rcAssert(ctx); - ctx->startTimer(RC_TIMER_BUILD_LAYERS); + rcScopedTimer timer(ctx, RC_TIMER_BUILD_LAYERS); const int w = chf.width; const int h = chf.height; @@ -446,10 +446,7 @@ bool rcBuildHeightfieldLayers(rcContext* ctx, rcCompactHeightfield& chf, // No layers, return empty. if (layerId == 0) - { - ctx->stopTimer(RC_TIMER_BUILD_LAYERS); return true; - } // Create layers. rcAssert(lset.layers == 0); @@ -612,7 +609,5 @@ bool rcBuildHeightfieldLayers(rcContext* ctx, rcCompactHeightfield& chf, layer->miny = layer->maxy = 0; } - ctx->stopTimer(RC_TIMER_BUILD_LAYERS); - return true; } diff --git a/Recast/Source/RecastMesh.cpp b/Recast/Source/RecastMesh.cpp index c885344..f806c3e 100644 --- a/Recast/Source/RecastMesh.cpp +++ b/Recast/Source/RecastMesh.cpp @@ -983,7 +983,7 @@ bool rcBuildPolyMesh(rcContext* ctx, rcContourSet& cset, const int nvp, rcPolyMe { rcAssert(ctx); - ctx->startTimer(RC_TIMER_BUILD_POLYMESH); + rcScopedTimer timer(ctx, RC_TIMER_BUILD_POLYMESH); rcVcopy(mesh.bmin, cset.bmin); rcVcopy(mesh.bmax, cset.bmax); @@ -1293,8 +1293,6 @@ bool rcBuildPolyMesh(rcContext* ctx, rcContourSet& cset, const int nvp, rcPolyMe ctx->log(RC_LOG_ERROR, "rcBuildPolyMesh: The resulting mesh has too many polygons %d (max %d). Data can be corrupted.", mesh.npolys, 0xffff); } - ctx->stopTimer(RC_TIMER_BUILD_POLYMESH); - return true; } @@ -1306,7 +1304,7 @@ bool rcMergePolyMeshes(rcContext* ctx, rcPolyMesh** meshes, const int nmeshes, r if (!nmeshes || !meshes) return true; - ctx->startTimer(RC_TIMER_MERGE_POLYMESH); + rcScopedTimer timer(ctx, RC_TIMER_MERGE_POLYMESH); mesh.nvp = meshes[0]->nvp; mesh.cs = meshes[0]->cs; @@ -1474,8 +1472,6 @@ bool rcMergePolyMeshes(rcContext* ctx, rcPolyMesh** meshes, const int nmeshes, r ctx->log(RC_LOG_ERROR, "rcMergePolyMeshes: The resulting mesh has too many polygons %d (max %d). Data can be corrupted.", mesh.npolys, 0xffff); } - ctx->stopTimer(RC_TIMER_MERGE_POLYMESH); - return true; } diff --git a/Recast/Source/RecastMeshDetail.cpp b/Recast/Source/RecastMeshDetail.cpp index 56b059d..3c6c45d 100644 --- a/Recast/Source/RecastMeshDetail.cpp +++ b/Recast/Source/RecastMeshDetail.cpp @@ -1120,7 +1120,7 @@ bool rcBuildPolyMeshDetail(rcContext* ctx, const rcPolyMesh& mesh, const rcCompa { rcAssert(ctx); - ctx->startTimer(RC_TIMER_BUILD_POLYMESHDETAIL); + rcScopedTimer timer(ctx, RC_TIMER_BUILD_POLYMESHDETAIL); if (mesh.nverts == 0 || mesh.npolys == 0) return true; @@ -1327,8 +1327,6 @@ bool rcBuildPolyMeshDetail(rcContext* ctx, const rcPolyMesh& mesh, const rcCompa } } - ctx->stopTimer(RC_TIMER_BUILD_POLYMESHDETAIL); - return true; } @@ -1337,7 +1335,7 @@ bool rcMergePolyMeshDetails(rcContext* ctx, rcPolyMeshDetail** meshes, const int { rcAssert(ctx); - ctx->startTimer(RC_TIMER_MERGE_POLYMESHDETAIL); + rcScopedTimer timer(ctx, RC_TIMER_MERGE_POLYMESHDETAIL); int maxVerts = 0; int maxTris = 0; @@ -1406,7 +1404,5 @@ bool rcMergePolyMeshDetails(rcContext* ctx, rcPolyMeshDetail** meshes, const int } } - ctx->stopTimer(RC_TIMER_MERGE_POLYMESHDETAIL); - return true; } diff --git a/Recast/Source/RecastRasterization.cpp b/Recast/Source/RecastRasterization.cpp index c3bda80..a6138ca 100644 --- a/Recast/Source/RecastRasterization.cpp +++ b/Recast/Source/RecastRasterization.cpp @@ -331,13 +331,11 @@ void rcRasterizeTriangle(rcContext* ctx, const float* v0, const float* v1, const { rcAssert(ctx); - ctx->startTimer(RC_TIMER_RASTERIZE_TRIANGLES); + rcScopedTimer timer(ctx, RC_TIMER_RASTERIZE_TRIANGLES); const float ics = 1.0f/solid.cs; const float ich = 1.0f/solid.ch; rasterizeTri(v0, v1, v2, area, solid, solid.bmin, solid.bmax, solid.cs, ics, ich, flagMergeThr); - - ctx->stopTimer(RC_TIMER_RASTERIZE_TRIANGLES); } /// @par @@ -351,7 +349,7 @@ void rcRasterizeTriangles(rcContext* ctx, const float* verts, const int /*nv*/, { rcAssert(ctx); - ctx->startTimer(RC_TIMER_RASTERIZE_TRIANGLES); + rcScopedTimer timer(ctx, RC_TIMER_RASTERIZE_TRIANGLES); const float ics = 1.0f/solid.cs; const float ich = 1.0f/solid.ch; @@ -364,8 +362,6 @@ void rcRasterizeTriangles(rcContext* ctx, const float* verts, const int /*nv*/, // Rasterize. rasterizeTri(v0, v1, v2, areas[i], solid, solid.bmin, solid.bmax, solid.cs, ics, ich, flagMergeThr); } - - ctx->stopTimer(RC_TIMER_RASTERIZE_TRIANGLES); } /// @par @@ -379,7 +375,7 @@ void rcRasterizeTriangles(rcContext* ctx, const float* verts, const int /*nv*/, { rcAssert(ctx); - ctx->startTimer(RC_TIMER_RASTERIZE_TRIANGLES); + rcScopedTimer timer(ctx, RC_TIMER_RASTERIZE_TRIANGLES); const float ics = 1.0f/solid.cs; const float ich = 1.0f/solid.ch; @@ -392,8 +388,6 @@ void rcRasterizeTriangles(rcContext* ctx, const float* verts, const int /*nv*/, // Rasterize. rasterizeTri(v0, v1, v2, areas[i], solid, solid.bmin, solid.bmax, solid.cs, ics, ich, flagMergeThr); } - - ctx->stopTimer(RC_TIMER_RASTERIZE_TRIANGLES); } /// @par @@ -406,7 +400,7 @@ void rcRasterizeTriangles(rcContext* ctx, const float* verts, const unsigned cha { rcAssert(ctx); - ctx->startTimer(RC_TIMER_RASTERIZE_TRIANGLES); + rcScopedTimer timer(ctx, RC_TIMER_RASTERIZE_TRIANGLES); const float ics = 1.0f/solid.cs; const float ich = 1.0f/solid.ch; @@ -419,6 +413,4 @@ void rcRasterizeTriangles(rcContext* ctx, const float* verts, const unsigned cha // Rasterize. rasterizeTri(v0, v1, v2, areas[i], solid, solid.bmin, solid.bmax, solid.cs, ics, ich, flagMergeThr); } - - ctx->stopTimer(RC_TIMER_RASTERIZE_TRIANGLES); } diff --git a/Recast/Source/RecastRegion.cpp b/Recast/Source/RecastRegion.cpp index 352ba57..90e0523 100644 --- a/Recast/Source/RecastRegion.cpp +++ b/Recast/Source/RecastRegion.cpp @@ -1257,7 +1257,7 @@ bool rcBuildDistanceField(rcContext* ctx, rcCompactHeightfield& chf) { rcAssert(ctx); - ctx->startTimer(RC_TIMER_BUILD_DISTANCEFIELD); + rcScopedTimer timer(ctx, RC_TIMER_BUILD_DISTANCEFIELD); if (chf.dist) { @@ -1281,25 +1281,23 @@ bool rcBuildDistanceField(rcContext* ctx, rcCompactHeightfield& chf) unsigned short maxDist = 0; - ctx->startTimer(RC_TIMER_BUILD_DISTANCEFIELD_DIST); - - calculateDistanceField(chf, src, maxDist); - chf.maxDistance = maxDist; - - ctx->stopTimer(RC_TIMER_BUILD_DISTANCEFIELD_DIST); - - ctx->startTimer(RC_TIMER_BUILD_DISTANCEFIELD_BLUR); - - // Blur - if (boxBlur(chf, 1, src, dst) != src) - rcSwap(src, dst); - - // Store distance. - chf.dist = src; - - ctx->stopTimer(RC_TIMER_BUILD_DISTANCEFIELD_BLUR); + { + rcScopedTimer timerDist(ctx, RC_TIMER_BUILD_DISTANCEFIELD_DIST); - ctx->stopTimer(RC_TIMER_BUILD_DISTANCEFIELD); + calculateDistanceField(chf, src, maxDist); + chf.maxDistance = maxDist; + } + + { + rcScopedTimer timerBlur(ctx, RC_TIMER_BUILD_DISTANCEFIELD_BLUR); + + // Blur + if (boxBlur(chf, 1, src, dst) != src) + rcSwap(src, dst); + + // Store distance. + chf.dist = src; + } rcFree(dst); @@ -1359,7 +1357,7 @@ bool rcBuildRegionsMonotone(rcContext* ctx, rcCompactHeightfield& chf, { rcAssert(ctx); - ctx->startTimer(RC_TIMER_BUILD_REGIONS); + rcScopedTimer timer(ctx, RC_TIMER_BUILD_REGIONS); const int w = chf.width; const int h = chf.height; @@ -1489,23 +1487,21 @@ bool rcBuildRegionsMonotone(rcContext* ctx, rcCompactHeightfield& chf, } - ctx->startTimer(RC_TIMER_BUILD_REGIONS_FILTER); + { + rcScopedTimer timerFilter(ctx, RC_TIMER_BUILD_REGIONS_FILTER); - // Merge regions and filter out small regions. - rcIntArray overlaps; - chf.maxRegions = id; - if (!mergeAndFilterRegions(ctx, minRegionArea, mergeRegionArea, chf.maxRegions, chf, srcReg, overlaps)) - return false; + // Merge regions and filter out small regions. + rcIntArray overlaps; + chf.maxRegions = id; + if (!mergeAndFilterRegions(ctx, minRegionArea, mergeRegionArea, chf.maxRegions, chf, srcReg, overlaps)) + return false; - // Monotone partitioning does not generate overlapping regions. - - ctx->stopTimer(RC_TIMER_BUILD_REGIONS_FILTER); + // Monotone partitioning does not generate overlapping regions. + } // Store the result out. for (int i = 0; i < chf.spanCount; ++i) chf.spans[i].reg = srcReg[i]; - - ctx->stopTimer(RC_TIMER_BUILD_REGIONS); return true; } @@ -1534,7 +1530,7 @@ bool rcBuildRegions(rcContext* ctx, rcCompactHeightfield& chf, { rcAssert(ctx); - ctx->startTimer(RC_TIMER_BUILD_REGIONS); + rcScopedTimer timer(ctx, RC_TIMER_BUILD_REGIONS); const int w = chf.width; const int h = chf.height; @@ -1603,33 +1599,33 @@ bool rcBuildRegions(rcContext* ctx, rcCompactHeightfield& chf, // ctx->stopTimer(RC_TIMER_DIVIDE_TO_LEVELS); - ctx->startTimer(RC_TIMER_BUILD_REGIONS_EXPAND); - - // Expand current regions until no empty connected cells found. - if (expandRegions(expandIters, level, chf, srcReg, srcDist, dstReg, dstDist, lvlStacks[sId], false) != srcReg) { - rcSwap(srcReg, dstReg); - rcSwap(srcDist, dstDist); - } - - ctx->stopTimer(RC_TIMER_BUILD_REGIONS_EXPAND); - - ctx->startTimer(RC_TIMER_BUILD_REGIONS_FLOOD); - - // Mark new regions with IDs. - for (int j=0; j= 0 && srcReg[i] == 0) + rcScopedTimer timerExpand(ctx, RC_TIMER_BUILD_REGIONS_EXPAND); + + // Expand current regions until no empty connected cells found. + if (expandRegions(expandIters, level, chf, srcReg, srcDist, dstReg, dstDist, lvlStacks[sId], false) != srcReg) { - if (floodRegion(x, y, i, level, regionId, chf, srcReg, srcDist, stack)) - regionId++; + rcSwap(srcReg, dstReg); + rcSwap(srcDist, dstDist); } } - ctx->stopTimer(RC_TIMER_BUILD_REGIONS_FLOOD); + { + rcScopedTimer timerFloor(ctx, RC_TIMER_BUILD_REGIONS_FLOOD); + + // Mark new regions with IDs. + for (int j = 0; j= 0 && srcReg[i] == 0) + { + if (floodRegion(x, y, i, level, regionId, chf, srcReg, srcDist, stack)) + regionId++; + } + } + } } // Expand current regions until no empty connected cells found. @@ -1641,28 +1637,26 @@ bool rcBuildRegions(rcContext* ctx, rcCompactHeightfield& chf, ctx->stopTimer(RC_TIMER_BUILD_REGIONS_WATERSHED); - ctx->startTimer(RC_TIMER_BUILD_REGIONS_FILTER); - - // Merge regions and filter out smalle regions. - rcIntArray overlaps; - chf.maxRegions = regionId; - if (!mergeAndFilterRegions(ctx, minRegionArea, mergeRegionArea, chf.maxRegions, chf, srcReg, overlaps)) - return false; - - // If overlapping regions were found during merging, split those regions. - if (overlaps.size() > 0) { - ctx->log(RC_LOG_ERROR, "rcBuildRegions: %d overlapping regions.", overlaps.size()); - } + rcScopedTimer timerFilter(ctx, RC_TIMER_BUILD_REGIONS_FILTER); - ctx->stopTimer(RC_TIMER_BUILD_REGIONS_FILTER); + // Merge regions and filter out smalle regions. + rcIntArray overlaps; + chf.maxRegions = regionId; + if (!mergeAndFilterRegions(ctx, minRegionArea, mergeRegionArea, chf.maxRegions, chf, srcReg, overlaps)) + return false; + + // If overlapping regions were found during merging, split those regions. + if (overlaps.size() > 0) + { + ctx->log(RC_LOG_ERROR, "rcBuildRegions: %d overlapping regions.", overlaps.size()); + } + } // Write the result out. for (int i = 0; i < chf.spanCount; ++i) chf.spans[i].reg = srcReg[i]; - ctx->stopTimer(RC_TIMER_BUILD_REGIONS); - return true; } @@ -1672,7 +1666,7 @@ bool rcBuildLayerRegions(rcContext* ctx, rcCompactHeightfield& chf, { rcAssert(ctx); - ctx->startTimer(RC_TIMER_BUILD_REGIONS); + rcScopedTimer timer(ctx, RC_TIMER_BUILD_REGIONS); const int w = chf.width; const int h = chf.height; @@ -1802,22 +1796,20 @@ bool rcBuildLayerRegions(rcContext* ctx, rcCompactHeightfield& chf, } - ctx->startTimer(RC_TIMER_BUILD_REGIONS_FILTER); - - // Merge monotone regions to layers and remove small regions. - rcIntArray overlaps; - chf.maxRegions = id; - if (!mergeAndFilterLayerRegions(ctx, minRegionArea, chf.maxRegions, chf, srcReg, overlaps)) - return false; - - ctx->stopTimer(RC_TIMER_BUILD_REGIONS_FILTER); + { + rcScopedTimer timerFilter(ctx, RC_TIMER_BUILD_REGIONS_FILTER); + + // Merge monotone regions to layers and remove small regions. + rcIntArray overlaps; + chf.maxRegions = id; + if (!mergeAndFilterLayerRegions(ctx, minRegionArea, chf.maxRegions, chf, srcReg, overlaps)) + return false; + } // Store the result out. for (int i = 0; i < chf.spanCount; ++i) chf.spans[i].reg = srcReg[i]; - ctx->stopTimer(RC_TIMER_BUILD_REGIONS); - return true; }