Recast: Detail API documentation for the members declared in Recast.h. (Complete)

Recast.h: Completed rcPolyMeshDetail through end, plus updates to existing documentation.
Configuration: Removed DebugUtils directory from the document build.
Configuration: Fixed issue 179. (Backslashes)
This commit is contained in:
Stephen Pratt 2011-08-29 23:03:16 +00:00
parent 5553d19d59
commit 6f5c9f9b82
13 changed files with 898 additions and 337 deletions

View File

@ -2,9 +2,36 @@
// elements defined in the Recast.h. // elements defined in the Recast.h.
/** /**
@defgroup recast Recast
Members in this module are used to create mesh data that is then
used to create Detour navigation meshes.
The are a large number of possible ways to building navigation mesh data.
One of the simple piplines is as follows:
-# Prepare the input triangle mesh.
-# Build a #rcHeightfield.
-# Build a #rcCompactHeightfield.
-# Build a #rcContourSet.
-# Build a #rcPolyMesh.
-# Build a #rcPolyMeshDetail.
-# Use the rcPolyMesh and rcPolyMeshDetail to build a Detour navigation mesh
tile.
The general life-cycle of the main classes is as follows:
-# Allocate the object using the Recast allocator. (E.g. #rcAllocHeightfield)
-# Initialize or build the object. (E.g. #rcCreateHeightfield)
-# Update the object as needed. (E.g. #rcRasterizeTriangles)
-# Use the object as part of the pipeline.
-# Free the object using the Recast allocator. (E.g. #rcFreeHeightField)
@note This is a summary list of members. Use the index or search
feature to find minor members.
@struct rcConfig @struct rcConfig
@ingroup recast
@par @par
The is a convenience structure that represents an aggregation of parameters The is a convenience structure that represents an aggregation of parameters
@ -107,7 +134,6 @@ is limited to <= #DT_VERTS_PER_POLYGON.
@struct rcHeightfield @struct rcHeightfield
@ingroup recast
@par @par
The grid of a heightfield is layed out on the xz-plane based on the The grid of a heightfield is layed out on the xz-plane based on the
@ -180,7 +206,6 @@ Useful instances of this type can only by obtained from a #rcCompactHeightfield
@struct rcCompactHeightfield @struct rcCompactHeightfield
@ingroup recast
@par @par
For this type of heightfield, the spans represent the open (unobstructed) For this type of heightfield, the spans represent the open (unobstructed)
@ -267,7 +292,6 @@ for (int y = 0; y < chf.height; ++y)
@see rcAllocCompactHeightfield, rcFreeCompactHeightfield, rcBuildCompactHeightfield @see rcAllocCompactHeightfield, rcFreeCompactHeightfield, rcBuildCompactHeightfield
@struct rcContour @struct rcContour
@ingroup recast
@par @par
A contour only exists within the context of a #rcContourSet object. A contour only exists within the context of a #rcContourSet object.
@ -320,18 +344,16 @@ if (r & RC_AREA_BORDER)
See #verts for information on element layout. See #verts for information on element layout.
@struct rcContourSet @struct rcContourSet
@ingroup recast
@par @par
All contours within the set share the minimum bounds and cell sizes of the set. All contours within the set share the minimum bounds and cell sizes of the set.
The standard process for building a contour set is to allocate it The standard process for building a contour set is to allocate it
using #rcAllocContourSet, then initialize is using #rcBuildContours. using #rcAllocContourSet, then initialize it using #rcBuildContours.
@see rcAllocContourSet, rcFreeContourSet, rcBuildContours @see rcAllocContourSet, rcFreeContourSet, rcBuildContours
@struct rcPolyMesh @struct rcPolyMesh
@ingroup recast
@par @par
A mesh of potentially overlapping convex polygons of between three A mesh of potentially overlapping convex polygons of between three
@ -424,4 +446,142 @@ Edges 3->4 and 4->8 are border edges not shared with any other polygon.
The standard build process assigns the value of #RC_WALKABLE_AREA to all walkable polygons. The standard build process assigns the value of #RC_WALKABLE_AREA to all walkable polygons.
This value can then be changed to meet user requirements. This value can then be changed to meet user requirements.
@struct rcPolyMeshDetail
@par
The detail mesh is made up of triangle sub-meshes that provide extra
height detail for each polygon in its assoicated polygon mesh.
The standard process for building a detail mesh is to allocate it
using #rcAllocPolyMeshDetail, then build it using #rcBuildPolyMeshDetail.
See the individual field definitions for details realted to the structure
the mesh.
@see rcAllocPolyMeshDetail, rcFreePolyMeshDetail, rcBuildPolyMeshDetail, rcPolyMesh
@var rcPolyMeshDetail::meshes
@par
[(baseVertIndex, vertCount, baseTriIndex, triCount) * #nmeshes]
Maximum number of vertices per sub-mesh: 127<br/>
Maximum number of triangles per sub-mesh: 255
The sub-meshes are stored in the same order as the polygons from the
rcPolyMesh they represent. E.g. rcPolyMeshDetail sub-mesh 5 is associated
with #rcPolyMesh polygon 5.
Example of iterating the triangles in a sub-mesh.
@code
// Where dmesh is a reference to a rcPolyMeshDetail object.
// Iterate the sub-meshes. (One for each source polygon.)
for (int i = 0; i < dmesh.nmeshes; ++i)
{
const unsigned int* meshDef = &dmesh.meshes[i*4];
const unsigned int baseVerts = meshDef[0];
const unsigned int baseTri = meshDef[2];
const int ntris = (int)meshDef[3];
const float* verts = &dmesh.verts[baseVerts*3];
const unsigned char* tris = &dmesh.tris[baseTri*4];
// Iterate the sub-mesh's triangles.
for (int j = 0; j < ntris; ++j)
{
const float x = verts[tris[j*4+0]*3];
const float y = verts[tris[j*4+1]*3];
const float z = verts[tris[j*4+2]*3];
// Do something with the vertex.
}
}
@endcode
@var rcPolyMeshDetail::verts
@par
[(x, y, z) * #nverts]
The vertices are grouped by sub-mesh and will contain duplicates since
each sub-mesh is independently defined.
The first group of vertices for each sub-mesh are in the same order as
the vertices for the sub-mesh's associated PolyMesh polygon. These
vertices are followed by any additional detail vertices. So it the
associated polygon has 5 vertices, the sub-mesh will have a minimum
of 5 vertices and the first 5 vertices will be equivalent to the 5
polygon vertices.
@var rcPolyMeshDetail::tris
@par
[(vertIndexA, vertIndexB, vertIndexC, flags) * #ntris]
The triangles are grouped by sub-mesh.
<b>Vertex Indices</b>
The vertex indices in the triangle array are local to the sub-mesh, not global.
To translate into an global index in the vertices array, the values must be
offset by the sub-mesh's base vertex index.
Example: If the baseVertexIndex for the sub-mesh is 5 and the triangle entry
is (4, 8, 7, 0), then the actual indices for the vertices are (4 + 5, 8 + 5, 7 + 5).
@b Flags
The flags entry indicates which edges are internal and which are external to
the sub-mesh. Internal edges connect to other triangles within the same sub-mesh.
External edges represent portals to other sub-meshes or the null region.
Each flag is stored in a 2-bit position. Where position 0 is the lowest 2-bits
and position 4 is the highest 2-bits:
<tt>
Position 0: Edge AB (>> 0)<br/>
Position 1: Edge BC (>> 2)<br/>
Position 2: Edge CA (>> 4)<br/>
Position 4: Unused<br/>
</tt>
Testing can be performed as follows:
@code
if (((flags >> 2) & 0x3) != 0)
{
// Edge BC is an external edge.
}
@endcode
@fn void rcSetCon(rcCompactSpan &s, int dir, int i)
@par
This function is used by the build process. It is rarely of use to end users.
@see #rcCompactHeightfield, #rcCompactSpan
@fn int rcGetCon(const rcCompactSpan &s, int dir)
@par
Can be used to locate neighbor spans in a compact heightfield. See the
#rcCompactHeightfield documentation for details on its use.
@see #rcCompactHeightfield, #rcCompactSpan
@fn int rcGetDirOffsetX(int dir)
@par
The value of @p dir will be automatically wrapped. So a value of 6 will be interpreted as 2.
See the #rcCompactHeightfield documentation for usage details.
@fn int rcGetDirOffsetY(int dir)
@par
The value of @p dir will be automatically wrapped. So a value of 6 will be interpreted as 2.
See the #rcCompactHeightfield documentation for usage details.
*/ */

