Updated recast to 1.5.1

This commit is contained in:
Johxz 2016-12-11 13:17:15 -06:00
parent 630949514a
commit c7e5b35744
55 changed files with 3277 additions and 1460 deletions

View file

@ -1,24 +0,0 @@
CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
SET(detour_SRCS
Source/DetourAlloc.cpp
Source/DetourCommon.cpp
Source/DetourNavMesh.cpp
Source/DetourNavMeshBuilder.cpp
Source/DetourNavMeshQuery.cpp
Source/DetourNode.cpp
)
SET(detour_HDRS
Include/DetourAlloc.h
Include/DetourAssert.h
Include/DetourCommon.h
Include/DetourNavMesh.h
Include/DetourNavMeshBuilder.h
Include/DetourNavMeshQuery.h
Include/DetourNode.h
)
INCLUDE_DIRECTORIES(Include)
ADD_LIBRARY(Detour ${detour_SRCS} ${detour_HDRS})

View file

@ -19,6 +19,8 @@
#ifndef DETOURALLOCATOR_H
#define DETOURALLOCATOR_H
#include <stddef.h>
/// Provides hint values to the memory allocator on how long the
/// memory is expected to be used.
enum dtAllocHint
@ -32,7 +34,7 @@ enum dtAllocHint
// @param[in] rcAllocHint A hint to the allocator on how long the memory is expected to be in use.
// @return A pointer to the beginning of the allocated memory block, or null if the allocation failed.
/// @see dtAllocSetCustom
typedef void* (dtAllocFunc)(int size, dtAllocHint hint);
typedef void* (dtAllocFunc)(size_t size, dtAllocHint hint);
/// A memory deallocation function.
/// @param[in] ptr A pointer to a memory block previously allocated using #dtAllocFunc.
@ -49,7 +51,7 @@ void dtAllocSetCustom(dtAllocFunc *allocFunc, dtFreeFunc *freeFunc);
/// @param[in] hint A hint to the allocator on how long the memory is expected to be in use.
/// @return A pointer to the beginning of the allocated memory block, or null if the allocation failed.
/// @see dtFree
void* dtAlloc(int size, dtAllocHint hint);
void* dtAlloc(size_t size, dtAllocHint hint);
/// Deallocates a memory block.
/// @param[in] ptr A pointer to a memory block previously allocated using #dtAlloc.

View file

@ -19,6 +19,8 @@
#ifndef DETOURCOMMON_H
#define DETOURCOMMON_H
#include "DetourMath.h"
/**
@defgroup detour Detour
@ -32,6 +34,11 @@ feature to find minor members.
/// @name General helper functions
/// @{
/// Used to ignore a function parameter. VS complains about unused parameters
/// and this silences the warning.
/// @param [in] _ Unused parameter
template<class T> void dtIgnoreUnused(const T&) { }
/// Swaps the values of the two parameters.
/// @param[in,out] a Value A
/// @param[in,out] b Value B
@ -66,11 +73,6 @@ template<class T> inline T dtSqr(T a) { return a*a; }
/// @return The value, clamped to the specified range.
template<class T> inline T dtClamp(T v, T mn, T mx) { return v < mn ? mn : (v > mx ? mx : v); }
/// Returns the square root of the value.
/// @param[in] x The value.
/// @return The square root of the vlaue.
float dtSqrt(float x);
/// @}
/// @name Vector helper functions.
/// @{
@ -197,7 +199,7 @@ inline void dtVcopy(float* dest, const float* a)
/// @return The scalar length of the vector.
inline float dtVlen(const float* v)
{
return dtSqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);
return dtMathSqrtf(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
}
/// Derives the square of the scalar length of the vector. (len * len)
@ -217,7 +219,7 @@ inline float dtVdist(const float* v1, const float* v2)
const float dx = v2[0] - v1[0];
const float dy = v2[1] - v1[1];
const float dz = v2[2] - v1[2];
return dtSqrt(dx*dx + dy*dy + dz*dz);
return dtMathSqrtf(dx*dx + dy*dy + dz*dz);
}
/// Returns the square of the distance between two points.
@ -242,7 +244,7 @@ inline float dtVdist2D(const float* v1, const float* v2)
{
const float dx = v2[0] - v1[0];
const float dz = v2[2] - v1[2];
return dtSqrt(dx*dx + dz*dz);
return dtMathSqrtf(dx*dx + dz*dz);
}
/// Derives the square of the distance between the specified points on the xz-plane.
@ -260,7 +262,7 @@ inline float dtVdist2DSqr(const float* v1, const float* v2)
/// @param[in,out] v The vector to normalize. [(x, y, z)]
inline void dtVnormalize(float* v)
{
float d = 1.0f / dtSqrt(dtSqr(v[0]) + dtSqr(v[1]) + dtSqr(v[2]));
float d = 1.0f / dtMathSqrtf(dtSqr(v[0]) + dtSqr(v[1]) + dtSqr(v[2]));
v[0] *= d;
v[1] *= d;
v[2] *= d;
@ -376,6 +378,10 @@ bool dtIntersectSegmentPoly2D(const float* p0, const float* p1,
float& tmin, float& tmax,
int& segMin, int& segMax);
bool dtIntersectSegSeg2D(const float* ap, const float* aq,
const float* bp, const float* bq,
float& s, float& t);
/// Determines if the specified point is inside the convex polygon on the xz-plane.
/// @param[in] pt The point to check. [(x, y, z)]
/// @param[in] verts The polygon vertices. [(x, y, z) * @p nverts]

View file

@ -0,0 +1,20 @@
/**
@defgroup detour Detour
Members in this module are wrappers around the standard math library
*/
#ifndef DETOURMATH_H
#define DETOURMATH_H
#include <math.h>
inline float dtMathFabsf(float x) { return fabsf(x); }
inline float dtMathSqrtf(float x) { return sqrtf(x); }
inline float dtMathFloorf(float x) { return floorf(x); }
inline float dtMathCeilf(float x) { return ceilf(x); }
inline float dtMathCosf(float x) { return cosf(x); }
inline float dtMathSinf(float x) { return sinf(x); }
inline float dtMathAtan2f(float y, float x) { return atan2f(y, x); }
#endif

