// // Copyright (c) 2009-2010 Mikko Mononen memon@inside.org // // 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. // #ifndef RECAST_H #define RECAST_H /** * @defgroup recast Recast * Elements related to path planning. * @note This list is not yet complete. (The documentation effort is still underway.) */ /// The value of PI used by Recast. static const float RC_PI = 3.14159265f; /// Recast log categories. /// @ingroup recast /// @see rcContext enum rcLogCategory { RC_LOG_PROGRESS = 1, ///< A progress log entry. RC_LOG_WARNING, ///< A warning log entry. RC_LOG_ERROR, ///< An error log entry. }; /// Recast performance timer categories. /// @ingroup recast /// @see rcContext enum rcTimerLabel { /// The user defined total time of the build. RC_TIMER_TOTAL, /// A user defined build time. RC_TIMER_TEMP, /// The time to rasterize the triangles. (See: #rcRasterizeTriangle) RC_TIMER_RASTERIZE_TRIANGLES, /// The time to build the compact heightfield. (See: #rcBuildCompactHeightfield) RC_TIMER_BUILD_COMPACTHEIGHTFIELD, /// The total time to build the contours. (See: #rcBuildContours) RC_TIMER_BUILD_CONTOURS, /// The time to trace the boundaries of the contours. (See: #rcBuildContours) RC_TIMER_BUILD_CONTOURS_TRACE, /// The time to simplify the contours. (See: #rcBuildContours) RC_TIMER_BUILD_CONTOURS_SIMPLIFY, /// The time to filter ledge spans. (See: #rcFilterLedgeSpans) RC_TIMER_FILTER_BORDER, /// The time to filter low height spans. (See: #rcFilterWalkableLowHeightSpans) RC_TIMER_FILTER_WALKABLE, /// The time to apply the median filter. (See: #rcMedianFilterWalkableArea) RC_TIMER_MEDIAN_AREA, /// The time to filter low obstacles. (See: #rcFilterLowHangingWalkableObstacles) RC_TIMER_FILTER_LOW_OBSTACLES, /// The time to build the polygon mesh. (See: #rcBuildPolyMesh) RC_TIMER_BUILD_POLYMESH, /// The time to merge polygon meshes. (See: #rcMergePolyMeshes) RC_TIMER_MERGE_POLYMESH, /// The time to erode the walkable area. (See: #rcErodeWalkableArea) RC_TIMER_ERODE_AREA, /// The time to mark a box area. (See: #rcMarkBoxArea) RC_TIMER_MARK_BOX_AREA, /// The time to mark a cylinder area. (See: #rcMarkCylinderArea) RC_TIMER_MARK_CYLINDER_AREA, /// The time to mark a convex polygon area. (See: #rcMarkConvexPolyArea) RC_TIMER_MARK_CONVEXPOLY_AREA, /// The total time to build the distance field. (See: #rcBuildDistanceField) RC_TIMER_BUILD_DISTANCEFIELD, /// The time to build the distances of the distance field. (See: #rcBuildDistanceField) RC_TIMER_BUILD_DISTANCEFIELD_DIST, /// The time to blur the distance field. (See: #rcBuildDistanceField) RC_TIMER_BUILD_DISTANCEFIELD_BLUR, /// The total time to build the regions. (See: #rcBuildRegions, #rcBuildRegionsMonotone) RC_TIMER_BUILD_REGIONS, /// The total time to apply the watershed algorithm. (See: #rcBuildRegions) RC_TIMER_BUILD_REGIONS_WATERSHED, /// The time to expand regions while applying the watershed algorithm. (See: #rcBuildRegions) RC_TIMER_BUILD_REGIONS_EXPAND, /// The time to flood regions while applying the watershed algorithm. (See: #rcBuildRegions) RC_TIMER_BUILD_REGIONS_FLOOD, /// The time to filter out small regions. (See: #rcBuildRegions, #rcBuildRegionsMonotone) RC_TIMER_BUILD_REGIONS_FILTER, /// The time to build heightfield layers. (See: #rcBuildHeightfieldLayers) RC_TIMER_BUILD_LAYERS, /// The time to build the polygon mesh detail. (See: #rcBuildPolyMeshDetail) RC_TIMER_BUILD_POLYMESHDETAIL, /// The time to merge polygon mesh details. (See: #rcMergePolyMeshDetails) RC_TIMER_MERGE_POLYMESHDETAIL, /// The maximum number of timers. (Used for iterating timers.) RC_MAX_TIMERS }; /// Provides an interface for optional logging and performance tracking of the Recast /// build process. class rcContext { public: /// Contructor. /// @param[in] state TRUE if the logging and performance timers should be enabled. [Default: true] inline rcContext(bool state = true) : m_logEnabled(state), m_timerEnabled(state) {} virtual ~rcContext() {} /// Enables or disables logging. /// @param[in] state TRUE if logging should be enabled. inline void enableLog(bool state) { m_logEnabled = state; } /// Clears all log entries. inline void resetLog() { if (m_logEnabled) doResetLog(); } /// Logs a message. /// @param[in] category The category of the message. /// @param[in] format The message. void log(const rcLogCategory category, const char* format, ...); /// Enables or disables the performance timers. /// @param[in] state TRUE if timers should be enabled. inline void enableTimer(bool state) { m_timerEnabled = state; } /// Clears all peformance timers. (Resets all to unused.) inline void resetTimers() { if (m_timerEnabled) doResetTimers(); } /// Starts the specified performance timer. /// @param label The category of timer. inline void startTimer(const rcTimerLabel label) { if (m_timerEnabled) doStartTimer(label); } /// Stops the specified performance timer. /// @param label The category of the timer. inline void stopTimer(const rcTimerLabel label) { if (m_timerEnabled) doStopTimer(label); } /// Returns the total accumulated time of the specified performance timer. /// @param label The category of the timer. /// @return The accumulated time of the timer, or -1 if timers are disabled or the timer has never been started. inline int getAccumulatedTime(const rcTimerLabel label) const { return m_timerEnabled ? doGetAccumulatedTime(label) : -1; } protected: /// @name Custom implementation functions. /// Logging and timer functionality must be provided by a concrete /// implementation of these functions. This class does not implement these functions. ///@{ /// Clears all log entries. virtual void doResetLog() {} /// Logs a message. /// @param[in] category The category of the message. /// @param[in] msg The formatted message. /// @param[in] len The length of the formatted message. virtual void doLog(const rcLogCategory /*category*/, const char* /*msg*/, const int /*len*/) {} /// Clears all timers. (Resets all to unused.) virtual void doResetTimers() {} /// Starts the specified performance timer. /// @param[in] label The category of timer. virtual void doStartTimer(const rcTimerLabel /*label*/) {} /// Stops the specified performance timer. /// @param[in] label The category of the timer. virtual void doStopTimer(const rcTimerLabel /*label*/) {} /// Returns the total accumulated time of the specified performance timer. /// @param[in] label The category of the timer. /// @return The accumulated time of the timer, or -1 if timers are disabled or the timer has never been started. virtual int doGetAccumulatedTime(const rcTimerLabel /*label*/) const { return -1; } ///@} /// True if logging is enabled. bool m_logEnabled; /// True if the performance timers are enabled. bool m_timerEnabled; }; /// Specifies a configuration to use when performing Recast builds. struct rcConfig { /// The width of the field along the x-axis. [Limit: >= 0] [Units: vx] int width; /// The height of the field along the z-axis. [Limit: >= 0] [Units: vx] int height; /// The width/height size of tile's on the xz-plane. [Limit: >= 0] [Units: vx] int tileSize; /// The size of the non-navigable border around the heightfield. [Limit: >=0] [Units: vx] int borderSize; /// The xz-plane cell size to use for fields. [Limit: > 0] [Units: wu] float cs; /// The y-axis cell size to use for fields. [Limit: > 0] [Units: wu] float ch; /// The minimum bounds of the field's AABB. [(x, y, z)] [Units: wu] float bmin[3]; /// The maximum bounds of the field's AABB. [(x, y, z)] [Units: wu] float bmax[3]; /// The maximum slope that is considered walkable. [Limits: 0 <= value < 90] [Units: Degrees] float walkableSlopeAngle; /// Minimum floor to 'ceiling' height that will still allow the floor area to /// be considered walkable. [Limit: >= 3] [Units: vx] int walkableHeight; /// Maximum ledge height that is considered to still be traversable. [Limit: >=0] [Units: vx] int walkableClimb; /// The distance to erode/shrink the walkable area of the heightfield away from /// obstructions. [Limit: >=0] [Units: vx] int walkableRadius; /// The maximum allowed length for contour edges along the border of the mesh. [Limit: >=0] [Units: vx] int maxEdgeLen; /// The maximum distance a simplfied contour's border edges should deviate /// the original raw contour. [Limit: >=0] [Units: wu] float maxSimplificationError; /// The minimum number of cells allowed to form isolated island regions. [Limit: >=0] [Units: vx] int minRegionArea; /// Any regions with a cell count smaller than this value will, if possible, /// be merged with larger regions. [Limit: >=0] [Units: vx] int mergeRegionArea; /// The maximum number of vertices allowed for polygons generated during the /// contour to polygon conversion process. [Limit: >= 3] int maxVertsPerPoly; /// Sets the sampling distance to use when generating the detail mesh. /// (For height detail only.) [Limits: 0 or >= 0.9] [Units: wu] float detailSampleDist; /// The maximum distance the detail mesh surface should deviate from heightfield /// data. (For height detail only.) [Limit: >=0] [Units: wu] float detailSampleMaxError; }; /// Defines number of bits in rcSpan::smin and rcSpan::smax. static const int RC_SPAN_HEIGHT_BITS = 13; /// Defines the maximum value for rcSpan::smin and rcSpan::smax. static const int RC_SPAN_MAX_HEIGHT = (1<> shift) & 0x3f; } inline int rcGetDirOffsetX(int dir) { const int offset[4] = { -1, 0, 1, 0, }; return offset[dir&0x03]; } inline int rcGetDirOffsetY(int dir) { const int offset[4] = { 0, 1, 0, -1 }; return offset[dir&0x03]; } /// @name Common helper functions ///@{ template inline void rcSwap(T& a, T& b) { T t = a; a = b; b = t; } template inline T rcMin(T a, T b) { return a < b ? a : b; } template inline T rcMax(T a, T b) { return a > b ? a : b; } template inline T rcAbs(T a) { return a < 0 ? -a : a; } template inline T rcSqr(T a) { return a*a; } template inline T rcClamp(T v, T mn, T mx) { return v < mn ? mn : (v > mx ? mx : v); } float rcSqrt(float x); inline int rcAlign4(int x) { return (x+3) & ~3; } ///@} /// @name Common vector helper functions. ///@{ inline void rcVcross(float* dest, const float* v1, const float* v2) { dest[0] = v1[1]*v2[2] - v1[2]*v2[1]; dest[1] = v1[2]*v2[0] - v1[0]*v2[2]; dest[2] = v1[0]*v2[1] - v1[1]*v2[0]; } inline float rcVdot(const float* v1, const float* v2) { return v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2]; } inline void rcVmad(float* dest, const float* v1, const float* v2, const float s) { dest[0] = v1[0]+v2[0]*s; dest[1] = v1[1]+v2[1]*s; dest[2] = v1[2]+v2[2]*s; } inline void rcVadd(float* dest, const float* v1, const float* v2) { dest[0] = v1[0]+v2[0]; dest[1] = v1[1]+v2[1]; dest[2] = v1[2]+v2[2]; } inline void rcVsub(float* dest, const float* v1, const float* v2) { dest[0] = v1[0]-v2[0]; dest[1] = v1[1]-v2[1]; dest[2] = v1[2]-v2[2]; } inline void rcVmin(float* mn, const float* v) { mn[0] = rcMin(mn[0], v[0]); mn[1] = rcMin(mn[1], v[1]); mn[2] = rcMin(mn[2], v[2]); } inline void rcVmax(float* mx, const float* v) { mx[0] = rcMax(mx[0], v[0]); mx[1] = rcMax(mx[1], v[1]); mx[2] = rcMax(mx[2], v[2]); } inline void rcVcopy(float* dest, const float* v) { dest[0] = v[0]; dest[1] = v[1]; dest[2] = v[2]; } inline float rcVdist(const float* v1, const float* v2) { float dx = v2[0] - v1[0]; float dy = v2[1] - v1[1]; float dz = v2[2] - v1[2]; return rcSqrt(dx*dx + dy*dy + dz*dz); } inline float rcVdistSqr(const float* v1, const float* v2) { float dx = v2[0] - v1[0]; float dy = v2[1] - v1[1]; float dz = v2[2] - v1[2]; return dx*dx + dy*dy + dz*dz; } inline void rcVnormalize(float* v) { float d = 1.0f / rcSqrt(rcSqr(v[0]) + rcSqr(v[1]) + rcSqr(v[2])); v[0] *= d; v[1] *= d; v[2] *= d; } inline bool rcVequal(const float* p0, const float* p1) { static const float thr = rcSqr(1.0f/16384.0f); const float d = rcVdistSqr(p0, p1); return d < thr; } ///@} /// Calculated bounding box of array of vertices. /// @param verts [in] array of vertices /// @param nv [in] vertex count /// @param bmin,bmax [out] bounding box void rcCalcBounds(const float* verts, int nv, float* bmin, float* bmax); /// Calculates grid size based on bounding box and grid cell size. /// @param bmin,bmax [in] bounding box /// @param cs [in] grid cell size /// @param w [out] grid width /// @param h [out] grid height void rcCalcGridSize(const float* bmin, const float* bmax, float cs, int* w, int* h); /// Creates and initializes new heightfield. /// @param hf [in,out] heightfield to initialize. /// @param width [in] width of the heightfield. /// @param height [in] height of the heightfield. /// @param bmin,bmax [in] bounding box of the heightfield /// @param cs [in] grid cell size /// @param ch [in] grid cell height bool rcCreateHeightfield(rcContext* ctx, rcHeightfield& hf, int width, int height, const float* bmin, const float* bmax, float cs, float ch); /// Sets the RC_WALKABLE_AREA for every triangle whose slope is below /// the maximum walkable slope angle. /// @param walkableSlopeAngle [in] maximum slope angle in degrees. /// @param verts [in] array of vertices /// @param nv [in] vertex count /// @param tris [in] array of triangle vertex indices /// @param nt [in] triangle count /// @param areas [out] array of triangle area types void rcMarkWalkableTriangles(rcContext* ctx, const float walkableSlopeAngle, const float* verts, int nv, const int* tris, int nt, unsigned char* areas); /// Sets the RC_NULL_AREA for every triangle whose slope is steeper than /// the maximum walkable slope angle. /// @param walkableSlopeAngle [in] maximum slope angle in degrees. /// @param verts [in] array of vertices /// @param nv [in] vertex count /// @param tris [in] array of triangle vertex indices /// @param nt [in] triangle count /// @param areas [out] array of triangle are types void rcClearUnwalkableTriangles(rcContext* ctx, const float walkableSlopeAngle, const float* verts, int nv, const int* tris, int nt, unsigned char* areas); /// Adds span to heightfield. /// The span addition can set to favor flags. If the span is merged to /// another span and the new smax is within 'flagMergeThr' units away /// from the existing span the span flags are merged and stored. /// @param x,y [in] location on the heightfield where the span is added /// @param smin,smax [in] spans min/max height /// @param area /// @param flagMergeThr [in] merge threshold. void rcAddSpan(rcContext* ctx, rcHeightfield& hf, const int x, const int y, const unsigned short smin, const unsigned short smax, const unsigned char area, const int flagMergeThr); /// Rasterizes a triangle into heightfield spans. /// @param v0,v1,v2 [in] the vertices of the triangle. /// @param area [in] area type of the triangle. /// @param solid [in] heightfield where the triangle is rasterized /// @param flagMergeThr [in] distance in voxel where walkable flag is favored over non-walkable. void rcRasterizeTriangle(rcContext* ctx, const float* v0, const float* v1, const float* v2, const unsigned char area, rcHeightfield& solid, const int flagMergeThr = 1); /// Rasterizes indexed triangle mesh into heightfield spans. /// @param verts [in] array of vertices /// @param nv [in] vertex count /// @param tris [in] array of triangle vertex indices /// @param areas [in] array of triangle area types. /// @param nt [in] triangle count /// @param solid [in] heightfield where the triangles are rasterized /// @param flagMergeThr [in] distance in voxel where walkable flag is favored over non-walkable. void rcRasterizeTriangles(rcContext* ctx, const float* verts, const int nv, const int* tris, const unsigned char* areas, const int nt, rcHeightfield& solid, const int flagMergeThr = 1); /// Rasterizes indexed triangle mesh into heightfield spans. /// @param verts [in] array of vertices /// @param nv [in] vertex count /// @param tris [in] array of triangle vertex indices /// @param areas [in] array of triangle area types. /// @param nt [in] triangle count /// @param solid [in] heightfield where the triangles are rasterized /// @param flagMergeThr [in] distance in voxel where walkable flag is favored over non-walkable. void rcRasterizeTriangles(rcContext* ctx, const float* verts, const int nv, const unsigned short* tris, const unsigned char* areas, const int nt, rcHeightfield& solid, const int flagMergeThr = 1); /// Rasterizes the triangles into heightfield spans. /// @param verts [in] array of vertices /// @param areas [in] array of triangle area types. /// @param nt [in] triangle count /// @param solid [in] heightfield where the triangles are rasterized void rcRasterizeTriangles(rcContext* ctx, const float* verts, const unsigned char* areas, const int nt, rcHeightfield& solid, const int flagMergeThr = 1); /// Marks non-walkable low obstacles as walkable if they are closer than walkableClimb /// from a walkable surface. Applying this filter allows to step over low hanging /// low obstacles. /// @param walkableClimb [in] maximum height between grid cells the agent can climb /// @param solid [in,out] heightfield describing the solid space /// @warning TODO: Misses ledge flag, must be called before rcFilterLedgeSpans! void rcFilterLowHangingWalkableObstacles(rcContext* ctx, const int walkableClimb, rcHeightfield& solid); /// Removes WALKABLE flag from all spans that are at ledges. This filtering /// removes possible overestimation of the conservative voxelization so that /// the resulting mesh will not have regions hanging in air over ledges. /// @param walkableHeight [in] minimum height where the agent can still walk /// @param walkableClimb [in] maximum height between grid cells the agent can climb /// @param solid [in,out] heightfield describing the solid space void rcFilterLedgeSpans(rcContext* ctx, const int walkableHeight, const int walkableClimb, rcHeightfield& solid); /// Removes WALKABLE flag from all spans which have smaller than /// 'walkableHeight' clearance above them. /// @param walkableHeight [in] minimum height where the agent can still walk /// @param solid [in,out] heightfield describing the solid space void rcFilterWalkableLowHeightSpans(rcContext* ctx, int walkableHeight, rcHeightfield& solid); /// Returns number of spans contained in a heightfield. /// @param hf [in] heightfield to be compacted /// @returns number of spans. int rcGetHeightFieldSpanCount(rcContext* ctx, rcHeightfield& hf); /// Builds compact representation of the heightfield. /// @param walkableHeight [in] minimum height where the agent can still walk /// @param walkableClimb [in] maximum height between grid cells the agent can climb /// @param hf [in] heightfield to be compacted /// @param chf [out] compact heightfield representing the open space. /// @returns false if operation ran out of memory. bool rcBuildCompactHeightfield(rcContext* ctx, const int walkableHeight, const int walkableClimb, rcHeightfield& hf, rcCompactHeightfield& chf); /// Erodes walkable area. /// @param radius [in] radius of erosion (max 255). /// @param chf [in,out] compact heightfield to erode. /// @returns false if operation ran out of memory. bool rcErodeWalkableArea(rcContext* ctx, int radius, rcCompactHeightfield& chf); /// Applies median filter to walkable area types, removing noise. /// @param chf [in,out] compact heightfield to erode. /// @returns false if operation ran out of memory. bool rcMedianFilterWalkableArea(rcContext* ctx, rcCompactHeightfield& chf); /// Marks the area of the convex polygon into the area type of the compact heightfield. /// @param bmin,bmax [in] bounds of the axis aligned box. /// @param areaId [in] area ID to mark. /// @param chf [in,out] compact heightfield to mark. void rcMarkBoxArea(rcContext* ctx, const float* bmin, const float* bmax, unsigned char areaId, rcCompactHeightfield& chf); /// Marks the area of the convex polygon into the area type of the compact heightfield. /// @param verts [in] vertices of the convex polygon. /// @param nverts [in] number of vertices in the polygon. /// @param hmin,hmax [in] min and max height of the polygon. /// @param areaId [in] area ID to mark. /// @param chf [in,out] compact heightfield to mark. void rcMarkConvexPolyArea(rcContext* ctx, const float* verts, const int nverts, const float hmin, const float hmax, unsigned char areaId, rcCompactHeightfield& chf); /// Marks the area of the cylinder into the area type of the compact heightfield. /// @param pos [in] center bottom location of hte cylinder. /// @param r [in] radius of the cylinder. /// @param h [in] height of the cylinder. /// @param areaId [in] area ID to mark. /// @param chf [in,out] compact heightfield to mark. void rcMarkCylinderArea(rcContext* ctx, const float* pos, const float r, const float h, unsigned char areaId, rcCompactHeightfield& chf); /// Builds distance field and stores it into the combat heightfield. /// @param chf [in,out] compact heightfield representing the open space. /// @returns false if operation ran out of memory. bool rcBuildDistanceField(rcContext* ctx, rcCompactHeightfield& chf); /// Divides the walkable heighfied into simple regions using watershed partitioning. /// Each region has only one contour and no overlaps. /// The regions are stored in the compact heightfield 'reg' field. /// The process sometimes creates small regions. If the area of a regions is /// smaller than 'mergeRegionArea' then the region will be merged with a neighbour /// region if possible. If multiple regions form an area which is smaller than /// 'minRegionArea' all the regions belonging to that area will be removed. /// Here area means the count of spans in an area. /// @param chf [in,out] compact heightfield representing the open space. /// @param borderSize [in] Non-navigable Border around the heightfield. /// @param minRegionArea [in] the smallest allowed region area. /// @param maxMergeRegionArea [in] the largest allowed region area which can be merged. /// @returns false if operation ran out of memory. bool rcBuildRegions(rcContext* ctx, rcCompactHeightfield& chf, const int borderSize, const int minRegionArea, const int mergeRegionArea); /// Divides the walkable heighfied into simple regions using simple monotone partitioning. /// Each region has only one contour and no overlaps. /// The regions are stored in the compact heightfield 'reg' field. /// The process sometimes creates small regions. If the area of a regions is /// smaller than 'mergeRegionArea' then the region will be merged with a neighbour /// region if possible. If multiple regions form an area which is smaller than /// 'minRegionArea' all the regions belonging to that area will be removed. /// Here area means the count of spans in an area. /// @param chf [in,out] compact heightfield representing the open space. /// @param borderSize [in] Non-navigable Border around the heightfield. /// @param minRegionArea [in] the smallest allowed regions size. /// @param maxMergeRegionArea [in] the largest allowed regions size which can be merged. /// @returns false if operation ran out of memory. bool rcBuildRegionsMonotone(rcContext* ctx, rcCompactHeightfield& chf, const int borderSize, const int minRegionArea, const int mergeRegionArea); /// Builds 2D layer representation of a heighfield. /// @param chf [in] compact heightfield representing the open space. /// @param borderSize [in] Non-navigable Border around the heightfield. /// @param walkableHeight [in] minimum height where the agent can still walk. /// @param lset [out] set of 2D heighfield layers. /// @returns false if operation ran out of memory. bool rcBuildHeightfieldLayers(rcContext* ctx, rcCompactHeightfield& chf, const int borderSize, const int walkableHeight, rcHeightfieldLayerSet& lset); /// Builds simplified contours from the regions outlines. /// @param chf [in] compact heightfield which has regions set. /// @param maxError [in] maximum allowed distance between simplified contour and cells. /// @param maxEdgeLen [in] maximum allowed contour edge length in cells. /// @param cset [out] Resulting contour set. /// @param flags [in] build flags, see rcBuildContoursFlags. /// @returns false if operation ran out of memory. bool rcBuildContours(rcContext* ctx, rcCompactHeightfield& chf, const float maxError, const int maxEdgeLen, rcContourSet& cset, const int flags = RC_CONTOUR_TESS_WALL_EDGES); /// Builds connected convex polygon mesh from contour polygons. /// @param cset [in] contour set. /// @param nvp [in] maximum number of vertices per polygon. /// @param mesh [out] poly mesh. /// @returns false if operation ran out of memory. bool rcBuildPolyMesh(rcContext* ctx, rcContourSet& cset, const int nvp, rcPolyMesh& mesh); bool rcMergePolyMeshes(rcContext* ctx, rcPolyMesh** meshes, const int nmeshes, rcPolyMesh& mesh); /// Builds detail triangle mesh for each polygon in the poly mesh. /// @param mesh [in] poly mesh to detail. /// @param chf [in] compact height field, used to query height for new vertices. /// @param sampleDist [in] spacing between height samples used to generate more detail into mesh. /// @param sampleMaxError [in] maximum allowed distance between simplified detail mesh and height sample. /// @param dmesh [out] detail mesh. /// @returns false if operation ran out of memory. bool rcBuildPolyMeshDetail(rcContext* ctx, const rcPolyMesh& mesh, const rcCompactHeightfield& chf, const float sampleDist, const float sampleMaxError, rcPolyMeshDetail& dmesh); bool rcMergePolyMeshDetails(rcContext* ctx, rcPolyMeshDetail** meshes, const int nmeshes, rcPolyMeshDetail& mesh); #endif // RECAST_H /////////////////////////////////////////////////////////////////////////// // Due to the large amount of detail documentation for this file, // the content normally located at the end of the header file has been separated // out to a file in the /Docs/Extern directory.