View File

@ -613,12 +613,11 @@ WARN_LOGFILE =
# with spaces. # with spaces.
INPUT = Detour \ INPUT = Detour \
DebugUtils \
DetourCrowd \ DetourCrowd \
DetourTileCache \ DetourTileCache \
Recast \ Recast \
Docs\Conceptual \ Docs/Conceptual \
Docs\Extern Docs/Extern
# This tag can be used to specify the character encoding of the source files # This tag can be used to specify the character encoding of the source files
# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is # that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is

File diff suppressed because it is too large Load Diff

View File

@ -39,7 +39,7 @@ typedef void* (rcAllocFunc)(int size, rcAllocHint hint);
// @param[in] ptr // @param[in] ptr
typedef void (rcFreeFunc)(void* ptr); typedef void (rcFreeFunc)(void* ptr);
/// Sets the custom allocation functions to be used by Recast. /// Sets the base custom allocation functions to be used by Recast.
/// @param[in] allocFunc The memory allocation function to be used by #rcAlloc /// @param[in] allocFunc The memory allocation function to be used by #rcAlloc
/// @param[in] freeFunc The memory de-allocation function to be used by #rcFree /// @param[in] freeFunc The memory de-allocation function to be used by #rcFree
void rcAllocSetCustom(rcAllocFunc *allocFunc, rcFreeFunc *freeFunc); void rcAllocSetCustom(rcAllocFunc *allocFunc, rcFreeFunc *freeFunc);