View file

@ -22,16 +22,39 @@
#include "DetourAlloc.h"
#include "DetourStatus.h"
// Undefine (or define in a build cofnig) the following line to use 64bit polyref.
// Generally not needed, useful for very large worlds.
// Note: tiles build using 32bit refs are not compatible with 64bit refs!
//#define DT_POLYREF64 1
#ifdef DT_POLYREF64
// TODO: figure out a multiplatform version of uint64_t
// - maybe: https://code.google.com/p/msinttypes/
// - or: http://www.azillionmonkeys.com/qed/pstdint.h
#include <stdint.h>
#endif
// Note: If you want to use 64-bit refs, change the types of both dtPolyRef & dtTileRef.
// It is also recommended that you change dtHashRef() to a proper 64-bit hash.
/// A handle to a polygon within a navigation mesh tile.
/// @ingroup detour
#ifdef DT_POLYREF64
static const unsigned int DT_SALT_BITS = 16;
static const unsigned int DT_TILE_BITS = 28;
static const unsigned int DT_POLY_BITS = 20;
typedef uint64_t dtPolyRef;
#else
typedef unsigned int dtPolyRef;
#endif
/// A handle to a tile within a navigation mesh.
/// @ingroup detour
#ifdef DT_POLYREF64
typedef uint64_t dtTileRef;
#else
typedef unsigned int dtTileRef;
#endif
/// The maximum number of vertices per navigation polygon.
/// @ingroup detour
@ -87,6 +110,31 @@ enum dtStraightPathFlags
DT_STRAIGHTPATH_OFFMESH_CONNECTION = 0x04, ///< The vertex is the start of an off-mesh connection.
};
/// Options for dtNavMeshQuery::findStraightPath.
enum dtStraightPathOptions
{
DT_STRAIGHTPATH_AREA_CROSSINGS = 0x01, ///< Add a vertex at every polygon edge crossing where area changes.
DT_STRAIGHTPATH_ALL_CROSSINGS = 0x02, ///< Add a vertex at every polygon edge crossing.
};
/// Options for dtNavMeshQuery::initSlicedFindPath and updateSlicedFindPath
enum dtFindPathOptions
{
DT_FINDPATH_ANY_ANGLE = 0x02, ///< use raycasts during pathfind to "shortcut" (raycast still consider costs)
};
/// Options for dtNavMeshQuery::raycast
enum dtRaycastOptions
{
DT_RAYCAST_USE_COSTS = 0x01, ///< Raycast should calculate movement cost along the ray and fill RaycastHit::cost
};
/// Limit raycasting during any angle pahfinding
/// The limit is given as a multiple of the character radius
static const float DT_RAY_CAST_LIMIT_PROPORTIONS = 50.0f;
/// Flags representing the type of a navigation mesh polygon.
enum dtPolyTypes
{
@ -97,7 +145,7 @@ enum dtPolyTypes
};
/// Defines a polyogn within a dtMeshTile object.
/// Defines a polygon within a dtMeshTile object.
/// @ingroup detour
struct dtPoly
{
@ -252,6 +300,9 @@ struct dtMeshTile
int dataSize; ///< Size of the tile data.
int flags; ///< Tile flags. (See: #dtTileFlags)
dtMeshTile* next; ///< The next free tile, or the next tile in the spatial grid.
private:
dtMeshTile(const dtMeshTile&);
dtMeshTile& operator=(const dtMeshTile&);
};
/// Configuration parameters used to define multi-tile navigation meshes.
@ -462,7 +513,11 @@ public:
/// @param[in] ip The index of the polygon within the tile.
inline dtPolyRef encodePolyId(unsigned int salt, unsigned int it, unsigned int ip) const
{
#ifdef DT_POLYREF64
return ((dtPolyRef)salt << (DT_POLY_BITS+DT_TILE_BITS)) | ((dtPolyRef)it << DT_POLY_BITS) | (dtPolyRef)ip;
#else
return ((dtPolyRef)salt << (m_polyBits+m_tileBits)) | ((dtPolyRef)it << m_polyBits) | (dtPolyRef)ip;
#endif
}
/// Decodes a standard polygon reference.
@ -474,12 +529,21 @@ public:
/// @see #encodePolyId
inline void decodePolyId(dtPolyRef ref, unsigned int& salt, unsigned int& it, unsigned int& ip) const
{
#ifdef DT_POLYREF64
const dtPolyRef saltMask = ((dtPolyRef)1<<DT_SALT_BITS)-1;
const dtPolyRef tileMask = ((dtPolyRef)1<<DT_TILE_BITS)-1;
const dtPolyRef polyMask = ((dtPolyRef)1<<DT_POLY_BITS)-1;
salt = (unsigned int)((ref >> (DT_POLY_BITS+DT_TILE_BITS)) & saltMask);
it = (unsigned int)((ref >> DT_POLY_BITS) & tileMask);
ip = (unsigned int)(ref & polyMask);
#else
const dtPolyRef saltMask = ((dtPolyRef)1<<m_saltBits)-1;
const dtPolyRef tileMask = ((dtPolyRef)1<<m_tileBits)-1;
const dtPolyRef polyMask = ((dtPolyRef)1<<m_polyBits)-1;
salt = (unsigned int)((ref >> (m_polyBits+m_tileBits)) & saltMask);
it = (unsigned int)((ref >> m_polyBits) & tileMask);
ip = (unsigned int)(ref & polyMask);
#endif
}
/// Extracts a tile's salt value from the specified polygon reference.
@ -488,8 +552,13 @@ public:
/// @see #encodePolyId
inline unsigned int decodePolyIdSalt(dtPolyRef ref) const
{
#ifdef DT_POLYREF64
const dtPolyRef saltMask = ((dtPolyRef)1<<DT_SALT_BITS)-1;
return (unsigned int)((ref >> (DT_POLY_BITS+DT_TILE_BITS)) & saltMask);
#else
const dtPolyRef saltMask = ((dtPolyRef)1<<m_saltBits)-1;
return (unsigned int)((ref >> (m_polyBits+m_tileBits)) & saltMask);
#endif
}
/// Extracts the tile's index from the specified polygon reference.
@ -498,8 +567,13 @@ public:
/// @see #encodePolyId
inline unsigned int decodePolyIdTile(dtPolyRef ref) const
{
#ifdef DT_POLYREF64
const dtPolyRef tileMask = ((dtPolyRef)1<<DT_TILE_BITS)-1;
return (unsigned int)((ref >> DT_POLY_BITS) & tileMask);
#else
const dtPolyRef tileMask = ((dtPolyRef)1<<m_tileBits)-1;
return (unsigned int)((ref >> m_polyBits) & tileMask);
#endif
}
/// Extracts the polygon's index (within its tile) from the specified polygon reference.
@ -508,13 +582,21 @@ public:
/// @see #encodePolyId
inline unsigned int decodePolyIdPoly(dtPolyRef ref) const
{
#ifdef DT_POLYREF64
const dtPolyRef polyMask = ((dtPolyRef)1<<DT_POLY_BITS)-1;
return (unsigned int)(ref & polyMask);
#else
const dtPolyRef polyMask = ((dtPolyRef)1<<m_polyBits)-1;
return (unsigned int)(ref & polyMask);
#endif
}
/// @}
private:
// Explicitly disabled copy constructor and copy assignment operator.
dtNavMesh(const dtNavMesh&);
dtNavMesh& operator=(const dtNavMesh&);
/// Returns pointer to tile in the tile array.
dtMeshTile* getTile(int i);
@ -543,7 +625,7 @@ private:
void connectExtOffMeshLinks(dtMeshTile* tile, dtMeshTile* target, int side);
/// Removes external links at specified side.
void unconnectExtLinks(dtMeshTile* tile, dtMeshTile* target);
void unconnectLinks(dtMeshTile* tile, dtMeshTile* target);
// TODO: These methods are duplicates from dtNavMeshQuery, but are needed for off-mesh connection finding.
@ -555,8 +637,7 @@ private:
dtPolyRef findNearestPolyInTile(const dtMeshTile* tile, const float* center,
const float* extents, float* nearestPt) const;
/// Returns closest point on polygon.
void closestPointOnPolyInTile(const dtMeshTile* tile, unsigned int ip,
const float* pos, float* closest) const;
void closestPointOnPoly(dtPolyRef ref, const float* pos, float* closest, bool* posOverPoly) const;
dtNavMeshParams m_params; ///< Current initialization params. TODO: do not store this info twice.
float m_orig[3]; ///< Origin of the tile (0,0)
@ -569,9 +650,11 @@ private:
dtMeshTile* m_nextFree; ///< Freelist of tiles.
dtMeshTile* m_tiles; ///< List of tiles.
#ifndef DT_POLYREF64
unsigned int m_saltBits; ///< Number of salt bits in the tile ID.
unsigned int m_tileBits; ///< Number of tile bits in the tile ID.
unsigned int m_polyBits; ///< Number of poly bits in the tile ID.
#endif
};
/// Allocates a navigation mesh object using the Detour allocator.

