// // Copyright (c) 2009-2010 Mikko Mononen [email protected] // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages // arising from the use of this software. // Permission is granted to anyone to use this software for any purpose, // including commercial applications, and to alter it and redistribute it // freely, subject to the following restrictions: // 1. The origin of this software must not be misrepresented; you must not // claim that you wrote the original software. If you use this software // in a product, an acknowledgment in the product documentation would be // appreciated but is not required. // 2. Altered source versions must be plainly marked as such, and must not be // misrepresented as being the original software. // 3. This notice may not be removed or altered from any source distribution. // #include <float.h> #include <math.h> #include <string.h> #include <stdlib.h> #include <stdio.h> #include "Recast.h" #include "RecastAlloc.h" #include "RecastAssert.h" namespace { struct LevelStackEntry { … }; } // namespace static void calculateDistanceField(rcCompactHeightfield& chf, unsigned short* src, unsigned short& maxDist) { … } static unsigned short* boxBlur(rcCompactHeightfield& chf, int thr, unsigned short* src, unsigned short* dst) { … } static bool floodRegion(int x, int y, int i, unsigned short level, unsigned short r, rcCompactHeightfield& chf, unsigned short* srcReg, unsigned short* srcDist, rcTempVector<LevelStackEntry>& stack) { … } // Struct to keep track of entries in the region table that have been changed. struct DirtyEntry { … }; static void expandRegions(int maxIter, unsigned short level, rcCompactHeightfield& chf, unsigned short* srcReg, unsigned short* srcDist, rcTempVector<LevelStackEntry>& stack, bool fillStack) { … } static void sortCellsByLevel(unsigned short startLevel, rcCompactHeightfield& chf, const unsigned short* srcReg, unsigned int nbStacks, rcTempVector<LevelStackEntry>* stacks, unsigned short loglevelsPerStack) // the levels per stack (2 in our case) as a bit shift { … } static void appendStacks(const rcTempVector<LevelStackEntry>& srcStack, rcTempVector<LevelStackEntry>& dstStack, const unsigned short* srcReg) { … } struct rcRegion { … }; static void removeAdjacentNeighbours(rcRegion& reg) { … } static void replaceNeighbour(rcRegion& reg, unsigned short oldId, unsigned short newId) { … } static bool canMergeWithRegion(const rcRegion& rega, const rcRegion& regb) { … } static void addUniqueFloorRegion(rcRegion& reg, int n) { … } static bool mergeRegions(rcRegion& rega, rcRegion& regb) { … } static bool isRegionConnectedToBorder(const rcRegion& reg) { … } static bool isSolidEdge(rcCompactHeightfield& chf, const unsigned short* srcReg, int x, int y, int i, int dir) { … } static void walkContour(int x, int y, int i, int dir, rcCompactHeightfield& chf, const unsigned short* srcReg, rcIntArray& cont) { … } static bool mergeAndFilterRegions(rcContext* ctx, int minRegionArea, int mergeRegionSize, unsigned short& maxRegionId, rcCompactHeightfield& chf, unsigned short* srcReg, rcIntArray& overlaps) { … } static void addUniqueConnection(rcRegion& reg, int n) { … } static bool mergeAndFilterLayerRegions(rcContext* ctx, int minRegionArea, unsigned short& maxRegionId, rcCompactHeightfield& chf, unsigned short* srcReg) { … } /// @par /// /// This is usually the second to the last step in creating a fully built /// compact heightfield. This step is required before regions are built /// using #rcBuildRegions or #rcBuildRegionsMonotone. /// /// After this step, the distance data is available via the rcCompactHeightfield::maxDistance /// and rcCompactHeightfield::dist fields. /// /// @see rcCompactHeightfield, rcBuildRegions, rcBuildRegionsMonotone bool rcBuildDistanceField(rcContext* ctx, rcCompactHeightfield& chf) { … } static void paintRectRegion(int minx, int maxx, int miny, int maxy, unsigned short regId, rcCompactHeightfield& chf, unsigned short* srcReg) { … } static const unsigned short RC_NULL_NEI = …; struct rcSweepSpan { … }; /// @par /// /// Non-null regions will consist of connected, non-overlapping walkable spans that form a single contour. /// Contours will form simple polygons. /// /// If multiple regions form an area that is smaller than @p minRegionArea, then all spans will be /// re-assigned to the zero (null) region. /// /// Partitioning can result in smaller than necessary regions. @p mergeRegionArea helps /// reduce unecessarily small regions. /// /// See the #rcConfig documentation for more information on the configuration parameters. /// /// The region data will be available via the rcCompactHeightfield::maxRegions /// and rcCompactSpan::reg fields. /// /// @warning The distance field must be created using #rcBuildDistanceField before attempting to build regions. /// /// @see rcCompactHeightfield, rcCompactSpan, rcBuildDistanceField, rcBuildRegionsMonotone, rcConfig bool rcBuildRegionsMonotone(rcContext* ctx, rcCompactHeightfield& chf, const int borderSize, const int minRegionArea, const int mergeRegionArea) { … } /// @par /// /// Non-null regions will consist of connected, non-overlapping walkable spans that form a single contour. /// Contours will form simple polygons. /// /// If multiple regions form an area that is smaller than @p minRegionArea, then all spans will be /// re-assigned to the zero (null) region. /// /// Watershed partitioning can result in smaller than necessary regions, especially in diagonal corridors. /// @p mergeRegionArea helps reduce unecessarily small regions. /// /// See the #rcConfig documentation for more information on the configuration parameters. /// /// The region data will be available via the rcCompactHeightfield::maxRegions /// and rcCompactSpan::reg fields. /// /// @warning The distance field must be created using #rcBuildDistanceField before attempting to build regions. /// /// @see rcCompactHeightfield, rcCompactSpan, rcBuildDistanceField, rcBuildRegionsMonotone, rcConfig bool rcBuildRegions(rcContext* ctx, rcCompactHeightfield& chf, const int borderSize, const int minRegionArea, const int mergeRegionArea) { … } bool rcBuildLayerRegions(rcContext* ctx, rcCompactHeightfield& chf, const int borderSize, const int minRegionArea) { … }