View File

@ -33,14 +33,13 @@ float rcSqrt(float x)
} }
/// @class rcContext /// @class rcContext
/// @ingroup recast
/// @par /// @par
/// ///
/// Logging and timer functionality must be provided by a concrete /// This class does not provide logging or timer functionality on its
/// implementation of this class. This class does not provide either on its /// own. Both must be provided by a concrete implementation
/// own. Also, this class does not provide an interface for extracting log /// by overriding the protected member functions. Also, this class does not
/// messages. (Only adding them.) So the concrete implementations must /// provide an interface for extracting log messages. (Only adding them.)
/// provide one. /// So concrete implementations must provide one.
/// ///
/// If no logging or timers are required, just pass an instance of this /// If no logging or timers are required, just pass an instance of this
/// class through the Recast build process. /// class through the Recast build process.
@ -185,7 +184,6 @@ void rcFreePolyMeshDetail(rcPolyMeshDetail* dmesh)
rcFree(dmesh); rcFree(dmesh);
} }
void rcCalcBounds(const float* verts, int nv, float* bmin, float* bmax) void rcCalcBounds(const float* verts, int nv, float* bmin, float* bmax)
{ {
// Calculate bounding box. // Calculate bounding box.
@ -205,6 +203,11 @@ void rcCalcGridSize(const float* bmin, const float* bmax, float cs, int* w, int*
*h = (int)((bmax[2] - bmin[2])/cs+0.5f); *h = (int)((bmax[2] - bmin[2])/cs+0.5f);
} }
/// @par
///
/// See the #rcConfig documentation for more information on the configuration parameters.
///
/// @see rcAllocHeightfield, rcHeightfield
bool rcCreateHeightfield(rcContext* /*ctx*/, rcHeightfield& hf, int width, int height, bool rcCreateHeightfield(rcContext* /*ctx*/, rcHeightfield& hf, int width, int height,
const float* bmin, const float* bmax, const float* bmin, const float* bmax,
float cs, float ch) float cs, float ch)
@ -234,6 +237,14 @@ static void calcTriNormal(const float* v0, const float* v1, const float* v2, flo
rcVnormalize(norm); rcVnormalize(norm);
} }
/// @par
///
/// Only sets the aread id's for the walkable triangles. Does not alter the
/// area id's for unwalkable triangles.
///
/// See the #rcConfig documentation for more information on the configuration parameters.
///
/// @see rcHeightfield, rcClearUnwalkableTriangles, rcRasterizeTriangles
void rcMarkWalkableTriangles(rcContext* /*ctx*/, const float walkableSlopeAngle, void rcMarkWalkableTriangles(rcContext* /*ctx*/, const float walkableSlopeAngle,
const float* verts, int /*nv*/, const float* verts, int /*nv*/,
const int* tris, int nt, const int* tris, int nt,
@ -256,6 +267,14 @@ void rcMarkWalkableTriangles(rcContext* /*ctx*/, const float walkableSlopeAngle,
} }
} }
/// @par
///
/// Only sets the aread id's for the unwalkable triangles. Does not alter the
/// area id's for walkable triangles.
///
/// See the #rcConfig documentation for more information on the configuration parameters.
///
/// @see rcHeightfield, rcClearUnwalkableTriangles, rcRasterizeTriangles
void rcClearUnwalkableTriangles(rcContext* /*ctx*/, const float walkableSlopeAngle, void rcClearUnwalkableTriangles(rcContext* /*ctx*/, const float walkableSlopeAngle,
const float* verts, int /*nv*/, const float* verts, int /*nv*/,
const int* tris, int nt, const int* tris, int nt,
@ -300,6 +319,15 @@ int rcGetHeightFieldSpanCount(rcContext* /*ctx*/, rcHeightfield& hf)
return spanCount; return spanCount;
} }
/// @par
///
/// This is just the beginning of the process of fully building a compact heightfield.
/// Various filters may be applied applied, then the distance field and regions built.
/// E.g: #rcBuildDistanceField and #rcBuildRegions
///
/// See the #rcConfig documentation for more information on the configuration parameters.
///
/// @see rcAllocCompactHeightfield, rcHeightfield, rcCompactHeightfield, rcConfig
bool rcBuildCompactHeightfield(rcContext* ctx, const int walkableHeight, const int walkableClimb, bool rcBuildCompactHeightfield(rcContext* ctx, const int walkableHeight, const int walkableClimb,
rcHeightfield& hf, rcCompactHeightfield& chf) rcHeightfield& hf, rcCompactHeightfield& chf)
{ {

View File

@ -26,7 +26,14 @@
#include "RecastAlloc.h" #include "RecastAlloc.h"
#include "RecastAssert.h" #include "RecastAssert.h"
/// @par
///
/// Basically, any spans that are closer to a boundary or obstruction than the specified radius
/// are marked as unwalkable.
///
/// This method is usually called immediately after the heightfield has been built.
///
/// @see rcCompactHeightfield, rcBuildCompactHeightfield, rcConfig::walkableRadius
bool rcErodeWalkableArea(rcContext* ctx, int radius, rcCompactHeightfield& chf) bool rcErodeWalkableArea(rcContext* ctx, int radius, rcCompactHeightfield& chf)
{ {
rcAssert(ctx); rcAssert(ctx);
@ -225,7 +232,12 @@ static void insertSort(unsigned char* a, const int n)
} }
} }
/// @par
///
/// This filter is usually applied after applying area id's using functions
/// such as #rcMarkBoxArea, #rcMarkConvexPolyArea, and #rcMarkCylinderArea.
///
/// @see rcCompactHeightfield
bool rcMedianFilterWalkableArea(rcContext* ctx, rcCompactHeightfield& chf) bool rcMedianFilterWalkableArea(rcContext* ctx, rcCompactHeightfield& chf)
{ {
rcAssert(ctx); rcAssert(ctx);
@ -300,6 +312,11 @@ bool rcMedianFilterWalkableArea(rcContext* ctx, rcCompactHeightfield& chf)
return true; return true;
} }
/// @par
///
/// The value of spacial parameters are in world units.
///
/// @see rcCompactHeightfield, rcMedianFilterWalkableArea
void rcMarkBoxArea(rcContext* ctx, const float* bmin, const float* bmax, unsigned char areaId, void rcMarkBoxArea(rcContext* ctx, const float* bmin, const float* bmax, unsigned char areaId,
rcCompactHeightfield& chf) rcCompactHeightfield& chf)
{ {
@ -360,6 +377,14 @@ static int pointInPoly(int nvert, const float* verts, const float* p)
return c; return c;
} }
/// @par
///
/// The value of spacial parameters are in world units.
///
/// The y-values of the polygon vertices are ignored. So the polygon is effectively
/// projected onto the xz-plane at @p hmin, then extruded to @p hmax.
///
/// @see rcCompactHeightfield, rcMedianFilterWalkableArea
void rcMarkConvexPolyArea(rcContext* ctx, const float* verts, const int nverts, void rcMarkConvexPolyArea(rcContext* ctx, const float* verts, const int nverts,
const float hmin, const float hmax, unsigned char areaId, const float hmin, const float hmax, unsigned char areaId,
rcCompactHeightfield& chf) rcCompactHeightfield& chf)
@ -427,6 +452,11 @@ void rcMarkConvexPolyArea(rcContext* ctx, const float* verts, const int nverts,
ctx->stopTimer(RC_TIMER_MARK_CONVEXPOLY_AREA); ctx->stopTimer(RC_TIMER_MARK_CONVEXPOLY_AREA);
} }
/// @par
///
/// The value of spacial parameters are in world units.
///
/// @see rcCompactHeightfield, rcMedianFilterWalkableArea
void rcMarkCylinderArea(rcContext* ctx, const float* pos, void rcMarkCylinderArea(rcContext* ctx, const float* pos,
const float r, const float h, unsigned char areaId, const float r, const float h, unsigned char areaId,
rcCompactHeightfield& chf) rcCompactHeightfield& chf)

