Recast: New API documentation, and standardized tab/space use.
Documented DetourAlloc.h and most members in DetourCommon.h. Added warning related to issue 180. (Limitation on use of dtNavmeshQuery::findNearestPoly.) Standardized the use of tab/space indenting in the API documentation.
This commit is contained in:
parent
79a61cbdb1
commit
923098b43c
@ -19,18 +19,41 @@
|
|||||||
#ifndef DETOURALLOCATOR_H
|
#ifndef DETOURALLOCATOR_H
|
||||||
#define DETOURALLOCATOR_H
|
#define DETOURALLOCATOR_H
|
||||||
|
|
||||||
|
/// Provides hint values to the memory allocator on how long the
|
||||||
|
/// memory is expected to be used.
|
||||||
enum dtAllocHint
|
enum dtAllocHint
|
||||||
{
|
{
|
||||||
DT_ALLOC_PERM, ///< Memory persist after a function call.
|
DT_ALLOC_PERM, ///< Memory persist after a function call.
|
||||||
DT_ALLOC_TEMP ///< Memory used temporarily within a function.
|
DT_ALLOC_TEMP ///< Memory used temporarily within a function.
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// A memory allocation function.
|
||||||
|
// @param[in] size The size, in bytes of memory, to allocate.
|
||||||
|
// @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)(int size, dtAllocHint hint);
|
||||||
|
|
||||||
|
/// A memory deallocation function.
|
||||||
|
/// @param[in] ptr A pointer to a memory block previously allocated using #dtAllocFunc.
|
||||||
|
/// @see dtAllocSetCustom
|
||||||
typedef void (dtFreeFunc)(void* ptr);
|
typedef void (dtFreeFunc)(void* ptr);
|
||||||
|
|
||||||
|
/// Sets the base custom allocation functions to be used by Detour.
|
||||||
|
/// @param[in] allocFunc The memory allocation function to be used by #dtAlloc
|
||||||
|
/// @param[in] freeFunc The memory de-allocation function to be used by #dtFree
|
||||||
void dtAllocSetCustom(dtAllocFunc *allocFunc, dtFreeFunc *freeFunc);
|
void dtAllocSetCustom(dtAllocFunc *allocFunc, dtFreeFunc *freeFunc);
|
||||||
|
|
||||||
|
/// Allocates a memory block.
|
||||||
|
/// @param[in] size The size, in bytes of memory, to allocate.
|
||||||
|
/// @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(int size, dtAllocHint hint);
|
||||||
|
|
||||||
|
/// Deallocates a memory block.
|
||||||
|
/// @param[in] ptr A pointer to a memory block previously allocated using #dtAlloc.
|
||||||
|
/// @see dtAlloc
|
||||||
void dtFree(void* ptr);
|
void dtFree(void* ptr);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -20,21 +20,65 @@
|
|||||||
#define DETOURCOMMON_H
|
#define DETOURCOMMON_H
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @defgroup detour Detour
|
@defgroup detour Detour
|
||||||
* Classes and functions related to path planning.
|
|
||||||
* @note This is a summary list. Use the index or documentation search
|
Members in this module are used to create, manipulate, and query navigation
|
||||||
* functionality to find minor elements.
|
meshes.
|
||||||
|
|
||||||
|
@note This is a summary list of members. Use the index or search
|
||||||
|
feature to find minor members.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/// @name General helper functions
|
||||||
|
/// @{
|
||||||
|
|
||||||
|
/// Swaps the values of the two parameters.
|
||||||
|
/// @param[in,out] a Value A
|
||||||
|
/// @param[in,out] b Value B
|
||||||
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; }
|
||||||
|
|
||||||
|
/// Returns the minimum of two values.
|
||||||
|
/// @param[in] a Value A
|
||||||
|
/// @param[in] b Value B
|
||||||
|
/// @return The minimum of the two values.
|
||||||
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; }
|
||||||
|
|
||||||
|
/// Returns the maximum of two values.
|
||||||
|
/// @param[in] a Value A
|
||||||
|
/// @param[in] b Value B
|
||||||
|
/// @return The maximum of the two values.
|
||||||
template<class T> inline T dtMax(T a, T b) { return a > b ? a : b; }
|
template<class T> inline T dtMax(T a, T b) { return a > b ? a : b; }
|
||||||
|
|
||||||
|
/// Returns the absolute value.
|
||||||
|
/// @param[in] a The value.
|
||||||
|
/// @return The absolute value of the specified value.
|
||||||
template<class T> inline T dtAbs(T a) { return a < 0 ? -a : a; }
|
template<class T> inline T dtAbs(T a) { return a < 0 ? -a : a; }
|
||||||
|
|
||||||
|
/// Returns the square of the value.
|
||||||
|
/// @param[in] a The value.
|
||||||
|
/// @return The square of the value.
|
||||||
template<class T> inline T dtSqr(T a) { return a*a; }
|
template<class T> inline T dtSqr(T a) { return a*a; }
|
||||||
|
|
||||||
|
/// Clamps the value to the specified range.
|
||||||
|
/// @param[in] v The value to clamp.
|
||||||
|
/// @param[in] mn The minimum permitted return value.
|
||||||
|
/// @param[in] mx The maximum permitted return value.
|
||||||
|
/// @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); }
|
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);
|
float dtSqrt(float x);
|
||||||
|
|
||||||
|
/// @}
|
||||||
|
/// @name Vector helper functions.
|
||||||
|
/// @{
|
||||||
|
|
||||||
|
/// Derives the cross product of two vectors. (@p v1 x @p v2)
|
||||||
|
/// @param[out] dest The cross product. [(x, y, z)]
|
||||||
|
/// @param[in] v1 A Vector [(x, y, z)]
|
||||||
|
/// @param[in] v2 A vector [(x, y, z)]
|
||||||
inline void dtVcross(float* dest, const float* v1, const float* v2)
|
inline void dtVcross(float* dest, const float* v1, const float* v2)
|
||||||
{
|
{
|
||||||
dest[0] = v1[1]*v2[2] - v1[2]*v2[1];
|
dest[0] = v1[1]*v2[2] - v1[2]*v2[1];
|
||||||
@ -42,11 +86,20 @@ inline void dtVcross(float* dest, const float* v1, const float* v2)
|
|||||||
dest[2] = v1[0]*v2[1] - v1[1]*v2[0];
|
dest[2] = v1[0]*v2[1] - v1[1]*v2[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Derives the dot product of two vectors. (@p v1 . @p v2)
|
||||||
|
/// @param[in] v1 A Vector [(x, y, z)]
|
||||||
|
/// @param[in] v2 A vector [(x, y, z)]
|
||||||
|
/// @return The dot product.
|
||||||
inline float dtVdot(const float* v1, const float* v2)
|
inline float dtVdot(const float* v1, const float* v2)
|
||||||
{
|
{
|
||||||
return v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2];
|
return v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Performs a scaled vector addition. (@p v1 + (@p v2 * @p s))
|
||||||
|
/// @param[out] dest The result vector. [(x, y, z)]
|
||||||
|
/// @param[in] v1 The base vector. [(x, y, z)]
|
||||||
|
/// @param[in] v2 The vector to scale and add to @p v1. [(x, y, z)]
|
||||||
|
/// @param[in] s The amount to scale @p v2 by before adding to @p v1.
|
||||||
inline void dtVmad(float* dest, const float* v1, const float* v2, const float s)
|
inline void dtVmad(float* dest, const float* v1, const float* v2, const float s)
|
||||||
{
|
{
|
||||||
dest[0] = v1[0]+v2[0]*s;
|
dest[0] = v1[0]+v2[0]*s;
|
||||||
@ -54,6 +107,11 @@ inline void dtVmad(float* dest, const float* v1, const float* v2, const float s)
|
|||||||
dest[2] = v1[2]+v2[2]*s;
|
dest[2] = v1[2]+v2[2]*s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Performs a linear interpolation between two vectors. (@p v1 toward @p v2)
|
||||||
|
/// @param[out] dest The result vector. [(x, y, x)]
|
||||||
|
/// @param[in] v1 The starting vector.
|
||||||
|
/// @param[in] v2 The destination vector.
|
||||||
|
/// @param[in] t The interpolation factor. [Limits: 0 <= value <= 1.0]
|
||||||
inline void dtVlerp(float* dest, const float* v1, const float* v2, const float t)
|
inline void dtVlerp(float* dest, const float* v1, const float* v2, const float t)
|
||||||
{
|
{
|
||||||
dest[0] = v1[0]+(v2[0]-v1[0])*t;
|
dest[0] = v1[0]+(v2[0]-v1[0])*t;
|
||||||
@ -61,6 +119,10 @@ inline void dtVlerp(float* dest, const float* v1, const float* v2, const float t
|
|||||||
dest[2] = v1[2]+(v2[2]-v1[2])*t;
|
dest[2] = v1[2]+(v2[2]-v1[2])*t;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Performs a vector addition. (@p v1 + @p v2)
|
||||||
|
/// @param[out] dest The result vector. [(x, y, z)]
|
||||||
|
/// @param[in] v1 The base vector. [(x, y, z)]
|
||||||
|
/// @param[in] v2 The vector to add to @p v1. [(x, y, z)]
|
||||||
inline void dtVadd(float* dest, const float* v1, const float* v2)
|
inline void dtVadd(float* dest, const float* v1, const float* v2)
|
||||||
{
|
{
|
||||||
dest[0] = v1[0]+v2[0];
|
dest[0] = v1[0]+v2[0];
|
||||||
@ -68,6 +130,10 @@ inline void dtVadd(float* dest, const float* v1, const float* v2)
|
|||||||
dest[2] = v1[2]+v2[2];
|
dest[2] = v1[2]+v2[2];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Performs a vector subtraction. (@p v1 - @p v2)
|
||||||
|
/// @param[out] dest The result vector. [(x, y, z)]
|
||||||
|
/// @param[in] v1 The base vector. [(x, y, z)]
|
||||||
|
/// @param[in] v2 The vector to subtract from @p v1. [(x, y, z)]
|
||||||
inline void dtVsub(float* dest, const float* v1, const float* v2)
|
inline void dtVsub(float* dest, const float* v1, const float* v2)
|
||||||
{
|
{
|
||||||
dest[0] = v1[0]-v2[0];
|
dest[0] = v1[0]-v2[0];
|
||||||
@ -75,6 +141,10 @@ inline void dtVsub(float* dest, const float* v1, const float* v2)
|
|||||||
dest[2] = v1[2]-v2[2];
|
dest[2] = v1[2]-v2[2];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Scales the vector by the specified value. (@p v * @p t)
|
||||||
|
/// @param[out] dest The result vector. [(x, y, z)]
|
||||||
|
/// @param[in] v The vector to scale. [(x, y, z)]
|
||||||
|
/// @param[in] t The scaling factor.
|
||||||
inline void dtVscale(float* dest, const float* v, const float t)
|
inline void dtVscale(float* dest, const float* v, const float t)
|
||||||
{
|
{
|
||||||
dest[0] = v[0]*t;
|
dest[0] = v[0]*t;
|
||||||
@ -82,6 +152,9 @@ inline void dtVscale(float* dest, const float* v, const float t)
|
|||||||
dest[2] = v[2]*t;
|
dest[2] = v[2]*t;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Selects the minimum value of each element from the specified vectors.
|
||||||
|
/// @param[in,out] mn A vector. (Will be updated with the result.) [(x, y, z)]
|
||||||
|
/// @param[in] v A vector. [(x, y, z)]
|
||||||
inline void dtVmin(float* mn, const float* v)
|
inline void dtVmin(float* mn, const float* v)
|
||||||
{
|
{
|
||||||
mn[0] = dtMin(mn[0], v[0]);
|
mn[0] = dtMin(mn[0], v[0]);
|
||||||
@ -89,6 +162,9 @@ inline void dtVmin(float* mn, const float* v)
|
|||||||
mn[2] = dtMin(mn[2], v[2]);
|
mn[2] = dtMin(mn[2], v[2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Selects the maximum value of each element from the specified vectors.
|
||||||
|
/// @param[in,out] mx A vector. (Will be updated with the result.) [(x, y, z)]
|
||||||
|
/// @param[in] v A vector. [(x, y, z)]
|
||||||
inline void dtVmax(float* mx, const float* v)
|
inline void dtVmax(float* mx, const float* v)
|
||||||
{
|
{
|
||||||
mx[0] = dtMax(mx[0], v[0]);
|
mx[0] = dtMax(mx[0], v[0]);
|
||||||
@ -96,11 +172,19 @@ inline void dtVmax(float* mx, const float* v)
|
|||||||
mx[2] = dtMax(mx[2], v[2]);
|
mx[2] = dtMax(mx[2], v[2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Sets the vector elements to the specified values.
|
||||||
|
/// @param[out] dest The result vector. [(x, y, z)]
|
||||||
|
/// @param[in] x The x-value of the vector.
|
||||||
|
/// @param[in] y The y-value of the vector.
|
||||||
|
/// @param[in] z The z-value of the vector.
|
||||||
inline void dtVset(float* dest, const float x, const float y, const float z)
|
inline void dtVset(float* dest, const float x, const float y, const float z)
|
||||||
{
|
{
|
||||||
dest[0] = x; dest[1] = y; dest[2] = z;
|
dest[0] = x; dest[1] = y; dest[2] = z;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Performs a vector copy.
|
||||||
|
/// @param[out] dest The result. [(x, y, z)]
|
||||||
|
/// @param[in] a The vector to copy. [(x, y, z)]
|
||||||
inline void dtVcopy(float* dest, const float* a)
|
inline void dtVcopy(float* dest, const float* a)
|
||||||
{
|
{
|
||||||
dest[0] = a[0];
|
dest[0] = a[0];
|
||||||
@ -108,16 +192,26 @@ inline void dtVcopy(float* dest, const float* a)
|
|||||||
dest[2] = a[2];
|
dest[2] = a[2];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Derives the scalar length of the vector.
|
||||||
|
/// @param[in] v The vector. [(x, y, z)]
|
||||||
|
/// @return The scalar length of the vector.
|
||||||
inline float dtVlen(const float* v)
|
inline float dtVlen(const float* v)
|
||||||
{
|
{
|
||||||
return dtSqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);
|
return dtSqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Derives the square of the scalar length of the vector. (len * len)
|
||||||
|
/// @param[in] v The vector. [(x, y, z)]
|
||||||
|
/// @return The square of the scalar length of the vector.
|
||||||
inline float dtVlenSqr(const float* v)
|
inline float dtVlenSqr(const float* v)
|
||||||
{
|
{
|
||||||
return v[0]*v[0] + v[1]*v[1] + v[2]*v[2];
|
return v[0]*v[0] + v[1]*v[1] + v[2]*v[2];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the distance between two points.
|
||||||
|
/// @param[in] v1 A point. [(x, y, z)]
|
||||||
|
/// @param[in] v2 A point. [(x, y, z)]
|
||||||
|
/// @return The distance between the two points.
|
||||||
inline float dtVdist(const float* v1, const float* v2)
|
inline float dtVdist(const float* v1, const float* v2)
|
||||||
{
|
{
|
||||||
const float dx = v2[0] - v1[0];
|
const float dx = v2[0] - v1[0];
|
||||||
@ -126,6 +220,10 @@ inline float dtVdist(const float* v1, const float* v2)
|
|||||||
return dtSqrt(dx*dx + dy*dy + dz*dz);
|
return dtSqrt(dx*dx + dy*dy + dz*dz);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the square of the distance between two points.
|
||||||
|
/// @param[in] v1 A point. [(x, y, z)]
|
||||||
|
/// @param[in] v2 A point. [(x, y, z)]
|
||||||
|
/// @return The square of the distance between the two points.
|
||||||
inline float dtVdistSqr(const float* v1, const float* v2)
|
inline float dtVdistSqr(const float* v1, const float* v2)
|
||||||
{
|
{
|
||||||
const float dx = v2[0] - v1[0];
|
const float dx = v2[0] - v1[0];
|
||||||
@ -134,6 +232,12 @@ inline float dtVdistSqr(const float* v1, const float* v2)
|
|||||||
return dx*dx + dy*dy + dz*dz;
|
return dx*dx + dy*dy + dz*dz;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Derives the distance between the specified points on the xz-plane.
|
||||||
|
/// @param[in] v1 A point. [(x, y, z)]
|
||||||
|
/// @param[in] v2 A point. [(x, y, z)]
|
||||||
|
/// @return The distance between the point on the xz-plane.
|
||||||
|
///
|
||||||
|
/// The vectors are projected onto the xz-plane, so the y-values are ignored.
|
||||||
inline float dtVdist2D(const float* v1, const float* v2)
|
inline float dtVdist2D(const float* v1, const float* v2)
|
||||||
{
|
{
|
||||||
const float dx = v2[0] - v1[0];
|
const float dx = v2[0] - v1[0];
|
||||||
@ -141,6 +245,10 @@ inline float dtVdist2D(const float* v1, const float* v2)
|
|||||||
return dtSqrt(dx*dx + dz*dz);
|
return dtSqrt(dx*dx + dz*dz);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Derives the square of the distance between the specified points on the xz-plane.
|
||||||
|
/// @param[in] v1 A point. [(x, y, z)]
|
||||||
|
/// @param[in] v2 A point. [(x, y, z)]
|
||||||
|
/// @return The square of the distance between the point on the xz-plane.
|
||||||
inline float dtVdist2DSqr(const float* v1, const float* v2)
|
inline float dtVdist2DSqr(const float* v1, const float* v2)
|
||||||
{
|
{
|
||||||
const float dx = v2[0] - v1[0];
|
const float dx = v2[0] - v1[0];
|
||||||
@ -148,6 +256,8 @@ inline float dtVdist2DSqr(const float* v1, const float* v2)
|
|||||||
return dx*dx + dz*dz;
|
return dx*dx + dz*dz;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Normalizes the vector.
|
||||||
|
/// @param[in,out] v The vector to normalize. [(x, y, z)]
|
||||||
inline void dtVnormalize(float* v)
|
inline void dtVnormalize(float* v)
|
||||||
{
|
{
|
||||||
float d = 1.0f / dtSqrt(dtSqr(v[0]) + dtSqr(v[1]) + dtSqr(v[2]));
|
float d = 1.0f / dtSqrt(dtSqr(v[0]) + dtSqr(v[1]) + dtSqr(v[2]));
|
||||||
@ -156,6 +266,13 @@ inline void dtVnormalize(float* v)
|
|||||||
v[2] *= d;
|
v[2] *= d;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Performs a 'sloppy' colocation check of the specified points.
|
||||||
|
/// @param[in] p0 A point. [(x, y, z)]
|
||||||
|
/// @param[in] p1 A point. [(x, y, z)]
|
||||||
|
/// @return True if the points are considered to be at the same location.
|
||||||
|
///
|
||||||
|
/// Basically, this function will return true if the specified points are
|
||||||
|
/// close enough to eachother to be considered colocated.
|
||||||
inline bool dtVequal(const float* p0, const float* p1)
|
inline bool dtVequal(const float* p0, const float* p1)
|
||||||
{
|
{
|
||||||
static const float thr = dtSqr(1.0f/16384.0f);
|
static const float thr = dtSqr(1.0f/16384.0f);
|
||||||
@ -163,6 +280,134 @@ inline bool dtVequal(const float* p0, const float* p1)
|
|||||||
return d < thr;
|
return d < thr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Derives the dot product of two vectors on the xz-plane. (@p u . @p v)
|
||||||
|
/// @param[in] u A vector [(x, y, z)]
|
||||||
|
/// @param[in] v A vector [(x, y, z)]
|
||||||
|
/// @return The dot product on the xz-plane.
|
||||||
|
///
|
||||||
|
/// The vectors are projected onto the xz-plane, so the y-values are ignored.
|
||||||
|
inline float dtVdot2D(const float* u, const float* v)
|
||||||
|
{
|
||||||
|
return u[0]*v[0] + u[2]*v[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Derives the xz-plane 2D perp product of the two vectors. (uz*vx - ux*vz)
|
||||||
|
/// @param[in] u The LHV vector [(x, y, z)]
|
||||||
|
/// @param[in] v The RHV vector [(x, y, z)]
|
||||||
|
/// @return The dot product on the xz-plane.
|
||||||
|
///
|
||||||
|
/// The vectors are projected onto the xz-plane, so the y-values are ignored.
|
||||||
|
inline float dtVperp2D(const float* u, const float* v)
|
||||||
|
{
|
||||||
|
return u[2]*v[0] - u[0]*v[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @}
|
||||||
|
/// @name Computational geometry helper functions.
|
||||||
|
/// @{
|
||||||
|
|
||||||
|
/// Derives the signed xz-plane area of the triangle ABC, or the relationship of line AB to point C.
|
||||||
|
/// @param[in] a Vertex A. [(x, y, z)]
|
||||||
|
/// @param[in] b Vertex B. [(x, y, z)]
|
||||||
|
/// @param[in] c Vertex C. [(x, y, z)]
|
||||||
|
/// @return The signed xz-plane area of the triangle.
|
||||||
|
inline float dtTriArea2D(const float* a, const float* b, const float* c)
|
||||||
|
{
|
||||||
|
const float abx = b[0] - a[0];
|
||||||
|
const float abz = b[2] - a[2];
|
||||||
|
const float acx = c[0] - a[0];
|
||||||
|
const float acz = c[2] - a[2];
|
||||||
|
return acx*abz - abx*acz;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Determines if two axis-aligned bounding boxes overlap.
|
||||||
|
/// @param[in] amin Minimum bounds of box A. [(x, y, z)]
|
||||||
|
/// @param[in] amax Maximum bounds of box A. [(x, y, z)]
|
||||||
|
/// @param[in] bmin Minimum bounds of box B. [(x, y, z)]
|
||||||
|
/// @param[in] bmax Maximum bounds of box B. [(x, y, z)]
|
||||||
|
/// @return True if the two AABB's overlap.
|
||||||
|
/// @see dtOverlapBounds
|
||||||
|
inline bool dtOverlapQuantBounds(const unsigned short amin[3], const unsigned short amax[3],
|
||||||
|
const unsigned short bmin[3], const unsigned short bmax[3])
|
||||||
|
{
|
||||||
|
bool overlap = true;
|
||||||
|
overlap = (amin[0] > bmax[0] || amax[0] < bmin[0]) ? false : overlap;
|
||||||
|
overlap = (amin[1] > bmax[1] || amax[1] < bmin[1]) ? false : overlap;
|
||||||
|
overlap = (amin[2] > bmax[2] || amax[2] < bmin[2]) ? false : overlap;
|
||||||
|
return overlap;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Determines if two axis-aligned bounding boxes overlap.
|
||||||
|
/// @param[in] amin Minimum bounds of box A. [(x, y, z)]
|
||||||
|
/// @param[in] amax Maximum bounds of box A. [(x, y, z)]
|
||||||
|
/// @param[in] bmin Minimum bounds of box B. [(x, y, z)]
|
||||||
|
/// @param[in] bmax Maximum bounds of box B. [(x, y, z)]
|
||||||
|
/// @return True if the two AABB's overlap.
|
||||||
|
/// @see dtOverlapQuantBounds
|
||||||
|
inline bool dtOverlapBounds(const float* amin, const float* amax,
|
||||||
|
const float* bmin, const float* bmax)
|
||||||
|
{
|
||||||
|
bool overlap = true;
|
||||||
|
overlap = (amin[0] > bmax[0] || amax[0] < bmin[0]) ? false : overlap;
|
||||||
|
overlap = (amin[1] > bmax[1] || amax[1] < bmin[1]) ? false : overlap;
|
||||||
|
overlap = (amin[2] > bmax[2] || amax[2] < bmin[2]) ? false : overlap;
|
||||||
|
return overlap;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Derives the closest point on a triangle from the specified reference point.
|
||||||
|
/// @param[out] closest The closest point on the triangle.
|
||||||
|
/// @param[in] p The reference point from which to test. [(x, y, z)]
|
||||||
|
/// @param[in] a Vertex A of triangle ABC. [(x, y, z)]
|
||||||
|
/// @param[in] b Vertex B of triangle ABC. [(x, y, z)]
|
||||||
|
/// @param[in] c Vertex C of triangle ABC. [(x, y, z)]
|
||||||
|
void dtClosestPtPointTriangle(float* closest, const float* p,
|
||||||
|
const float* a, const float* b, const float* c);
|
||||||
|
|
||||||
|
/// Derives the y-axis height of the closest point on the triangle from the specified reference point.
|
||||||
|
/// @param[in] p The reference point from which to test. [(x, y, z)]
|
||||||
|
/// @param[in] a Vertex A of triangle ABC. [(x, y, z)]
|
||||||
|
/// @param[in] b Vertex B of triangle ABC. [(x, y, z)]
|
||||||
|
/// @param[in] c Vertex C of triangle ABC. [(x, y, z)]
|
||||||
|
/// @param[out] h The resulting height.
|
||||||
|
bool dtClosestHeightPointTriangle(const float* p, const float* a, const float* b, const float* c, float& h);
|
||||||
|
|
||||||
|
bool dtIntersectSegmentPoly2D(const float* p0, const float* p1,
|
||||||
|
const float* verts, int nverts,
|
||||||
|
float& tmin, float& tmax,
|
||||||
|
int& segMin, int& segMax);
|
||||||
|
|
||||||
|
/// 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]
|
||||||
|
/// @param[in] nverts The number of vertices. [Limit: >= 3]
|
||||||
|
/// @return True if the point is inside the polygon.
|
||||||
|
bool dtPointInPolygon(const float* pt, const float* verts, const int nverts);
|
||||||
|
|
||||||
|
bool dtDistancePtPolyEdgesSqr(const float* pt, const float* verts, const int nverts,
|
||||||
|
float* ed, float* et);
|
||||||
|
|
||||||
|
float dtDistancePtSegSqr2D(const float* pt, const float* p, const float* q, float& t);
|
||||||
|
|
||||||
|
/// Derives the centroid of a convex polygon.
|
||||||
|
/// @param[out] tc The centroid of the polgyon. [(x, y, z)]
|
||||||
|
/// @param[in] idx The polygon indices. [(vertIndex) * @p nidx]
|
||||||
|
/// @param[in] nidx The number of indices in the polygon. [Limit: >= 3]
|
||||||
|
/// @param[in] verts The polygon vertices. [(x, y, z) * vertCount]
|
||||||
|
void dtCalcPolyCenter(float* tc, const unsigned short* idx, int nidx, const float* verts);
|
||||||
|
|
||||||
|
/// Determines if the two convex polygons overlap on the xz-plane.
|
||||||
|
/// @param[in] polya Polygon A vertices. [(x, y, z) * @p npolya]
|
||||||
|
/// @param[in] npolya The number of vertices in polygon A.
|
||||||
|
/// @param[in] polyb Polygon B vertices. [(x, y, z) * @p npolyb]
|
||||||
|
/// @param[in] npolyb The number of vertices in polygon B.
|
||||||
|
/// @return True if the two polygons overlap.
|
||||||
|
bool dtOverlapPolyPoly2D(const float* polya, const int npolya,
|
||||||
|
const float* polyb, const int npolyb);
|
||||||
|
|
||||||
|
/// @}
|
||||||
|
/// @name Miscellanious functions.
|
||||||
|
/// @{
|
||||||
|
|
||||||
inline unsigned int dtNextPow2(unsigned int v)
|
inline unsigned int dtNextPow2(unsigned int v)
|
||||||
{
|
{
|
||||||
v--;
|
v--;
|
||||||
@ -191,65 +436,51 @@ inline int dtAlign4(int x) { return (x+3) & ~3; }
|
|||||||
|
|
||||||
inline int dtOppositeTile(int side) { return (side+4) & 0x7; }
|
inline int dtOppositeTile(int side) { return (side+4) & 0x7; }
|
||||||
|
|
||||||
inline float dtVdot2D(const float* u, const float* v)
|
/// @}
|
||||||
{
|
|
||||||
return u[0]*v[0] + u[2]*v[2];
|
|
||||||
}
|
|
||||||
|
|
||||||
inline float dtVperp2D(const float* u, const float* v)
|
|
||||||
{
|
|
||||||
return u[2]*v[0] - u[0]*v[2];
|
|
||||||
}
|
|
||||||
|
|
||||||
inline float dtTriArea2D(const float* a, const float* b, const float* c)
|
|
||||||
{
|
|
||||||
const float abx = b[0] - a[0];
|
|
||||||
const float abz = b[2] - a[2];
|
|
||||||
const float acx = c[0] - a[0];
|
|
||||||
const float acz = c[2] - a[2];
|
|
||||||
return acx*abz - abx*acz;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool dtOverlapQuantBounds(const unsigned short amin[3], const unsigned short amax[3],
|
|
||||||
const unsigned short bmin[3], const unsigned short bmax[3])
|
|
||||||
{
|
|
||||||
bool overlap = true;
|
|
||||||
overlap = (amin[0] > bmax[0] || amax[0] < bmin[0]) ? false : overlap;
|
|
||||||
overlap = (amin[1] > bmax[1] || amax[1] < bmin[1]) ? false : overlap;
|
|
||||||
overlap = (amin[2] > bmax[2] || amax[2] < bmin[2]) ? false : overlap;
|
|
||||||
return overlap;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool dtOverlapBounds(const float* amin, const float* amax,
|
|
||||||
const float* bmin, const float* bmax)
|
|
||||||
{
|
|
||||||
bool overlap = true;
|
|
||||||
overlap = (amin[0] > bmax[0] || amax[0] < bmin[0]) ? false : overlap;
|
|
||||||
overlap = (amin[1] > bmax[1] || amax[1] < bmin[1]) ? false : overlap;
|
|
||||||
overlap = (amin[2] > bmax[2] || amax[2] < bmin[2]) ? false : overlap;
|
|
||||||
return overlap;
|
|
||||||
}
|
|
||||||
|
|
||||||
void dtClosestPtPointTriangle(float* closest, const float* p,
|
|
||||||
const float* a, const float* b, const float* c);
|
|
||||||
|
|
||||||
bool dtClosestHeightPointTriangle(const float* p, const float* a, const float* b, const float* c, float& h);
|
|
||||||
|
|
||||||
bool dtIntersectSegmentPoly2D(const float* p0, const float* p1,
|
|
||||||
const float* verts, int nverts,
|
|
||||||
float& tmin, float& tmax,
|
|
||||||
int& segMin, int& segMax);
|
|
||||||
|
|
||||||
bool dtPointInPolygon(const float* pt, const float* verts, const int nverts);
|
|
||||||
|
|
||||||
bool dtDistancePtPolyEdgesSqr(const float* pt, const float* verts, const int nverts,
|
|
||||||
float* ed, float* et);
|
|
||||||
|
|
||||||
float dtDistancePtSegSqr2D(const float* pt, const float* p, const float* q, float& t);
|
|
||||||
|
|
||||||
void dtCalcPolyCenter(float* tc, const unsigned short* idx, int nidx, const float* verts);
|
|
||||||
|
|
||||||
bool dtOverlapPolyPoly2D(const float* polya, const int npolya,
|
|
||||||
const float* polyb, const int npolyb);
|
|
||||||
|
|
||||||
#endif // DETOURCOMMON_H
|
#endif // DETOURCOMMON_H
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// This section contains detailed documentation for members that don't have
|
||||||
|
// a source file. It reduces clutter in the main section of the header.
|
||||||
|
|
||||||
|
/**
|
||||||
|
|
||||||
|
@fn float dtTriArea2D(const float* a, const float* b, const float* c)
|
||||||
|
@par
|
||||||
|
|
||||||
|
The vertices are projected onto the xz-plane, so the y-values are ignored.
|
||||||
|
|
||||||
|
This is a low cost function than can be used for various purposes. Its main purpose
|
||||||
|
is for point/line relationship testing.
|
||||||
|
|
||||||
|
In all cases: A value of zero indicates that all vertices are collinear or represent the same point.
|
||||||
|
(On the xz-plane.)
|
||||||
|
|
||||||
|
When used for point/line relationship tests, AB usually represents a line against which
|
||||||
|
the C point is to be tested. In this case:
|
||||||
|
|
||||||
|
A positive value indicates that point C is to the left of line AB, looking from A toward B.<br/>
|
||||||
|
A negative value indicates that point C is to the right of lineAB, looking from A toward B.
|
||||||
|
|
||||||
|
When used for evaluating a triangle:
|
||||||
|
|
||||||
|
The absolute value of the return value is two times the area of the triangle when it is
|
||||||
|
projected onto the xz-plane.
|
||||||
|
|
||||||
|
A positive return value indicates:
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li>The vertices are wrapped in the normal Detour wrap direction.</li>
|
||||||
|
<li>The triangle's 3D face normal is in the general up direction.</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
A negative return value indicates:
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li>The vertices are reverse wrapped. (Wrapped opposite the normal Detour wrap direction.)</li>
|
||||||
|
<li>The triangle's 3D face normal is in the general down direction.</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
*/
|
||||||
|
@ -22,9 +22,8 @@
|
|||||||
#include "DetourAlloc.h"
|
#include "DetourAlloc.h"
|
||||||
#include "DetourStatus.h"
|
#include "DetourStatus.h"
|
||||||
|
|
||||||
|
|
||||||
// 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 that you change dtHashRef() to a proper 64-bit hash.
|
||||||
|
|
||||||
/// A handle to a polygon within a navigation mesh tile.
|
/// A handle to a polygon within a navigation mesh tile.
|
||||||
/// @ingroup detour
|
/// @ingroup detour
|
||||||
@ -589,92 +588,95 @@ void dtFreeNavMesh(dtNavMesh* navmesh);
|
|||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
// This section contains detailed documentation for types that don't have
|
// This section contains detailed documentation for members that don't have
|
||||||
// a source file. It reduces clutter in the main section of the header.
|
// 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
|
@typedef dtPolyRef
|
||||||
/// @par
|
@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]
|
Polygon references are subject to the same invalidate/preserve/restore
|
||||||
/// @par
|
rules that apply to #dtTileRef's. If the #dtTileRef for the polygon's
|
||||||
///
|
tile changes, the polygon reference becomes invalid.
|
||||||
/// 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
|
Changing a polygon's flags, area id, etc. does not impact its polygon
|
||||||
/// @par
|
reference.
|
||||||
///
|
|
||||||
/// 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
|
@typedef dtTileRef
|
||||||
/// @par
|
@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]
|
The following changes will invalidate a tile reference:
|
||||||
/// @par
|
|
||||||
///
|
- The referenced tile has been removed from the navigation mesh.
|
||||||
/// For a properly built navigation mesh, vertex A will always be within the bounds of the mesh.
|
- The navigation mesh has been initialized using a different set
|
||||||
/// Vertex B is not required to be within the bounds of the mesh.
|
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.
|
||||||
|
|
||||||
|
*/
|
||||||
|
@ -238,6 +238,9 @@ bool dtClosestHeightPointTriangle(const float* p, const float* a, const float* b
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @par
|
||||||
|
///
|
||||||
|
/// All points are projected onto the xz-plane, so the y-values are ignored.
|
||||||
bool dtPointInPolygon(const float* pt, const float* verts, const int nverts)
|
bool dtPointInPolygon(const float* pt, const float* verts, const int nverts)
|
||||||
{
|
{
|
||||||
// TODO: Replace pnpoly with triArea2D tests?
|
// TODO: Replace pnpoly with triArea2D tests?
|
||||||
@ -291,6 +294,9 @@ inline bool overlapRange(const float amin, const float amax,
|
|||||||
return ((amin+eps) > bmax || (amax-eps) < bmin) ? false : true;
|
return ((amin+eps) > bmax || (amax-eps) < bmin) ? false : true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @par
|
||||||
|
///
|
||||||
|
/// All vertices are projected onto the xz-plane, so the y-values are ignored.
|
||||||
bool dtOverlapPolyPoly2D(const float* polya, const int npolya,
|
bool dtOverlapPolyPoly2D(const float* polya, const int npolya,
|
||||||
const float* polyb, const int npolyb)
|
const float* polyb, const int npolyb)
|
||||||
{
|
{
|
||||||
|
@ -439,6 +439,9 @@ dtStatus dtNavMeshQuery::getPolyHeight(dtPolyRef ref, const float* pos, float* h
|
|||||||
/// return #DT_SUCCESS, but @p nearestRef will be zero. So if in doubt, check
|
/// return #DT_SUCCESS, but @p nearestRef will be zero. So if in doubt, check
|
||||||
/// @p nearestRef before using @p nearestPt.
|
/// @p nearestRef before using @p nearestPt.
|
||||||
///
|
///
|
||||||
|
/// @warning This function is not suitable for large area searches. If the search
|
||||||
|
/// extents overlaps more than 128 polygons it may return an invalid result.
|
||||||
|
///
|
||||||
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
|
||||||
|
Loading…
x
Reference in New Issue
Block a user