Detour: Detail API documentation covering the DetourCommon.h and DetourNavMeshQuery.h files

This commit is contained in:
Stephen Pratt 2011-08-15 17:01:16 +00:00
parent 11fe155861
commit c150272f99
5 changed files with 1085 additions and 373 deletions

View File

@ -19,6 +19,12 @@
#ifndef DETOURCOMMON_H #ifndef DETOURCOMMON_H
#define DETOURCOMMON_H #define DETOURCOMMON_H
/**
* @defgroup detour Detour
* Classes and functions related to path planning.
* @note This is a summary list. Use the index or documentation search
* functionality to find minor elements.
*/
template<class T> inline void dtSwap(T& a, T& b) { T t = a; a = b; b = t; } template<class T> inline void dtSwap(T& a, T& b) { T t = a; a = b; b = t; }
template<class T> inline T dtMin(T a, T b) { return a < b ? a : b; } template<class T> inline T dtMin(T a, T b) { return a < b ? a : b; }

View File

@ -26,283 +26,453 @@
// Note: If you want to use 64-bit refs, change the types of both dtPolyRef & dtTileRef. // Note: If you want to use 64-bit refs, change the types of both dtPolyRef & dtTileRef.
// It is also recommended to change dtHashRef() to proper 64-bit hash too. // It is also recommended to change dtHashRef() to proper 64-bit hash too.
/// Reference to navigation polygon. /// A handle to a polygon within a navigation mesh tile.
/// @ingroup detour
typedef unsigned int dtPolyRef; typedef unsigned int dtPolyRef;
/// Reference to navigation mesh tile. /// A handle to a tile within a navigation mesh.
/// @ingroup detour
typedef unsigned int dtTileRef; typedef unsigned int dtTileRef;
/// Maximum number of vertices per navigation polygon. /// The maximum number of vertices per navigation polygon.
/// @ingroup detour
static const int DT_VERTS_PER_POLYGON = 6; static const int DT_VERTS_PER_POLYGON = 6;
static const int DT_NAVMESH_MAGIC = 'D'<<24 | 'N'<<16 | 'A'<<8 | 'V'; ///< 'DNAV' /// @{
/// @name Tile Serialization Constants
/// These constants are used to detect whether a navigation tile's data
/// and state format is compatible with the current build.
///
/// A magic number used to detect compatibility of navigation tile data.
static const int DT_NAVMESH_MAGIC = 'D'<<24 | 'N'<<16 | 'A'<<8 | 'V';
/// A version number used to detect compatibility of navigation tile data.
static const int DT_NAVMESH_VERSION = 7; static const int DT_NAVMESH_VERSION = 7;
static const int DT_NAVMESH_STATE_MAGIC = 'D'<<24 | 'N'<<16 | 'M'<<8 | 'S'; ///< 'DNMS' /// A magic number used to detect the compatibility of navigation tile states.
static const int DT_NAVMESH_STATE_MAGIC = 'D'<<24 | 'N'<<16 | 'M'<<8 | 'S';
/// A version number used to detect compatibility of navigation tile states.
static const int DT_NAVMESH_STATE_VERSION = 1; static const int DT_NAVMESH_STATE_VERSION = 1;
/// @}
/// A flag that indicates that an entity links to an external entity.
/// (E.g. A polygon edge is a portal that links to another polygon.)
static const unsigned short DT_EXT_LINK = 0x8000; static const unsigned short DT_EXT_LINK = 0x8000;
/// A value that indicates the entity does not link to anything.
static const unsigned int DT_NULL_LINK = 0xffffffff; static const unsigned int DT_NULL_LINK = 0xffffffff;
/// A flag that indicates that an off-mesh connection can be traversed in both directions. (Is bi-directional.)
static const unsigned int DT_OFFMESH_CON_BIDIR = 1; static const unsigned int DT_OFFMESH_CON_BIDIR = 1;
/// The maximum number of user defined area ids.
/// @ingroup detour
static const int DT_MAX_AREAS = 64; static const int DT_MAX_AREAS = 64;
/// Flags for addTile /// Tile flags used for various functions and fields.
/// For an example, see dtNavMesh::addTile().
enum dtTileFlags enum dtTileFlags
{ {
DT_TILE_FREE_DATA = 0x01, ///< Navmesh owns the tile memory and should free it. /// The navigation mesh owns the tile memory and is responsible for freeing it.
DT_TILE_FREE_DATA = 0x01,
}; };
/// Flags returned by findStraightPath(). /// Vertex flags returned by dtNavMeshQuery::findStraightPath.
enum dtStraightPathFlags enum dtStraightPathFlags
{ {
DT_STRAIGHTPATH_START = 0x01, ///< The vertex is the start position. DT_STRAIGHTPATH_START = 0x01, ///< The vertex is the start position in the path.
DT_STRAIGHTPATH_END = 0x02, ///< The vertex is the end position. DT_STRAIGHTPATH_END = 0x02, ///< The vertex is the end position in the path.
DT_STRAIGHTPATH_OFFMESH_CONNECTION = 0x04, ///< The vertex is start of an off-mesh link. DT_STRAIGHTPATH_OFFMESH_CONNECTION = 0x04, ///< The vertex is the start of an off-mesh connection.
}; };
/// Flags describing polygon properties. /// Flags representing the type of a navigation mesh polygon.
enum dtPolyTypes enum dtPolyTypes
{ {
DT_POLYTYPE_GROUND = 0, ///< Regular ground polygons. /// The polygon is a standard convex polygon that is part of the surface of the mesh.
DT_POLYTYPE_OFFMESH_CONNECTION = 1, ///< Off-mesh connections. DT_POLYTYPE_GROUND = 0,
/// The polygon is an off-mesh connection consisting of two vertices.
DT_POLYTYPE_OFFMESH_CONNECTION = 1,
}; };
/// Structure describing the navigation polygon data. /// Defines a polyogn within a dtMeshTile object.
/// @ingroup detour
struct dtPoly struct dtPoly
{ {
unsigned int firstLink; ///< Index to first link in linked list. /// Index to first link in linked list. (Or #DT_NULL_LINK if there is no link.)
unsigned short verts[DT_VERTS_PER_POLYGON]; ///< Indices to vertices of the poly. unsigned int firstLink;
unsigned short neis[DT_VERTS_PER_POLYGON]; ///< Refs to neighbours of the poly.
unsigned short flags; ///< Flags (see dtPolyFlags). /// The indices of the polygon's vertices.
unsigned char vertCount; ///< Number of vertices. /// The actual vertices are located in dtMeshTile::verts.
unsigned char areaAndtype; ///< Bit packed: Area ID of the polygon, and Polygon type, see dtPolyTypes.. unsigned short verts[DT_VERTS_PER_POLYGON];
/// Packed data representing neighbor polygons references and flags for each edge.
unsigned short neis[DT_VERTS_PER_POLYGON];
/// The user defined polygon flags.
unsigned short flags;
/// The number of vertices in the polygon.
unsigned char vertCount;
/// The bit packed area id and polygon type.
/// @note Use the structure's set and get methods to acess this value.
unsigned char areaAndtype;
/// Sets the user defined area id. [Limit: < #DT_MAX_AREAS]
inline void setArea(unsigned char a) { areaAndtype = (areaAndtype & 0xc0) | (a & 0x3f); } inline void setArea(unsigned char a) { areaAndtype = (areaAndtype & 0xc0) | (a & 0x3f); }
/// Sets the polygon type. (See: #dtPolyTypes.)
inline void setType(unsigned char t) { areaAndtype = (areaAndtype & 0x3f) | (t << 6); } inline void setType(unsigned char t) { areaAndtype = (areaAndtype & 0x3f) | (t << 6); }
/// Gets the user defined area id.
inline unsigned char getArea() const { return areaAndtype & 0x3f; } inline unsigned char getArea() const { return areaAndtype & 0x3f; }
/// Gets the polygon type. (See: #dtPolyTypes)
inline unsigned char getType() const { return areaAndtype >> 6; } inline unsigned char getType() const { return areaAndtype >> 6; }
}; };
/// Stucture describing polygon detail triangles. /// Defines the location of detail sub-mesh data within a dtMeshTile.
struct dtPolyDetail struct dtPolyDetail
{ {
unsigned int vertBase; ///< Offset to detail vertex array. unsigned int vertBase; ///< The offset of the vertices in the dtMeshTile::detailVerts array.
unsigned int triBase; ///< Offset to detail triangle array. unsigned int triBase; ///< The offset of the triangles in the dtMeshTile::detailTris array.
unsigned char vertCount; ///< Number of vertices in the detail mesh. unsigned char vertCount; ///< The number of vertices in the sub-mesh.
unsigned char triCount; ///< Number of triangles. unsigned char triCount; ///< The number of triangles in the sub-mesh.
}; };
/// Stucture describing a link to another polygon. /// Defines a link between polygons.
/// @note This structure is rarely if ever used by the end user.
/// @see dtMeshTile
struct dtLink struct dtLink
{ {
dtPolyRef ref; ///< Neighbour reference. dtPolyRef ref; ///< Neighbour reference. (The neighbor that is linked to.)
unsigned int next; ///< Index to next link. unsigned int next; ///< Index of the next link.
unsigned char edge; ///< Index to polygon edge which owns this link. unsigned char edge; ///< Index of the polygon edge that owns this link.
unsigned char side; ///< If boundary link, defines on which side the link is. unsigned char side; ///< If a boundary link, defines on which side the link is.
unsigned char bmin, bmax; ///< If boundary link, defines the sub edge area. unsigned char bmin; ///< If a boundary link, defines the minimum sub-edge area.
unsigned char bmax; ///< If a boundary link, defines the maximum sub-edge area.
}; };
/// Bounding volume node.
/// @note This structure is rarely if ever used by the end user.
/// @see dtMeshTile
struct dtBVNode struct dtBVNode
{ {
unsigned short bmin[3], bmax[3]; ///< BVnode bounds unsigned short bmin[3]; ///< Minimum bounds of the node's AABB. [(x, y, z)]
int i; ///< Index to item or if negative, escape index. unsigned short bmax[3]; ///< Maximum bounds of the node's AABB. [(x, y, z)]
int i; ///< The node's index. (Negative for escape sequence.)
}; };
/// Defines an navigation mesh off-mesh connection within a dtMeshTile object.
/// An off-mesh connection is a user defined traversable connection made up to two vertices.
struct dtOffMeshConnection struct dtOffMeshConnection
{ {
float pos[6]; ///< Both end point locations. /// The endpoints of the connection. [(ax, ay, az, bx, by, bz)]
float rad; ///< Link connection radius. float pos[6];
unsigned short poly; ///< Poly Id
unsigned char flags; ///< Link flags /// The radius of the endpoints. [Limit: >= 0]
unsigned char side; ///< End point side. float rad;
unsigned int userId; ///< User ID to identify this connection.
/// The polygon reference of the connection within the tile.
unsigned short poly;
/// Link flags.
/// @note These are not the connection's user defined flags. Those are assigned via the
/// connection's dtPoly definition. These are link flags used for internal purposes.
unsigned char flags;
/// End point side.
unsigned char side;
/// The id of the offmesh connection. (User assigned when the navigation mesh is built.)
unsigned int userId;
}; };
/// Provides high level information related to a dtMeshTile object.
/// @ingroup detour
struct dtMeshHeader struct dtMeshHeader
{ {
int magic; ///< Magic number, used to identify the data. int magic; ///< Tile magic number. (Used to identify the data format.)
int version; ///< Data version number. int version; ///< Tile data format version number.
int x, y, layer; ///< Location of the tile on the grid. int x; ///< The x-position of the tile within the dtNavMesh tile grid. (x, y, layer)
unsigned int userId; ///< User ID of the tile. int y; ///< The y-position of the tile within the dtNavMesh tile grid. (x, y, layer)
int polyCount; ///< Number of polygons in the tile. int layer; ///< The layer of the tile within the dtNavMesh tile grid. (x, y, layer)
int vertCount; ///< Number of vertices in the tile. unsigned int userId; ///< The user defined id of the tile.
int maxLinkCount; ///< Number of allocated links. int polyCount; ///< The number of polygons in the tile.
int detailMeshCount; ///< Number of detail meshes. int vertCount; ///< The number of vertices in the tile.
int detailVertCount; ///< Number of detail vertices. int maxLinkCount; ///< The number of allocated links.
int detailTriCount; ///< Number of detail triangles. int detailMeshCount; ///< The number of sub-meshes in the detail mesh.
int bvNodeCount; ///< Number of BVtree nodes.
int offMeshConCount; ///< Number of Off-Mesh links. /// The number of unique vertices in the detail mesh. (In addition to the polygon vertices.)
int offMeshBase; ///< Index to first polygon which is Off-Mesh link. int detailVertCount;
float walkableHeight; ///< Height of the agent.
float walkableRadius; ///< Radius of the agent int detailTriCount; ///< The number of triangles in the detail mesh.
float walkableClimb; ///< Max climb height of the agent. int bvNodeCount; ///< The number of bounding volume nodes. (Zero if bounding volumes are disabled.)
float bmin[3], bmax[3]; ///< Bounding box of the tile. int offMeshConCount; ///< The number of off-mesh connections.
float bvQuantFactor; ///< BVtree quantization factor (world to bvnode coords) int offMeshBase; ///< The index of the first polygon which is an off-mesh connection.
float walkableHeight; ///< The height of the agents using the tile.
float walkableRadius; ///< The radius of the agents using the tile.
float walkableClimb; ///< The maximum climb height of the agents using the tile.
float bmin[3]; ///< The minimum bounds of the tile's AABB. [(x, y, z)]
float bmax[3]; ///< The maximum bounds of the tile's AABB. [(x, y, z)]
/// The bounding volume quantization factor.
float bvQuantFactor;
}; };
/// Defines a navigation mesh tile.
/// @ingroup detour
struct dtMeshTile struct dtMeshTile
{ {
unsigned int salt; ///< Counter describing modifications to the tile. unsigned int salt; ///< Counter describing modifications to the tile.
unsigned int linksFreeList; ///< Index to next free link. unsigned int linksFreeList; ///< Index to the next free link.
dtMeshHeader* header; ///< Pointer to tile header. dtMeshHeader* header; ///< The tile header.
dtPoly* polys; ///< Pointer to the polygons (will be updated when tile is added). dtPoly* polys; ///< The tile polygons. [Size: dtMeshHeader::polyCount]
float* verts; ///< Pointer to the vertices (will be updated when tile added). float* verts; ///< The tile vertices. [Size: dtMeshHeader::vertCount]
dtLink* links; ///< Pointer to the links (will be updated when tile added). dtLink* links; ///< The tile links. [Size: dtMeshHeader::maxLinkCount]
dtPolyDetail* detailMeshes; ///< Pointer to detail meshes (will be updated when tile added). dtPolyDetail* detailMeshes; ///< The tile's detail sub-meshes. [Size: dtMeshHeader::detailMeshCount]
float* detailVerts; ///< Pointer to detail vertices (will be updated when tile added).
unsigned char* detailTris; ///< Pointer to detail triangles (will be updated when tile added).
dtBVNode* bvTree; ///< Pointer to BVtree nodes (will be updated when tile added).
dtOffMeshConnection* offMeshCons; ///< Pointer to Off-Mesh links. (will be updated when tile added).
unsigned char* data; ///< Pointer to tile data. /// The detail mesh's unique vertices. [(x, y, z) * dtMeshHeader::detailVertCount]
float* detailVerts;
/// The detail mesh's triangles. [(vertA, vertB, vertC) * dtMeshHeader::detailTriCount]
unsigned char* detailTris;
/// The tile bounding volume nodes. [Size: dtMeshHeader::bvNodeCount]
/// (Will be null if bounding volumes are disabled.)
dtBVNode* bvTree;
dtOffMeshConnection* offMeshCons; ///< The tile off-mesh connections. [Size: dtMeshHeader::offMeshConCount]
unsigned char* data; ///< The tile data. (Not directly accessed under normal situations.)
int dataSize; ///< Size of the tile data. int dataSize; ///< Size of the tile data.
int flags; ///< Tile flags, see dtTileFlags. int flags; ///< Tile flags. (See: #dtTileFlags)
dtMeshTile* next; ///< Next free tile or, next tile in spatial grid. dtMeshTile* next; ///< The next free tile, or the next tile in the spatial grid.
}; };
/// Configutration parameters used to define multi-tile navigation meshes.
/// The values are used to allocate space during the initialization of a navigation mesh.
/// @see dtNavMesh::init()
/// @ingroup detour
struct dtNavMeshParams struct dtNavMeshParams
{ {
float orig[3]; ///< Origin of the nav mesh tile space. float orig[3]; ///< The world space origin of the navigation mesh's tile space. [(x, y, z)]
float tileWidth, tileHeight; ///< Width and height of each tile. float tileWidth; ///< The width of each tile. (Along the x-axis.)
int maxTiles; ///< Maximum number of tiles the navmesh can contain. float tileHeight; ///< The height of each tile. (Along the z-axis.)
int maxPolys; ///< Maximum number of polygons each tile can contain. int maxTiles; ///< The maximum number of tiles the navigation mesh can contain.
int maxPolys; ///< The maximum number of polygons each tile can contain.
}; };
/// A navigation mesh based on tiles of convex polygons.
/// @ingroup detour
class dtNavMesh class dtNavMesh
{ {
public: public:
dtNavMesh(); dtNavMesh();
~dtNavMesh(); ~dtNavMesh();
/// Initializes the nav mesh for tiled use. /// @{
/// @param params [in] navmesh initialization params, see dtNavMeshParams. /// @name Initialization and Tile Management
/// @return True if succeed, else false.
/// Initializes the navigation mesh for tiled use.
/// @param[in] params Initialization parameters.
/// @return The status flags for the operation.
dtStatus init(const dtNavMeshParams* params); dtStatus init(const dtNavMeshParams* params);
/// Initializes the nav mesh for single tile use. /// Initializes the navigation mesh for single tile use.
/// @param data - [in] Data of the new tile mesh. /// @param[in] data Data of the new tile. (See: #dtCreateNavMeshData)
/// @param dataSize - [in] Data size of the new tile mesh. /// @param[in] dataSize The data size of the new tile.
/// @param flags - [in] Tile flags, see dtTileFlags. /// @param[in] flags The tile flags. (See: #dtTileFlags)
/// @return True if succeed, else false. /// @return The status flags for the operation.
/// @see dtCreateNavMeshData
dtStatus init(unsigned char* data, const int dataSize, const int flags); dtStatus init(unsigned char* data, const int dataSize, const int flags);
/// Returns pointer to navmesh initialization params. /// The navigation mesh initialization params.
const dtNavMeshParams* getParams() const; const dtNavMeshParams* getParams() const;
/// Adds new tile into the navmesh. /// Adds a tile to the navigation mesh.
/// The add will fail if the data is in wrong format, /// @param[in] data Data for the new tile mesh. (See: #dtCreateNavMeshData)
/// there is not enough tiles left, or if there is a tile already at the location. /// @param[in] dataSize Data size of the new tile mesh.
/// @param data [in] Data of the new tile mesh. /// @param[in] flags Tile flags. (See: #dtTileFlags)
/// @param dataSize [in] Data size of the new tile mesh. /// @param[in] lastRef The desired reference for the tile. (When reloading a tile.) [opt] [Default: 0]
/// @param flags [in] Tile flags, see dtTileFlags. /// @param[out] result The tile reference. (If the tile was succesfully added.) [opt]
/// @param lastRef [in,optional] Last tile ref, the tile will be restored so that /// @return The status flags for the operation.
/// the reference (as well as poly references) will be the same. Default: 0.
/// @param result [out,optional] tile ref if the tile was succesfully added.
dtStatus addTile(unsigned char* data, int dataSize, int flags, dtTileRef lastRef, dtTileRef* result); dtStatus addTile(unsigned char* data, int dataSize, int flags, dtTileRef lastRef, dtTileRef* result);
/// Removes specified tile. /// Removes the specified tile from the navigation mesh.
/// @param ref [in] Reference to the tile to remove. /// @param[in] ref The reference of the tile to remove.
/// @param data [out] Data associated with deleted tile. /// @param[out] data Data associated with deleted tile.
/// @param dataSize [out] Size of the data associated with deleted tile. /// @param[out] dataSize Size of the data associated with deleted tile.
/// @return The status flags for the operation.
dtStatus removeTile(dtTileRef ref, unsigned char** data, int* dataSize); dtStatus removeTile(dtTileRef ref, unsigned char** data, int* dataSize);
/// Calculates tile location based in input world position. /// @}
/// @param pos [in] world position of the query.
/// @param tx [out] tile x location. /// @{
/// @param ty [out] tile y location. /// @name Query Functions
/// Calculates the tile grid location for the specified world position.
/// @param[in] pos The world position for the query. [(x, y, z)]
/// @param[out] tx The tile's x-location. (x, y)
/// @param[out] ty The tile's y-location. (x, y)
void calcTileLoc(const float* pos, int* tx, int* ty) const; void calcTileLoc(const float* pos, int* tx, int* ty) const;
/// Returns pointer to tile at specified location. /// Gets the tile at the specified grid location.
/// @param x,y [in] Location of the tile to get. /// @param[in] x The tile's x-location. (x, y, layer)
/// @returns pointer to tile if tile exists or 0 tile does not exists. /// @param[in] y The tile's y-location. (x, y, layer)
/// @param[in] layer The tile's layer. (x, y, layer)
/// @return The tile, or null if the tile does not exist.
const dtMeshTile* getTileAt(const int x, const int y, const int layer) const; const dtMeshTile* getTileAt(const int x, const int y, const int layer) const;
/// Gets all tiles at the specified grid location. (All layers.)
/// @param[in] x The tile's x-location. (x, y)
/// @param[in] y The tile's y-location. (x, y)
/// @param[out] tiles A pointer to an array of tiles that will hold the result.
/// @param[in] maxTiles The maximum tiles the tiles parameter can hold.
/// @return The number of tiles returned in the tiles array.
int getTilesAt(const int x, const int y, int getTilesAt(const int x, const int y,
dtMeshTile const** tiles, const int maxTiles) const; dtMeshTile const** tiles, const int maxTiles) const;
/// Returns reference to tile at specified location. /// Gets the tile reference for the tile at specified grid location.
/// @param x,y [in] Location of the tile to get. /// @param[in] x The tile's x-location. (x, y, layer)
/// @returns reference to tile if tile exists or 0 tile does not exists. /// @param[in] y The tile's y-location. (x, y, layer)
/// @param[in] layer The tile's layer. (x, y, layer)
/// @return The tile reference of the tile, or 0 if there is none.
dtTileRef getTileRefAt(int x, int y, int layer) const; dtTileRef getTileRefAt(int x, int y, int layer) const;
/// Returns tile references of a tile based on tile pointer. /// Gets the tile reference for the specified tile.
/// @param[in] tile The tile.
/// @return The tile reference of the tile.
dtTileRef getTileRef(const dtMeshTile* tile) const; dtTileRef getTileRef(const dtMeshTile* tile) const;
/// Returns tile based on references. /// Gets the tile for the specified tile reference.
/// @param[in] ref The tile reference of the tile to retrieve.
/// @return The tile for the specified reference, or null if the
/// reference is invalid.
const dtMeshTile* getTileByRef(dtTileRef ref) const; const dtMeshTile* getTileByRef(dtTileRef ref) const;
/// Returns max number of tiles. /// The maximum number of tiles supported by the navigation mesh.
/// @return The maximum number of tiles supported by the navigation mesh.
int getMaxTiles() const; int getMaxTiles() const;
/// Returns pointer to tile in the tile array. /// Gets the tile at the specified index.
/// @param i [in] Index to the tile to retrieve, max index is getMaxTiles()-1. /// @param[in] i The tile index. [Limit: 0 >= index < #getMaxTiles()]
/// @returns Pointer to specified tile. /// @return The tile at the specified index.
const dtMeshTile* getTile(int i) const; const dtMeshTile* getTile(int i) const;
/// Returns pointer to tile and polygon pointed by the polygon reference. /// Gets the tile and polygon for the specified polygon reference.
/// @param ref [in] reference to a polygon. /// @param[in] ref The reference for the a polygon.
/// @param tile [out] pointer to the tile containing the polygon. /// @param[out] tile The tile containing the polygon.
/// @param poly [out] pointer to the polygon. /// @param[out] poly The polygon.
/// @return The status flags for the operation.
dtStatus getTileAndPolyByRef(const dtPolyRef ref, const dtMeshTile** tile, const dtPoly** poly) const; dtStatus getTileAndPolyByRef(const dtPolyRef ref, const dtMeshTile** tile, const dtPoly** poly) const;
/// Returns pointer to tile and polygon pointed by the polygon reference. /// Returns the tile and polygon for the specified polygon reference.
/// Note: this function does not check if 'ref' s valid, and is thus faster. Use only with valid refs! /// @param[in] ref A known valid reference for a polygon.
/// /// @param[out] tile The tile containing the polygon.
/// @param ref [in] reference to a polygon. /// @param[out] poly The polygon.
/// @param tile [out] pointer to the tile containing the polygon.
/// @param poly [out] pointer to the polygon.
void getTileAndPolyByRefUnsafe(const dtPolyRef ref, const dtMeshTile** tile, const dtPoly** poly) const; void getTileAndPolyByRefUnsafe(const dtPolyRef ref, const dtMeshTile** tile, const dtPoly** poly) const;
/// Returns true if polygon reference points to valid data. /// Checks the validity of a polygon reference.
/// @param[in] ref The polygon reference to check.
/// @return True if polygon reference is valid for the navigation mesh.
bool isValidPolyRef(dtPolyRef ref) const; bool isValidPolyRef(dtPolyRef ref) const;
/// Returns base poly id for specified tile, polygon refs can be deducted from this. /// Gets the polygon reference for the tile's base polygon.
/// @param[in] tile The tile.
/// @return The polygon reference for the base polygon in the specified tile.
dtPolyRef getPolyRefBase(const dtMeshTile* tile) const; dtPolyRef getPolyRefBase(const dtMeshTile* tile) const;
/// Returns start and end location of an off-mesh link polygon. /// Gets the endpoints for an off-mesh connection, ordered by "direction of travel".
/// @param prevRef [in] ref to the polygon before the link (used to select direction). /// @param[in] prevRef The reference of the polygon before the connection.
/// @param polyRef [in] ref to the off-mesh link polygon. /// @param[in] polyRef The reference of the off-mesh connection polygon.
/// @param startPos[3] [out] start point of the link. /// @param[out] startPos The start position of the off-mesh connection. [(x, y, z)]
/// @param endPos[3] [out] end point of the link. /// @param[out] endPos The end position of the off-mesh connection. [(x, y, z)]
/// @returns true if link is found. /// @return The status flags for the operation.
dtStatus getOffMeshConnectionPolyEndPoints(dtPolyRef prevRef, dtPolyRef polyRef, float* startPos, float* endPos) const; dtStatus getOffMeshConnectionPolyEndPoints(dtPolyRef prevRef, dtPolyRef polyRef, float* startPos, float* endPos) const;
/// Returns pointer to off-mesh connection based on polyref, or null if ref not valid. /// Gets the specified off-mesh connection.
/// @param[in] ref The polygon reference of the off-mesh connection.
/// @return The specified off-mesh connection, or null if the polygon reference is not valid.
const dtOffMeshConnection* getOffMeshConnectionByRef(dtPolyRef ref) const; const dtOffMeshConnection* getOffMeshConnectionByRef(dtPolyRef ref) const;
/// Sets polygon flags. /// @}
/// @{
/// @name State Management
/// These functions do not effect #dtTileRef or #dtPolyRef's.
/// Sets the user defined flags for the specified polygon.
/// @param[in] ref The polygon reference.
/// @param[in] flags The new flags for the polygon.
/// @return The status flags for the operation.
dtStatus setPolyFlags(dtPolyRef ref, unsigned short flags); dtStatus setPolyFlags(dtPolyRef ref, unsigned short flags);
/// Return polygon flags. /// Gets the user defined flags for the specified polygon.
/// @param[in] ref The polygon reference.
/// @param[out] resultFlags The polygon flags.
/// @return The status flags for the operation.
dtStatus getPolyFlags(dtPolyRef ref, unsigned short* resultFlags) const; dtStatus getPolyFlags(dtPolyRef ref, unsigned short* resultFlags) const;
/// Set polygon type. /// Sets the user defined area for the specified polygon.
/// @param[in] ref The polygon reference.
/// @param[in] area The new area id for the polygon. [Limit: < #DT_MAX_AREAS]
/// @return The status flags for the operation.
dtStatus setPolyArea(dtPolyRef ref, unsigned char area); dtStatus setPolyArea(dtPolyRef ref, unsigned char area);
/// Return polygon area type. /// Gets the user defined area for the specified polygon.
/// @param[in] ref The polygon reference.
/// @param[out] resultArea The area id for the polygon.
/// @return The status flags for the operation.
dtStatus getPolyArea(dtPolyRef ref, unsigned char* resultArea) const; dtStatus getPolyArea(dtPolyRef ref, unsigned char* resultArea) const;
/// Gets the size of the buffer required by #storeTileState to store the specified tile's state.
/// Returns number of bytes required to store tile state. /// @param[in] tile The tile.
/// @return The size of the buffer required to store the state.
int getTileStateSize(const dtMeshTile* tile) const; int getTileStateSize(const dtMeshTile* tile) const;
/// Stores tile state to buffer. /// Stores the non-structural state of the tile in the specified buffer. (Flags, area ids, etc.)
/// @param[in] tile The tile.
/// @param[out] data The buffer to store the tile's state in.
/// @param[in] maxDataSize The size of the data buffer. [Limit: >= #getTileStateSize]
/// @return The status flags for the operation.
dtStatus storeTileState(const dtMeshTile* tile, unsigned char* data, const int maxDataSize) const; dtStatus storeTileState(const dtMeshTile* tile, unsigned char* data, const int maxDataSize) const;
/// Restores tile state. /// Restores the state of the tile.
/// @param[in] tile The tile.
/// @param[in] data The new state. (Obtained from #storeTileState.)
/// @param[in] maxDataSize The size of the state within the data buffer.
/// @return The status flags for the operation.
dtStatus restoreTileState(dtMeshTile* tile, const unsigned char* data, const int maxDataSize); dtStatus restoreTileState(dtMeshTile* tile, const unsigned char* data, const int maxDataSize);
/// @}
/// Encodes a tile id. /// @{
/// @name Encoding and Decoding
/// These functions are generally meant for internal use only.
/// Derives a standard polygon reference.
/// @note This function is generally meant for internal use only.
/// @param[in] salt The tile's salt value.
/// @param[in] it The index of the tile.
/// @param[in] ip The index of the polygon within the tile.
inline dtPolyRef encodePolyId(unsigned int salt, unsigned int it, unsigned int ip) const inline dtPolyRef encodePolyId(unsigned int salt, unsigned int it, unsigned int ip) const
{ {
return ((dtPolyRef)salt << (m_polyBits+m_tileBits)) | ((dtPolyRef)it << m_polyBits) | (dtPolyRef)ip; return ((dtPolyRef)salt << (m_polyBits+m_tileBits)) | ((dtPolyRef)it << m_polyBits) | (dtPolyRef)ip;
} }
/// Decodes a tile id. /// Decodes a standard polygon reference.
/// @note This function is generally meant for internal use only.
/// @param[in] ref The polygon reference to decode.
/// @param[out] salt The tile's salt value.
/// @param[out] it The index of the tile.
/// @param[out] ip The index of the polygon within the tile.
/// @see #encodePolyId
inline void decodePolyId(dtPolyRef ref, unsigned int& salt, unsigned int& it, unsigned int& ip) const inline void decodePolyId(dtPolyRef ref, unsigned int& salt, unsigned int& it, unsigned int& ip) const
{ {
const dtPolyRef saltMask = ((dtPolyRef)1<<m_saltBits)-1; const dtPolyRef saltMask = ((dtPolyRef)1<<m_saltBits)-1;
@ -313,27 +483,38 @@ public:
ip = (unsigned int)(ref & polyMask); ip = (unsigned int)(ref & polyMask);
} }
/// Decodes a tile salt. /// Extracts a tile's salt value from the specified polygon reference.
/// @note This function is generally meant for internal use only.
/// @param[in] ref The polygon reference.
/// @see #encodePolyId
inline unsigned int decodePolyIdSalt(dtPolyRef ref) const inline unsigned int decodePolyIdSalt(dtPolyRef ref) const
{ {
const dtPolyRef saltMask = ((dtPolyRef)1<<m_saltBits)-1; const dtPolyRef saltMask = ((dtPolyRef)1<<m_saltBits)-1;
return (unsigned int)((ref >> (m_polyBits+m_tileBits)) & saltMask); return (unsigned int)((ref >> (m_polyBits+m_tileBits)) & saltMask);
} }
/// Decodes a tile id. /// Extracts the tile's index from the specified polygon reference.
/// @note This function is generally meant for internal use only.
/// @param[in] ref The polygon reference.
/// @see #encodePolyId
inline unsigned int decodePolyIdTile(dtPolyRef ref) const inline unsigned int decodePolyIdTile(dtPolyRef ref) const
{ {
const dtPolyRef tileMask = ((dtPolyRef)1<<m_tileBits)-1; const dtPolyRef tileMask = ((dtPolyRef)1<<m_tileBits)-1;
return (unsigned int)((ref >> m_polyBits) & tileMask); return (unsigned int)((ref >> m_polyBits) & tileMask);
} }
/// Decodes a poly id. /// Extracts the polygon's index (within its tile) from the specified polygon reference.
/// @note This function is generally meant for internal use only.
/// @param[in] ref The polygon reference.
/// @see #encodePolyId
inline unsigned int decodePolyIdPoly(dtPolyRef ref) const inline unsigned int decodePolyIdPoly(dtPolyRef ref) const
{ {
const dtPolyRef polyMask = ((dtPolyRef)1<<m_polyBits)-1; const dtPolyRef polyMask = ((dtPolyRef)1<<m_polyBits)-1;
return (unsigned int)(ref & polyMask); return (unsigned int)(ref & polyMask);
} }
/// @}
private: private:
/// Returns pointer to tile in the tile array. /// Returns pointer to tile in the tile array.
@ -394,8 +575,106 @@ private:
unsigned int m_polyBits; ///< Number of poly bits in the tile ID. unsigned int m_polyBits; ///< Number of poly bits in the tile ID.
}; };
/// Helper function to allocate navmesh class using Detour allocator. /// Allocates a navigation mesh object using the Detour allocator.
/// @return A navigation mesh that is ready for initialization, or null on failure.
/// @ingroup detour
dtNavMesh* dtAllocNavMesh(); dtNavMesh* dtAllocNavMesh();
/// Frees the specified navigation mesh object using the Detour allocator.
/// @param[in] navmesh A navigation mesh allocated using #dtAllocNavMesh
/// @ingroup detour
void dtFreeNavMesh(dtNavMesh* navmesh); void dtFreeNavMesh(dtNavMesh* navmesh);
#endif // DETOURNAVMESH_H #endif // DETOURNAVMESH_H
///////////////////////////////////////////////////////////////////////////
// This section contains detailed documentation for types that don't have
// a source file. It reduces clutter in the main section of the header.
/// @typedef dtPolyRef
/// @par
///
/// Polygon references are subject to the same invalidate/preserve/restore
/// rules that apply to #dtTileRef's. If the #dtTileRef for the polygon's
/// tile changes, the polygon reference becomes invalid.
///
/// Changing a polygon's flags, area id, etc. does not impact its polygon
/// reference.
/// @typedef dtTileRef
/// @par
///
/// The following changes will invalidate a tile reference:
///
/// - The referenced tile has been removed from the navigation mesh.
/// - The navigation mesh has been initialized using a different set
/// of #dtNavMeshParams.
///
/// A tile reference is preserved/restored if the tile is added to a navigation
/// mesh initialized with the original #dtNavMeshParams and is added at the
/// original reference location. (E.g. The lastRef parameter is used with
/// dtNavMesh::addTile.)
///
/// Basically, if the storage structure of a tile changes, its associated
/// tile reference changes.
///
/// @var unsigned short dtPoly::neis[DT_VERTS_PER_POLYGON]
/// @par
///
/// Each entry represents data for the edge starting at the vertex of the same index.
/// E.g. The entry at index n represents the edge data for vertex[n] to vertex[n+1].
///
/// A value of zero indicates the edge has no polygon connection. (It makes up the
/// border of the navigation mesh.)
///
/// The information can be extracted as follows:
/// @code
/// neighborRef = neis[n] & 0xff; // Get the neighbor polygon reference.
///
/// if (neis[n] & #DT_EX_LINK)
/// {
/// // The edge is an external (portal) edge.
/// }
/// @endcode
/// @var float dtMeshHeader::bvQuantFactor
/// @par
///
/// This value is used for converting between world and bounding volume coordinates.
/// For example:
/// @code
/// const float cs = 1.0f / tile->header->bvQuantFactor;
/// const dtBVNode* n = &tile->bvTree[i];
/// if (n->i >= 0)
/// {
/// // This is a leaf node.
/// float worldMinX = tile->header->bmin[0] + n->bmin[0]*cs;
/// float worldMinY = tile->header->bmin[0] + n->bmin[1]*cs;
/// // Etc...
/// }
/// @endcode
/// @struct dtMeshTile
/// @par
///
/// Tiles generally only exist within the context of a dtNavMesh object.
///
/// Some tile content is optional. For example, a tile may not contain any
/// off-mesh connections. In this case the associated pointer will be null.
///
/// If a detail mesh exists it will share vertices with the base polygon mesh.
/// Only the vertices unique to the detail mesh will be stored in #detailVerts.
///
/// @warning Tiles returned by a dtNavMesh object are not guarenteed to be populated.
/// For example: The tile at a location might not have been loaded yet, or may have been removed.
/// In this case, pointers will be null. So if in doubt, check the polygon count in the
/// tile's header to determine if a tile has polygons defined.
/// @var float dtOffMeshConnection::pos[6]
/// @par
///
/// For a properly built navigation mesh, vertex A will always be within the bounds of the mesh.
/// Vertex B is not required to be within the bounds of the mesh.
///