View file

@ -41,6 +41,10 @@ class dtQueryFilter
public:
dtQueryFilter();
#ifdef DT_VIRTUAL_QUERYFILTER
virtual ~dtQueryFilter() { }
#endif
/// Returns true if the polygon can be visited. (I.e. Is traversable.)
/// @param[in] ref The reference id of the polygon test.
/// @param[in] tile The tile containing the polygon.
@ -115,6 +119,37 @@ public:
};
/// Provides information about raycast hit
/// filled by dtNavMeshQuery::raycast
/// @ingroup detour
struct dtRaycastHit
{
/// The hit parameter. (FLT_MAX if no wall hit.)
float t;
/// hitNormal The normal of the nearest wall hit. [(x, y, z)]
float hitNormal[3];
/// The index of the edge on the final polygon where the wall was hit.
int hitEdgeIndex;
/// Pointer to an array of reference ids of the visited polygons. [opt]
dtPolyRef* path;
/// The number of visited polygons. [opt]
int pathCount;
/// The maximum number of polygons the @p path array can hold.
int maxPath;
/// The cost of the path until hit.
float pathCost;
};
/// Provides the ability to perform pathfinding related queries against
/// a navigation mesh.
/// @ingroup detour
@ -126,7 +161,7 @@ public:
/// Initializes the query object.
/// @param[in] nav Pointer to the dtNavMesh object to use for all queries.
/// @param[in] maxNodes Maximum number of search nodes. [Limits: 0 < value <= 65536]
/// @param[in] maxNodes Maximum number of search nodes. [Limits: 0 < value <= 65535]
/// @returns The status flags for the query.
dtStatus init(const dtNavMesh* nav, const int maxNodes);
@ -158,11 +193,12 @@ public:
/// @param[out] straightPathRefs The reference id of the polygon that is being entered at each point. [opt]
/// @param[out] straightPathCount The number of points in the straight path.
/// @param[in] maxStraightPath The maximum number of points the straight path arrays can hold. [Limit: > 0]
/// @param[in] options Query options. (see: #dtStraightPathOptions)
/// @returns The status flags for the query.
dtStatus findStraightPath(const float* startPos, const float* endPos,
const dtPolyRef* path, const int pathSize,
float* straightPath, unsigned char* straightPathFlags, dtPolyRef* straightPathRefs,
int* straightPathCount, const int maxStraightPath) const;
int* straightPathCount, const int maxStraightPath, const int options = 0) const;
///@}
/// @name Sliced Pathfinding Functions
@ -178,10 +214,11 @@ public:
/// @param[in] startPos A position within the start polygon. [(x, y, z)]
/// @param[in] endPos A position within the end polygon. [(x, y, z)]
/// @param[in] filter The polygon filter to apply to the query.
/// @param[in] options query options (see: #dtFindPathOptions)
/// @returns The status flags for the query.
dtStatus initSlicedFindPath(dtPolyRef startRef, dtPolyRef endRef,
const float* startPos, const float* endPos,
const dtQueryFilter* filter);
const dtQueryFilter* filter, const unsigned int options = 0);
/// Updates an in-progress sliced path query.
/// @param[in] maxIter The maximum number of iterations to perform.
@ -199,8 +236,8 @@ public:
/// Finalizes and returns the results of an incomplete sliced path query, returning the path to the furthest
/// 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[in] existing An array of polygon references for the existing path.
/// @param[in] 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.
@ -307,6 +344,7 @@ public:
/// Casts a 'walkability' ray along the surface of the navigation mesh from
/// the start position toward the end position.
/// @note A wrapper around raycast(..., RaycastHit*). Retained for backward compatibility.
/// @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)]
@ -322,6 +360,22 @@ public:
const dtQueryFilter* filter,
float* t, float* hitNormal, dtPolyRef* path, int* pathCount, const int maxPath) 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[in] filter The polygon filter to apply to the query.
/// @param[in] flags govern how the raycast behaves. See dtRaycastOptions
/// @param[out] hit Pointer to a raycast hit structure which will be filled by the results.
/// @param[in] prevRef parent of start ref. Used during for cost calculation [opt]
/// @returns The status flags for the query.
dtStatus raycast(dtPolyRef startRef, const float* startPos, const float* endPos,
const dtQueryFilter* filter, const unsigned int options,
dtRaycastHit* hit, dtPolyRef prevRef = 0) 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)]
@ -377,8 +431,9 @@ public:
/// @param[in] ref The reference id of the polygon.
/// @param[in] pos The position to check. [(x, y, z)]
/// @param[out] closest The closest point on the polygon. [(x, y, z)]
/// @param[out] posOverPoly True of the position is over the polygon.
/// @returns The status flags for the query.
dtStatus closestPointOnPoly(dtPolyRef ref, const float* pos, float* closest) const;
dtStatus closestPointOnPoly(dtPolyRef ref, const float* pos, float* closest, bool* posOverPoly) const;
/// Returns a point on the boundary closest to the source point if the source point is outside the
/// polygon's xz-bounds.
@ -420,6 +475,9 @@ public:
/// @}
private:
// Explicitly disabled copy constructor and copy assignment operator
dtNavMeshQuery(const dtNavMeshQuery&);
dtNavMeshQuery& operator=(const dtNavMeshQuery&);
/// Returns neighbour tile based on side.
dtMeshTile* getNeighbourTileAt(int x, int y, int side) const;
@ -427,12 +485,7 @@ private:
/// Queries polygons within a tile.
int queryPolygonsInTile(const dtMeshTile* tile, const float* qmin, const float* qmax, const dtQueryFilter* filter,
dtPolyRef* polys, const int maxPolys) const;
/// Find nearest polygon within a tile.
dtPolyRef findNearestPolyInTile(const dtMeshTile* tile, const float* center, const float* extents,
const dtQueryFilter* filter, float* nearestPt) const;
/// Returns closest point on polygon.
void closestPointOnPolyInTile(const dtMeshTile* tile, const dtPoly* poly, const float* pos, float* closest) const;
/// Returns portal points between two polygons.
dtStatus getPortalPoints(dtPolyRef from, dtPolyRef to, float* left, float* right,
unsigned char& fromType, unsigned char& toType) const;
@ -446,6 +499,16 @@ private:
dtPolyRef to, const dtPoly* toPoly, const dtMeshTile* toTile,
float* mid) const;
// Appends vertex to a straight path
dtStatus appendVertex(const float* pos, const unsigned char flags, const dtPolyRef ref,
float* straightPath, unsigned char* straightPathFlags, dtPolyRef* straightPathRefs,
int* straightPathCount, const int maxStraightPath) const;
// Appends intermediate portal points to a straight path.
dtStatus appendPortals(const int startIdx, const int endIdx, const float* endPos, const dtPolyRef* path,
float* straightPath, unsigned char* straightPathFlags, dtPolyRef* straightPathRefs,
int* straightPathCount, const int maxStraightPath, const int options) const;
const dtNavMesh* m_nav; ///< Pointer to navmesh data.
struct dtQueryData
@ -456,6 +519,8 @@ private:
dtPolyRef startRef, endRef;
float startPos[3], endPos[3];
const dtQueryFilter* filter;
unsigned int options;
float raycastLimitSqr;
};
dtQueryData m_query; ///< Sliced query state.