View File

@ -592,6 +592,19 @@ static bool mergeContours(rcContour& ca, rcContour& cb, int ia, int ib)
return true; return true;
} }
/// @par
///
/// The raw contours will match the region outlines exactly. The @p maxError and @p maxEdgeLen
/// parameters control how closely the simplified contours will match the raw contours.
///
/// Simplified contours are generated such that the vertices for portals between areas match up.
/// (They are considered mandatory vertices.)
///
/// Setting @p maxEdgeLength to zero will disabled the edge length feature.
///
/// See the #rcConfig documentation for more information on the configuration parameters.
///
/// @see rcAllocContourSet, rcCompactHeightfield, rcContourSet, rcConfig
bool rcBuildContours(rcContext* ctx, rcCompactHeightfield& chf, bool rcBuildContours(rcContext* ctx, rcCompactHeightfield& chf,
const float maxError, const int maxEdgeLen, const float maxError, const int maxEdgeLen,
rcContourSet& cset, const int buildFlags) rcContourSet& cset, const int buildFlags)

View File

@ -22,7 +22,17 @@
#include "Recast.h" #include "Recast.h"
#include "RecastAssert.h" #include "RecastAssert.h"
/// @par
///
/// Allows the formation of walkable regions that will flow over low lying
/// objects such as curbs, and up structures such as stairways.
///
/// Two neighboring spans are walkable if: <tt>rcAbs(currentSpan.smax - neighborSpan.smax) < waklableClimb</tt>
///
/// @warning Will override the effect of #rcFilterLedgeSpans. So if both filters are used, call
/// #rcFilterLedgeSpans after calling this filter.
///
/// @see rcHeightfield, rcConfig
void rcFilterLowHangingWalkableObstacles(rcContext* ctx, const int walkableClimb, rcHeightfield& solid) void rcFilterLowHangingWalkableObstacles(rcContext* ctx, const int walkableClimb, rcHeightfield& solid)
{ {
rcAssert(ctx); rcAssert(ctx);
@ -60,7 +70,17 @@ void rcFilterLowHangingWalkableObstacles(rcContext* ctx, const int walkableClimb
ctx->stopTimer(RC_TIMER_FILTER_LOW_OBSTACLES); ctx->stopTimer(RC_TIMER_FILTER_LOW_OBSTACLES);
} }
/// @par
///
/// A ledge is a span with one or more neighbors whose maximum is further away than @p walkableClimb
/// from the current span's maximum.
/// This method removes the impact of the overestimation of conservative voxelization
/// so the resulting mesh will not have regions hanging in the air over ledges.
///
/// A span is a ledge if: <tt>rcAbs(currentSpan.smax - neighborSpan.smax) > walkableClimb</tt>
///
/// @see rcHeightfield, rcConfig
void rcFilterLedgeSpans(rcContext* ctx, const int walkableHeight, const int walkableClimb, void rcFilterLedgeSpans(rcContext* ctx, const int walkableHeight, const int walkableClimb,
rcHeightfield& solid) rcHeightfield& solid)
{ {
@ -151,6 +171,12 @@ void rcFilterLedgeSpans(rcContext* ctx, const int walkableHeight, const int walk
ctx->stopTimer(RC_TIMER_FILTER_BORDER); ctx->stopTimer(RC_TIMER_FILTER_BORDER);
} }
/// @par
///
/// For this filter, the clearance above the span is the distance from the span's
/// maximum to the next higher span's minimum. (Same grid column.)
///
/// @see rcHeightfield, rcConfig
void rcFilterWalkableLowHeightSpans(rcContext* ctx, int walkableHeight, rcHeightfield& solid) void rcFilterWalkableLowHeightSpans(rcContext* ctx, int walkableHeight, rcHeightfield& solid)
{ {
rcAssert(ctx); rcAssert(ctx);

View File

@ -76,7 +76,11 @@ struct rcLayerSweepSpan
unsigned char nei; // neighbour id unsigned char nei; // neighbour id
}; };
/// @par
///
/// See the #rcConfig documentation for more information on the configuration parameters.
///
/// @see rcAllocHeightfieldLayerSet, rcCompactHeightfield, rcHeightfieldLayerSet, rcConfig
bool rcBuildHeightfieldLayers(rcContext* ctx, rcCompactHeightfield& chf, bool rcBuildHeightfieldLayers(rcContext* ctx, rcCompactHeightfield& chf,
const int borderSize, const int walkableHeight, const int borderSize, const int walkableHeight,
rcHeightfieldLayerSet& lset) rcHeightfieldLayerSet& lset)

View File

@ -895,7 +895,12 @@ static bool removeVertex(rcContext* ctx, rcPolyMesh& mesh, const unsigned short
return true; return true;
} }
/// @par
///
/// @note If the mesh data is to be used to construct a Detour navigation mesh, then the upper
/// limit must be retricted to <= #DT_VERTS_PER_POLYGON.
///
/// @see rcAllocPolyMesh, rcContourSet, rcPolyMesh, rcConfig
bool rcBuildPolyMesh(rcContext* ctx, rcContourSet& cset, const int nvp, rcPolyMesh& mesh) bool rcBuildPolyMesh(rcContext* ctx, rcContourSet& cset, const int nvp, rcPolyMesh& mesh)
{ {
rcAssert(ctx); rcAssert(ctx);
@ -1212,6 +1217,7 @@ bool rcBuildPolyMesh(rcContext* ctx, rcContourSet& cset, const int nvp, rcPolyMe
return true; return true;
} }
/// @see rcAllocPolyMesh, rcPolyMesh
bool rcMergePolyMeshes(rcContext* ctx, rcPolyMesh** meshes, const int nmeshes, rcPolyMesh& mesh) bool rcMergePolyMeshes(rcContext* ctx, rcPolyMesh** meshes, const int nmeshes, rcPolyMesh& mesh)
{ {
rcAssert(ctx); rcAssert(ctx);

View File

@ -941,8 +941,11 @@ static unsigned char getTriFlags(const float* va, const float* vb, const float*
return flags; return flags;
} }
/// @par
///
/// See the #rcConfig documentation for more information on the configuration parameters.
///
/// @see rcAllocPolyMeshDetail, rcPolyMesh, rcCompactHeightfield, rcPolyMeshDetail, rcConfig
bool rcBuildPolyMeshDetail(rcContext* ctx, const rcPolyMesh& mesh, const rcCompactHeightfield& chf, bool rcBuildPolyMeshDetail(rcContext* ctx, const rcPolyMesh& mesh, const rcCompactHeightfield& chf,
const float sampleDist, const float sampleMaxError, const float sampleDist, const float sampleMaxError,
rcPolyMeshDetail& dmesh) rcPolyMeshDetail& dmesh)
@ -1161,6 +1164,7 @@ bool rcBuildPolyMeshDetail(rcContext* ctx, const rcPolyMesh& mesh, const rcCompa
return true; return true;
} }
/// @see rcAllocPolyMeshDetail, rcPolyMeshDetail
bool rcMergePolyMeshDetails(rcContext* ctx, rcPolyMeshDetail** meshes, const int nmeshes, rcPolyMeshDetail& mesh) bool rcMergePolyMeshDetails(rcContext* ctx, rcPolyMeshDetail** meshes, const int nmeshes, rcPolyMeshDetail& mesh)
{ {
rcAssert(ctx); rcAssert(ctx);

View File

@ -154,6 +154,13 @@ static void addSpan(rcHeightfield& hf, const int x, const int y,
} }
} }
/// @par
///
/// The span addition can be set to favor flags. If the span is merged to
/// another span and the new @p smax is within @p flagMergeThr units
/// from the existing span, the span flags are merged.
///
/// @see rcHeightfield, rcSpan.
void rcAddSpan(rcContext* /*ctx*/, rcHeightfield& hf, const int x, const int y, void rcAddSpan(rcContext* /*ctx*/, rcHeightfield& hf, const int x, const int y,
const unsigned short smin, const unsigned short smax, const unsigned short smin, const unsigned short smax,
const unsigned char area, const int flagMergeThr) const unsigned char area, const int flagMergeThr)
@ -276,6 +283,11 @@ static void rasterizeTri(const float* v0, const float* v1, const float* v2,
} }
} }
/// @par
///
/// No spans will be added if the triangle does not overlap the heightfield grid.
///
/// @see rcHeightfield
void rcRasterizeTriangle(rcContext* ctx, const float* v0, const float* v1, const float* v2, void rcRasterizeTriangle(rcContext* ctx, const float* v0, const float* v1, const float* v2,
const unsigned char area, rcHeightfield& solid, const unsigned char area, rcHeightfield& solid,
const int flagMergeThr) const int flagMergeThr)
@ -291,6 +303,11 @@ void rcRasterizeTriangle(rcContext* ctx, const float* v0, const float* v1, const
ctx->stopTimer(RC_TIMER_RASTERIZE_TRIANGLES); ctx->stopTimer(RC_TIMER_RASTERIZE_TRIANGLES);
} }
/// @par
///
/// Spans will only be added for triangles that overlap the heightfield grid.
///
/// @see rcHeightfield
void rcRasterizeTriangles(rcContext* ctx, const float* verts, const int /*nv*/, void rcRasterizeTriangles(rcContext* ctx, const float* verts, const int /*nv*/,
const int* tris, const unsigned char* areas, const int nt, const int* tris, const unsigned char* areas, const int nt,
rcHeightfield& solid, const int flagMergeThr) rcHeightfield& solid, const int flagMergeThr)
@ -314,6 +331,11 @@ void rcRasterizeTriangles(rcContext* ctx, const float* verts, const int /*nv*/,
ctx->stopTimer(RC_TIMER_RASTERIZE_TRIANGLES); ctx->stopTimer(RC_TIMER_RASTERIZE_TRIANGLES);
} }
/// @par
///
/// Spans will only be added for triangles that overlap the heightfield grid.
///
/// @see rcHeightfield
void rcRasterizeTriangles(rcContext* ctx, const float* verts, const int /*nv*/, void rcRasterizeTriangles(rcContext* ctx, const float* verts, const int /*nv*/,
const unsigned short* tris, const unsigned char* areas, const int nt, const unsigned short* tris, const unsigned char* areas, const int nt,
rcHeightfield& solid, const int flagMergeThr) rcHeightfield& solid, const int flagMergeThr)
@ -337,6 +359,11 @@ void rcRasterizeTriangles(rcContext* ctx, const float* verts, const int /*nv*/,
ctx->stopTimer(RC_TIMER_RASTERIZE_TRIANGLES); ctx->stopTimer(RC_TIMER_RASTERIZE_TRIANGLES);
} }
/// @par
///
/// Spans will only be added for triangles that overlap the heightfield grid.
///
/// @see rcHeightfield
void rcRasterizeTriangles(rcContext* ctx, const float* verts, const unsigned char* areas, const int nt, void rcRasterizeTriangles(rcContext* ctx, const float* verts, const unsigned char* areas, const int nt,
rcHeightfield& solid, const int flagMergeThr) rcHeightfield& solid, const int flagMergeThr)
{ {

View File

@ -936,7 +936,16 @@ static bool filterSmallRegions(rcContext* ctx, int minRegionArea, int mergeRegio
return true; return true;
} }
/// @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) bool rcBuildDistanceField(rcContext* ctx, rcCompactHeightfield& chf)
{ {
rcAssert(ctx); rcAssert(ctx);
@ -1019,6 +1028,25 @@ struct rcSweepSpan
unsigned short nei; // neighbour id unsigned short nei; // neighbour id
}; };
/// @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, bool rcBuildRegionsMonotone(rcContext* ctx, rcCompactHeightfield& chf,
const int borderSize, const int minRegionArea, const int mergeRegionArea) const int borderSize, const int minRegionArea, const int mergeRegionArea)
{ {
@ -1171,6 +1199,25 @@ bool rcBuildRegionsMonotone(rcContext* ctx, rcCompactHeightfield& chf,
return true; return true;
} }
/// @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, bool rcBuildRegions(rcContext* ctx, rcCompactHeightfield& chf,
const int borderSize, const int minRegionArea, const int mergeRegionArea) const int borderSize, const int minRegionArea, const int mergeRegionArea)
{ {