View File

@ -25,34 +25,26 @@
// Define DT_VIRTUAL_QUERYFILTER if you wish to derive a custom filter from dtQueryFilter. // Define DT_VIRTUAL_QUERYFILTER if you wish to derive a custom filter from dtQueryFilter.
// On certain platforms indirect or virtual function call is expensive. The default // On certain platforms indirect or virtual function call is expensive. The default
// setting is to use non-virtual functions, the actualy implementations of the functions // setting is to use non-virtual functions, the actual implementations of the functions
// are declared as inline for maximum speed. // are declared as inline for maximum speed.
//#define DT_VIRTUAL_QUERYFILTER 1 //#define DT_VIRTUAL_QUERYFILTER 1
/// Class for polygon filtering and cost calculation during query operations. /// Defines polygon filtering and traversal costs for navigation mesh query operations.
/// - It is possible to derive a custom query filter from dtQueryFilter by overriding /// @ingroup detour
/// the virtual functions passFilter() and getCost().
/// - Both functions should be as fast as possible. Use cached local copy of data
/// instead of accessing your own objects where possible.
/// - You do not need to adhere to the flags and cost logic provided by the default
/// implementation.
/// - In order for the A* to work properly, the cost should be proportional to
/// the travel distance. Using cost modifier less than 1.0 is likely to lead
/// to problems during pathfinding.
class dtQueryFilter class dtQueryFilter
{ {
float m_areaCost[DT_MAX_AREAS]; ///< Array storing cost per area type, used by default implementation. float m_areaCost[DT_MAX_AREAS]; ///< Cost per area type. (Used by default implementation.)
unsigned short m_includeFlags; ///< Include poly flags, used by default implementation. unsigned short m_includeFlags; ///< Flags for polygons that can be visited. (Used by default implementation.)
unsigned short m_excludeFlags; ///< Exclude poly flags, used by default implementation. unsigned short m_excludeFlags; ///< Flags for polygons that should not be visted. (Used by default implementation.)
public: public:
dtQueryFilter(); dtQueryFilter();
/// Returns true if the polygon is can visited. /// Returns true if the polygon can be visited. (I.e. Is traversable.)
/// @param ref [in] reference to the polygon test. /// @param[in] ref The reference id of the polygon test.
/// @param tile [in] pointer to the tile of the polygon test. /// @param[in] tile The tile containing the polygon.
/// @param poly [in] pointer to the polygon test. /// @param[in] poly The polygon to test.
#ifdef DT_VIRTUAL_QUERYFILTER #ifdef DT_VIRTUAL_QUERYFILTER
virtual bool passFilter(const dtPolyRef ref, virtual bool passFilter(const dtPolyRef ref,
const dtMeshTile* tile, const dtMeshTile* tile,
@ -63,15 +55,19 @@ public:
const dtPoly* poly) const; const dtPoly* poly) const;
#endif #endif
/// Returns cost to travel from 'pa' to 'pb'.' /// Returns cost to move from the beginning to the end of a line segment
/// The segment is fully contained inside 'cur'. /// that is fully contained within a polygon.
/// 'pa' lies on the edge between 'prev' and 'cur', /// @param[in] pa The start position on the edge of the previous and current polygon. [(x, y, z)]
/// 'pb' lies on the edge between 'cur' and 'next'. /// @param[in] pb The end position on the edge of the current and next polygon. [(x, y, z)]
/// @param pa [in] segment start position. /// @param[in] prevRef The reference id of the previous polygon. [opt]
/// @param pb [in] segment end position. /// @param[in] prevTile The tile containing the previous polygon. [opt]
/// @param prevRef, prevTile, prevPoly [in] data describing the previous polygon, can be null. /// @param[in] prevPoly The previous polygon. [opt]
/// @param curRef, curTile, curPoly [in] data describing the current polygon. /// @param[in] curRef The reference id of the current polygon.
/// @param nextRef, nextTile, nextPoly [in] data describing the next polygon, can be null. /// @param[in] curTile The tile containing the current polygon.
/// @param[in] curPoly The current polygon.
/// @param[in] nextRef The refernece id of the next polygon. [opt]
/// @param[in] nextTile The tile containing the next polygon. [opt]
/// @param[in] nextPoly The next polygon. [opt]
#ifdef DT_VIRTUAL_QUERYFILTER #ifdef DT_VIRTUAL_QUERYFILTER
virtual float getCost(const float* pa, const float* pb, virtual float getCost(const float* pa, const float* pb,
const dtPolyRef prevRef, const dtMeshTile* prevTile, const dtPoly* prevPoly, const dtPolyRef prevRef, const dtMeshTile* prevTile, const dtPoly* prevPoly,
@ -86,258 +82,319 @@ public:
/// @name Getters and setters for the default implementation data. /// @name Getters and setters for the default implementation data.
///@{ ///@{
/// Returns the traversal cost of the area.
/// @param[in] i The id of the area.
/// @returns The traversal cost of the area.
inline float getAreaCost(const int i) const { return m_areaCost[i]; } inline float getAreaCost(const int i) const { return m_areaCost[i]; }
/// Sets the traversal cost of the area.
/// @param[in] i The id of the area.
/// @param[in] cost The new cost of traversing the area.
inline void setAreaCost(const int i, const float cost) { m_areaCost[i] = cost; } inline void setAreaCost(const int i, const float cost) { m_areaCost[i] = cost; }
/// Returns the include flags for the filter.
/// Any polygons that include one or more of these flags will be
/// included in the operation.
inline unsigned short getIncludeFlags() const { return m_includeFlags; } inline unsigned short getIncludeFlags() const { return m_includeFlags; }
/// Sets the include flags for the filter.
/// @param[in] flags The new flags.
inline void setIncludeFlags(const unsigned short flags) { m_includeFlags = flags; } inline void setIncludeFlags(const unsigned short flags) { m_includeFlags = flags; }
/// Returns the exclude flags for the filter.
/// Any polygons that include one ore more of these flags will be
/// excluded from the operation.
inline unsigned short getExcludeFlags() const { return m_excludeFlags; } inline unsigned short getExcludeFlags() const { return m_excludeFlags; }
/// Sets the exclude flags for the filter.
/// @param[in] flags The new flags.
inline void setExcludeFlags(const unsigned short flags) { m_excludeFlags = flags; } inline void setExcludeFlags(const unsigned short flags) { m_excludeFlags = flags; }
///@} ///@}
}; };
/// Provides the ability to perform pathfinding related queries against
/// a navigation mesh.
/// @ingroup detour
class dtNavMeshQuery class dtNavMeshQuery
{ {
public: public:
dtNavMeshQuery(); dtNavMeshQuery();
~dtNavMeshQuery(); ~dtNavMeshQuery();
/// Initializes the nav mesh query. /// Initializes the query object.
/// @param nav [in] pointer to navigation mesh data. /// @param[in] nav Pointer to the dtNavMesh object to use for all queries.
/// @param maxNodes [in] Maximum number of search nodes to use (max 65536). /// @param[in] maxNodes Maximum number of search nodes. [Limits: 0 < value <= 65536]
/// @returns The status flags for the query.
dtStatus init(const dtNavMesh* nav, const int maxNodes); dtStatus init(const dtNavMesh* nav, const int maxNodes);
/// Finds the nearest navigation polygon around the center location. /// @name Standard Pathfinding Functions
/// @param center[3] [in] The center of the search box. // /@{
/// @param extents[3] [in] The extents of the search box.
/// @param filter [in] path polygon filter.
/// @param nearestRef [out] Reference to the nearest polygon.
/// @param nearestPt[3] [out, opt] The nearest point on found polygon, null if not needed.
dtStatus findNearestPoly(const float* center, const float* extents,
const dtQueryFilter* filter,
dtPolyRef* nearestRef, float* nearestPt) const;
/// Returns polygons which overlap the query box. /// Finds a path from the start polygon to the end polygon.
/// @param center[3] [in] the center of the search box. /// @param[in] startRef The refrence id of the start polygon.
/// @param extents[3] [in] the extents of the search box. /// @param[in] endRef The reference id of the end polygon.
/// @param filter [in] path polygon filter. /// @param[in] startPos A position within the start polygon. [(x, y, z)]
/// @param polys [out] array holding the search result. /// @param[in] endPos A position within the end polygon. [(x, y, z)]
/// @param polyCount [out] Number of polygons in search result array. /// @param[in] filter The polygon filter to apply to the query.
/// @param maxPolys [in] The max number of polygons the polys array can hold. /// @param[out] path An ordered list of polygon references representing the path. (Start to end.)
dtStatus queryPolygons(const float* center, const float* extents, /// [(polyRef) * @p pathCount]
const dtQueryFilter* filter, /// @param[out] pathCount The number of polygons returned in the @p path array.
dtPolyRef* polys, int* polyCount, const int maxPolys) const; /// @param[in] maxPath The maximum number of polygons the @p path array can hold. [Limit: >= 1]
/// Finds path from start polygon to end polygon.
/// If target polygon canno be reached through the navigation graph,
/// the last node on the array is nearest node to the end polygon.
/// Start end end positions are needed to calculate more accurate
/// traversal cost at start end end polygons.
/// @param startRef [in] ref to path start polygon.
/// @param endRef [in] ref to path end polygon.
/// @param startPos[3] [in] Path start location.
/// @param endPos[3] [in] Path end location.
/// @param filter [in] path polygon filter.
/// @param path [out] array holding the search result.
/// @param pathCount [out] Number of polygons in search result array.
/// @param maxPath [in] The max number of polygons the path array can hold. Must be at least 1.
dtStatus findPath(dtPolyRef startRef, dtPolyRef endRef, dtStatus findPath(dtPolyRef startRef, dtPolyRef endRef,
const float* startPos, const float* endPos, const float* startPos, const float* endPos,
const dtQueryFilter* filter, const dtQueryFilter* filter,
dtPolyRef* path, int* pathCount, const int maxPath) const; dtPolyRef* path, int* pathCount, const int maxPath) const;
/// Intializes sliced path find query. /// Finds the straight path from the start to the end position within the polygon corridor.
/// Note 1: calling any other dtNavMeshQuery method before calling findPathEnd() /// @param[in] startPos Path start position. [(x, y, z)]
/// may results in corrupted data! /// @param[in] endPos Path end position. [(x, y, z)]
/// Note 2: The pointer to filter is store, and used in subsequent /// @param[in] path An array of polygon references that represent the path corridor.
/// calls to updateSlicedFindPath(). /// @param[in] pathSize The number of polygons in the @p path array.
/// @param startRef [in] ref to path start polygon. /// @param[out] straightPath Points describing the straight path. [(x, y, z) * @p straightPathCount].
/// @param endRef [in] ref to path end polygon. /// @param[out] straightPathFlags Flags describing each point. (See: #dtStraightPathFlags) [opt]
/// @param startPos[3] [in] Path start location. /// @param[out] straightPathRefs The reference id of the polygon that is being entered at each point. [opt]
/// @param endPos[3] [in] Path end location. /// @param[out] straightPathCount The number of points in the straight path.
/// @param filter [in] path polygon filter. /// @param[in] maxStraightPath The maximum number of points the straight path arrays can hold. [Limit: > 0]
dtStatus initSlicedFindPath(dtPolyRef startRef, dtPolyRef endRef, /// @returns The status flags for the query.
const float* startPos, const float* endPos,
const dtQueryFilter* filter);
/// Updates sliced path find query.
/// @param maxIter [in] Max number of iterations to update.
/// @param doneIters [out,opt] Number of iterations done during the update.
/// Returns: Path query state.
dtStatus updateSlicedFindPath(const int maxIter, int* doneIters);
/// Finalizes sliced path find query and returns found path.
/// @param path [out] array holding the search result.
/// @param pathCount [out] Number of polygons in search result array.
/// @param maxPath [in] The max number of polygons the path array can hold.
dtStatus finalizeSlicedFindPath(dtPolyRef* path, int* pathCount, const int maxPath);
/// Finalizes partial sliced path find query and returns path to the furthest
/// polygon on the existing path that was visited during the search.
/// @param existing [out] Array of polygons in the existing path.
/// @param existingSize [out] Number of polygons in existing path array.
/// @param path [out] array holding the search result.
/// @param pathCount [out] Number of polygons in search result array.
/// @param maxPath [in] The max number of polygons the path array can hold.
dtStatus finalizeSlicedFindPathPartial(const dtPolyRef* existing, const int existingSize,
dtPolyRef* path, int* pathCount, const int maxPath);
/// Finds a straight path from start to end locations within the corridor
/// described by the path polygons.
/// Start and end locations will be clamped on the corridor.
/// The returned polygon references are point to polygon which was entered when
/// a path point was added. For the end point, zero will be returned. This allows
/// to match for example off-mesh link points to their representative polygons.
/// @param startPos[3] [in] Path start location.
/// @param endPos[3] [in] Path end location.
/// @param path [in] Array of connected polygons describing the corridor.
/// @param pathSize [in] Number of polygons in path array.
/// @param straightPath [out] Points describing the straight path.
/// @param straightPathFlags [out, opt] Flags describing each point type, see dtStraightPathFlags.
/// @param straightPathRefs [out, opt] References to polygons at point locations.
/// @param straightPathCount [out] Number of points in the path.
/// @param maxStraightPath [in] The max number of points the straight path array can hold. Must be at least 1.
dtStatus findStraightPath(const float* startPos, const float* endPos, dtStatus findStraightPath(const float* startPos, const float* endPos,
const dtPolyRef* path, const int pathSize, const dtPolyRef* path, const int pathSize,
float* straightPath, unsigned char* straightPathFlags, dtPolyRef* straightPathRefs, float* straightPath, unsigned char* straightPathFlags, dtPolyRef* straightPathRefs,
int* straightPathCount, const int maxStraightPath) const; int* straightPathCount, const int maxStraightPath) const;
/// Moves from startPos to endPos constrained to the navmesh. ///@}
/// If the endPos is reachable, the resultPos will be endPos, /// @name Sliced Pathfinding Functions
/// or else the resultPos will be the nearest point in navmesh. /// Common use case:
/// Note: The resulting point is not projected to the ground, use getPolyHeight() to get height. /// -# Call initSlicedFindPath() to initialize the sliced path query.
/// Note: The algorithm is optimized for small delta movement and small number of polygons. /// -# Call updateSlicedFindPath() until it returns complete.
/// @param startRef [in] ref to the polygon where startPos lies. /// -# Call finalizeSlicedFindPath() to get the path.
/// @param startPos[3] [in] start position of the mover. ///@{
/// @param endPos[3] [in] desired end position of the mover.
/// @param filter [in] path polygon filter.
/// @param resultPos[3] [out] new position of the mover.
/// @param visited [out] array of visited polygons.
/// @param visitedCount [out] Number of entries in the visited array.
/// @param maxVisitedSize [in] max number of polygons in the visited array.
dtStatus moveAlongSurface(dtPolyRef startRef, const float* startPos, const float* endPos,
const dtQueryFilter* filter,
float* resultPos, dtPolyRef* visited, int* visitedCount, const int maxVisitedSize) const;
/// Casts 'walkability' ray along the navmesh surface from startPos towards the endPos. /// Intializes a sliced path query.
/// @param startRef [in] ref to the polygon where the start lies. /// @param[in] startRef The refrence id of the start polygon.
/// @param startPos[3] [in] start position of the query. /// @param[in] endRef The reference id of the end polygon.
/// @param endPos[3] [in] end position of the query. /// @param[in] startPos A position within the start polygon. [(x, y, z)]
/// @param t [out] hit parameter along the segment, FLT_MAX if no hit. /// @param[in] endPos A position within the end polygon. [(x, y, z)]
/// @param hitNormal[3] [out] normal of the nearest hit. /// @param[in] filter The polygon filter to apply to the query.
/// @param filter [in] path polygon filter. /// @returns The status flags for the query.
/// @param path [out,opt] visited path polygons. dtStatus initSlicedFindPath(dtPolyRef startRef, dtPolyRef endRef,
/// @param pathCount [out,opt] Number of polygons visited. const float* startPos, const float* endPos,
/// @param maxPath [in] max number of polygons in the path array. const dtQueryFilter* filter);
dtStatus raycast(dtPolyRef startRef, const float* startPos, const float* endPos,
const dtQueryFilter* filter,
float* t, float* hitNormal, dtPolyRef* path, int* pathCount, const int maxPath) const;
/// Returns distance to nearest wall from the specified location. /// Updates an in-progress sliced path query.
/// @param startRef [in] ref to the polygon where the center lies. /// @param[in] maxIter The maximum number of iterations to perform.
/// @param centerPos[3] [in] center if the query circle. /// @param[out] doneIters The actual number of iterations completed. [opt]
/// @param maxRadius [in] max search radius. /// @returns The status flags for the query.
/// @param filter [in] path polygon filter. dtStatus updateSlicedFindPath(const int maxIter, int* doneIters);
/// @param hitDist [out] distance to nearest wall from the test location.
/// @param hitPos[3] [out] location of the nearest hit.
/// @param hitNormal[3] [out] normal of the nearest hit.
dtStatus findDistanceToWall(dtPolyRef startRef, const float* centerPos, const float maxRadius,
const dtQueryFilter* filter,
float* hitDist, float* hitPos, float* hitNormal) const;
/// Finds polygons found along the navigation graph which touch the specified circle. /// Finalizes and returns the results of a sliced path query.
/// @param startRef [in] ref to the polygon where the search starts. /// @param[out] path An ordered list of polygon references representing the path. (Start to end.)
/// @param centerPos[3] [in] center if the query circle. /// [(polyRef) * @p pathCount]
/// @param radius [in] radius of the query circle. /// @param[out] pathCount The number of polygons returned in the @p path array.
/// @param filter [in] path polygon filter. /// @param[in] maxPath The max number of polygons the path array can hold. [Limit: >= 1]
/// @param resultRef [out, opt] refs to the polygons touched by the circle. /// @returns The status flags for the query.
/// @param resultParent [out, opt] parent of each result polygon. dtStatus finalizeSlicedFindPath(dtPolyRef* path, int* pathCount, const int maxPath);
/// @param resultCost [out, opt] search cost at each result polygon.
/// @param resultCount [out, opt] Number of results. /// Finalizes and returns the results of an incomplete sliced path query, returning the path to the furthest
/// @param maxResult [int] maximum capacity of search results. /// polygon on the existing path that was visited during the search.
/// @param[out] existing An array of polygon references for the existing path.
/// @param[out] existingSize The number of polygon in the @p existing array.
/// @param[out] path An ordered list of polygon references representing the path. (Start to end.)
/// [(polyRef) * @p pathCount]
/// @param[out] pathCount The number of polygons returned in the @p path array.
/// @param[in] maxPath The max number of polygons the @p path array can hold. [Limit: >= 1]
/// @returns The status flags for the query.
dtStatus finalizeSlicedFindPathPartial(const dtPolyRef* existing, const int existingSize,
dtPolyRef* path, int* pathCount, const int maxPath);
///@}
/// @name Dijkstra Search Functions
/// @{
/// Finds the polygons along the navigation graph that touch the specified circle.
/// @param[in] startRef The reference id of the polygon where the search starts.
/// @param[in] centerPos The center of the search circle. [(x, y, z)]
/// @param[in] radius The radius of the search circle.
/// @param[in] filter The polygon filter to apply to the query.
/// @param[out] resultRef The reference ids of the polygons touched by the circle. [opt]
/// @param[out] resultParent The reference ids of the parent polygons for each result.
/// Zero if a result polygon has no parent. [opt]
/// @param[out] resultCost The search cost from @p centerPos to the polygon. [opt]
/// @param[out] resultCount The number of polygons found. [opt]
/// @param[in] maxResult The maximum number of polygons the result arrays can hold.
/// @returns The status flags for the query.
dtStatus findPolysAroundCircle(dtPolyRef startRef, const float* centerPos, const float radius, dtStatus findPolysAroundCircle(dtPolyRef startRef, const float* centerPos, const float radius,
const dtQueryFilter* filter, const dtQueryFilter* filter,
dtPolyRef* resultRef, dtPolyRef* resultParent, float* resultCost, dtPolyRef* resultRef, dtPolyRef* resultParent, float* resultCost,
int* resultCount, const int maxResult) const; int* resultCount, const int maxResult) const;
/// Finds polygons found along the navigation graph which touch the convex polygon shape. /// Finds the polygons along the naviation graph that touch the specified convex polygon.
/// @param startRef [in] ref to the polygon where the search starts. /// @param[in] startRef The reference id of the polygon where the search starts.
/// @param verts[3*n] [in] vertices describing convex polygon shape (CCW). /// @param[in] verts The vertices describing the convex polygon. (CCW)
/// @param nverts [in] number of vertices in the polygon. /// [(x, y, z) * @p nverts]
/// @param filter [in] path polygon filter. /// @param[in] nverts The number of vertices in the polygon.
/// @param resultRef [out, opt] refs to the polygons touched by the circle. /// @param[in] filter The polygon filter to apply to the query.
/// @param resultParent [out, opt] parent of each result polygon. /// @param[out] resultRef The reference ids of the polygons touched by the search polygon. [opt]
/// @param resultCost [out, opt] search cost at each result polygon. /// @param[out] resultParent The reference ids of the parent polygons for each result. Zero if a
/// @param resultCount [out] number of results. /// result polygon has no parent. [opt]
/// @param maxResult [int] maximum capacity of search results. /// @param[out] resultCost The search cost from the centroid point to the polygon. [opt]
/// @param[out] resultCount The number of polygons found.
/// @param[in] maxResult The maximum number of polygons the result arrays can hold.
/// @returns The status flags for the query.
dtStatus findPolysAroundShape(dtPolyRef startRef, const float* verts, const int nverts, dtStatus findPolysAroundShape(dtPolyRef startRef, const float* verts, const int nverts,
const dtQueryFilter* filter, const dtQueryFilter* filter,
dtPolyRef* resultRef, dtPolyRef* resultParent, float* resultCost, dtPolyRef* resultRef, dtPolyRef* resultParent, float* resultCost,
int* resultCount, const int maxResult) const; int* resultCount, const int maxResult) const;
/// Finds non-overlapping local neighbourhood around center location. /// @}
/// Note: The algorithm is optimized for small query radius and small number of polygons. /// @name Local Query Functions
/// @param startRef [in] ref to the polygon where the search starts. ///@{
/// @param centerPos[3] [in] center if the query circle.
/// @param radius [in] radius of the query circle. /// Finds the polygon nearest to the specified center point.
/// @param filter [in] path polygon filter. /// @param[in] center The center of the search box. [(x, y, z)]
/// @param resultRef [out] refs to the polygons touched by the circle. /// @param[in] extents The search distance along each axis. [(x, y, z)]
/// @param resultParent [out, opt] parent of each result polygon. /// @param[in] filter The polygon filter to apply to the query.
/// @param resultCount [out] number of results. /// @param[out] nearestRef The reference id of the nearest polygon.
/// @param maxResult [int] maximum capacity of search results. /// @param[out] nearestPt The nearest point on the polygon. [opt] [(x, y, z)]
/// @returns The status flags for the query.
dtStatus findNearestPoly(const float* center, const float* extents,
const dtQueryFilter* filter,
dtPolyRef* nearestRef, float* nearestPt) const;
/// Finds polygons that overlap the search box.
/// @param[in] center The center of the search box. [(x, y, z)]
/// @param[in] extents The search distance along each axis. [(x, y, z)]
/// @param[in] filter The polygon filter to apply to the query.
/// @param[out] polys The reference ids of the polygons that overlap the query box.
/// @param[out] polyCount The number of polygons in the search result.
/// @param[in] maxPolys The maximum number of polygons the search result can hold.
/// @returns The status flags for the query.
dtStatus queryPolygons(const float* center, const float* extents,
const dtQueryFilter* filter,
dtPolyRef* polys, int* polyCount, const int maxPolys) const;
/// Finds the non-overlapping navigation polygons in the local neighbourhood around the center position.
/// @param[in] startRef The reference id of the polygon where the search starts.
/// @param[in] centerPos The center of the query circle. [(x, y, z)]
/// @param[in] radius The radius of the query circle.
/// @param[in] filter The polygon filter to apply to the query.
/// @param[out] resultRef The reference ids of the polygons touched by the circle.
/// @param[out] resultParent The reference ids of the parent polygons for each result.
/// Zero if a result polygon has no parent. [opt]
/// @param[out] resultCount The number of polygons found.
/// @param[in] maxResult The maximum number of polygons the result arrays can hold.
/// @returns The status flags for the query.
dtStatus findLocalNeighbourhood(dtPolyRef startRef, const float* centerPos, const float radius, dtStatus findLocalNeighbourhood(dtPolyRef startRef, const float* centerPos, const float radius,
const dtQueryFilter* filter, const dtQueryFilter* filter,
dtPolyRef* resultRef, dtPolyRef* resultParent, dtPolyRef* resultRef, dtPolyRef* resultParent,
int* resultCount, const int maxResult) const; int* resultCount, const int maxResult) const;
/// Returns wall segments of specified polygon. /// Moves from the start to the end position constrained to the navigation mesh.
/// If 'segmentRefs' is specified, both the wall and portal segments are returned. /// @param[in] startRef The reference id of the start polygon.
/// Wall segments will have null (0) polyref, and portal segments store the polygon they lead to. /// @param[in] startPos A position of the mover within the start polygon. [(x, y, x)]
/// @param ref [in] ref to the polygon. /// @param[in] endPos The desired end position of the mover. [(x, y, z)]
/// @param filter [in] path polygon filter. /// @param[in] filter The polygon filter to apply to the query.
/// @param segmentVerts[6*maxSegments] [out] wall segments (2 endpoints per segment). /// @param[out] resultPos The result position of the mover. [(x, y, z)]
/// @param segmentRefs[maxSegments] [out,opt] reference to a neighbour. /// @param[out] visited The reference ids of the polygons visited during the move.
/// @param segmentCount [out] number of wall segments. /// @param[out] visitedCount The number of polygons visited during the move.
/// @param maxSegments [in] max number of segments that can be stored in 'segments'. /// @param[in] maxVisitedSize The maximum number of polygons the @p visited array can hold.
/// @returns The status flags for the query.
dtStatus moveAlongSurface(dtPolyRef startRef, const float* startPos, const float* endPos,
const dtQueryFilter* filter,
float* resultPos, dtPolyRef* visited, int* visitedCount, const int maxVisitedSize) const;
/// Casts a 'walkability' ray along the surface of the navigation mesh from
/// the start position toward the end position.
/// @param[in] startRef The reference id of the start polygon.
/// @param[in] startPos A position within the start polygon representing
/// the start of the ray. [(x, y, z)]
/// @param[in] endPos The position to cast the ray toward. [(x, y, z)]
/// @param[out] t The hit parameter. (FLT_MAX if no wall hit.)
/// @param[out] hitNormal The normal of the nearest wall hit. [(x, y, z)]
/// @param[in] filter The polygon filter to apply to the query.
/// @param[out] path The reference ids of the visited polygons. [opt]
/// @param[out] pathCount The number of visited polygons. [opt]
/// @param[in] maxPath The maximum number of polygons the @p path array can hold.
/// @returns The status flags for the query.
dtStatus raycast(dtPolyRef startRef, const float* startPos, const float* endPos,
const dtQueryFilter* filter,
float* t, float* hitNormal, dtPolyRef* path, int* pathCount, const int maxPath) const;
/// Finds the distance from the specified position to the nearest polygon wall.
/// @param[in] startRef The reference id of the polygon containing @p centerPos.
/// @param[in] centerPos The center of the search circle. [(x, y, z)]
/// @param[in] maxRadius The radius of the search circle.
/// @param[in] filter The polygon filter to apply to the query.
/// @param[out] hitDist The distance to the nearest wall from @p centerPos.
/// @param[out] hitPos The nearest position on the wall that was hit. [(x, y, z)]
/// @param[out] hitNormal The normalized ray formed from the wall point to the
/// source point. [(x, y, z)]
/// @returns The status flags for the query.
dtStatus findDistanceToWall(dtPolyRef startRef, const float* centerPos, const float maxRadius,
const dtQueryFilter* filter,
float* hitDist, float* hitPos, float* hitNormal) const;
/// Returns the segments for the specified polygon, optionally including portals.
/// @param[in] ref The reference id of the polygon.
/// @param[in] filter The polygon filter to apply to the query.
/// @param[out] segmentVerts The segments. [(ax, ay, az, bx, by, bz) * segmentCount]
/// @param[out] segmentRefs The reference ids of each segment's neighbor polygon.
/// Or zero if the segment is a wall. [opt] [(parentRef) * @p segmentCount]
/// @param[out] segmentCount The number of segments returned.
/// @param[in] maxSegments The maximum number of segments the result arrays can hold.
/// @returns The status flags for the query.
dtStatus getPolyWallSegments(dtPolyRef ref, const dtQueryFilter* filter, dtStatus getPolyWallSegments(dtPolyRef ref, const dtQueryFilter* filter,
float* segmentVerts, dtPolyRef* segmentRefs, int* segmentCount, float* segmentVerts, dtPolyRef* segmentRefs, int* segmentCount,
const int maxSegments) const; const int maxSegments) const;
/// Returns closest point on navigation polygon. /// Finds the closest point on the specified polygon.
/// Uses detail polygons to find the closest point to the navigation polygon surface. /// @param[in] ref The reference id of the polygon.
/// @param ref [in] ref to the polygon. /// @param[in] pos The position to check. [(x, y, z)]
/// @param pos[3] [in] the point to check. /// @param[out] closest The closest point on the polygon. [(x, y, z)]
/// @param closest[3] [out] closest point. /// @returns The status flags for the query.
/// @returns true if closest point found.
dtStatus closestPointOnPoly(dtPolyRef ref, const float* pos, float* closest) const; dtStatus closestPointOnPoly(dtPolyRef ref, const float* pos, float* closest) const;
/// Returns closest point on navigation polygon boundary. /// Returns a point on the boundary closest to the source point if the source point is outside the
/// Uses the navigation polygon boundary to snap the point to poly boundary /// polygon's xz-bounds.
/// if it is outside the polygon. Much faster than closestPointToPoly. Does not affect height. /// @param[in] ref The reference id to the polygon.
/// @param ref [in] ref to the polygon. /// @param[in] pos The position to check. [(x, y, z)]
/// @param pos[3] [in] the point to check. /// @param[out] closest The closest point. [(x, y, z)]
/// @param closest[3] [out] closest point. /// @returns The status flags for the query.
/// @returns true if closest point found.
dtStatus closestPointOnPolyBoundary(dtPolyRef ref, const float* pos, float* closest) const; dtStatus closestPointOnPolyBoundary(dtPolyRef ref, const float* pos, float* closest) const;
/// Returns height of the polygon at specified location. /// Gets the height of the polygon at the provided position using the height detail. (Most accurate.)
/// @param ref [in] ref to the polygon. /// @param[in] ref The reference id of the polygon.
/// @param pos[3] [in] the point where to locate the height. /// @param[in] pos A position within the xz-bounds of the polygon. [(x, y, z)]
/// @param height [out] height at the location. /// @param[out] height The height at the surface of the polygon.
/// @returns true if over polygon. /// @returns The status flags for the query.
dtStatus getPolyHeight(dtPolyRef ref, const float* pos, float* height) const; dtStatus getPolyHeight(dtPolyRef ref, const float* pos, float* height) const;
// Returns true if polygon reference points to valid data and passes the filter. /// @}
/// @name Miscellaneous Functions
/// @{
/// Returns true if the polygon reference is valid and passes the filter restrictions.
/// @param[in] ref The polygon reference to check.
/// @param[in] filter The filter to apply.
bool isValidPolyRef(dtPolyRef ref, const dtQueryFilter* filter) const; bool isValidPolyRef(dtPolyRef ref, const dtQueryFilter* filter) const;
// Returns true if poly reference ins in closed list. /// Returns true if the polygon reference is in the closed list.
/// @param[in] ref The reference id of the polygon to check.
/// @returns True if the polygon is in closed list.
bool isInClosedList(dtPolyRef ref) const; bool isInClosedList(dtPolyRef ref) const;
/// Gets the node pool.
/// @returns The node pool.
class dtNodePool* getNodePool() const { return m_nodePool; } class dtNodePool* getNodePool() const { return m_nodePool; }
/// Gets the navigation mesh the query object is using.
/// @return The navigation mesh the query object is using.
const dtNavMesh* getAttachedNavMesh() const { return m_nav; } const dtNavMesh* getAttachedNavMesh() const { return m_nav; }
/// @}
private: private:
/// Returns neighbour tile based on side. /// Returns neighbour tile based on side.
@ -383,8 +440,14 @@ private:
class dtNodeQueue* m_openList; ///< Pointer to open list queue. class dtNodeQueue* m_openList; ///< Pointer to open list queue.
}; };
/// Helper function to allocate navmesh query class using Detour allocator. /// Allocates a query object using the Detour allocator.
/// @return An allocated query object, or null on failure.
/// @ingroup detour
dtNavMeshQuery* dtAllocNavMeshQuery(); dtNavMeshQuery* dtAllocNavMeshQuery();
/// Frees the specified query object using the Detour allocator.
/// @param[in] query A query object allocated using #dtAllocNavMeshQuery
/// @ingroup detour
void dtFreeNavMeshQuery(dtNavMeshQuery* query); void dtFreeNavMeshQuery(dtNavMeshQuery* query);
#endif // DETOURNAVMESHQUERY_H #endif // DETOURNAVMESHQUERY_H

View File

@ -142,6 +142,10 @@ dtNavMesh* dtAllocNavMesh()
return new(mem) dtNavMesh; return new(mem) dtNavMesh;
} }
/// @par
///
/// This function will only free the memory for tiles with the #DT_TILE_FREE_DATA
/// flag set.
void dtFreeNavMesh(dtNavMesh* navmesh) void dtFreeNavMesh(dtNavMesh* navmesh)
{ {
if (!navmesh) return; if (!navmesh) return;
@ -150,6 +154,19 @@ void dtFreeNavMesh(dtNavMesh* navmesh)
} }
////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////
/// @class dtNavMesh
///
/// This class is usually used in conjunction with the dtNavMeshQuery class.
///
/// Technically, all navigation meshes are tiled. A 'solo' mesh is simply a navigation mesh initialized
/// to have only a single tile.
///
/// This class does not implement any asynchronous methods. So the ::dtStatus result of all methods will
/// always contain either a success or failure flag.
///
/// @see dtNavMeshQuery, dtCreateNavMeshData(), dtNavMeshCreateParams, #dtAllocNavMesh, #dtFreeNavMesh
dtNavMesh::dtNavMesh() : dtNavMesh::dtNavMesh() :
m_tileWidth(0), m_tileWidth(0),
m_tileHeight(0), m_tileHeight(0),
@ -246,6 +263,10 @@ dtStatus dtNavMesh::init(unsigned char* data, const int dataSize, const int flag
return addTile(data, dataSize, flags, 0, 0); return addTile(data, dataSize, flags, 0, 0);
} }
/// @par
///
/// @note The parameters are created automatically when the single tile
/// initialization is performed.
const dtNavMeshParams* dtNavMesh::getParams() const const dtNavMeshParams* dtNavMesh::getParams() const
{ {
return &m_params; return &m_params;
@ -726,6 +747,17 @@ int dtNavMesh::queryPolygonsInTile(const dtMeshTile* tile, const float* qmin, co
} }
} }
/// @par
///
/// The add operation will fail if the data is in the wrong format, the allocated tile
/// space is full, or there is a tile already at the specified reference.
///
/// The lastRef parameter is used to restore a tile with the same tile
/// reference it had previously used. In this case the #dtPolyRef's for the
/// tile will be restored to the same values they were before the tile was
/// removed.
///
/// @see dtCreateNavMeshData, #removeTile
dtStatus dtNavMesh::addTile(unsigned char* data, int dataSize, int flags, dtStatus dtNavMesh::addTile(unsigned char* data, int dataSize, int flags,
dtTileRef lastRef, dtTileRef* result) dtTileRef lastRef, dtTileRef* result)
{ {
@ -922,6 +954,10 @@ int dtNavMesh::getTilesAt(const int x, const int y, dtMeshTile** tiles, const in
return n; return n;
} }
/// @par
///
/// This function will not fail if the tiles array is too small to hold the
/// entire result set. It will simply fill the array to capacity.
int dtNavMesh::getTilesAt(const int x, const int y, dtMeshTile const** tiles, const int maxTiles) const int dtNavMesh::getTilesAt(const int x, const int y, dtMeshTile const** tiles, const int maxTiles) const
{ {
int n = 0; int n = 0;
@ -1012,6 +1048,11 @@ dtStatus dtNavMesh::getTileAndPolyByRef(const dtPolyRef ref, const dtMeshTile**
return DT_SUCCESS; return DT_SUCCESS;
} }
/// @par
///
/// @warning Only use this function if it is known that the provided polygon
/// reference is valid. This function is faster than #getTileAndPolyByRef, but
/// it does not validate the reference.
void dtNavMesh::getTileAndPolyByRefUnsafe(const dtPolyRef ref, const dtMeshTile** tile, const dtPoly** poly) const void dtNavMesh::getTileAndPolyByRefUnsafe(const dtPolyRef ref, const dtMeshTile** tile, const dtPoly** poly) const
{ {
unsigned int salt, it, ip; unsigned int salt, it, ip;
@ -1031,6 +1072,12 @@ bool dtNavMesh::isValidPolyRef(dtPolyRef ref) const
return true; return true;
} }
/// @par
///
/// This function returns the data for the tile so that, if desired,
/// it can be added back to the navigation mesh at a later point.
///
/// @see #addTile
dtStatus dtNavMesh::removeTile(dtTileRef ref, unsigned char** data, int* dataSize) dtStatus dtNavMesh::removeTile(dtTileRef ref, unsigned char** data, int* dataSize)
{ {
if (!ref) if (!ref)
@ -1130,6 +1177,20 @@ dtTileRef dtNavMesh::getTileRef(const dtMeshTile* tile) const
return (dtTileRef)encodePolyId(tile->salt, it, 0); return (dtTileRef)encodePolyId(tile->salt, it, 0);
} }
/// @par
///
/// Example use case:
/// @code
///
/// const dtPolyRef base = navmesh->getPolyRefBase(tile);
/// for (int i = 0; i < tile->header->polyCount; ++i)
/// {
/// const dtPoly* p = &tile->polys[i];
/// const dtPolyRef ref = base | (dtPolyRef)i;
///
/// // Use the reference to access the polygon data.
/// }
/// @endcode
dtPolyRef dtNavMesh::getPolyRefBase(const dtMeshTile* tile) const dtPolyRef dtNavMesh::getPolyRefBase(const dtMeshTile* tile) const
{ {
if (!tile) return 0; if (!tile) return 0;
@ -1150,6 +1211,7 @@ struct dtPolyState
unsigned char area; // Area ID of the polygon. unsigned char area; // Area ID of the polygon.
}; };
/// @see #storeTileState
int dtNavMesh::getTileStateSize(const dtMeshTile* tile) const int dtNavMesh::getTileStateSize(const dtMeshTile* tile) const
{ {
if (!tile) return 0; if (!tile) return 0;
@ -1158,6 +1220,11 @@ int dtNavMesh::getTileStateSize(const dtMeshTile* tile) const
return headerSize + polyStateSize; return headerSize + polyStateSize;
} }
/// @par
///
/// Tile state includes non-structural data such as polygon flags, area ids, etc.
/// @note The state data is only valid until the tile reference changes.
/// @see #getTileStateSize, #restoreTileState
dtStatus dtNavMesh::storeTileState(const dtMeshTile* tile, unsigned char* data, const int maxDataSize) const dtStatus dtNavMesh::storeTileState(const dtMeshTile* tile, unsigned char* data, const int maxDataSize) const
{ {
// Make sure there is enough space to store the state. // Make sure there is enough space to store the state.
@ -1185,6 +1252,11 @@ dtStatus dtNavMesh::storeTileState(const dtMeshTile* tile, unsigned char* data,
return DT_SUCCESS; return DT_SUCCESS;
} }
/// @par
///
/// Tile state includes non-structural data such as polygon flags, area ids, etc.
/// @note This function does not impact the tile's #dtTileRef and #dtPolyRef's.
/// @see #storeTileState
dtStatus dtNavMesh::restoreTileState(dtMeshTile* tile, const unsigned char* data, const int maxDataSize) dtStatus dtNavMesh::restoreTileState(dtMeshTile* tile, const unsigned char* data, const int maxDataSize)
{ {
// Make sure there is enough space to store the state. // Make sure there is enough space to store the state.
@ -1215,7 +1287,13 @@ dtStatus dtNavMesh::restoreTileState(dtMeshTile* tile, const unsigned char* data
return DT_SUCCESS; return DT_SUCCESS;
} }
// Returns start and end location of an off-mesh link polygon. /// @par
///
/// Off-mesh connections are stored in the navigation mesh as special 2-vertex
/// polygons with a single edge. At least one of the vertices is expected to be
/// inside a normal polygon. So an off-mesh connection is "entered" from a
/// normal polygon at one of its endpoints. This is the polygon identified by
/// the prevRef parameter.
dtStatus dtNavMesh::getOffMeshConnectionPolyEndPoints(dtPolyRef prevRef, dtPolyRef polyRef, float* startPos, float* endPos) const dtStatus dtNavMesh::getOffMeshConnectionPolyEndPoints(dtPolyRef prevRef, dtPolyRef polyRef, float* startPos, float* endPos) const
{ {
unsigned int salt, it, ip; unsigned int salt, it, ip;

View File

@ -27,6 +27,38 @@
#include "DetourAssert.h" #include "DetourAssert.h"
#include <new> #include <new>
/// @class dtQueryFilter
///
/// <b>The Default Implmentation</b>
///
/// At construction: All area costs default to 1.0. All flags are included
/// and none are excluded.
///
/// If a polygon has both an include and an exclude flag, it will be excluded.
///
/// The way filtering works, a navigation mesh polygon must have at least one flag
/// set to ever be considered by a query. So a polygon with no flags will never
/// be considered.
///
/// Setting the include flags to 0 will result in all polygons being excluded.
///
/// <b>Custom Implementations</b>
///
/// DT_VIRTUAL_QUERYFILTER must be defined in order to extend this class.
///
/// Implement a custom query filter by overriding the virtual passFilter()
/// and getCost() functions. If this is done, both functions should be as
/// fast as possible. Use cached local copies of data rather than accessing
/// your own objects where possible.
///
/// Custom implementations do not need to adhere to the flags or cost logic
/// used by the default implementation.
///
/// In order for A* searches to work properly, the cost should be proportional to
/// the travel distance. Implementing a cost modifier less than 1.0 is likely
/// to lead to problems during pathfinding.
///
/// @see dtNavMeshQuery
dtQueryFilter::dtQueryFilter() : dtQueryFilter::dtQueryFilter() :
m_includeFlags(0xffff), m_includeFlags(0xffff),
@ -86,6 +118,23 @@ void dtFreeNavMeshQuery(dtNavMeshQuery* navmesh)
} }
////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////
/// @class dtNavMeshQuery
///
/// For methods that support undersized buffers, if the buffer is too small
/// to hold the entire result set the return status of the method will include
/// the #DT_BUFFER_TOO_SMALL flag.
///
/// Constant member functions can be used by multiple clients without side
/// effects. (E.g. No change to the closed list. No impact on an in-progress
/// sliced path query. Etc.)
///
/// Walls and portals: A @e wall is a polygon segment that is
/// considered impassable. A @e portal is a passable segment between polygons.
/// A portal may be treated as a wall based on the dtQueryFilter used for a query.
///
/// @see dtNavMesh, dtQueryFilter, #dtAllocNavMeshQuery(), #dtAllocNavMeshQuery()
dtNavMeshQuery::dtNavMeshQuery() : dtNavMeshQuery::dtNavMeshQuery() :
m_tinyNodePool(0), m_tinyNodePool(0),
m_nodePool(0), m_nodePool(0),
@ -107,6 +156,12 @@ dtNavMeshQuery::~dtNavMeshQuery()
dtFree(m_openList); dtFree(m_openList);
} }
/// @par
///
/// Must be the first function called after construction, before other
/// functions are used.
///
/// This function can be used multiple times.
dtStatus dtNavMeshQuery::init(const dtNavMesh* nav, const int maxNodes) dtStatus dtNavMeshQuery::init(const dtNavMesh* nav, const int maxNodes)
{ {
m_nav = nav; m_nav = nav;
@ -161,6 +216,15 @@ dtStatus dtNavMeshQuery::init(const dtNavMesh* nav, const int maxNodes)
} }
////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////
/// @par
///
/// Uses the detail polygons to find the surface height. (Most accurate.)
///
/// @p pos does not have to be within the bounds of the polygon or navigation mesh.
///
/// See closestPointOnPolyBoundary() for a limited but faster option.
///
dtStatus dtNavMeshQuery::closestPointOnPoly(dtPolyRef ref, const float* pos, float* closest) const dtStatus dtNavMeshQuery::closestPointOnPoly(dtPolyRef ref, const float* pos, float* closest) const
{ {
dtAssert(m_nav); dtAssert(m_nav);
@ -257,6 +321,17 @@ void dtNavMeshQuery::closestPointOnPolyInTile(const dtMeshTile* tile, const dtPo
} }
} }
/// @par
///
/// Much faster than closestPointOnPoly().
///
/// If the provided position lies within the polygon's xz-bounds (above or below),
/// then @p pos and @p closest will be equal.
///
/// The height of @p closest will be the polygon boundary. The height detail is not used.
///
/// @p pos does not have to be within the bounds of the polybon or the navigation mesh.
///
dtStatus dtNavMeshQuery::closestPointOnPolyBoundary(dtPolyRef ref, const float* pos, float* closest) const dtStatus dtNavMeshQuery::closestPointOnPolyBoundary(dtPolyRef ref, const float* pos, float* closest) const
{ {
dtAssert(m_nav); dtAssert(m_nav);
@ -304,7 +379,11 @@ dtStatus dtNavMeshQuery::closestPointOnPolyBoundary(dtPolyRef ref, const float*
return DT_SUCCESS; return DT_SUCCESS;
} }
/// @par
///
/// Will return #DT_FAILURE if the provided position is outside the xz-bounds
/// of the polygon.
///
dtStatus dtNavMeshQuery::getPolyHeight(dtPolyRef ref, const float* pos, float* height) const dtStatus dtNavMeshQuery::getPolyHeight(dtPolyRef ref, const float* pos, float* height) const
{ {
dtAssert(m_nav); dtAssert(m_nav);
@ -353,6 +432,12 @@ dtStatus dtNavMeshQuery::getPolyHeight(dtPolyRef ref, const float* pos, float* h
return DT_FAILURE | DT_INVALID_PARAM; return DT_FAILURE | DT_INVALID_PARAM;
} }
/// @par
///
/// @note If the search box does not intersect any polygons the search will
/// return #DT_SUCCESS, but @p nearestRef will be zero. So if in doubt, check
/// @p nearestRef before using @p nearestPt.
///
dtStatus dtNavMeshQuery::findNearestPoly(const float* center, const float* extents, dtStatus dtNavMeshQuery::findNearestPoly(const float* center, const float* extents,
const dtQueryFilter* filter, const dtQueryFilter* filter,
dtPolyRef* nearestRef, float* nearestPt) const dtPolyRef* nearestRef, float* nearestPt) const
@ -519,6 +604,15 @@ int dtNavMeshQuery::queryPolygonsInTile(const dtMeshTile* tile, const float* qmi
} }
} }
/// @par
///
/// If no polygons are found, the function will return #DT_SUCCESS with a
/// @p polyCount of zero.
///
/// If @p polys is too small to hold the entire result set, then the array will
/// be filled to capacity. The method of choosing which polygons from the
/// full set are included in the partial result set is undefined.
///
dtStatus dtNavMeshQuery::queryPolygons(const float* center, const float* extents, dtStatus dtNavMeshQuery::queryPolygons(const float* center, const float* extents,
const dtQueryFilter* filter, const dtQueryFilter* filter,
dtPolyRef* polys, int* polyCount, const int maxPolys) const dtPolyRef* polys, int* polyCount, const int maxPolys) const
@ -559,6 +653,17 @@ dtStatus dtNavMeshQuery::queryPolygons(const float* center, const float* extents
return DT_SUCCESS; return DT_SUCCESS;
} }
/// @par
///
/// If the end polygon cannot be reached through the navigation graph,
/// the last polygon in the path will be the nearest the end polygon.
///
/// If the path array is to small to hold the full result, it will be filled as
/// far as possible from the start polygon toward the end polygon.
///
/// The start and end positions are used to calculate traversal costs.
/// (The y-values impact the result.)
///
dtStatus dtNavMeshQuery::findPath(dtPolyRef startRef, dtPolyRef endRef, dtStatus dtNavMeshQuery::findPath(dtPolyRef startRef, dtPolyRef endRef,
const float* startPos, const float* endPos, const float* startPos, const float* endPos,
const dtQueryFilter* filter, const dtQueryFilter* filter,
@ -769,6 +874,14 @@ dtStatus dtNavMeshQuery::findPath(dtPolyRef startRef, dtPolyRef endRef,
return status; return status;
} }
/// @par
///
/// @warning Calling any non-slice methods before calling finalizeSlicedFindPath()
/// or finalizeSlicedFindPathPartial() may result in corrupted data!
///
/// The @p filter pointer is stored and used for the duration of the sliced
/// path query.
///
dtStatus dtNavMeshQuery::initSlicedFindPath(dtPolyRef startRef, dtPolyRef endRef, dtStatus dtNavMeshQuery::initSlicedFindPath(dtPolyRef startRef, dtPolyRef endRef,
const float* startPos, const float* endPos, const float* startPos, const float* endPos,
const dtQueryFilter* filter) const dtQueryFilter* filter)
@ -1134,7 +1247,23 @@ dtStatus dtNavMeshQuery::finalizeSlicedFindPathPartial(const dtPolyRef* existing
return DT_SUCCESS | details; return DT_SUCCESS | details;
} }
/// @par
///
/// This method peforms what is often called 'string pulling'.
///
/// The start position is clamped to the first polygon in the path, and the
/// end position is clamped to the last. So the start and end positions should
/// normally be within or very near the first and last polygons respectively.
///
/// The returned polygon references represent the reference id of the polygon
/// that is entered at the associated path position. The reference id associated
/// with the end point will always be zero. This allows, for example, matching
/// off-mesh link points to their representative polygons.
///
/// If the provided result buffers are too small for the entire result set,
/// they will be filled as far as possible from the start toward the end
/// position.
///
dtStatus dtNavMeshQuery::findStraightPath(const float* startPos, const float* endPos, dtStatus dtNavMeshQuery::findStraightPath(const float* startPos, const float* endPos,
const dtPolyRef* path, const int pathSize, const dtPolyRef* path, const int pathSize,
float* straightPath, unsigned char* straightPathFlags, dtPolyRef* straightPathRefs, float* straightPath, unsigned char* straightPathFlags, dtPolyRef* straightPathRefs,
@ -1378,6 +1507,26 @@ dtStatus dtNavMeshQuery::findStraightPath(const float* startPos, const float* en
return DT_SUCCESS | ((n >= maxStraightPath) ? DT_BUFFER_TOO_SMALL : 0); return DT_SUCCESS | ((n >= maxStraightPath) ? DT_BUFFER_TOO_SMALL : 0);
} }
/// @par
///
/// This method is optimized for small delta movement and a small number of
/// polygons. If used for too great a distance, the result set will form an
/// incomplete path.
///
/// @p resultPos will equal the @p endPos if the end is reached.
/// Otherwise the closest reachable position will be returned.
///
/// @p resultPos is not projected onto the surface of the navigation
/// mesh. Use #getPolyHeight if this is needed.
///
/// This method treats the end position in the same manner as
/// the #raycast method. (As a 2D point.) See that method's documentation
/// for details.
///
/// If the @p visited array is too small to hold the entire result set, it will
/// be filled as far as possible from the start position toward the end
/// position.
///
dtStatus dtNavMeshQuery::moveAlongSurface(dtPolyRef startRef, const float* startPos, const float* endPos, dtStatus dtNavMeshQuery::moveAlongSurface(dtPolyRef startRef, const float* startPos, const float* endPos,
const dtQueryFilter* filter, const dtQueryFilter* filter,
float* resultPos, dtPolyRef* visited, int* visitedCount, const int maxVisitedSize) const float* resultPos, dtPolyRef* visited, int* visitedCount, const int maxVisitedSize) const
@ -1696,6 +1845,44 @@ dtStatus dtNavMeshQuery::getEdgeMidPoint(dtPolyRef from, const dtPoly* fromPoly,
return DT_SUCCESS; return DT_SUCCESS;
} }
/// @par
///
/// This method is meant to be used for quick, short distance checks.
///
/// If the path array is too small to hold the result, it will be filled as
/// far as possible from the start postion toward the end position.
///
/// <b>Using the Hit Parameter (t)</b>
///
/// If the hit parameter is a very high value (FLT_MAX), then the ray has hit
/// the end position. In this case the path represents a valid corridor to the
/// end position and the value of @p hitNormal is undefined.
///
/// If the hit parameter is zero, then the start position is on the wall that
/// was hit and the value of @p hitNormal is undefined.
///
/// If 0 < t < 1.0 then the following applies:
///
/// @code
/// distanceToHitBorder = distanceToEndPosition * t
/// hitPoint = startPos + (endPos - startPos) * t
/// @endcode
///
/// <b>Use Case Restriction</b>
///
/// The raycast ignores the y-value of the end position. (2D check.) This
/// places significant limits on how it can be used. For example:
///
/// Consider a scene where there is a main floor with a second floor balcony
/// that hangs over the main floor. So the first floor mesh extends below the
/// balcony mesh. The start position is somewhere on the first floor. The end
/// position is on the balcony.
///
/// The raycast will search toward the end position along the first floor mesh.
/// If it reaches the end position's xz-coordinates it will indicate FLT_MAX
/// (no wall hit), meaning it reached the end position. This is one example of why
/// this method is meant for short distance checks.
///
dtStatus dtNavMeshQuery::raycast(dtPolyRef startRef, const float* startPos, const float* endPos, dtStatus dtNavMeshQuery::raycast(dtPolyRef startRef, const float* startPos, const float* endPos,
const dtQueryFilter* filter, const dtQueryFilter* filter,
float* t, float* hitNormal, dtPolyRef* path, int* pathCount, const int maxPath) const float* t, float* hitNormal, dtPolyRef* path, int* pathCount, const int maxPath) const
@ -1877,6 +2064,35 @@ dtStatus dtNavMeshQuery::raycast(dtPolyRef startRef, const float* startPos, cons
return status; return status;
} }
/// @par
///
/// At least one result array must be provided.
///
/// The order of the result set is from least to highest cost to reach the polygon.
///
/// A common use case for this method is to perform Dijkstra searches.
/// Candidate polygons are found by searching the graph beginning at the start polygon.
///
/// If a polygon is not found via the graph search, even if it intersects the
/// search circle, it will not be included in the result set. For example:
///
/// polyA is the start polygon.
/// polyB shares an edge with polyA. (Is adjacent.)
/// polyC shares an edge with polyB, but not with polyA
/// Even if the search circle overlaps polyC, it will not be included in the
/// result set unless polyB is also in the set.
///
/// The value of the center point is used as the start position for cost
/// calculations. It is not projected onto the surface of the mesh, so its
/// y-value will effect the costs.
///
/// Intersection tests occur in 2D. All polygons and the search circle are
/// projected onto the xz-plane. So the y-value of the center point does not
/// effect intersection tests.
///
/// If the result arrays are to small to hold the entire result set, they will be
/// filled to capacity.
///
dtStatus dtNavMeshQuery::findPolysAroundCircle(dtPolyRef startRef, const float* centerPos, const float radius, dtStatus dtNavMeshQuery::findPolysAroundCircle(dtPolyRef startRef, const float* centerPos, const float radius,
const dtQueryFilter* filter, const dtQueryFilter* filter,
dtPolyRef* resultRef, dtPolyRef* resultParent, float* resultCost, dtPolyRef* resultRef, dtPolyRef* resultParent, float* resultCost,
@ -2030,6 +2246,28 @@ dtStatus dtNavMeshQuery::findPolysAroundCircle(dtPolyRef startRef, const float*
return status; return status;
} }
/// @par
///
/// The order of the result set is from least to highest cost.
///
/// At least one result array must be provided.
///
/// A common use case for this method is to perform Dijkstra searches.
/// Candidate polygons are found by searching the graph beginning at the start
/// polygon.
///
/// The same intersection test restrictions that apply to findPolysAroundCircle()
/// method apply to this method.
///
/// The 3D centroid of the search polygon is used as the start position for cost
/// calculations.
///
/// Intersection tests occur in 2D. All polygons are projected onto the
/// xz-plane. So the y-values of the vertices do not effect intersection tests.
///
/// If the result arrays are is too small to hold the entire result set, they will
/// be filled to capacity.
///
dtStatus dtNavMeshQuery::findPolysAroundShape(dtPolyRef startRef, const float* verts, const int nverts, dtStatus dtNavMeshQuery::findPolysAroundShape(dtPolyRef startRef, const float* verts, const int nverts,
const dtQueryFilter* filter, const dtQueryFilter* filter,
dtPolyRef* resultRef, dtPolyRef* resultParent, float* resultCost, dtPolyRef* resultRef, dtPolyRef* resultParent, float* resultCost,
@ -2188,6 +2426,28 @@ dtStatus dtNavMeshQuery::findPolysAroundShape(dtPolyRef startRef, const float* v
return status; return status;
} }
/// @par
///
/// This method is optimized for a small search radius and small number of result
/// polygons.
///
/// Candidate polygons are found by searching the navigation graph beginning at
/// the start polygon.
///
/// The same intersection test restrictions that apply to the findPolysAroundCircle
/// mehtod applies to this method.
///
/// The value of the center point is used as the start point for cost calculations.
/// It is not projected onto the surface of the mesh, so its y-value will effect
/// the costs.
///
/// Intersection tests occur in 2D. All polygons and the search circle are
/// projected onto the xz-plane. So the y-value of the center point does not
/// effect intersection tests.
///
/// If the result arrays are is too small to hold the entire result set, they will
/// be filled to capacity.
///
dtStatus dtNavMeshQuery::findLocalNeighbourhood(dtPolyRef startRef, const float* centerPos, const float radius, dtStatus dtNavMeshQuery::findLocalNeighbourhood(dtPolyRef startRef, const float* centerPos, const float radius,
const dtQueryFilter* filter, const dtQueryFilter* filter,
dtPolyRef* resultRef, dtPolyRef* resultParent, dtPolyRef* resultRef, dtPolyRef* resultParent,
@ -2392,6 +2652,17 @@ static void insertInterval(dtSegInterval* ints, int& nints, const int maxInts,
nints++; nints++;
} }
/// @par
///
/// If the @p segmentRefs parameter is provided, then all polygon segments will be returned.
/// Otherwise only the wall segments are returned.
///
/// A segment that is normally a portal will be included in the result set as a
/// wall if the @p filter results in the neighbor polygon becoomming impassable.
///
/// The @p segmentVerts and @p segmentRefs buffers should normally be sized for the
/// maximum segments per polygon of the source navigation mesh.
///
dtStatus dtNavMeshQuery::getPolyWallSegments(dtPolyRef ref, const dtQueryFilter* filter, dtStatus dtNavMeshQuery::getPolyWallSegments(dtPolyRef ref, const dtQueryFilter* filter,
float* segmentVerts, dtPolyRef* segmentRefs, int* segmentCount, float* segmentVerts, dtPolyRef* segmentRefs, int* segmentCount,
const int maxSegments) const const int maxSegments) const
@ -2532,6 +2803,16 @@ dtStatus dtNavMeshQuery::getPolyWallSegments(dtPolyRef ref, const dtQueryFilter*
return status; return status;
} }
/// @par
///
/// @p hitPos is not adjusted using the height detail data.
///
/// @p hitDist will equal the search radius if there is no wall within the
/// radius. In this case the values of @p hitPos and @p hitNormal are
/// undefined.
///
/// The normal will become unpredicable if @p hitDist is a very small number.
///
dtStatus dtNavMeshQuery::findDistanceToWall(dtPolyRef startRef, const float* centerPos, const float maxRadius, dtStatus dtNavMeshQuery::findDistanceToWall(dtPolyRef startRef, const float* centerPos, const float maxRadius,
const dtQueryFilter* filter, const dtQueryFilter* filter,
float* hitDist, float* hitPos, float* hitNormal) const float* hitDist, float* hitPos, float* hitNormal) const
@ -2728,6 +3009,11 @@ bool dtNavMeshQuery::isValidPolyRef(dtPolyRef ref, const dtQueryFilter* filter)
return true; return true;
} }
/// @par
///
/// The closed list is the list of polygons that were fully evaluated during
/// the last navigation graph search. (A* or Dijkstra)
///
bool dtNavMeshQuery::isInClosedList(dtPolyRef ref) const bool dtNavMeshQuery::isInClosedList(dtPolyRef ref) const
{ {
if (!m_nodePool) return false; if (!m_nodePool) return false;