View file

@ -25,48 +25,56 @@ enum dtNodeFlags
{
DT_NODE_OPEN = 0x01,
DT_NODE_CLOSED = 0x02,
DT_NODE_PARENT_DETACHED = 0x04, // parent of the node is not adjacent. Found using raycast.
};
typedef unsigned short dtNodeIndex;
static const dtNodeIndex DT_NULL_IDX = (dtNodeIndex)~0;
static const int DT_NODE_PARENT_BITS = 24;
static const int DT_NODE_STATE_BITS = 2;
struct dtNode
{
float pos[3]; ///< Position of the node.
float cost; ///< Cost from previous node to current node.
float total; ///< Cost up to the node.
unsigned int pidx : 30; ///< Index to parent node.
unsigned int flags : 2; ///< Node flags 0/open/closed.
dtPolyRef id; ///< Polygon ref the node corresponds to.
float pos[3]; ///< Position of the node.
float cost; ///< Cost from previous node to current node.
float total; ///< Cost up to the node.
unsigned int pidx : DT_NODE_PARENT_BITS; ///< Index to parent node.
unsigned int state : DT_NODE_STATE_BITS; ///< extra state information. A polyRef can have multiple nodes with different extra info. see DT_MAX_STATES_PER_NODE
unsigned int flags : 3; ///< Node flags. A combination of dtNodeFlags.
dtPolyRef id; ///< Polygon ref the node corresponds to.
};
static const int DT_MAX_STATES_PER_NODE = 1 << DT_NODE_STATE_BITS; // number of extra states per node. See dtNode::state
class dtNodePool
{
public:
dtNodePool(int maxNodes, int hashSize);
~dtNodePool();
inline void operator=(const dtNodePool&) {}
void clear();
dtNode* getNode(dtPolyRef id);
dtNode* findNode(dtPolyRef id);
// Get a dtNode by ref and extra state information. If there is none then - allocate
// There can be more than one node for the same polyRef but with different extra state information
dtNode* getNode(dtPolyRef id, unsigned char state=0);
dtNode* findNode(dtPolyRef id, unsigned char state);
unsigned int findNodes(dtPolyRef id, dtNode** nodes, const int maxNodes);
inline unsigned int getNodeIdx(const dtNode* node) const
{
if (!node) return 0;
return (unsigned int)(node - m_nodes)+1;
return (unsigned int)(node - m_nodes) + 1;
}
inline dtNode* getNodeAtIdx(unsigned int idx)
{
if (!idx) return 0;
return &m_nodes[idx-1];
return &m_nodes[idx - 1];
}
inline const dtNode* getNodeAtIdx(unsigned int idx) const
{
if (!idx) return 0;
return &m_nodes[idx-1];
return &m_nodes[idx - 1];
}
inline int getMemUsed() const
@ -82,8 +90,12 @@ public:
inline int getHashSize() const { return m_hashSize; }
inline dtNodeIndex getFirst(int bucket) const { return m_first[bucket]; }
inline dtNodeIndex getNext(int i) const { return m_next[i]; }
inline int getNodeCount() const { return m_nodeCount; }
private:
// Explicitly disabled copy constructor and copy assignment operator.
dtNodePool(const dtNodePool&);
dtNodePool& operator=(const dtNodePool&);
dtNode* m_nodes;
dtNodeIndex* m_first;
@ -98,17 +110,10 @@ class dtNodeQueue
public:
dtNodeQueue(int n);
~dtNodeQueue();
inline void operator=(dtNodeQueue&) {}
inline void clear()
{
m_size = 0;
}
inline void clear() { m_size = 0; }
inline dtNode* top()
{
return m_heap[0];
}
inline dtNode* top() { return m_heap[0]; }
inline dtNode* pop()
{
@ -141,12 +146,16 @@ public:
inline int getMemUsed() const
{
return sizeof(*this) +
sizeof(dtNode*)*(m_capacity+1);
sizeof(dtNode*) * (m_capacity + 1);
}
inline int getCapacity() const { return m_capacity; }
private:
// Explicitly disabled copy constructor and copy assignment operator.
dtNodeQueue(const dtNodeQueue&);
dtNodeQueue& operator=(const dtNodeQueue&);
void bubbleUp(int i, dtNode* node);
void trickleDown(int i, dtNode* node);

View file

@ -19,7 +19,7 @@
#include <stdlib.h>
#include "DetourAlloc.h"
static void *dtAllocDefault(int size, dtAllocHint)
static void *dtAllocDefault(size_t size, dtAllocHint)
{
return malloc(size);
}
@ -38,7 +38,7 @@ void dtAllocSetCustom(dtAllocFunc *allocFunc, dtFreeFunc *freeFunc)
sFreeFunc = freeFunc ? freeFunc : dtFreeDefault;
}
void* dtAlloc(int size, dtAllocHint hint)
void* dtAlloc(size_t size, dtAllocHint hint)
{
return sAllocFunc(size, hint);
}

View file

@ -16,16 +16,11 @@
// 3. This notice may not be removed or altered from any source distribution.
//
#include <math.h>
#include "DetourCommon.h"
#include "DetourMath.h"
//////////////////////////////////////////////////////////////////////////////////////////
float dtSqrt(float x)
{
return sqrtf(x);
}
void dtClosestPtPointTriangle(float* closest, const float* p,
const float* a, const float* b, const float* c)
{
@ -360,7 +355,7 @@ void dtRandomPointInConvexPoly(const float* pts, const int npts, float* areas,
acc += dacc;
}
float v = dtSqrt(t);
float v = dtMathSqrtf(t);
const float a = 1 - v;
const float b = (1 - u) * v;
@ -374,3 +369,20 @@ void dtRandomPointInConvexPoly(const float* pts, const int npts, float* areas,
out[2] = a*pa[2] + b*pb[2] + c*pc[2];
}
inline float vperpXZ(const float* a, const float* b) { return a[0]*b[2] - a[2]*b[0]; }
bool dtIntersectSegSeg2D(const float* ap, const float* aq,
const float* bp, const float* bq,
float& s, float& t)
{
float u[3], v[3], w[3];
dtVsub(u,aq,ap);
dtVsub(v,bq,bp);
dtVsub(w,ap,bp);
float d = vperpXZ(u,v);
if (fabsf(d) < 1e-6f) return false;
s = vperpXZ(v,w) / d;
t = vperpXZ(u,w) / d;
return true;
}

View file

@ -16,13 +16,13 @@
// 3. This notice may not be removed or altered from any source distribution.
//
#include <math.h>
#include <float.h>
#include <string.h>
#include <stdio.h>
#include "DetourNavMesh.h"
#include "DetourNode.h"
#include "DetourCommon.h"
#include "DetourMath.h"
#include "DetourAlloc.h"
#include "DetourAssert.h"
#include <new>
@ -193,11 +193,13 @@ dtNavMesh::dtNavMesh() :
m_tileLutMask(0),
m_posLookup(0),
m_nextFree(0),
m_tiles(0),
m_saltBits(0),
m_tileBits(0),
m_polyBits(0)
m_tiles(0)
{
#ifndef DT_POLYREF64
m_saltBits = 0;
m_tileBits = 0;
m_polyBits = 0;
#endif
memset(&m_params, 0, sizeof(dtNavMeshParams));
m_orig[0] = 0;
m_orig[1] = 0;
@ -249,12 +251,15 @@ dtStatus dtNavMesh::init(const dtNavMeshParams* params)
}
// Init ID generator values.
#ifndef DT_POLYREF64
m_tileBits = dtIlog2(dtNextPow2((unsigned int)params->maxTiles));
m_polyBits = dtIlog2(dtNextPow2((unsigned int)params->maxPolys));
// Only allow 31 salt bits, since the salt mask is calculated using 32bit uint and it will overflow.
m_saltBits = dtMin((unsigned int)31, 32 - m_tileBits - m_polyBits);
if (m_saltBits < 10)
return DT_FAILURE | DT_INVALID_PARAM;
#endif
return DT_SUCCESS;
}
@ -345,7 +350,7 @@ int dtNavMesh::findConnectingPolys(const float* va, const float* vb,
return n;
}
void dtNavMesh::unconnectExtLinks(dtMeshTile* tile, dtMeshTile* target)
void dtNavMesh::unconnectLinks(dtMeshTile* tile, dtMeshTile* target)
{
if (!tile || !target) return;
@ -358,10 +363,9 @@ void dtNavMesh::unconnectExtLinks(dtMeshTile* tile, dtMeshTile* target)
unsigned int pj = DT_NULL_LINK;
while (j != DT_NULL_LINK)
{
if (tile->links[j].side != 0xff &&
decodePolyIdTile(tile->links[j].ref) == targetNum)
if (decodePolyIdTile(tile->links[j].ref) == targetNum)
{
// Revove link.
// Remove link.
unsigned int nj = tile->links[j].next;
if (pj == DT_NULL_LINK)
poly->firstLink = nj;
@ -612,14 +616,65 @@ void dtNavMesh::baseOffMeshLinks(dtMeshTile* tile)
}
}
void dtNavMesh::closestPointOnPolyInTile(const dtMeshTile* tile, unsigned int ip,
const float* pos, float* closest) const
void dtNavMesh::closestPointOnPoly(dtPolyRef ref, const float* pos, float* closest, bool* posOverPoly) const
{
const dtPoly* poly = &tile->polys[ip];
const dtMeshTile* tile = 0;
const dtPoly* poly = 0;
getTileAndPolyByRefUnsafe(ref, &tile, &poly);
float closestDistSqr = FLT_MAX;
// Off-mesh connections don't have detail polygons.
if (poly->getType() == DT_POLYTYPE_OFFMESH_CONNECTION)
{
const float* v0 = &tile->verts[poly->verts[0]*3];
const float* v1 = &tile->verts[poly->verts[1]*3];
const float d0 = dtVdist(pos, v0);
const float d1 = dtVdist(pos, v1);
const float u = d0 / (d0+d1);
dtVlerp(closest, v0, v1, u);
if (posOverPoly)
*posOverPoly = false;
return;
}
const unsigned int ip = (unsigned int)(poly - tile->polys);
const dtPolyDetail* pd = &tile->detailMeshes[ip];
// Clamp point to be inside the polygon.
float verts[DT_VERTS_PER_POLYGON*3];
float edged[DT_VERTS_PER_POLYGON];
float edget[DT_VERTS_PER_POLYGON];
const int nv = poly->vertCount;
for (int i = 0; i < nv; ++i)
dtVcopy(&verts[i*3], &tile->verts[poly->verts[i]*3]);
dtVcopy(closest, pos);
if (!dtDistancePtPolyEdgesSqr(pos, verts, nv, edged, edget))
{
// Point is outside the polygon, dtClamp to nearest edge.
float dmin = FLT_MAX;
int imin = -1;
for (int i = 0; i < nv; ++i)
{
if (edged[i] < dmin)
{
dmin = edged[i];
imin = i;
}
}
const float* va = &verts[imin*3];
const float* vb = &verts[((imin+1)%nv)*3];
dtVlerp(closest, va, vb, edget[imin]);
if (posOverPoly)
*posOverPoly = false;
}
else
{
if (posOverPoly)
*posOverPoly = true;
}
// Find height at the location.
for (int j = 0; j < pd->triCount; ++j)
{
const unsigned char* t = &tile->detailTris[(pd->triBase+j)*4];
@ -631,13 +686,11 @@ void dtNavMesh::closestPointOnPolyInTile(const dtMeshTile* tile, unsigned int ip
else
v[k] = &tile->detailVerts[(pd->vertBase+(t[k]-poly->vertCount))*3];
}
float pt[3];
dtClosestPtPointTriangle(pt, pos, v[0], v[1], v[2]);
float d = dtVdistSqr(pos, pt);
if (d < closestDistSqr)
float h;
if (dtClosestHeightPointTriangle(pos, v[0], v[1], v[2], h))
{
dtVcopy(closest, pt);
closestDistSqr = d;
closest[1] = h;
break;
}
}
}
@ -661,12 +714,27 @@ dtPolyRef dtNavMesh::findNearestPolyInTile(const dtMeshTile* tile,
{
dtPolyRef ref = polys[i];
float closestPtPoly[3];
closestPointOnPolyInTile(tile, decodePolyIdPoly(ref), center, closestPtPoly);
float d = dtVdistSqr(center, closestPtPoly);
float diff[3];
bool posOverPoly = false;
float d;
closestPointOnPoly(ref, center, closestPtPoly, &posOverPoly);
// If a point is directly over a polygon and closer than
// climb height, favor that instead of straight line nearest point.
dtVsub(diff, center, closestPtPoly);
if (posOverPoly)
{
d = dtAbs(diff[1]) - tile->header->walkableClimb;
d = d > 0 ? d*d : 0;
}
else
{
d = dtVlenSqr(diff);
}
if (d < nearestDistanceSqr)
{
if (nearestPt)
dtVcopy(nearestPt, closestPtPoly);
dtVcopy(nearestPt, closestPtPoly);
nearestDistanceSqr = d;
nearest = ref;
}
@ -769,6 +837,11 @@ int dtNavMesh::queryPolygonsInTile(const dtMeshTile* tile, const float* qmin, co
/// tile will be restored to the same values they were before the tile was
/// removed.
///
/// The nav mesh assumes exclusive access to the data passed and will make
/// changes to the dynamic portion of the data. For that reason the data
/// should not be reused in other nav meshes until the tile has been successfully
/// removed from this nav mesh.
///
/// @see dtCreateNavMeshData, #removeTile
dtStatus dtNavMesh::addTile(unsigned char* data, int dataSize, int flags,
dtTileRef lastRef, dtTileRef* result)
@ -1123,25 +1196,24 @@ dtStatus dtNavMesh::removeTile(dtTileRef ref, unsigned char** data, int* dataSiz
}
// Remove connections to neighbour tiles.
// Create connections with neighbour tiles.
static const int MAX_NEIS = 32;
dtMeshTile* neis[MAX_NEIS];
int nneis;
// Connect with layers in current tile.
// Disconnect from other layers in current tile.
nneis = getTilesAt(tile->header->x, tile->header->y, neis, MAX_NEIS);
for (int j = 0; j < nneis; ++j)
{
if (neis[j] == tile) continue;
unconnectExtLinks(neis[j], tile);
unconnectLinks(neis[j], tile);
}
// Connect with neighbour tiles.
// Disconnect from neighbour tiles.
for (int i = 0; i < 8; ++i)
{
nneis = getNeighbourTilesAt(tile->header->x, tile->header->y, i, neis, MAX_NEIS);
for (int j = 0; j < nneis; ++j)
unconnectExtLinks(neis[j], tile);
unconnectLinks(neis[j], tile);
}
// Reset tile.
@ -1173,7 +1245,11 @@ dtStatus dtNavMesh::removeTile(dtTileRef ref, unsigned char** data, int* dataSiz
tile->offMeshCons = 0;
// Update salt, salt should never be zero.
#ifdef DT_POLYREF64
tile->salt = (tile->salt+1) & ((1<<DT_SALT_BITS)-1);
#else
tile->salt = (tile->salt+1) & ((1<<m_saltBits)-1);
#endif
if (tile->salt == 0)
tile->salt++;

View file

@ -16,13 +16,13 @@
// 3. This notice may not be removed or altered from any source distribution.
//
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <float.h>
#include "DetourNavMesh.h"
#include "DetourCommon.h"
#include "DetourMath.h"
#include "DetourNavMeshBuilder.h"
#include "DetourAlloc.h"
#include "DetourAssert.h"
@ -202,8 +202,8 @@ static int createBVTree(const unsigned short* verts, const int /*nverts*/,
if (z > it.bmax[2]) it.bmax[2] = z;
}
// Remap y
it.bmin[1] = (unsigned short)floorf((float)it.bmin[1]*ch/cs);
it.bmax[1] = (unsigned short)ceilf((float)it.bmax[1]*ch/cs);
it.bmin[1] = (unsigned short)dtMathFloorf((float)it.bmin[1]*ch/cs);
it.bmax[1] = (unsigned short)dtMathCeilf((float)it.bmax[1]*ch/cs);
}
int curNode = 0;

File diff suppressed because it is too large Load diff

View file

@ -22,6 +22,19 @@
#include "DetourCommon.h"
#include <string.h>
#ifdef DT_POLYREF64
// From Thomas Wang, https://gist.github.com/badboy/6267743
inline unsigned int dtHashRef(dtPolyRef a)
{
a = (~a) + (a << 18); // a = (a << 18) - a - 1;
a = a ^ (a >> 31);
a = a * 21; // a = (a + (a << 2)) + (a << 4);
a = a ^ (a >> 11);
a = a + (a << 6);
a = a ^ (a >> 22);
return (unsigned int)a;
}
#else
inline unsigned int dtHashRef(dtPolyRef a)
{
a += ~(a<<15);
@ -32,6 +45,7 @@ inline unsigned int dtHashRef(dtPolyRef a)
a ^= (a>>16);
return (unsigned int)a;
}
#endif
//////////////////////////////////////////////////////////////////////////////////////////
dtNodePool::dtNodePool(int maxNodes, int hashSize) :
@ -43,7 +57,9 @@ dtNodePool::dtNodePool(int maxNodes, int hashSize) :
m_nodeCount(0)
{
dtAssert(dtNextPow2(m_hashSize) == (unsigned int)m_hashSize);
dtAssert(m_maxNodes > 0);
// pidx is special as 0 means "none" and 1 is the first node. For that reason
// we have 1 fewer nodes available than the number of values it can contain.
dtAssert(m_maxNodes > 0 && m_maxNodes <= DT_NULL_IDX && m_maxNodes <= (1 << DT_NODE_PARENT_BITS) - 1);
m_nodes = (dtNode*)dtAlloc(sizeof(dtNode)*m_maxNodes, DT_ALLOC_PERM);
m_next = (dtNodeIndex*)dtAlloc(sizeof(dtNodeIndex)*m_maxNodes, DT_ALLOC_PERM);
@ -70,27 +86,46 @@ void dtNodePool::clear()
m_nodeCount = 0;
}
dtNode* dtNodePool::findNode(dtPolyRef id)
unsigned int dtNodePool::findNodes(dtPolyRef id, dtNode** nodes, const int maxNodes)
{
int n = 0;
unsigned int bucket = dtHashRef(id) & (m_hashSize-1);
dtNodeIndex i = m_first[bucket];
while (i != DT_NULL_IDX)
{
if (m_nodes[i].id == id)
{
if (n >= maxNodes)
return n;
nodes[n++] = &m_nodes[i];
}
i = m_next[i];
}
return n;
}
dtNode* dtNodePool::findNode(dtPolyRef id, unsigned char state)
{
unsigned int bucket = dtHashRef(id) & (m_hashSize-1);
dtNodeIndex i = m_first[bucket];
while (i != DT_NULL_IDX)
{
if (m_nodes[i].id == id && m_nodes[i].state == state)
return &m_nodes[i];
i = m_next[i];
}
return 0;
}
dtNode* dtNodePool::getNode(dtPolyRef id)
dtNode* dtNodePool::getNode(dtPolyRef id, unsigned char state)
{
unsigned int bucket = dtHashRef(id) & (m_hashSize-1);
dtNodeIndex i = m_first[bucket];
dtNode* node = 0;
while (i != DT_NULL_IDX)
{
if (m_nodes[i].id == id)
if (m_nodes[i].id == id && m_nodes[i].state == state)
return &m_nodes[i];
i = m_next[i];
}
@ -107,6 +142,7 @@ dtNode* dtNodePool::getNode(dtPolyRef id)
node->cost = 0;
node->total = 0;
node->id = id;
node->state = state;
node->flags = 0;
m_next[i] = m_first[bucket];