mirror of
https://github.com/ornfelt/azerothcore_lua_scripts
synced 2026-08-22 06:26:03 -04:00
10789 lines
408 KiB
Diff
10789 lines
408 KiB
Diff
|
|
From a6b4e0855ceeee3bf8860c84bfe569c3474bdba0 Mon Sep 17 00:00:00 2001
|
||
|
|
From: Vstar <vstar0v0@hotmail.com>
|
||
|
|
Date: Tue, 5 Nov 2013 07:05:00 +0800
|
||
|
|
Subject: [Info] MMaps rollback to the previous version
|
||
|
|
Subject: [Type] Function
|
||
|
|
Subject: [From] Nothing
|
||
|
|
Subject: [Work] Unknown
|
||
|
|
Subject: [BUG] Unknown
|
||
|
|
Subject: [Code] NO
|
||
|
|
|
||
|
|
---
|
||
|
|
dep/recastnavigation/Detour/DetourAlloc.h | 27 +-
|
||
|
|
dep/recastnavigation/Detour/DetourAssert.h | 2 +-
|
||
|
|
dep/recastnavigation/Detour/DetourCommon.cpp | 64 -
|
||
|
|
dep/recastnavigation/Detour/DetourCommon.h | 338 +-----
|
||
|
|
dep/recastnavigation/Detour/DetourNavMesh.cpp | 573 +++------
|
||
|
|
dep/recastnavigation/Detour/DetourNavMesh.h | 710 ++++-------
|
||
|
|
.../Detour/DetourNavMeshBuilder.cpp | 356 +++---
|
||
|
|
dep/recastnavigation/Detour/DetourNavMeshBuilder.h | 157 +--
|
||
|
|
dep/recastnavigation/Detour/DetourNavMeshQuery.cpp | 1265 ++++----------------
|
||
|
|
dep/recastnavigation/Detour/DetourNavMeshQuery.h | 591 ++++-----
|
||
|
|
dep/recastnavigation/Detour/DetourNode.cpp | 17 +-
|
||
|
|
dep/recastnavigation/Detour/DetourNode.h | 32 +-
|
||
|
|
dep/recastnavigation/Detour/DetourStatus.h | 64 -
|
||
|
|
dep/recastnavigation/Recast/CMakeLists.txt | 1 -
|
||
|
|
dep/recastnavigation/Recast/Recast.cpp | 80 +-
|
||
|
|
dep/recastnavigation/Recast/Recast.h | 1180 ++++++------------
|
||
|
|
dep/recastnavigation/Recast/RecastAlloc.cpp | 21 -
|
||
|
|
dep/recastnavigation/Recast/RecastAlloc.h | 65 +-
|
||
|
|
dep/recastnavigation/Recast/RecastArea.cpp | 199 +--
|
||
|
|
dep/recastnavigation/Recast/RecastAssert.h | 2 +-
|
||
|
|
dep/recastnavigation/Recast/RecastContour.cpp | 75 +-
|
||
|
|
dep/recastnavigation/Recast/RecastFilter.cpp | 34 +-
|
||
|
|
dep/recastnavigation/Recast/RecastLayers.cpp | 620 ----------
|
||
|
|
dep/recastnavigation/Recast/RecastMesh.cpp | 128 +-
|
||
|
|
dep/recastnavigation/Recast/RecastMeshDetail.cpp | 40 +-
|
||
|
|
.../Recast/RecastRasterization.cpp | 27 -
|
||
|
|
dep/recastnavigation/Recast/RecastRegion.cpp | 116 +-
|
||
|
|
src/server/collision/Management/MMapManager.cpp | 10 +-
|
||
|
|
src/server/game/Grids/GridDefines.h | 2 +-
|
||
|
|
src/server/game/Miscellaneous/SharedDefines.h | 2 +-
|
||
|
|
src/server/game/Movement/PathGenerator.cpp | 34 +-
|
||
|
|
src/server/scripts/Commands/cs_mmaps.cpp | 21 +-
|
||
|
|
src/tools/mmaps_generator/Info/readme.txt | 4 +-
|
||
|
|
src/tools/mmaps_generator/MapBuilder.cpp | 235 ++--
|
||
|
|
src/tools/mmaps_generator/MapBuilder.h | 2 +-
|
||
|
|
src/tools/mmaps_generator/PathCommon.h | 1 +
|
||
|
|
src/tools/mmaps_generator/PathGenerator.cpp | 4 +-
|
||
|
|
src/tools/mmaps_generator/TerrainBuilder.cpp | 6 +-
|
||
|
|
src/tools/mmaps_generator/TerrainBuilder.h | 2 +-
|
||
|
|
39 files changed, 1715 insertions(+), 5392 deletions(-)
|
||
|
|
delete mode 100644 dep/recastnavigation/Detour/DetourStatus.h
|
||
|
|
delete mode 100644 dep/recastnavigation/Recast/RecastLayers.cpp
|
||
|
|
|
||
|
|
diff --git a/dep/recastnavigation/Detour/DetourAlloc.h b/dep/recastnavigation/Detour/DetourAlloc.h
|
||
|
|
index e814b62..8693475 100644
|
||
|
|
--- a/dep/recastnavigation/Detour/DetourAlloc.h
|
||
|
|
+++ b/dep/recastnavigation/Detour/DetourAlloc.h
|
||
|
|
@@ -19,41 +19,18 @@
|
||
|
|
#ifndef DETOURALLOCATOR_H
|
||
|
|
#define DETOURALLOCATOR_H
|
||
|
|
|
||
|
|
-/// Provides hint values to the memory allocator on how long the
|
||
|
|
-/// memory is expected to be used.
|
||
|
|
enum dtAllocHint
|
||
|
|
{
|
||
|
|
- DT_ALLOC_PERM, ///< Memory persist after a function call.
|
||
|
|
- DT_ALLOC_TEMP ///< Memory used temporarily within a function.
|
||
|
|
+ DT_ALLOC_PERM, // Memory persist after a function call.
|
||
|
|
+ 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);
|
||
|
|
-
|
||
|
|
-/// A memory deallocation function.
|
||
|
|
-/// @param[in] ptr A pointer to a memory block previously allocated using #dtAllocFunc.
|
||
|
|
-/// @see dtAllocSetCustom
|
||
|
|
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);
|
||
|
|
|
||
|
|
-/// 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);
|
||
|
|
-
|
||
|
|
-/// Deallocates a memory block.
|
||
|
|
-/// @param[in] ptr A pointer to a memory block previously allocated using #dtAlloc.
|
||
|
|
-/// @see dtAlloc
|
||
|
|
void dtFree(void* ptr);
|
||
|
|
|
||
|
|
#endif
|
||
|
|
diff --git a/dep/recastnavigation/Detour/DetourAssert.h b/dep/recastnavigation/Detour/DetourAssert.h
|
||
|
|
index 3cf6522..709ebd9 100644
|
||
|
|
--- a/dep/recastnavigation/Detour/DetourAssert.h
|
||
|
|
+++ b/dep/recastnavigation/Detour/DetourAssert.h
|
||
|
|
@@ -24,7 +24,7 @@
|
||
|
|
|
||
|
|
#ifdef NDEBUG
|
||
|
|
// From http://cnicholson.net/2009/02/stupid-c-tricks-adventures-in-assert/
|
||
|
|
-# define dtAssert(x) do { (void)sizeof(x); } while((void)(__LINE__==-1),false)
|
||
|
|
+# define dtAssert(x) do { (void)sizeof(x); } while(__LINE__==-1,false)
|
||
|
|
#else
|
||
|
|
# include <assert.h>
|
||
|
|
# define dtAssert assert
|
||
|
|
diff --git a/dep/recastnavigation/Detour/DetourCommon.cpp b/dep/recastnavigation/Detour/DetourCommon.cpp
|
||
|
|
index b5700f5..c0b973e 100644
|
||
|
|
--- a/dep/recastnavigation/Detour/DetourCommon.cpp
|
||
|
|
+++ b/dep/recastnavigation/Detour/DetourCommon.cpp
|
||
|
|
@@ -238,9 +238,6 @@ bool dtClosestHeightPointTriangle(const float* p, const float* a, const float* b
|
||
|
|
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)
|
||
|
|
{
|
||
|
|
// TODO: Replace pnpoly with triArea2D tests?
|
||
|
|
@@ -294,9 +291,6 @@ inline bool overlapRange(const float amin, const float amax,
|
||
|
|
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,
|
||
|
|
const float* polyb, const int npolyb)
|
||
|
|
{
|
||
|
|
@@ -333,61 +327,3 @@ bool dtOverlapPolyPoly2D(const float* polya, const int npolya,
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
-// Returns a random point in a convex polygon.
|
||
|
|
-// Adapted from Graphics Gems article.
|
||
|
|
-void dtRandomPointInConvexPoly(const float* pts, const int npts, float* areas,
|
||
|
|
- const float s, const float t, float* out)
|
||
|
|
-{
|
||
|
|
- // Calc triangle araes
|
||
|
|
- float areasum = 0.0f;
|
||
|
|
- for (int i = 2; i < npts; i++) {
|
||
|
|
- areas[i] = dtTriArea2D(&pts[0], &pts[(i-1)*3], &pts[i*3]);
|
||
|
|
- areasum += dtMax(0.001f, areas[i]);
|
||
|
|
- }
|
||
|
|
- // Find sub triangle weighted by area.
|
||
|
|
- const float thr = s*areasum;
|
||
|
|
- float acc = 0.0f;
|
||
|
|
- float u = 0.0f;
|
||
|
|
- int tri = 0;
|
||
|
|
- for (int i = 2; i < npts; i++) {
|
||
|
|
- const float dacc = areas[i];
|
||
|
|
- if (thr >= acc && thr < (acc+dacc))
|
||
|
|
- {
|
||
|
|
- u = (thr - acc) / dacc;
|
||
|
|
- tri = i;
|
||
|
|
- break;
|
||
|
|
- }
|
||
|
|
- acc += dacc;
|
||
|
|
- }
|
||
|
|
-
|
||
|
|
- float v = dtSqrt(t);
|
||
|
|
-
|
||
|
|
- const float a = 1 - v;
|
||
|
|
- const float b = (1 - u) * v;
|
||
|
|
- const float c = u * v;
|
||
|
|
- const float* pa = &pts[0];
|
||
|
|
- const float* pb = &pts[(tri-1)*3];
|
||
|
|
- const float* pc = &pts[tri*3];
|
||
|
|
-
|
||
|
|
- out[0] = a*pa[0] + b*pb[0] + c*pc[0];
|
||
|
|
- out[1] = a*pa[1] + b*pb[1] + c*pc[1];
|
||
|
|
- 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;
|
||
|
|
-}
|
||
|
|
-
|
||
|
|
diff --git a/dep/recastnavigation/Detour/DetourCommon.h b/dep/recastnavigation/Detour/DetourCommon.h
|
||
|
|
index ed7c514..3cee3f6 100644
|
||
|
|
--- a/dep/recastnavigation/Detour/DetourCommon.h
|
||
|
|
+++ b/dep/recastnavigation/Detour/DetourCommon.h
|
||
|
|
@@ -19,66 +19,15 @@
|
||
|
|
#ifndef DETOURCOMMON_H
|
||
|
|
#define DETOURCOMMON_H
|
||
|
|
|
||
|
|
-/**
|
||
|
|
-@defgroup detour Detour
|
||
|
|
-
|
||
|
|
-Members in this module are used to create, manipulate, and query navigation
|
||
|
|
-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; }
|
||
|
|
-
|
||
|
|
-/// 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; }
|
||
|
|
-
|
||
|
|
-/// 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; }
|
||
|
|
-
|
||
|
|
-/// 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; }
|
||
|
|
-
|
||
|
|
-/// 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; }
|
||
|
|
-
|
||
|
|
-/// 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); }
|
||
|
|
|
||
|
|
-/// 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.
|
||
|
|
-/// @{
|
||
|
|
-
|
||
|
|
-/// 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)
|
||
|
|
{
|
||
|
|
dest[0] = v1[1]*v2[2] - v1[2]*v2[1];
|
||
|
|
@@ -86,20 +35,11 @@ inline void dtVcross(float* dest, const float* v1, const float* v2)
|
||
|
|
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)
|
||
|
|
{
|
||
|
|
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)
|
||
|
|
{
|
||
|
|
dest[0] = v1[0]+v2[0]*s;
|
||
|
|
@@ -107,11 +47,6 @@ inline void dtVmad(float* dest, const float* v1, const float* v2, const float 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)
|
||
|
|
{
|
||
|
|
dest[0] = v1[0]+(v2[0]-v1[0])*t;
|
||
|
|
@@ -119,10 +54,6 @@ inline void dtVlerp(float* dest, const float* v1, const float* v2, const float 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)
|
||
|
|
{
|
||
|
|
dest[0] = v1[0]+v2[0];
|
||
|
|
@@ -130,10 +61,6 @@ inline void dtVadd(float* dest, const float* v1, const float* v2)
|
||
|
|
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)
|
||
|
|
{
|
||
|
|
dest[0] = v1[0]-v2[0];
|
||
|
|
@@ -141,10 +68,6 @@ inline void dtVsub(float* dest, const float* v1, const float* v2)
|
||
|
|
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)
|
||
|
|
{
|
||
|
|
dest[0] = v[0]*t;
|
||
|
|
@@ -152,9 +75,6 @@ inline void dtVscale(float* dest, const float* v, const float 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)
|
||
|
|
{
|
||
|
|
mn[0] = dtMin(mn[0], v[0]);
|
||
|
|
@@ -162,9 +82,6 @@ inline void dtVmin(float* mn, const float* v)
|
||
|
|
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)
|
||
|
|
{
|
||
|
|
mx[0] = dtMax(mx[0], v[0]);
|
||
|
|
@@ -172,19 +89,11 @@ inline void dtVmax(float* mx, const float* v)
|
||
|
|
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)
|
||
|
|
{
|
||
|
|
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)
|
||
|
|
{
|
||
|
|
dest[0] = a[0];
|
||
|
|
@@ -192,26 +101,16 @@ inline void dtVcopy(float* dest, const float* a)
|
||
|
|
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)
|
||
|
|
{
|
||
|
|
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)
|
||
|
|
{
|
||
|
|
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)
|
||
|
|
{
|
||
|
|
const float dx = v2[0] - v1[0];
|
||
|
|
@@ -220,10 +119,6 @@ inline float dtVdist(const float* v1, const float* v2)
|
||
|
|
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)
|
||
|
|
{
|
||
|
|
const float dx = v2[0] - v1[0];
|
||
|
|
@@ -232,12 +127,6 @@ inline float dtVdistSqr(const float* v1, const float* v2)
|
||
|
|
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)
|
||
|
|
{
|
||
|
|
const float dx = v2[0] - v1[0];
|
||
|
|
@@ -245,10 +134,6 @@ inline float dtVdist2D(const float* v1, const float* v2)
|
||
|
|
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)
|
||
|
|
{
|
||
|
|
const float dx = v2[0] - v1[0];
|
||
|
|
@@ -256,8 +141,6 @@ inline float dtVdist2DSqr(const float* v1, const float* v2)
|
||
|
|
return dx*dx + dz*dz;
|
||
|
|
}
|
||
|
|
|
||
|
|
-/// Normalizes the vector.
|
||
|
|
-/// @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]));
|
||
|
|
@@ -266,13 +149,6 @@ inline void dtVnormalize(float* v)
|
||
|
|
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)
|
||
|
|
{
|
||
|
|
static const float thr = dtSqr(1.0f/16384.0f);
|
||
|
|
@@ -280,37 +156,44 @@ inline bool dtVequal(const float* p0, const float* p1)
|
||
|
|
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 unsigned int dtNextPow2(unsigned int v)
|
||
|
|
+{
|
||
|
|
+ v--;
|
||
|
|
+ v |= v >> 1;
|
||
|
|
+ v |= v >> 2;
|
||
|
|
+ v |= v >> 4;
|
||
|
|
+ v |= v >> 8;
|
||
|
|
+ v |= v >> 16;
|
||
|
|
+ v++;
|
||
|
|
+ return v;
|
||
|
|
+}
|
||
|
|
+
|
||
|
|
+inline unsigned int dtIlog2(unsigned int v)
|
||
|
|
+{
|
||
|
|
+ unsigned int r;
|
||
|
|
+ unsigned int shift;
|
||
|
|
+ r = (v > 0xffff) << 4; v >>= r;
|
||
|
|
+ shift = (v > 0xff) << 3; v >>= shift; r |= shift;
|
||
|
|
+ shift = (v > 0xf) << 2; v >>= shift; r |= shift;
|
||
|
|
+ shift = (v > 0x3) << 1; v >>= shift; r |= shift;
|
||
|
|
+ r |= (v >> 1);
|
||
|
|
+ return r;
|
||
|
|
+}
|
||
|
|
+
|
||
|
|
+inline int dtAlign4(int x) { return (x+3) & ~3; }
|
||
|
|
+
|
||
|
|
+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];
|
||
|
|
}
|
||
|
|
|
||
|
|
-/// 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];
|
||
|
|
@@ -320,13 +203,6 @@ inline float dtTriArea2D(const float* a, const float* b, const float* c)
|
||
|
|
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])
|
||
|
|
{
|
||
|
|
@@ -337,13 +213,6 @@ inline bool dtOverlapQuantBounds(const unsigned short amin[3], const unsigned sh
|
||
|
|
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)
|
||
|
|
{
|
||
|
|
@@ -354,21 +223,9 @@ inline bool dtOverlapBounds(const float* amin, const float* amax,
|
||
|
|
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,
|
||
|
|
@@ -376,15 +233,6 @@ 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]
|
||
|
|
-/// @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,
|
||
|
|
@@ -392,139 +240,9 @@ bool dtDistancePtPolyEdgesSqr(const float* pt, const float* verts, const int nve
|
||
|
|
|
||
|
|
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)
|
||
|
|
-{
|
||
|
|
- v--;
|
||
|
|
- v |= v >> 1;
|
||
|
|
- v |= v >> 2;
|
||
|
|
- v |= v >> 4;
|
||
|
|
- v |= v >> 8;
|
||
|
|
- v |= v >> 16;
|
||
|
|
- v++;
|
||
|
|
- return v;
|
||
|
|
-}
|
||
|
|
-
|
||
|
|
-inline unsigned int dtIlog2(unsigned int v)
|
||
|
|
-{
|
||
|
|
- unsigned int r;
|
||
|
|
- unsigned int shift;
|
||
|
|
- r = (v > 0xffff) << 4; v >>= r;
|
||
|
|
- shift = (v > 0xff) << 3; v >>= shift; r |= shift;
|
||
|
|
- shift = (v > 0xf) << 2; v >>= shift; r |= shift;
|
||
|
|
- shift = (v > 0x3) << 1; v >>= shift; r |= shift;
|
||
|
|
- r |= (v >> 1);
|
||
|
|
- return r;
|
||
|
|
-}
|
||
|
|
-
|
||
|
|
-inline int dtAlign4(int x) { return (x+3) & ~3; }
|
||
|
|
-
|
||
|
|
-inline int dtOppositeTile(int side) { return (side+4) & 0x7; }
|
||
|
|
-
|
||
|
|
-inline void dtSwapByte(unsigned char* a, unsigned char* b)
|
||
|
|
-{
|
||
|
|
- unsigned char tmp = *a;
|
||
|
|
- *a = *b;
|
||
|
|
- *b = tmp;
|
||
|
|
-}
|
||
|
|
-
|
||
|
|
-inline void dtSwapEndian(unsigned short* v)
|
||
|
|
-{
|
||
|
|
- unsigned char* x = (unsigned char*)v;
|
||
|
|
- dtSwapByte(x+0, x+1);
|
||
|
|
-}
|
||
|
|
-
|
||
|
|
-inline void dtSwapEndian(short* v)
|
||
|
|
-{
|
||
|
|
- unsigned char* x = (unsigned char*)v;
|
||
|
|
- dtSwapByte(x+0, x+1);
|
||
|
|
-}
|
||
|
|
-
|
||
|
|
-inline void dtSwapEndian(unsigned int* v)
|
||
|
|
-{
|
||
|
|
- unsigned char* x = (unsigned char*)v;
|
||
|
|
- dtSwapByte(x+0, x+3); dtSwapByte(x+1, x+2);
|
||
|
|
-}
|
||
|
|
-
|
||
|
|
-inline void dtSwapEndian(int* v)
|
||
|
|
-{
|
||
|
|
- unsigned char* x = (unsigned char*)v;
|
||
|
|
- dtSwapByte(x+0, x+3); dtSwapByte(x+1, x+2);
|
||
|
|
-}
|
||
|
|
-
|
||
|
|
-inline void dtSwapEndian(float* v)
|
||
|
|
-{
|
||
|
|
- unsigned char* x = (unsigned char*)v;
|
||
|
|
- dtSwapByte(x+0, x+3); dtSwapByte(x+1, x+2);
|
||
|
|
-}
|
||
|
|
-
|
||
|
|
-void dtRandomPointInConvexPoly(const float* pts, const int npts, float* areas,
|
||
|
|
- const float s, const float t, float* out);
|
||
|
|
-
|
||
|
|
-/// @}
|
||
|
|
-
|
||
|
|
#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>
|
||
|
|
-
|
||
|
|
-*/
|
||
|
|
diff --git a/dep/recastnavigation/Detour/DetourNavMesh.cpp b/dep/recastnavigation/Detour/DetourNavMesh.cpp
|
||
|
|
index 6b8e2d9..e139e3f 100644
|
||
|
|
--- a/dep/recastnavigation/Detour/DetourNavMesh.cpp
|
||
|
|
+++ b/dep/recastnavigation/Detour/DetourNavMesh.cpp
|
||
|
|
@@ -64,15 +64,6 @@ inline bool overlapSlabs(const float* amin, const float* amax,
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
-static float getSlabCoord(const float* va, const int side)
|
||
|
|
-{
|
||
|
|
- if (side == 0 || side == 4)
|
||
|
|
- return va[0];
|
||
|
|
- else if (side == 2 || side == 6)
|
||
|
|
- return va[2];
|
||
|
|
- return 0;
|
||
|
|
-}
|
||
|
|
-
|
||
|
|
static void calcSlabEndPoints(const float* va, const float* vb, float* bmin, float* bmax, const int side)
|
||
|
|
{
|
||
|
|
if (side == 0 || side == 4)
|
||
|
|
@@ -142,10 +133,6 @@ dtNavMesh* dtAllocNavMesh()
|
||
|
|
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)
|
||
|
|
{
|
||
|
|
if (!navmesh) return;
|
||
|
|
@@ -154,37 +141,6 @@ void dtFreeNavMesh(dtNavMesh* navmesh)
|
||
|
|
}
|
||
|
|
|
||
|
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||
|
|
-
|
||
|
|
-/**
|
||
|
|
-@class dtNavMesh
|
||
|
|
-
|
||
|
|
-The navigation mesh consists of one or more tiles defining three primary types of structural data:
|
||
|
|
-
|
||
|
|
-A polygon mesh which defines most of the navigation graph. (See rcPolyMesh for its structure.)
|
||
|
|
-A detail mesh used for determining surface height on the polygon mesh. (See rcPolyMeshDetail for its structure.)
|
||
|
|
-Off-mesh connections, which define custom point-to-point edges within the navigation graph.
|
||
|
|
-
|
||
|
|
-The general build process is as follows:
|
||
|
|
-
|
||
|
|
--# Create rcPolyMesh and rcPolyMeshDetail data using the Recast build pipeline.
|
||
|
|
--# Optionally, create off-mesh connection data.
|
||
|
|
--# Combine the source data into a dtNavMeshCreateParams structure.
|
||
|
|
--# Create a tile data array using dtCreateNavMeshData().
|
||
|
|
--# Allocate at dtNavMesh object and initialize it. (For single tile navigation meshes,
|
||
|
|
- the tile data is loaded during this step.)
|
||
|
|
--# For multi-tile navigation meshes, load the tile data using dtNavMesh::addTile().
|
||
|
|
-
|
||
|
|
-Notes:
|
||
|
|
-
|
||
|
|
-- This class is usually used in conjunction with the dtNavMeshQuery class for pathfinding.
|
||
|
|
-- 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() :
|
||
|
|
m_tileWidth(0),
|
||
|
|
m_tileHeight(0),
|
||
|
|
@@ -198,7 +154,6 @@ dtNavMesh::dtNavMesh() :
|
||
|
|
m_tileBits(0),
|
||
|
|
m_polyBits(0)
|
||
|
|
{
|
||
|
|
- memset(&m_params, 0, sizeof(dtNavMeshParams));
|
||
|
|
m_orig[0] = 0;
|
||
|
|
m_orig[1] = 0;
|
||
|
|
m_orig[2] = 0;
|
||
|
|
@@ -234,10 +189,10 @@ dtStatus dtNavMesh::init(const dtNavMeshParams* params)
|
||
|
|
|
||
|
|
m_tiles = (dtMeshTile*)dtAlloc(sizeof(dtMeshTile)*m_maxTiles, DT_ALLOC_PERM);
|
||
|
|
if (!m_tiles)
|
||
|
|
- return DT_FAILURE | DT_OUT_OF_MEMORY;
|
||
|
|
+ return DT_FAILURE;
|
||
|
|
m_posLookup = (dtMeshTile**)dtAlloc(sizeof(dtMeshTile*)*m_tileLutSize, DT_ALLOC_PERM);
|
||
|
|
if (!m_posLookup)
|
||
|
|
- return DT_FAILURE | DT_OUT_OF_MEMORY;
|
||
|
|
+ return DT_FAILURE;
|
||
|
|
memset(m_tiles, 0, sizeof(dtMeshTile)*m_maxTiles);
|
||
|
|
memset(m_posLookup, 0, sizeof(dtMeshTile*)*m_tileLutSize);
|
||
|
|
m_nextFree = 0;
|
||
|
|
@@ -248,11 +203,13 @@ dtStatus dtNavMesh::init(const dtNavMeshParams* params)
|
||
|
|
m_nextFree = &m_tiles[i];
|
||
|
|
}
|
||
|
|
|
||
|
|
- // Edited by TC
|
||
|
|
- m_tileBits = STATIC_TILE_BITS;
|
||
|
|
- m_polyBits = STATIC_POLY_BITS;
|
||
|
|
- m_saltBits = STATIC_SALT_BITS;
|
||
|
|
-
|
||
|
|
+ // Init ID generator values.
|
||
|
|
+ m_tileBits = STATIC_TILE_BITS; //dtIlog2(dtNextPow2((unsigned int)params->maxTiles));
|
||
|
|
+ m_polyBits = STATIC_POLY_BITS; //dtIlog2(dtNextPow2((unsigned int)params->maxPolys));
|
||
|
|
+ m_saltBits = STATIC_SALT_BITS; //sizeof(dtPolyRef)*8 - m_tileBits - m_polyBits;
|
||
|
|
+ //if (m_saltBits < SALT_MIN_BITS)
|
||
|
|
+ //return DT_FAILURE;
|
||
|
|
+
|
||
|
|
return DT_SUCCESS;
|
||
|
|
}
|
||
|
|
|
||
|
|
@@ -261,9 +218,9 @@ dtStatus dtNavMesh::init(unsigned char* data, const int dataSize, const int flag
|
||
|
|
// Make sure the data is in right format.
|
||
|
|
dtMeshHeader* header = (dtMeshHeader*)data;
|
||
|
|
if (header->magic != DT_NAVMESH_MAGIC)
|
||
|
|
- return DT_FAILURE | DT_WRONG_MAGIC;
|
||
|
|
+ return DT_FAILURE;
|
||
|
|
if (header->version != DT_NAVMESH_VERSION)
|
||
|
|
- return DT_FAILURE | DT_WRONG_VERSION;
|
||
|
|
+ return DT_FAILURE;
|
||
|
|
|
||
|
|
dtNavMeshParams params;
|
||
|
|
dtVcopy(params.orig, header->bmin);
|
||
|
|
@@ -272,17 +229,13 @@ dtStatus dtNavMesh::init(unsigned char* data, const int dataSize, const int flag
|
||
|
|
params.maxTiles = 1;
|
||
|
|
params.maxPolys = header->polyCount;
|
||
|
|
|
||
|
|
- dtStatus status = init(¶ms);
|
||
|
|
- if (dtStatusFailed(status))
|
||
|
|
- return status;
|
||
|
|
+ dtStatus res = init(¶ms);
|
||
|
|
+ if (res != DT_SUCCESS)
|
||
|
|
+ return res;
|
||
|
|
|
||
|
|
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
|
||
|
|
{
|
||
|
|
return &m_params;
|
||
|
|
@@ -297,7 +250,6 @@ int dtNavMesh::findConnectingPolys(const float* va, const float* vb,
|
||
|
|
|
||
|
|
float amin[2], amax[2];
|
||
|
|
calcSlabEndPoints(va,vb, amin,amax, side);
|
||
|
|
- const float apos = getSlabCoord(va, side);
|
||
|
|
|
||
|
|
// Remove links pointing to 'side' and compact the links array.
|
||
|
|
float bmin[2], bmax[2];
|
||
|
|
@@ -314,18 +266,11 @@ int dtNavMesh::findConnectingPolys(const float* va, const float* vb,
|
||
|
|
{
|
||
|
|
// Skip edges which do not point to the right side.
|
||
|
|
if (poly->neis[j] != m) continue;
|
||
|
|
-
|
||
|
|
+ // Check if the segments touch.
|
||
|
|
const float* vc = &tile->verts[poly->verts[j]*3];
|
||
|
|
const float* vd = &tile->verts[poly->verts[(j+1) % nv]*3];
|
||
|
|
- const float bpos = getSlabCoord(vc, side);
|
||
|
|
-
|
||
|
|
- // Segments are not close enough.
|
||
|
|
- if (dtAbs(apos-bpos) > 0.01f)
|
||
|
|
- continue;
|
||
|
|
-
|
||
|
|
- // Check if the segments touch.
|
||
|
|
calcSlabEndPoints(vc,vd, bmin,bmax, side);
|
||
|
|
-
|
||
|
|
+
|
||
|
|
if (!overlapSlabs(amin,amax, bmin,bmax, 0.01f, tile->header->walkableClimb)) continue;
|
||
|
|
|
||
|
|
// Add return value.
|
||
|
|
@@ -342,11 +287,9 @@ int dtNavMesh::findConnectingPolys(const float* va, const float* vb,
|
||
|
|
return n;
|
||
|
|
}
|
||
|
|
|
||
|
|
-void dtNavMesh::unconnectExtLinks(dtMeshTile* tile, dtMeshTile* target)
|
||
|
|
+void dtNavMesh::unconnectExtLinks(dtMeshTile* tile, int side)
|
||
|
|
{
|
||
|
|
- if (!tile || !target) return;
|
||
|
|
-
|
||
|
|
- const unsigned int targetNum = decodePolyIdTile(getTileRef(target));
|
||
|
|
+ if (!tile) return;
|
||
|
|
|
||
|
|
for (int i = 0; i < tile->header->polyCount; ++i)
|
||
|
|
{
|
||
|
|
@@ -355,8 +298,7 @@ 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 (tile->links[j].side == side)
|
||
|
|
{
|
||
|
|
// Revove link.
|
||
|
|
unsigned int nj = tile->links[j].next;
|
||
|
|
@@ -387,25 +329,19 @@ void dtNavMesh::connectExtLinks(dtMeshTile* tile, dtMeshTile* target, int side)
|
||
|
|
dtPoly* poly = &tile->polys[i];
|
||
|
|
|
||
|
|
// Create new links.
|
||
|
|
-// unsigned short m = DT_EXT_LINK | (unsigned short)side;
|
||
|
|
-
|
||
|
|
+ unsigned short m = DT_EXT_LINK | (unsigned short)side;
|
||
|
|
const int nv = poly->vertCount;
|
||
|
|
for (int j = 0; j < nv; ++j)
|
||
|
|
{
|
||
|
|
- // Skip non-portal edges.
|
||
|
|
- if ((poly->neis[j] & DT_EXT_LINK) == 0)
|
||
|
|
- continue;
|
||
|
|
-
|
||
|
|
- const int dir = (int)(poly->neis[j] & 0xff);
|
||
|
|
- if (side != -1 && dir != side)
|
||
|
|
- continue;
|
||
|
|
+ // Skip edges which do not point to the right side.
|
||
|
|
+ if (poly->neis[j] != m) continue;
|
||
|
|
|
||
|
|
// Create new links
|
||
|
|
const float* va = &tile->verts[poly->verts[j]*3];
|
||
|
|
const float* vb = &tile->verts[poly->verts[(j+1) % nv]*3];
|
||
|
|
dtPolyRef nei[4];
|
||
|
|
float neia[4*2];
|
||
|
|
- int nnei = findConnectingPolys(va,vb, target, dtOppositeTile(dir), nei,neia,4);
|
||
|
|
+ int nnei = findConnectingPolys(va,vb, target, dtOppositeTile(side), nei,neia,4);
|
||
|
|
for (int k = 0; k < nnei; ++k)
|
||
|
|
{
|
||
|
|
unsigned int idx = allocLink(tile);
|
||
|
|
@@ -414,13 +350,13 @@ void dtNavMesh::connectExtLinks(dtMeshTile* tile, dtMeshTile* target, int side)
|
||
|
|
dtLink* link = &tile->links[idx];
|
||
|
|
link->ref = nei[k];
|
||
|
|
link->edge = (unsigned char)j;
|
||
|
|
- link->side = (unsigned char)dir;
|
||
|
|
+ link->side = (unsigned char)side;
|
||
|
|
|
||
|
|
link->next = poly->firstLink;
|
||
|
|
poly->firstLink = idx;
|
||
|
|
|
||
|
|
// Compress portal limits to a byte value.
|
||
|
|
- if (dir == 0 || dir == 4)
|
||
|
|
+ if (side == 0 || side == 4)
|
||
|
|
{
|
||
|
|
float tmin = (neia[k*2+0]-va[2]) / (vb[2]-va[2]);
|
||
|
|
float tmax = (neia[k*2+1]-va[2]) / (vb[2]-va[2]);
|
||
|
|
@@ -429,7 +365,7 @@ void dtNavMesh::connectExtLinks(dtMeshTile* tile, dtMeshTile* target, int side)
|
||
|
|
link->bmin = (unsigned char)(dtClamp(tmin, 0.0f, 1.0f)*255.0f);
|
||
|
|
link->bmax = (unsigned char)(dtClamp(tmax, 0.0f, 1.0f)*255.0f);
|
||
|
|
}
|
||
|
|
- else if (dir == 2 || dir == 6)
|
||
|
|
+ else if (side == 2 || side == 6)
|
||
|
|
{
|
||
|
|
float tmin = (neia[k*2+0]-va[0]) / (vb[0]-va[0]);
|
||
|
|
float tmax = (neia[k*2+1]-va[0]) / (vb[0]-va[0]);
|
||
|
|
@@ -450,18 +386,15 @@ void dtNavMesh::connectExtOffMeshLinks(dtMeshTile* tile, dtMeshTile* target, int
|
||
|
|
|
||
|
|
// Connect off-mesh links.
|
||
|
|
// We are interested on links which land from target tile to this tile.
|
||
|
|
- const unsigned char oppositeSide = (side == -1) ? 0xff : (unsigned char)dtOppositeTile(side);
|
||
|
|
+ const unsigned char oppositeSide = (unsigned char)dtOppositeTile(side);
|
||
|
|
|
||
|
|
for (int i = 0; i < target->header->offMeshConCount; ++i)
|
||
|
|
{
|
||
|
|
dtOffMeshConnection* targetCon = &target->offMeshCons[i];
|
||
|
|
if (targetCon->side != oppositeSide)
|
||
|
|
continue;
|
||
|
|
-
|
||
|
|
+
|
||
|
|
dtPoly* targetPoly = &target->polys[targetCon->poly];
|
||
|
|
- // Skip off-mesh connections which start location could not be connected at all.
|
||
|
|
- if (targetPoly->firstLink == DT_NULL_LINK)
|
||
|
|
- continue;
|
||
|
|
|
||
|
|
const float ext[3] = { targetCon->rad, target->header->walkableClimb, targetCon->rad };
|
||
|
|
|
||
|
|
@@ -469,8 +402,7 @@ void dtNavMesh::connectExtOffMeshLinks(dtMeshTile* tile, dtMeshTile* target, int
|
||
|
|
const float* p = &targetCon->pos[3];
|
||
|
|
float nearestPt[3];
|
||
|
|
dtPolyRef ref = findNearestPolyInTile(tile, p, ext, nearestPt);
|
||
|
|
- if (!ref)
|
||
|
|
- continue;
|
||
|
|
+ if (!ref) continue;
|
||
|
|
// findNearestPoly may return too optimistic results, further check to make sure.
|
||
|
|
if (dtSqr(nearestPt[0]-p[0])+dtSqr(nearestPt[2]-p[2]) > dtSqr(targetCon->rad))
|
||
|
|
continue;
|
||
|
|
@@ -495,19 +427,19 @@ void dtNavMesh::connectExtOffMeshLinks(dtMeshTile* tile, dtMeshTile* target, int
|
||
|
|
// Link target poly to off-mesh connection.
|
||
|
|
if (targetCon->flags & DT_OFFMESH_CON_BIDIR)
|
||
|
|
{
|
||
|
|
- unsigned int tidx = allocLink(tile);
|
||
|
|
- if (tidx != DT_NULL_LINK)
|
||
|
|
+ unsigned int idx = allocLink(tile);
|
||
|
|
+ if (idx != DT_NULL_LINK)
|
||
|
|
{
|
||
|
|
const unsigned short landPolyIdx = (unsigned short)decodePolyIdPoly(ref);
|
||
|
|
dtPoly* landPoly = &tile->polys[landPolyIdx];
|
||
|
|
- dtLink* link = &tile->links[tidx];
|
||
|
|
+ dtLink* link = &tile->links[idx];
|
||
|
|
link->ref = getPolyRefBase(target) | (dtPolyRef)(targetCon->poly);
|
||
|
|
link->edge = 0xff;
|
||
|
|
- link->side = (unsigned char)(side == -1 ? 0xff : side);
|
||
|
|
+ link->side = (unsigned char)side;
|
||
|
|
link->bmin = link->bmax = 0;
|
||
|
|
// Add to linked list.
|
||
|
|
link->next = landPoly->firstLink;
|
||
|
|
- landPoly->firstLink = tidx;
|
||
|
|
+ landPoly->firstLink = idx;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
@@ -551,13 +483,13 @@ void dtNavMesh::connectIntLinks(dtMeshTile* tile)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
-void dtNavMesh::baseOffMeshLinks(dtMeshTile* tile)
|
||
|
|
+void dtNavMesh::connectIntOffMeshLinks(dtMeshTile* tile)
|
||
|
|
{
|
||
|
|
if (!tile) return;
|
||
|
|
|
||
|
|
dtPolyRef base = getPolyRefBase(tile);
|
||
|
|
|
||
|
|
- // Base off-mesh connection start points.
|
||
|
|
+ // Find Off-mesh connection end points.
|
||
|
|
for (int i = 0; i < tile->header->offMeshConCount; ++i)
|
||
|
|
{
|
||
|
|
dtOffMeshConnection* con = &tile->offMeshCons[i];
|
||
|
|
@@ -565,96 +497,72 @@ void dtNavMesh::baseOffMeshLinks(dtMeshTile* tile)
|
||
|
|
|
||
|
|
const float ext[3] = { con->rad, tile->header->walkableClimb, con->rad };
|
||
|
|
|
||
|
|
- // Find polygon to connect to.
|
||
|
|
- const float* p = &con->pos[0]; // First vertex
|
||
|
|
- float nearestPt[3];
|
||
|
|
- dtPolyRef ref = findNearestPolyInTile(tile, p, ext, nearestPt);
|
||
|
|
- if (!ref) continue;
|
||
|
|
- // findNearestPoly may return too optimistic results, further check to make sure.
|
||
|
|
- if (dtSqr(nearestPt[0]-p[0])+dtSqr(nearestPt[2]-p[2]) > dtSqr(con->rad))
|
||
|
|
- continue;
|
||
|
|
- // Make sure the location is on current mesh.
|
||
|
|
- float* v = &tile->verts[poly->verts[0]*3];
|
||
|
|
- dtVcopy(v, nearestPt);
|
||
|
|
-
|
||
|
|
- // Link off-mesh connection to target poly.
|
||
|
|
- unsigned int idx = allocLink(tile);
|
||
|
|
- if (idx != DT_NULL_LINK)
|
||
|
|
+ for (int j = 0; j < 2; ++j)
|
||
|
|
{
|
||
|
|
- dtLink* link = &tile->links[idx];
|
||
|
|
- link->ref = ref;
|
||
|
|
- link->edge = (unsigned char)0;
|
||
|
|
- link->side = 0xff;
|
||
|
|
- link->bmin = link->bmax = 0;
|
||
|
|
- // Add to linked list.
|
||
|
|
- link->next = poly->firstLink;
|
||
|
|
- poly->firstLink = idx;
|
||
|
|
- }
|
||
|
|
+ unsigned char side = j == 0 ? 0xff : con->side;
|
||
|
|
|
||
|
|
- // Start end-point is always connect back to off-mesh connection.
|
||
|
|
- unsigned int tidx = allocLink(tile);
|
||
|
|
- if (tidx != DT_NULL_LINK)
|
||
|
|
- {
|
||
|
|
- const unsigned short landPolyIdx = (unsigned short)decodePolyIdPoly(ref);
|
||
|
|
- dtPoly* landPoly = &tile->polys[landPolyIdx];
|
||
|
|
- dtLink* link = &tile->links[tidx];
|
||
|
|
- link->ref = base | (dtPolyRef)(con->poly);
|
||
|
|
- link->edge = 0xff;
|
||
|
|
- link->side = 0xff;
|
||
|
|
- link->bmin = link->bmax = 0;
|
||
|
|
- // Add to linked list.
|
||
|
|
- link->next = landPoly->firstLink;
|
||
|
|
- landPoly->firstLink = tidx;
|
||
|
|
+ if (side == 0xff)
|
||
|
|
+ {
|
||
|
|
+ // Find polygon to connect to.
|
||
|
|
+ const float* p = &con->pos[j*3];
|
||
|
|
+ float nearestPt[3];
|
||
|
|
+ dtPolyRef ref = findNearestPolyInTile(tile, p, ext, nearestPt);
|
||
|
|
+ if (!ref) continue;
|
||
|
|
+ // findNearestPoly may return too optimistic results, further check to make sure.
|
||
|
|
+ if (dtSqr(nearestPt[0]-p[0])+dtSqr(nearestPt[2]-p[2]) > dtSqr(con->rad))
|
||
|
|
+ continue;
|
||
|
|
+ // Make sure the location is on current mesh.
|
||
|
|
+ float* v = &tile->verts[poly->verts[j]*3];
|
||
|
|
+ dtVcopy(v, nearestPt);
|
||
|
|
+
|
||
|
|
+ // Link off-mesh connection to target poly.
|
||
|
|
+ unsigned int idx = allocLink(tile);
|
||
|
|
+ if (idx != DT_NULL_LINK)
|
||
|
|
+ {
|
||
|
|
+ dtLink* link = &tile->links[idx];
|
||
|
|
+ link->ref = ref;
|
||
|
|
+ link->edge = (unsigned char)j;
|
||
|
|
+ link->side = 0xff;
|
||
|
|
+ link->bmin = link->bmax = 0;
|
||
|
|
+ // Add to linked list.
|
||
|
|
+ link->next = poly->firstLink;
|
||
|
|
+ poly->firstLink = idx;
|
||
|
|
+ }
|
||
|
|
+
|
||
|
|
+ // Start end-point is always connect back to off-mesh connection,
|
||
|
|
+ // Destination end-point only if it is bidirectional link.
|
||
|
|
+ if (j == 0 || (j == 1 && (con->flags & DT_OFFMESH_CON_BIDIR)))
|
||
|
|
+ {
|
||
|
|
+ // Link target poly to off-mesh connection.
|
||
|
|
+ unsigned int idx = allocLink(tile);
|
||
|
|
+ if (idx != DT_NULL_LINK)
|
||
|
|
+ {
|
||
|
|
+ const unsigned short landPolyIdx = (unsigned short)decodePolyIdPoly(ref);
|
||
|
|
+ dtPoly* landPoly = &tile->polys[landPolyIdx];
|
||
|
|
+ dtLink* link = &tile->links[idx];
|
||
|
|
+ link->ref = base | (dtPolyRef)(con->poly);
|
||
|
|
+ link->edge = 0xff;
|
||
|
|
+ link->side = 0xff;
|
||
|
|
+ link->bmin = link->bmax = 0;
|
||
|
|
+ // Add to linked list.
|
||
|
|
+ link->next = landPoly->firstLink;
|
||
|
|
+ landPoly->firstLink = idx;
|
||
|
|
+ }
|
||
|
|
+ }
|
||
|
|
+
|
||
|
|
+ }
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
-void dtNavMesh::closestPointOnPolyInTile(const dtMeshTile* tile, unsigned int ip,
|
||
|
|
- const float* pos, float* closest) const
|
||
|
|
+dtStatus dtNavMesh::closestPointOnPolyInTile(const dtMeshTile* tile, unsigned int ip,
|
||
|
|
+ const float* pos, float* closest) const
|
||
|
|
{
|
||
|
|
const dtPoly* poly = &tile->polys[ip];
|
||
|
|
- // 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);
|
||
|
|
- return;
|
||
|
|
- }
|
||
|
|
|
||
|
|
+ float closestDistSqr = FLT_MAX;
|
||
|
|
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]);
|
||
|
|
- }
|
||
|
|
-
|
||
|
|
- // Find height at the location.
|
||
|
|
for (int j = 0; j < pd->triCount; ++j)
|
||
|
|
{
|
||
|
|
const unsigned char* t = &tile->detailTris[(pd->triBase+j)*4];
|
||
|
|
@@ -666,13 +574,17 @@ void dtNavMesh::closestPointOnPolyInTile(const dtMeshTile* tile, unsigned int ip
|
||
|
|
else
|
||
|
|
v[k] = &tile->detailVerts[(pd->vertBase+(t[k]-poly->vertCount))*3];
|
||
|
|
}
|
||
|
|
- float h;
|
||
|
|
- if (dtClosestHeightPointTriangle(pos, v[0], v[1], v[2], h))
|
||
|
|
+ float pt[3];
|
||
|
|
+ dtClosestPtPointTriangle(pt, pos, v[0], v[1], v[2]);
|
||
|
|
+ float d = dtVdistSqr(pos, pt);
|
||
|
|
+ if (d < closestDistSqr)
|
||
|
|
{
|
||
|
|
- closest[1] = h;
|
||
|
|
- break;
|
||
|
|
+ dtVcopy(closest, pt);
|
||
|
|
+ closestDistSqr = d;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
+
|
||
|
|
+ return DT_SUCCESS;
|
||
|
|
}
|
||
|
|
|
||
|
|
dtPolyRef dtNavMesh::findNearestPolyInTile(const dtMeshTile* tile,
|
||
|
|
@@ -694,7 +606,8 @@ dtPolyRef dtNavMesh::findNearestPolyInTile(const dtMeshTile* tile,
|
||
|
|
{
|
||
|
|
dtPolyRef ref = polys[i];
|
||
|
|
float closestPtPoly[3];
|
||
|
|
- closestPointOnPolyInTile(tile, decodePolyIdPoly(ref), center, closestPtPoly);
|
||
|
|
+ if (closestPointOnPolyInTile(tile, decodePolyIdPoly(ref), center, closestPtPoly) != DT_SUCCESS)
|
||
|
|
+ continue;
|
||
|
|
float d = dtVdistSqr(center, closestPtPoly);
|
||
|
|
if (d < nearestDistanceSqr)
|
||
|
|
{
|
||
|
|
@@ -768,11 +681,8 @@ int dtNavMesh::queryPolygonsInTile(const dtMeshTile* tile, const float* qmin, co
|
||
|
|
dtPolyRef base = getPolyRefBase(tile);
|
||
|
|
for (int i = 0; i < tile->header->polyCount; ++i)
|
||
|
|
{
|
||
|
|
- dtPoly* p = &tile->polys[i];
|
||
|
|
- // Do not return off-mesh connection polygons.
|
||
|
|
- if (p->getType() == DT_POLYTYPE_OFFMESH_CONNECTION)
|
||
|
|
- continue;
|
||
|
|
// Calc polygon bounds.
|
||
|
|
+ dtPoly* p = &tile->polys[i];
|
||
|
|
const float* v = &tile->verts[p->verts[0]*3];
|
||
|
|
dtVcopy(bmin, v);
|
||
|
|
dtVcopy(bmax, v);
|
||
|
|
@@ -792,29 +702,18 @@ 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,
|
||
|
|
dtTileRef lastRef, dtTileRef* result)
|
||
|
|
{
|
||
|
|
// Make sure the data is in right format.
|
||
|
|
dtMeshHeader* header = (dtMeshHeader*)data;
|
||
|
|
if (header->magic != DT_NAVMESH_MAGIC)
|
||
|
|
- return DT_FAILURE | DT_WRONG_MAGIC;
|
||
|
|
+ return DT_FAILURE_DATA_MAGIC;
|
||
|
|
if (header->version != DT_NAVMESH_VERSION)
|
||
|
|
- return DT_FAILURE | DT_WRONG_VERSION;
|
||
|
|
+ return DT_FAILURE_DATA_VERSION;
|
||
|
|
|
||
|
|
// Make sure the location is free.
|
||
|
|
- if (getTileAt(header->x, header->y, header->layer))
|
||
|
|
+ if (getTileAt(header->x, header->y))
|
||
|
|
return DT_FAILURE;
|
||
|
|
|
||
|
|
// Allocate a tile.
|
||
|
|
@@ -833,7 +732,7 @@ dtStatus dtNavMesh::addTile(unsigned char* data, int dataSize, int flags,
|
||
|
|
// Try to relocate the tile to specific index with same salt.
|
||
|
|
int tileIndex = (int)decodePolyIdTile((dtPolyRef)lastRef);
|
||
|
|
if (tileIndex >= m_maxTiles)
|
||
|
|
- return DT_FAILURE | DT_OUT_OF_MEMORY;
|
||
|
|
+ return DT_FAILURE_OUT_OF_MEMORY;
|
||
|
|
// Try to find the specific tile id from the free list.
|
||
|
|
dtMeshTile* target = &m_tiles[tileIndex];
|
||
|
|
dtMeshTile* prev = 0;
|
||
|
|
@@ -845,7 +744,7 @@ dtStatus dtNavMesh::addTile(unsigned char* data, int dataSize, int flags,
|
||
|
|
}
|
||
|
|
// Could not find the correct location.
|
||
|
|
if (tile != target)
|
||
|
|
- return DT_FAILURE | DT_OUT_OF_MEMORY;
|
||
|
|
+ return DT_FAILURE_OUT_OF_MEMORY;
|
||
|
|
// Remove from freelist
|
||
|
|
if (!prev)
|
||
|
|
m_nextFree = tile->next;
|
||
|
|
@@ -858,7 +757,7 @@ dtStatus dtNavMesh::addTile(unsigned char* data, int dataSize, int flags,
|
||
|
|
|
||
|
|
// Make sure we could allocate a tile.
|
||
|
|
if (!tile)
|
||
|
|
- return DT_FAILURE | DT_OUT_OF_MEMORY;
|
||
|
|
+ return DT_FAILURE_OUT_OF_MEMORY;
|
||
|
|
|
||
|
|
// Insert tile into the position lut.
|
||
|
|
int h = computeTileHash(header->x, header->y, m_tileLutMask);
|
||
|
|
@@ -886,10 +785,6 @@ dtStatus dtNavMesh::addTile(unsigned char* data, int dataSize, int flags,
|
||
|
|
tile->bvTree = (dtBVNode*)d; d += bvtreeSize;
|
||
|
|
tile->offMeshCons = (dtOffMeshConnection*)d; d += offMeshLinksSize;
|
||
|
|
|
||
|
|
- // If there are no items in the bvtree, reset the tree pointer.
|
||
|
|
- if (!bvtreeSize)
|
||
|
|
- tile->bvTree = 0;
|
||
|
|
-
|
||
|
|
// Build links freelist
|
||
|
|
tile->linksFreeList = 0;
|
||
|
|
tile->links[header->maxLinkCount-1].next = DT_NULL_LINK;
|
||
|
|
@@ -903,36 +798,18 @@ dtStatus dtNavMesh::addTile(unsigned char* data, int dataSize, int flags,
|
||
|
|
tile->flags = flags;
|
||
|
|
|
||
|
|
connectIntLinks(tile);
|
||
|
|
- baseOffMeshLinks(tile);
|
||
|
|
+ connectIntOffMeshLinks(tile);
|
||
|
|
|
||
|
|
- // Create connections with neighbour tiles.
|
||
|
|
- static const int MAX_NEIS = 32;
|
||
|
|
- dtMeshTile* neis[MAX_NEIS];
|
||
|
|
- int nneis;
|
||
|
|
-
|
||
|
|
- // Connect with layers in current tile.
|
||
|
|
- nneis = getTilesAt(header->x, header->y, neis, MAX_NEIS);
|
||
|
|
- for (int j = 0; j < nneis; ++j)
|
||
|
|
- {
|
||
|
|
- if (neis[j] != tile)
|
||
|
|
- {
|
||
|
|
- connectExtLinks(tile, neis[j], -1);
|
||
|
|
- connectExtLinks(neis[j], tile, -1);
|
||
|
|
- }
|
||
|
|
- connectExtOffMeshLinks(tile, neis[j], -1);
|
||
|
|
- connectExtOffMeshLinks(neis[j], tile, -1);
|
||
|
|
- }
|
||
|
|
-
|
||
|
|
- // Connect with neighbour tiles.
|
||
|
|
+ // Create connections connections.
|
||
|
|
for (int i = 0; i < 8; ++i)
|
||
|
|
{
|
||
|
|
- nneis = getNeighbourTilesAt(header->x, header->y, i, neis, MAX_NEIS);
|
||
|
|
- for (int j = 0; j < nneis; ++j)
|
||
|
|
+ dtMeshTile* nei = getNeighbourTileAt(header->x, header->y, i);
|
||
|
|
+ if (nei)
|
||
|
|
{
|
||
|
|
- connectExtLinks(tile, neis[j], i);
|
||
|
|
- connectExtLinks(neis[j], tile, dtOppositeTile(i));
|
||
|
|
- connectExtOffMeshLinks(tile, neis[j], i);
|
||
|
|
- connectExtOffMeshLinks(neis[j], tile, dtOppositeTile(i));
|
||
|
|
+ connectExtLinks(tile, nei, i);
|
||
|
|
+ connectExtLinks(nei, tile, dtOppositeTile(i));
|
||
|
|
+ connectExtOffMeshLinks(tile, nei, i);
|
||
|
|
+ connectExtOffMeshLinks(nei, tile, dtOppositeTile(i));
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
@@ -942,106 +819,55 @@ dtStatus dtNavMesh::addTile(unsigned char* data, int dataSize, int flags,
|
||
|
|
return DT_SUCCESS;
|
||
|
|
}
|
||
|
|
|
||
|
|
-const dtMeshTile* dtNavMesh::getTileAt(const int x, const int y, const int layer) const
|
||
|
|
+const dtMeshTile* dtNavMesh::getTileAt(int x, int y) const
|
||
|
|
{
|
||
|
|
// Find tile based on hash.
|
||
|
|
int h = computeTileHash(x,y,m_tileLutMask);
|
||
|
|
dtMeshTile* tile = m_posLookup[h];
|
||
|
|
while (tile)
|
||
|
|
{
|
||
|
|
- if (tile->header &&
|
||
|
|
- tile->header->x == x &&
|
||
|
|
- tile->header->y == y &&
|
||
|
|
- tile->header->layer == layer)
|
||
|
|
- {
|
||
|
|
+ if (tile->header && tile->header->x == x && tile->header->y == y)
|
||
|
|
return tile;
|
||
|
|
- }
|
||
|
|
tile = tile->next;
|
||
|
|
}
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
-int dtNavMesh::getNeighbourTilesAt(const int x, const int y, const int side, dtMeshTile** tiles, const int maxTiles) const
|
||
|
|
+dtMeshTile* dtNavMesh::getNeighbourTileAt(int x, int y, int side) const
|
||
|
|
{
|
||
|
|
- int nx = x, ny = y;
|
||
|
|
switch (side)
|
||
|
|
{
|
||
|
|
- case 0: nx++; break;
|
||
|
|
- case 1: nx++; ny++; break;
|
||
|
|
- case 2: ny++; break;
|
||
|
|
- case 3: nx--; ny++; break;
|
||
|
|
- case 4: nx--; break;
|
||
|
|
- case 5: nx--; ny--; break;
|
||
|
|
- case 6: ny--; break;
|
||
|
|
- case 7: nx++; ny--; break;
|
||
|
|
+ case 0: x++; break;
|
||
|
|
+ case 1: x++; y++; break;
|
||
|
|
+ case 2: y++; break;
|
||
|
|
+ case 3: x--; y++; break;
|
||
|
|
+ case 4: x--; break;
|
||
|
|
+ case 5: x--; y--; break;
|
||
|
|
+ case 6: y--; break;
|
||
|
|
+ case 7: x++; y--; break;
|
||
|
|
};
|
||
|
|
|
||
|
|
- return getTilesAt(nx, ny, tiles, maxTiles);
|
||
|
|
-}
|
||
|
|
-
|
||
|
|
-int dtNavMesh::getTilesAt(const int x, const int y, dtMeshTile** tiles, const int maxTiles) const
|
||
|
|
-{
|
||
|
|
- int n = 0;
|
||
|
|
-
|
||
|
|
- // Find tile based on hash.
|
||
|
|
- int h = computeTileHash(x,y,m_tileLutMask);
|
||
|
|
- dtMeshTile* tile = m_posLookup[h];
|
||
|
|
- while (tile)
|
||
|
|
- {
|
||
|
|
- if (tile->header &&
|
||
|
|
- tile->header->x == x &&
|
||
|
|
- tile->header->y == y)
|
||
|
|
- {
|
||
|
|
- if (n < maxTiles)
|
||
|
|
- tiles[n++] = tile;
|
||
|
|
- }
|
||
|
|
- tile = tile->next;
|
||
|
|
- }
|
||
|
|
-
|
||
|
|
- 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 n = 0;
|
||
|
|
-
|
||
|
|
// Find tile based on hash.
|
||
|
|
int h = computeTileHash(x,y,m_tileLutMask);
|
||
|
|
dtMeshTile* tile = m_posLookup[h];
|
||
|
|
while (tile)
|
||
|
|
{
|
||
|
|
- if (tile->header &&
|
||
|
|
- tile->header->x == x &&
|
||
|
|
- tile->header->y == y)
|
||
|
|
- {
|
||
|
|
- if (n < maxTiles)
|
||
|
|
- tiles[n++] = tile;
|
||
|
|
- }
|
||
|
|
+ if (tile->header && tile->header->x == x && tile->header->y == y)
|
||
|
|
+ return tile;
|
||
|
|
tile = tile->next;
|
||
|
|
}
|
||
|
|
-
|
||
|
|
- return n;
|
||
|
|
+ return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
-
|
||
|
|
-dtTileRef dtNavMesh::getTileRefAt(const int x, const int y, const int layer) const
|
||
|
|
+dtTileRef dtNavMesh::getTileRefAt(int x, int y) const
|
||
|
|
{
|
||
|
|
// Find tile based on hash.
|
||
|
|
int h = computeTileHash(x,y,m_tileLutMask);
|
||
|
|
dtMeshTile* tile = m_posLookup[h];
|
||
|
|
while (tile)
|
||
|
|
{
|
||
|
|
- if (tile->header &&
|
||
|
|
- tile->header->x == x &&
|
||
|
|
- tile->header->y == y &&
|
||
|
|
- tile->header->layer == layer)
|
||
|
|
- {
|
||
|
|
+ if (tile->header && tile->header->x == x && tile->header->y == y)
|
||
|
|
return getTileRef(tile);
|
||
|
|
- }
|
||
|
|
tile = tile->next;
|
||
|
|
}
|
||
|
|
return 0;
|
||
|
|
@@ -1084,22 +910,16 @@ void dtNavMesh::calcTileLoc(const float* pos, int* tx, int* ty) const
|
||
|
|
|
||
|
|
dtStatus dtNavMesh::getTileAndPolyByRef(const dtPolyRef ref, const dtMeshTile** tile, const dtPoly** poly) const
|
||
|
|
{
|
||
|
|
- if (!ref) return DT_FAILURE;
|
||
|
|
unsigned int salt, it, ip;
|
||
|
|
decodePolyId(ref, salt, it, ip);
|
||
|
|
- if (it >= (unsigned int)m_maxTiles) return DT_FAILURE | DT_INVALID_PARAM;
|
||
|
|
- if (m_tiles[it].salt != salt || m_tiles[it].header == 0) return DT_FAILURE | DT_INVALID_PARAM;
|
||
|
|
- if (ip >= (unsigned int)m_tiles[it].header->polyCount) return DT_FAILURE | DT_INVALID_PARAM;
|
||
|
|
+ if (it >= (unsigned int)m_maxTiles) return DT_FAILURE;
|
||
|
|
+ if (m_tiles[it].salt != salt || m_tiles[it].header == 0) return DT_FAILURE;
|
||
|
|
+ if (ip >= (unsigned int)m_tiles[it].header->polyCount) return DT_FAILURE;
|
||
|
|
*tile = &m_tiles[it];
|
||
|
|
*poly = &m_tiles[it].polys[ip];
|
||
|
|
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
|
||
|
|
{
|
||
|
|
unsigned int salt, it, ip;
|
||
|
|
@@ -1110,7 +930,6 @@ void dtNavMesh::getTileAndPolyByRefUnsafe(const dtPolyRef ref, const dtMeshTile*
|
||
|
|
|
||
|
|
bool dtNavMesh::isValidPolyRef(dtPolyRef ref) const
|
||
|
|
{
|
||
|
|
- if (!ref) return false;
|
||
|
|
unsigned int salt, it, ip;
|
||
|
|
decodePolyId(ref, salt, it, ip);
|
||
|
|
if (it >= (unsigned int)m_maxTiles) return false;
|
||
|
|
@@ -1119,23 +938,17 @@ bool dtNavMesh::isValidPolyRef(dtPolyRef ref) const
|
||
|
|
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)
|
||
|
|
{
|
||
|
|
if (!ref)
|
||
|
|
- return DT_FAILURE | DT_INVALID_PARAM;
|
||
|
|
+ return DT_FAILURE;
|
||
|
|
unsigned int tileIndex = decodePolyIdTile((dtPolyRef)ref);
|
||
|
|
unsigned int tileSalt = decodePolyIdSalt((dtPolyRef)ref);
|
||
|
|
if ((int)tileIndex >= m_maxTiles)
|
||
|
|
- return DT_FAILURE | DT_INVALID_PARAM;
|
||
|
|
+ return DT_FAILURE;
|
||
|
|
dtMeshTile* tile = &m_tiles[tileIndex];
|
||
|
|
if (tile->salt != tileSalt)
|
||
|
|
- return DT_FAILURE | DT_INVALID_PARAM;
|
||
|
|
+ return DT_FAILURE;
|
||
|
|
|
||
|
|
// Remove tile from hash lookup.
|
||
|
|
int h = computeTileHash(tile->header->x,tile->header->y,m_tileLutMask);
|
||
|
|
@@ -1156,27 +969,14 @@ 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.
|
||
|
|
- 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);
|
||
|
|
- }
|
||
|
|
-
|
||
|
|
- // Connect with 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);
|
||
|
|
+ dtMeshTile* nei = getNeighbourTileAt(tile->header->x,tile->header->y,i);
|
||
|
|
+ if (!nei) continue;
|
||
|
|
+ unconnectExtLinks(nei, dtOppositeTile(i));
|
||
|
|
}
|
||
|
|
-
|
||
|
|
+
|
||
|
|
+
|
||
|
|
// Reset tile.
|
||
|
|
if (tile->flags & DT_TILE_FREE_DATA)
|
||
|
|
{
|
||
|
|
@@ -1220,28 +1020,14 @@ dtStatus dtNavMesh::removeTile(dtTileRef ref, unsigned char** data, int* dataSiz
|
||
|
|
dtTileRef dtNavMesh::getTileRef(const dtMeshTile* tile) const
|
||
|
|
{
|
||
|
|
if (!tile) return 0;
|
||
|
|
- const unsigned int it = (unsigned int)(tile - m_tiles);
|
||
|
|
+ const unsigned int it = tile - m_tiles;
|
||
|
|
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
|
||
|
|
{
|
||
|
|
if (!tile) return 0;
|
||
|
|
- const unsigned int it = (unsigned int)(tile - m_tiles);
|
||
|
|
+ const unsigned int it = tile - m_tiles;
|
||
|
|
return encodePolyId(tile->salt, it, 0);
|
||
|
|
}
|
||
|
|
|
||
|
|
@@ -1258,7 +1044,6 @@ struct dtPolyState
|
||
|
|
unsigned char area; // Area ID of the polygon.
|
||
|
|
};
|
||
|
|
|
||
|
|
-/// @see #storeTileState
|
||
|
|
int dtNavMesh::getTileStateSize(const dtMeshTile* tile) const
|
||
|
|
{
|
||
|
|
if (!tile) return 0;
|
||
|
|
@@ -1267,17 +1052,12 @@ int dtNavMesh::getTileStateSize(const dtMeshTile* tile) const
|
||
|
|
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
|
||
|
|
{
|
||
|
|
// Make sure there is enough space to store the state.
|
||
|
|
const int sizeReq = getTileStateSize(tile);
|
||
|
|
if (maxDataSize < sizeReq)
|
||
|
|
- return DT_FAILURE | DT_BUFFER_TOO_SMALL;
|
||
|
|
+ return DT_FAILURE;
|
||
|
|
|
||
|
|
dtTileState* tileState = (dtTileState*)data; data += dtAlign4(sizeof(dtTileState));
|
||
|
|
dtPolyState* polyStates = (dtPolyState*)data; data += dtAlign4(sizeof(dtPolyState) * tile->header->polyCount);
|
||
|
|
@@ -1299,28 +1079,23 @@ dtStatus dtNavMesh::storeTileState(const dtMeshTile* tile, unsigned char* data,
|
||
|
|
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)
|
||
|
|
{
|
||
|
|
// Make sure there is enough space to store the state.
|
||
|
|
const int sizeReq = getTileStateSize(tile);
|
||
|
|
if (maxDataSize < sizeReq)
|
||
|
|
- return DT_FAILURE | DT_INVALID_PARAM;
|
||
|
|
+ return DT_FAILURE;
|
||
|
|
|
||
|
|
const dtTileState* tileState = (const dtTileState*)data; data += dtAlign4(sizeof(dtTileState));
|
||
|
|
const dtPolyState* polyStates = (const dtPolyState*)data; data += dtAlign4(sizeof(dtPolyState) * tile->header->polyCount);
|
||
|
|
|
||
|
|
// Check that the restore is possible.
|
||
|
|
if (tileState->magic != DT_NAVMESH_STATE_MAGIC)
|
||
|
|
- return DT_FAILURE | DT_WRONG_MAGIC;
|
||
|
|
+ return DT_FAILURE_DATA_MAGIC;
|
||
|
|
if (tileState->version != DT_NAVMESH_STATE_VERSION)
|
||
|
|
- return DT_FAILURE | DT_WRONG_VERSION;
|
||
|
|
+ return DT_FAILURE_DATA_VERSION;
|
||
|
|
if (tileState->ref != getTileRef(tile))
|
||
|
|
- return DT_FAILURE | DT_INVALID_PARAM;
|
||
|
|
+ return DT_FAILURE;
|
||
|
|
|
||
|
|
// Restore per poly state.
|
||
|
|
for (int i = 0; i < tile->header->polyCount; ++i)
|
||
|
|
@@ -1334,26 +1109,17 @@ dtStatus dtNavMesh::restoreTileState(dtMeshTile* tile, const unsigned char* data
|
||
|
|
return DT_SUCCESS;
|
||
|
|
}
|
||
|
|
|
||
|
|
-/// @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.
|
||
|
|
+// Returns start and end location of an off-mesh link polygon.
|
||
|
|
dtStatus dtNavMesh::getOffMeshConnectionPolyEndPoints(dtPolyRef prevRef, dtPolyRef polyRef, float* startPos, float* endPos) const
|
||
|
|
{
|
||
|
|
unsigned int salt, it, ip;
|
||
|
|
|
||
|
|
- if (!polyRef)
|
||
|
|
- return DT_FAILURE;
|
||
|
|
-
|
||
|
|
// Get current polygon
|
||
|
|
decodePolyId(polyRef, salt, it, ip);
|
||
|
|
- if (it >= (unsigned int)m_maxTiles) return DT_FAILURE | DT_INVALID_PARAM;
|
||
|
|
- if (m_tiles[it].salt != salt || m_tiles[it].header == 0) return DT_FAILURE | DT_INVALID_PARAM;
|
||
|
|
+ if (it >= (unsigned int)m_maxTiles) return DT_FAILURE;
|
||
|
|
+ if (m_tiles[it].salt != salt || m_tiles[it].header == 0) return DT_FAILURE;
|
||
|
|
const dtMeshTile* tile = &m_tiles[it];
|
||
|
|
- if (ip >= (unsigned int)tile->header->polyCount) return DT_FAILURE | DT_INVALID_PARAM;
|
||
|
|
+ if (ip >= (unsigned int)tile->header->polyCount) return DT_FAILURE;
|
||
|
|
const dtPoly* poly = &tile->polys[ip];
|
||
|
|
|
||
|
|
// Make sure that the current poly is indeed off-mesh link.
|
||
|
|
@@ -1388,9 +1154,6 @@ const dtOffMeshConnection* dtNavMesh::getOffMeshConnectionByRef(dtPolyRef ref) c
|
||
|
|
{
|
||
|
|
unsigned int salt, it, ip;
|
||
|
|
|
||
|
|
- if (!ref)
|
||
|
|
- return 0;
|
||
|
|
-
|
||
|
|
// Get current polygon
|
||
|
|
decodePolyId(ref, salt, it, ip);
|
||
|
|
if (it >= (unsigned int)m_maxTiles) return 0;
|
||
|
|
@@ -1411,13 +1174,12 @@ const dtOffMeshConnection* dtNavMesh::getOffMeshConnectionByRef(dtPolyRef ref) c
|
||
|
|
|
||
|
|
dtStatus dtNavMesh::setPolyFlags(dtPolyRef ref, unsigned short flags)
|
||
|
|
{
|
||
|
|
- if (!ref) return DT_FAILURE;
|
||
|
|
unsigned int salt, it, ip;
|
||
|
|
decodePolyId(ref, salt, it, ip);
|
||
|
|
- if (it >= (unsigned int)m_maxTiles) return DT_FAILURE | DT_INVALID_PARAM;
|
||
|
|
- if (m_tiles[it].salt != salt || m_tiles[it].header == 0) return DT_FAILURE | DT_INVALID_PARAM;
|
||
|
|
+ if (it >= (unsigned int)m_maxTiles) return DT_FAILURE;
|
||
|
|
+ if (m_tiles[it].salt != salt || m_tiles[it].header == 0) return DT_FAILURE;
|
||
|
|
dtMeshTile* tile = &m_tiles[it];
|
||
|
|
- if (ip >= (unsigned int)tile->header->polyCount) return DT_FAILURE | DT_INVALID_PARAM;
|
||
|
|
+ if (ip >= (unsigned int)tile->header->polyCount) return DT_FAILURE;
|
||
|
|
dtPoly* poly = &tile->polys[ip];
|
||
|
|
|
||
|
|
// Change flags.
|
||
|
|
@@ -1428,13 +1190,12 @@ dtStatus dtNavMesh::setPolyFlags(dtPolyRef ref, unsigned short flags)
|
||
|
|
|
||
|
|
dtStatus dtNavMesh::getPolyFlags(dtPolyRef ref, unsigned short* resultFlags) const
|
||
|
|
{
|
||
|
|
- if (!ref) return DT_FAILURE;
|
||
|
|
unsigned int salt, it, ip;
|
||
|
|
decodePolyId(ref, salt, it, ip);
|
||
|
|
- if (it >= (unsigned int)m_maxTiles) return DT_FAILURE | DT_INVALID_PARAM;
|
||
|
|
- if (m_tiles[it].salt != salt || m_tiles[it].header == 0) return DT_FAILURE | DT_INVALID_PARAM;
|
||
|
|
+ if (it >= (unsigned int)m_maxTiles) return DT_FAILURE;
|
||
|
|
+ if (m_tiles[it].salt != salt || m_tiles[it].header == 0) return DT_FAILURE;
|
||
|
|
const dtMeshTile* tile = &m_tiles[it];
|
||
|
|
- if (ip >= (unsigned int)tile->header->polyCount) return DT_FAILURE | DT_INVALID_PARAM;
|
||
|
|
+ if (ip >= (unsigned int)tile->header->polyCount) return DT_FAILURE;
|
||
|
|
const dtPoly* poly = &tile->polys[ip];
|
||
|
|
|
||
|
|
*resultFlags = poly->flags;
|
||
|
|
@@ -1444,13 +1205,12 @@ dtStatus dtNavMesh::getPolyFlags(dtPolyRef ref, unsigned short* resultFlags) con
|
||
|
|
|
||
|
|
dtStatus dtNavMesh::setPolyArea(dtPolyRef ref, unsigned char area)
|
||
|
|
{
|
||
|
|
- if (!ref) return DT_FAILURE;
|
||
|
|
unsigned int salt, it, ip;
|
||
|
|
decodePolyId(ref, salt, it, ip);
|
||
|
|
- if (it >= (unsigned int)m_maxTiles) return DT_FAILURE | DT_INVALID_PARAM;
|
||
|
|
- if (m_tiles[it].salt != salt || m_tiles[it].header == 0) return DT_FAILURE | DT_INVALID_PARAM;
|
||
|
|
+ if (it >= (unsigned int)m_maxTiles) return DT_FAILURE;
|
||
|
|
+ if (m_tiles[it].salt != salt || m_tiles[it].header == 0) return DT_FAILURE;
|
||
|
|
dtMeshTile* tile = &m_tiles[it];
|
||
|
|
- if (ip >= (unsigned int)tile->header->polyCount) return DT_FAILURE | DT_INVALID_PARAM;
|
||
|
|
+ if (ip >= (unsigned int)tile->header->polyCount) return DT_FAILURE;
|
||
|
|
dtPoly* poly = &tile->polys[ip];
|
||
|
|
|
||
|
|
poly->setArea(area);
|
||
|
|
@@ -1460,13 +1220,12 @@ dtStatus dtNavMesh::setPolyArea(dtPolyRef ref, unsigned char area)
|
||
|
|
|
||
|
|
dtStatus dtNavMesh::getPolyArea(dtPolyRef ref, unsigned char* resultArea) const
|
||
|
|
{
|
||
|
|
- if (!ref) return DT_FAILURE;
|
||
|
|
unsigned int salt, it, ip;
|
||
|
|
decodePolyId(ref, salt, it, ip);
|
||
|
|
- if (it >= (unsigned int)m_maxTiles) return DT_FAILURE | DT_INVALID_PARAM;
|
||
|
|
- if (m_tiles[it].salt != salt || m_tiles[it].header == 0) return DT_FAILURE | DT_INVALID_PARAM;
|
||
|
|
+ if (it >= (unsigned int)m_maxTiles) return DT_FAILURE;
|
||
|
|
+ if (m_tiles[it].salt != salt || m_tiles[it].header == 0) return DT_FAILURE;
|
||
|
|
const dtMeshTile* tile = &m_tiles[it];
|
||
|
|
- if (ip >= (unsigned int)tile->header->polyCount) return DT_FAILURE | DT_INVALID_PARAM;
|
||
|
|
+ if (ip >= (unsigned int)tile->header->polyCount) return DT_FAILURE;
|
||
|
|
const dtPoly* poly = &tile->polys[ip];
|
||
|
|
|
||
|
|
*resultArea = poly->getArea();
|
||
|
|
diff --git a/dep/recastnavigation/Detour/DetourNavMesh.h b/dep/recastnavigation/Detour/DetourNavMesh.h
|
||
|
|
index c094e41..b146631 100644
|
||
|
|
--- a/dep/recastnavigation/Detour/DetourNavMesh.h
|
||
|
|
+++ b/dep/recastnavigation/Detour/DetourNavMesh.h
|
||
|
|
@@ -20,12 +20,9 @@
|
||
|
|
#define DETOURNAVMESH_H
|
||
|
|
|
||
|
|
#include "DetourAlloc.h"
|
||
|
|
-#include "DetourStatus.h"
|
||
|
|
|
||
|
|
-
|
||
|
|
-// Edited by TC
|
||
|
|
#if defined(WIN32) && !defined(__MINGW32__)
|
||
|
|
-typedef unsigned __int64 uint64;
|
||
|
|
+ typedef unsigned __int64 uint64;
|
||
|
|
#else
|
||
|
|
#include <stdint.h>
|
||
|
|
#ifndef uint64_t
|
||
|
|
@@ -33,473 +30,312 @@ typedef unsigned __int64 uint64;
|
||
|
|
#include <linux/types.h>
|
||
|
|
#endif
|
||
|
|
#endif
|
||
|
|
-typedef uint64_t uint64;
|
||
|
|
-#endif
|
||
|
|
+ typedef uint64_t uint64;
|
||
|
|
+#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.
|
||
|
|
-
|
||
|
|
-// Edited by TC
|
||
|
|
-// We cannot have over 31 bits for either tile nor poly
|
||
|
|
-// without changing polyCount to use 64bits too.
|
||
|
|
-static const int STATIC_SALT_BITS = 12;
|
||
|
|
-static const int STATIC_TILE_BITS = 21;
|
||
|
|
-static const int STATIC_POLY_BITS = 31;
|
||
|
|
+// It is also recommended to change dtHashRef() to proper 64-bit hash too.
|
||
|
|
|
||
|
|
-/// A handle to a polygon within a navigation mesh tile.
|
||
|
|
-/// @ingroup detour
|
||
|
|
-typedef uint64 dtPolyRef; // Edited by TC
|
||
|
|
+// Reference to navigation polygon.
|
||
|
|
+typedef uint64 dtPolyRef;
|
||
|
|
|
||
|
|
-/// A handle to a tile within a navigation mesh.
|
||
|
|
-/// @ingroup detour
|
||
|
|
-typedef uint64 dtTileRef; // Edited by TC
|
||
|
|
+// Reference to navigation mesh tile.
|
||
|
|
+typedef uint64 dtTileRef;
|
||
|
|
|
||
|
|
-/// The maximum number of vertices per navigation polygon.
|
||
|
|
-/// @ingroup detour
|
||
|
|
+// Maximum number of vertices per navigation polygon.
|
||
|
|
static const int DT_VERTS_PER_POLYGON = 6;
|
||
|
|
|
||
|
|
-/// @{
|
||
|
|
-/// @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_MAGIC = 'D'<<24 | 'N'<<16 | 'A'<<8 | 'V'; //'DNAV';
|
||
|
|
+static const int DT_NAVMESH_VERSION = 6;
|
||
|
|
|
||
|
|
-/// 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_MAGIC = 'D'<<24 | 'N'<<16 | 'M'<<8 | 'S'; //'DNMS';
|
||
|
|
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;
|
||
|
|
-
|
||
|
|
-/// A value that indicates the entity does not link to anything.
|
||
|
|
static const unsigned int DT_NULL_LINK = 0xffffffff;
|
||
|
|
-
|
||
|
|
-/// A flag that indicates that an off-mesh connection can be traversed in both directions. (Is bidirectional.)
|
||
|
|
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;
|
||
|
|
|
||
|
|
-/// Tile flags used for various functions and fields.
|
||
|
|
-/// For an example, see dtNavMesh::addTile().
|
||
|
|
+static const int STATIC_SALT_BITS = 12;
|
||
|
|
+static const int STATIC_TILE_BITS = 21;
|
||
|
|
+static const int STATIC_POLY_BITS = 31;
|
||
|
|
+// we cannot have over 31 bits for either tile nor poly
|
||
|
|
+// without changing polyCount to use 64bits too.
|
||
|
|
+
|
||
|
|
+// Flags for addTile
|
||
|
|
enum dtTileFlags
|
||
|
|
{
|
||
|
|
- /// The navigation mesh owns the tile memory and is responsible for freeing it.
|
||
|
|
- DT_TILE_FREE_DATA = 0x01,
|
||
|
|
+ DT_TILE_FREE_DATA = 0x01, // Navmesh owns the tile memory and should free it.
|
||
|
|
};
|
||
|
|
|
||
|
|
-/// Vertex flags returned by dtNavMeshQuery::findStraightPath.
|
||
|
|
+// Flags returned by findStraightPath().
|
||
|
|
enum dtStraightPathFlags
|
||
|
|
{
|
||
|
|
- DT_STRAIGHTPATH_START = 0x01, ///< The vertex is the start position in the path.
|
||
|
|
- DT_STRAIGHTPATH_END = 0x02, ///< The vertex is the end position in the path.
|
||
|
|
- DT_STRAIGHTPATH_OFFMESH_CONNECTION = 0x04, ///< The vertex is the start of an off-mesh connection.
|
||
|
|
+ DT_STRAIGHTPATH_START = 0x01, // The vertex is the start position.
|
||
|
|
+ DT_STRAIGHTPATH_END = 0x02, // The vertex is the end position.
|
||
|
|
+ DT_STRAIGHTPATH_OFFMESH_CONNECTION = 0x04, // The vertex is start of an off-mesh link.
|
||
|
|
};
|
||
|
|
|
||
|
|
-/// Options for dtNavMeshQuery::findStraightPath.
|
||
|
|
-enum dtStraightPathOptions
|
||
|
|
+// Flags describing polygon properties.
|
||
|
|
+enum dtPolyTypes
|
||
|
|
{
|
||
|
|
- 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.
|
||
|
|
+ DT_POLYTYPE_GROUND = 0, // Regular ground polygons.
|
||
|
|
+ DT_POLYTYPE_OFFMESH_CONNECTION = 1, // Off-mesh connections.
|
||
|
|
};
|
||
|
|
|
||
|
|
-/// Flags representing the type of a navigation mesh polygon.
|
||
|
|
-enum dtPolyTypes
|
||
|
|
+enum dtStatus
|
||
|
|
{
|
||
|
|
- /// The polygon is a standard convex polygon that is part of the surface of the mesh.
|
||
|
|
- DT_POLYTYPE_GROUND = 0,
|
||
|
|
- /// The polygon is an off-mesh connection consisting of two vertices.
|
||
|
|
- DT_POLYTYPE_OFFMESH_CONNECTION = 1,
|
||
|
|
+ DT_FAILURE = 0, // Operation failed.
|
||
|
|
+ DT_FAILURE_DATA_MAGIC,
|
||
|
|
+ DT_FAILURE_DATA_VERSION,
|
||
|
|
+ DT_FAILURE_OUT_OF_MEMORY,
|
||
|
|
+ DT_SUCCESS, // Operation succeed.
|
||
|
|
+ DT_IN_PROGRESS, // Operation still in progress.
|
||
|
|
};
|
||
|
|
|
||
|
|
|
||
|
|
-/// Defines a polyogn within a dtMeshTile object.
|
||
|
|
-/// @ingroup detour
|
||
|
|
+// Structure describing the navigation polygon data.
|
||
|
|
struct dtPoly
|
||
|
|
{
|
||
|
|
- /// Index to first link in linked list. (Or #DT_NULL_LINK if there is no link.)
|
||
|
|
- unsigned int firstLink;
|
||
|
|
-
|
||
|
|
- /// The indices of the polygon's vertices.
|
||
|
|
- /// The actual vertices are located in dtMeshTile::verts.
|
||
|
|
- 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]
|
||
|
|
+ unsigned int firstLink; // Index to first link in linked list.
|
||
|
|
+ unsigned short verts[DT_VERTS_PER_POLYGON]; // Indices to vertices of the poly.
|
||
|
|
+ unsigned short neis[DT_VERTS_PER_POLYGON]; // Refs to neighbours of the poly.
|
||
|
|
+ unsigned short flags; // Flags (see dtPolyFlags).
|
||
|
|
+ unsigned char vertCount; // Number of vertices.
|
||
|
|
+ unsigned char areaAndtype; // Bit packed: Area ID of the polygon, and Polygon type, see dtPolyTypes..
|
||
|
|
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); }
|
||
|
|
-
|
||
|
|
- /// Gets the user defined area id.
|
||
|
|
inline unsigned char getArea() const { return areaAndtype & 0x3f; }
|
||
|
|
-
|
||
|
|
- /// Gets the polygon type. (See: #dtPolyTypes)
|
||
|
|
inline unsigned char getType() const { return areaAndtype >> 6; }
|
||
|
|
};
|
||
|
|
|
||
|
|
-/// Defines the location of detail sub-mesh data within a dtMeshTile.
|
||
|
|
+// Stucture describing polygon detail triangles.
|
||
|
|
struct dtPolyDetail
|
||
|
|
{
|
||
|
|
- unsigned int vertBase; ///< The offset of the vertices in the dtMeshTile::detailVerts array.
|
||
|
|
- unsigned int triBase; ///< The offset of the triangles in the dtMeshTile::detailTris array.
|
||
|
|
- unsigned char vertCount; ///< The number of vertices in the sub-mesh.
|
||
|
|
- unsigned char triCount; ///< The number of triangles in the sub-mesh.
|
||
|
|
+ unsigned int vertBase; // Offset to detail vertex array.
|
||
|
|
+ unsigned int triBase; // Offset to detail triangle array.
|
||
|
|
+ unsigned char vertCount; // Number of vertices in the detail mesh.
|
||
|
|
+ unsigned char triCount; // Number of triangles.
|
||
|
|
};
|
||
|
|
|
||
|
|
-/// Defines a link between polygons.
|
||
|
|
-/// @note This structure is rarely if ever used by the end user.
|
||
|
|
-/// @see dtMeshTile
|
||
|
|
+// Stucture describing a link to another polygon.
|
||
|
|
struct dtLink
|
||
|
|
{
|
||
|
|
- dtPolyRef ref; ///< Neighbour reference. (The neighbor that is linked to.)
|
||
|
|
- unsigned int next; ///< Index of the next link.
|
||
|
|
- unsigned char edge; ///< Index of the polygon edge that owns this link.
|
||
|
|
- unsigned char side; ///< If a boundary link, defines on which side the link is.
|
||
|
|
- 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.
|
||
|
|
+ dtPolyRef ref; // Neighbour reference.
|
||
|
|
+ unsigned int next; // Index to next link.
|
||
|
|
+ unsigned char edge; // Index to polygon edge which owns this link.
|
||
|
|
+ unsigned char side; // If boundary link, defines on which side the link is.
|
||
|
|
+ unsigned char bmin, bmax; // If boundary link, defines the sub edge area.
|
||
|
|
};
|
||
|
|
|
||
|
|
-/// Bounding volume node.
|
||
|
|
-/// @note This structure is rarely if ever used by the end user.
|
||
|
|
-/// @see dtMeshTile
|
||
|
|
struct dtBVNode
|
||
|
|
{
|
||
|
|
- unsigned short bmin[3]; ///< Minimum bounds of the node's AABB. [(x, y, z)]
|
||
|
|
- unsigned short bmax[3]; ///< Maximum bounds of the node's AABB. [(x, y, z)]
|
||
|
|
- int i; ///< The node's index. (Negative for escape sequence.)
|
||
|
|
+ unsigned short bmin[3], bmax[3]; // BVnode bounds
|
||
|
|
+ int i; // Index to item or if negative, escape index.
|
||
|
|
};
|
||
|
|
|
||
|
|
-/// 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
|
||
|
|
{
|
||
|
|
- /// The endpoints of the connection. [(ax, ay, az, bx, by, bz)]
|
||
|
|
- float pos[6];
|
||
|
|
-
|
||
|
|
- /// The radius of the endpoints. [Limit: >= 0]
|
||
|
|
- float rad;
|
||
|
|
-
|
||
|
|
- /// 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;
|
||
|
|
+ float pos[6]; // Both end point locations.
|
||
|
|
+ float rad; // Link connection radius.
|
||
|
|
+ unsigned short poly; // Poly Id
|
||
|
|
+ unsigned char flags; // Link flags
|
||
|
|
+ unsigned char side; // End point side.
|
||
|
|
+ unsigned int userId; // User ID to identify this connection.
|
||
|
|
};
|
||
|
|
|
||
|
|
-/// Provides high level information related to a dtMeshTile object.
|
||
|
|
-/// @ingroup detour
|
||
|
|
struct dtMeshHeader
|
||
|
|
{
|
||
|
|
- int magic; ///< Tile magic number. (Used to identify the data format.)
|
||
|
|
- int version; ///< Tile data format version number.
|
||
|
|
- int x; ///< The x-position of the tile within the dtNavMesh tile grid. (x, y, layer)
|
||
|
|
- int y; ///< The y-position of the tile within the dtNavMesh tile grid. (x, y, layer)
|
||
|
|
- int layer; ///< The layer of the tile within the dtNavMesh tile grid. (x, y, layer)
|
||
|
|
- unsigned int userId; ///< The user defined id of the tile.
|
||
|
|
- int polyCount; ///< The number of polygons in the tile.
|
||
|
|
- int vertCount; ///< The number of vertices in the tile.
|
||
|
|
- int maxLinkCount; ///< The number of allocated links.
|
||
|
|
- int detailMeshCount; ///< The number of sub-meshes in the detail mesh.
|
||
|
|
-
|
||
|
|
- /// The number of unique vertices in the detail mesh. (In addition to the polygon vertices.)
|
||
|
|
- int detailVertCount;
|
||
|
|
-
|
||
|
|
- int detailTriCount; ///< The number of triangles in the detail mesh.
|
||
|
|
- int bvNodeCount; ///< The number of bounding volume nodes. (Zero if bounding volumes are disabled.)
|
||
|
|
- int offMeshConCount; ///< The number of off-mesh connections.
|
||
|
|
- 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;
|
||
|
|
+ int magic; // Magic number, used to identify the data.
|
||
|
|
+ int version; // Data version number.
|
||
|
|
+ int x, y; // Location of the time on the grid.
|
||
|
|
+ unsigned int userId; // User ID of the tile.
|
||
|
|
+ int polyCount; // Number of polygons in the tile.
|
||
|
|
+ int vertCount; // Number of vertices in the tile.
|
||
|
|
+ int maxLinkCount; // Number of allocated links.
|
||
|
|
+ int detailMeshCount; // Number of detail meshes.
|
||
|
|
+ int detailVertCount; // Number of detail vertices.
|
||
|
|
+ int detailTriCount; // Number of detail triangles.
|
||
|
|
+ int bvNodeCount; // Number of BVtree nodes.
|
||
|
|
+ int offMeshConCount; // Number of Off-Mesh links.
|
||
|
|
+ int offMeshBase; // Index to first polygon which is Off-Mesh link.
|
||
|
|
+ float walkableHeight; // Height of the agent.
|
||
|
|
+ float walkableRadius; // Radius of the agent
|
||
|
|
+ float walkableClimb; // Max climb height of the agent.
|
||
|
|
+ float bmin[3], bmax[3]; // Bounding box of the tile.
|
||
|
|
+ float bvQuantFactor; // BVtree quantization factor (world to bvnode coords)
|
||
|
|
};
|
||
|
|
|
||
|
|
-/// Defines a navigation mesh tile.
|
||
|
|
-/// @ingroup detour
|
||
|
|
struct dtMeshTile
|
||
|
|
{
|
||
|
|
- unsigned int salt; ///< Counter describing modifications to the tile.
|
||
|
|
-
|
||
|
|
- unsigned int linksFreeList; ///< Index to the next free link.
|
||
|
|
- dtMeshHeader* header; ///< The tile header.
|
||
|
|
- dtPoly* polys; ///< The tile polygons. [Size: dtMeshHeader::polyCount]
|
||
|
|
- float* verts; ///< The tile vertices. [Size: dtMeshHeader::vertCount]
|
||
|
|
- dtLink* links; ///< The tile links. [Size: dtMeshHeader::maxLinkCount]
|
||
|
|
- dtPolyDetail* detailMeshes; ///< The tile's detail sub-meshes. [Size: dtMeshHeader::detailMeshCount]
|
||
|
|
-
|
||
|
|
- /// 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 int salt; // Counter describing modifications to the tile.
|
||
|
|
+
|
||
|
|
+ unsigned int linksFreeList; // Index to next free link.
|
||
|
|
+ dtMeshHeader* header; // Pointer to tile header.
|
||
|
|
+ dtPoly* polys; // Pointer to the polygons (will be updated when tile is added).
|
||
|
|
+ float* verts; // Pointer to the vertices (will be updated when tile added).
|
||
|
|
+ dtLink* links; // Pointer to the links (will be updated when tile added).
|
||
|
|
+ dtPolyDetail* detailMeshes; // Pointer to detail meshes (will be updated when tile added).
|
||
|
|
+ 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; ///< The tile data. (Not directly accessed under normal situations.)
|
||
|
|
- 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.
|
||
|
|
+ unsigned char* data; // Pointer to tile data.
|
||
|
|
+ int dataSize; // Size of the tile data.
|
||
|
|
+ int flags; // Tile flags, see dtTileFlags.
|
||
|
|
+ dtMeshTile* next; // Next free tile or, next tile in spatial grid.
|
||
|
|
};
|
||
|
|
|
||
|
|
-/// Configuration 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
|
||
|
|
{
|
||
|
|
- float orig[3]; ///< The world space origin of the navigation mesh's tile space. [(x, y, z)]
|
||
|
|
- float tileWidth; ///< The width of each tile. (Along the x-axis.)
|
||
|
|
- float tileHeight; ///< The height of each tile. (Along the z-axis.)
|
||
|
|
- int maxTiles; ///< The maximum number of tiles the navigation mesh can contain.
|
||
|
|
- int maxPolys; ///< The maximum number of polygons each tile can contain.
|
||
|
|
+ float orig[3]; // Origin of the nav mesh tile space.
|
||
|
|
+ float tileWidth, tileHeight; // Width and height of each tile.
|
||
|
|
+ int maxTiles; // Maximum number of tiles the navmesh can contain.
|
||
|
|
+ int maxPolys; // Maximum number of polygons each tile can contain.
|
||
|
|
};
|
||
|
|
|
||
|
|
-/// A navigation mesh based on tiles of convex polygons.
|
||
|
|
-/// @ingroup detour
|
||
|
|
+
|
||
|
|
class dtNavMesh
|
||
|
|
{
|
||
|
|
public:
|
||
|
|
dtNavMesh();
|
||
|
|
~dtNavMesh();
|
||
|
|
|
||
|
|
- /// @{
|
||
|
|
- /// @name Initialization and Tile Management
|
||
|
|
-
|
||
|
|
- /// Initializes the navigation mesh for tiled use.
|
||
|
|
- /// @param[in] params Initialization parameters.
|
||
|
|
- /// @return The status flags for the operation.
|
||
|
|
+ // Initializes the nav mesh for tiled use.
|
||
|
|
+ // Params:
|
||
|
|
+ // params - (in) navmesh initialization params, see dtNavMeshParams.
|
||
|
|
+ // Returns: True if succeed, else false.
|
||
|
|
dtStatus init(const dtNavMeshParams* params);
|
||
|
|
|
||
|
|
- /// Initializes the navigation mesh for single tile use.
|
||
|
|
- /// @param[in] data Data of the new tile. (See: #dtCreateNavMeshData)
|
||
|
|
- /// @param[in] dataSize The data size of the new tile.
|
||
|
|
- /// @param[in] flags The tile flags. (See: #dtTileFlags)
|
||
|
|
- /// @return The status flags for the operation.
|
||
|
|
- /// @see dtCreateNavMeshData
|
||
|
|
+ // Initializes the nav mesh for single tile use.
|
||
|
|
+ // Params:
|
||
|
|
+ // data - (in) Data of the new tile mesh.
|
||
|
|
+ // dataSize - (in) Data size of the new tile mesh.
|
||
|
|
+ // flags - (in) Tile flags, see dtTileFlags.
|
||
|
|
+ // Returns: True if succeed, else false.
|
||
|
|
dtStatus init(unsigned char* data, const int dataSize, const int flags);
|
||
|
|
|
||
|
|
- /// The navigation mesh initialization params.
|
||
|
|
+ // Returns pointer to navmesh initialization params.
|
||
|
|
const dtNavMeshParams* getParams() const;
|
||
|
|
-
|
||
|
|
- /// Adds a tile to the navigation mesh.
|
||
|
|
- /// @param[in] data Data for the new tile mesh. (See: #dtCreateNavMeshData)
|
||
|
|
- /// @param[in] dataSize Data size of the new tile mesh.
|
||
|
|
- /// @param[in] flags Tile flags. (See: #dtTileFlags)
|
||
|
|
- /// @param[in] lastRef The desired reference for the tile. (When reloading a tile.) [opt] [Default: 0]
|
||
|
|
- /// @param[out] result The tile reference. (If the tile was succesfully added.) [opt]
|
||
|
|
- /// @return The status flags for the operation.
|
||
|
|
+
|
||
|
|
+ // Adds new tile into the navmesh.
|
||
|
|
+ // The add will fail if the data is in wrong format,
|
||
|
|
+ // there is not enough tiles left, or if there is a tile already at the location.
|
||
|
|
+ // Params:
|
||
|
|
+ // data - (in) Data of the new tile mesh.
|
||
|
|
+ // dataSize - (in) Data size of the new tile mesh.
|
||
|
|
+ // flags - (in) Tile flags, see dtTileFlags.
|
||
|
|
+ // lastRef - (in,optional) Last tile ref, the tile will be restored so that
|
||
|
|
+ // the reference (as well as poly references) will be the same. Default: 0.
|
||
|
|
+ // result - (out,optional) tile ref if the tile was succesfully added.
|
||
|
|
dtStatus addTile(unsigned char* data, int dataSize, int flags, dtTileRef lastRef, dtTileRef* result);
|
||
|
|
|
||
|
|
- /// Removes the specified tile from the navigation mesh.
|
||
|
|
- /// @param[in] ref The reference of the tile to remove.
|
||
|
|
- /// @param[out] data Data associated with deleted tile.
|
||
|
|
- /// @param[out] dataSize Size of the data associated with deleted tile.
|
||
|
|
- /// @return The status flags for the operation.
|
||
|
|
+ // Removes specified tile.
|
||
|
|
+ // Params:
|
||
|
|
+ // ref - (in) Reference to the tile to remove.
|
||
|
|
+ // data - (out) Data associated with deleted tile.
|
||
|
|
+ // dataSize - (out) Size of the data associated with deleted tile.
|
||
|
|
dtStatus removeTile(dtTileRef ref, unsigned char** data, int* dataSize);
|
||
|
|
|
||
|
|
- /// @}
|
||
|
|
-
|
||
|
|
- /// @{
|
||
|
|
- /// @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)
|
||
|
|
+ // Calculates tile location based in input world position.
|
||
|
|
+ // Params:
|
||
|
|
+ // pos - (in) world position of the query.
|
||
|
|
+ // tx - (out) tile x location.
|
||
|
|
+ // ty - (out) tile y location.
|
||
|
|
void calcTileLoc(const float* pos, int* tx, int* ty) const;
|
||
|
|
|
||
|
|
- /// Gets the tile at the specified grid location.
|
||
|
|
- /// @param[in] x The tile's x-location. (x, y, layer)
|
||
|
|
- /// @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;
|
||
|
|
-
|
||
|
|
- /// 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,
|
||
|
|
- dtMeshTile const** tiles, const int maxTiles) const;
|
||
|
|
+ // Returns pointer to tile at specified location.
|
||
|
|
+ // Params:
|
||
|
|
+ // x,y - (in) Location of the tile to get.
|
||
|
|
+ // Returns: pointer to tile if tile exists or 0 tile does not exists.
|
||
|
|
+ const dtMeshTile* getTileAt(int x, int y) const;
|
||
|
|
+
|
||
|
|
+ // Returns reference to tile at specified location.
|
||
|
|
+ // Params:
|
||
|
|
+ // x,y - (in) Location of the tile to get.
|
||
|
|
+ // Returns: reference to tile if tile exists or 0 tile does not exists.
|
||
|
|
+ dtTileRef getTileRefAt(int x, int y) const;
|
||
|
|
|
||
|
|
- /// Gets the tile reference for the tile at specified grid location.
|
||
|
|
- /// @param[in] x The tile's x-location. (x, y, layer)
|
||
|
|
- /// @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;
|
||
|
|
-
|
||
|
|
- /// Gets the tile reference for the specified tile.
|
||
|
|
- /// @param[in] tile The tile.
|
||
|
|
- /// @return The tile reference of the tile.
|
||
|
|
+ // Returns tile references of a tile based on tile pointer.
|
||
|
|
dtTileRef getTileRef(const dtMeshTile* tile) const;
|
||
|
|
|
||
|
|
- /// 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.
|
||
|
|
+ // Returns tile based on references.
|
||
|
|
const dtMeshTile* getTileByRef(dtTileRef ref) const;
|
||
|
|
|
||
|
|
- /// The maximum number of tiles supported by the navigation mesh.
|
||
|
|
- /// @return The maximum number of tiles supported by the navigation mesh.
|
||
|
|
+ // Returns max number of tiles.
|
||
|
|
int getMaxTiles() const;
|
||
|
|
|
||
|
|
- /// Gets the tile at the specified index.
|
||
|
|
- /// @param[in] i The tile index. [Limit: 0 >= index < #getMaxTiles()]
|
||
|
|
- /// @return The tile at the specified index.
|
||
|
|
+ // Returns pointer to tile in the tile array.
|
||
|
|
+ // Params:
|
||
|
|
+ // i - (in) Index to the tile to retrieve, max index is getMaxTiles()-1.
|
||
|
|
+ // Returns: Pointer to specified tile.
|
||
|
|
const dtMeshTile* getTile(int i) const;
|
||
|
|
|
||
|
|
- /// Gets the tile and polygon for the specified polygon reference.
|
||
|
|
- /// @param[in] ref The reference for the a polygon.
|
||
|
|
- /// @param[out] tile The tile containing the polygon.
|
||
|
|
- /// @param[out] poly The polygon.
|
||
|
|
- /// @return The status flags for the operation.
|
||
|
|
+ // Returns pointer to tile and polygon pointed by the polygon reference.
|
||
|
|
+ // Params:
|
||
|
|
+ // ref - (in) reference to a polygon.
|
||
|
|
+ // tile - (out) pointer to the tile containing the polygon.
|
||
|
|
+ // poly - (out) pointer to the polygon.
|
||
|
|
dtStatus getTileAndPolyByRef(const dtPolyRef ref, const dtMeshTile** tile, const dtPoly** poly) const;
|
||
|
|
|
||
|
|
- /// Returns the tile and polygon for the specified polygon reference.
|
||
|
|
- /// @param[in] ref A known valid reference for a polygon.
|
||
|
|
- /// @param[out] tile The tile containing the polygon.
|
||
|
|
- /// @param[out] poly The polygon.
|
||
|
|
+ // Returns pointer to tile and polygon pointed by the polygon reference.
|
||
|
|
+ // Note: this function does not check if 'ref' s valid, and is thus faster. Use only with valid refs!
|
||
|
|
+ // Params:
|
||
|
|
+ // ref - (in) reference to a polygon.
|
||
|
|
+ // tile - (out) pointer to the tile containing the polygon.
|
||
|
|
+ // poly - (out) pointer to the polygon.
|
||
|
|
void getTileAndPolyByRefUnsafe(const dtPolyRef ref, const dtMeshTile** tile, const dtPoly** poly) const;
|
||
|
|
|
||
|
|
- /// 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.
|
||
|
|
+ // Returns true if polygon reference points to valid data.
|
||
|
|
bool isValidPolyRef(dtPolyRef ref) const;
|
||
|
|
|
||
|
|
- /// 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.
|
||
|
|
+ // Returns base poly id for specified tile, polygon refs can be deducted from this.
|
||
|
|
dtPolyRef getPolyRefBase(const dtMeshTile* tile) const;
|
||
|
|
|
||
|
|
- /// Gets the endpoints for an off-mesh connection, ordered by "direction of travel".
|
||
|
|
- /// @param[in] prevRef The reference of the polygon before the connection.
|
||
|
|
- /// @param[in] polyRef The reference of the off-mesh connection polygon.
|
||
|
|
- /// @param[out] startPos The start position of the off-mesh connection. [(x, y, z)]
|
||
|
|
- /// @param[out] endPos The end position of the off-mesh connection. [(x, y, z)]
|
||
|
|
- /// @return The status flags for the operation.
|
||
|
|
+ // Returns start and end location of an off-mesh link polygon.
|
||
|
|
+ // Params:
|
||
|
|
+ // prevRef - (in) ref to the polygon before the link (used to select direction).
|
||
|
|
+ // polyRef - (in) ref to the off-mesh link polygon.
|
||
|
|
+ // startPos[3] - (out) start point of the link.
|
||
|
|
+ // endPos[3] - (out) end point of the link.
|
||
|
|
+ // Returns: true if link is found.
|
||
|
|
dtStatus getOffMeshConnectionPolyEndPoints(dtPolyRef prevRef, dtPolyRef polyRef, float* startPos, float* endPos) const;
|
||
|
|
|
||
|
|
- /// 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.
|
||
|
|
+ // Returns pointer to off-mesh connection based on polyref, or null if ref not valid.
|
||
|
|
const dtOffMeshConnection* getOffMeshConnectionByRef(dtPolyRef ref) const;
|
||
|
|
|
||
|
|
- /// @}
|
||
|
|
-
|
||
|
|
- /// @{
|
||
|
|
- /// @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.
|
||
|
|
+ // Sets polygon flags.
|
||
|
|
dtStatus setPolyFlags(dtPolyRef ref, unsigned short 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.
|
||
|
|
+ // Return polygon flags.
|
||
|
|
dtStatus getPolyFlags(dtPolyRef ref, unsigned short* resultFlags) const;
|
||
|
|
|
||
|
|
- /// 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.
|
||
|
|
+ // Set polygon type.
|
||
|
|
dtStatus setPolyArea(dtPolyRef ref, unsigned char area);
|
||
|
|
|
||
|
|
- /// 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.
|
||
|
|
+ // Return polygon area type.
|
||
|
|
dtStatus getPolyArea(dtPolyRef ref, unsigned char* resultArea) const;
|
||
|
|
|
||
|
|
- /// Gets the size of the buffer required by #storeTileState to store the specified tile's state.
|
||
|
|
- /// @param[in] tile The tile.
|
||
|
|
- /// @return The size of the buffer required to store the state.
|
||
|
|
+
|
||
|
|
+ // Returns number of bytes required to store tile state.
|
||
|
|
int getTileStateSize(const dtMeshTile* tile) const;
|
||
|
|
|
||
|
|
- /// 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.
|
||
|
|
+ // Stores tile state to buffer.
|
||
|
|
dtStatus storeTileState(const dtMeshTile* tile, unsigned char* data, const int maxDataSize) const;
|
||
|
|
|
||
|
|
- /// 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.
|
||
|
|
+ // Restores tile state.
|
||
|
|
dtStatus restoreTileState(dtMeshTile* tile, const unsigned char* data, const int maxDataSize);
|
||
|
|
|
||
|
|
- /// @}
|
||
|
|
|
||
|
|
- /// @{
|
||
|
|
- /// @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.
|
||
|
|
+ // Encodes a tile id.
|
||
|
|
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;
|
||
|
|
}
|
||
|
|
|
||
|
|
- /// 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
|
||
|
|
+ // Decodes a tile id.
|
||
|
|
inline void decodePolyId(dtPolyRef ref, unsigned int& salt, unsigned int& it, unsigned int& ip) const
|
||
|
|
{
|
||
|
|
const dtPolyRef saltMask = ((dtPolyRef)1<<m_saltBits)-1;
|
||
|
|
@@ -510,201 +346,83 @@ public:
|
||
|
|
ip = (unsigned int)(ref & polyMask);
|
||
|
|
}
|
||
|
|
|
||
|
|
- /// 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
|
||
|
|
+ // Decodes a tile salt.
|
||
|
|
inline unsigned int decodePolyIdSalt(dtPolyRef ref) const
|
||
|
|
{
|
||
|
|
const dtPolyRef saltMask = ((dtPolyRef)1<<m_saltBits)-1;
|
||
|
|
return (unsigned int)((ref >> (m_polyBits+m_tileBits)) & saltMask);
|
||
|
|
}
|
||
|
|
|
||
|
|
- /// 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
|
||
|
|
+ // Decodes a tile id.
|
||
|
|
inline unsigned int decodePolyIdTile(dtPolyRef ref) const
|
||
|
|
{
|
||
|
|
const dtPolyRef tileMask = ((dtPolyRef)1<<m_tileBits)-1;
|
||
|
|
return (unsigned int)((ref >> m_polyBits) & tileMask);
|
||
|
|
}
|
||
|
|
|
||
|
|
- /// 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
|
||
|
|
+ // Decodes a poly id.
|
||
|
|
inline unsigned int decodePolyIdPoly(dtPolyRef ref) const
|
||
|
|
{
|
||
|
|
const dtPolyRef polyMask = ((dtPolyRef)1<<m_polyBits)-1;
|
||
|
|
return (unsigned int)(ref & polyMask);
|
||
|
|
}
|
||
|
|
-
|
||
|
|
- /// @}
|
||
|
|
|
||
|
|
private:
|
||
|
|
|
||
|
|
- /// Returns pointer to tile in the tile array.
|
||
|
|
+ // Returns pointer to tile in the tile array.
|
||
|
|
dtMeshTile* getTile(int i);
|
||
|
|
|
||
|
|
- /// Returns neighbour tile based on side.
|
||
|
|
- int getTilesAt(const int x, const int y,
|
||
|
|
- dtMeshTile** tiles, const int maxTiles) const;
|
||
|
|
-
|
||
|
|
- /// Returns neighbour tile based on side.
|
||
|
|
- int getNeighbourTilesAt(const int x, const int y, const int side,
|
||
|
|
- dtMeshTile** tiles, const int maxTiles) const;
|
||
|
|
-
|
||
|
|
- /// Returns all polygons in neighbour tile based on portal defined by the segment.
|
||
|
|
+ // Returns neighbour tile based on side.
|
||
|
|
+ dtMeshTile* getNeighbourTileAt(int x, int y, int side) const;
|
||
|
|
+ // Returns all polygons in neighbour tile based on portal defined by the segment.
|
||
|
|
int findConnectingPolys(const float* va, const float* vb,
|
||
|
|
const dtMeshTile* tile, int side,
|
||
|
|
dtPolyRef* con, float* conarea, int maxcon) const;
|
||
|
|
|
||
|
|
- /// Builds internal polygons links for a tile.
|
||
|
|
+ // Builds internal polygons links for a tile.
|
||
|
|
void connectIntLinks(dtMeshTile* tile);
|
||
|
|
- /// Builds internal polygons links for a tile.
|
||
|
|
- void baseOffMeshLinks(dtMeshTile* tile);
|
||
|
|
+ // Builds internal polygons links for a tile.
|
||
|
|
+ void connectIntOffMeshLinks(dtMeshTile* tile);
|
||
|
|
|
||
|
|
- /// Builds external polygon links for a tile.
|
||
|
|
+ // Builds external polygon links for a tile.
|
||
|
|
void connectExtLinks(dtMeshTile* tile, dtMeshTile* target, int side);
|
||
|
|
- /// Builds external polygon links for a tile.
|
||
|
|
+ // Builds external polygon links for a tile.
|
||
|
|
void connectExtOffMeshLinks(dtMeshTile* tile, dtMeshTile* target, int side);
|
||
|
|
|
||
|
|
- /// Removes external links at specified side.
|
||
|
|
- void unconnectExtLinks(dtMeshTile* tile, dtMeshTile* target);
|
||
|
|
+ // Removes external links at specified side.
|
||
|
|
+ void unconnectExtLinks(dtMeshTile* tile, int side);
|
||
|
|
|
||
|
|
|
||
|
|
// TODO: These methods are duplicates from dtNavMeshQuery, but are needed for off-mesh connection finding.
|
||
|
|
|
||
|
|
- /// Queries polygons within a tile.
|
||
|
|
+ // Queries polygons within a tile.
|
||
|
|
int queryPolygonsInTile(const dtMeshTile* tile, const float* qmin, const float* qmax,
|
||
|
|
dtPolyRef* polys, const int maxPolys) const;
|
||
|
|
- /// Find nearest polygon within a tile.
|
||
|
|
+ // Find nearest polygon within a tile.
|
||
|
|
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;
|
||
|
|
+ // Returns closest point on polygon.
|
||
|
|
+ dtStatus closestPointOnPolyInTile(const dtMeshTile* tile, unsigned int ip,
|
||
|
|
+ const float* pos, float* closest) const;
|
||
|
|
|
||
|
|
- dtNavMeshParams m_params; ///< Current initialization params. TODO: do not store this info twice.
|
||
|
|
- float m_orig[3]; ///< Origin of the tile (0,0)
|
||
|
|
- float m_tileWidth, m_tileHeight; ///< Dimensions of each tile.
|
||
|
|
- int m_maxTiles; ///< Max number of tiles.
|
||
|
|
- int m_tileLutSize; ///< Tile hash lookup size (must be pot).
|
||
|
|
- int m_tileLutMask; ///< Tile hash lookup mask.
|
||
|
|
-
|
||
|
|
- dtMeshTile** m_posLookup; ///< Tile hash lookup.
|
||
|
|
- dtMeshTile* m_nextFree; ///< Freelist of tiles.
|
||
|
|
- dtMeshTile* m_tiles; ///< List of tiles.
|
||
|
|
+ dtNavMeshParams m_params; // Current initialization params. TODO: do not store this info twice.
|
||
|
|
+ float m_orig[3]; // Origin of the tile (0,0)
|
||
|
|
+ float m_tileWidth, m_tileHeight; // Dimensions of each tile.
|
||
|
|
+ int m_maxTiles; // Max number of tiles.
|
||
|
|
+ int m_tileLutSize; // Tile hash lookup size (must be pot).
|
||
|
|
+ int m_tileLutMask; // Tile hash lookup mask.
|
||
|
|
+
|
||
|
|
+ dtMeshTile** m_posLookup; // Tile hash lookup.
|
||
|
|
+ dtMeshTile* m_nextFree; // Freelist of tiles.
|
||
|
|
+ dtMeshTile* m_tiles; // List of tiles.
|
||
|
|
|
||
|
|
- 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.
|
||
|
|
+ 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.
|
||
|
|
};
|
||
|
|
|
||
|
|
-/// Allocates a navigation mesh object using the Detour allocator.
|
||
|
|
-/// @return A navigation mesh that is ready for initialization, or null on failure.
|
||
|
|
-/// @ingroup detour
|
||
|
|
+// Helper function to allocate navmesh class using Detour allocator.
|
||
|
|
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);
|
||
|
|
|
||
|
|
#endif // DETOURNAVMESH_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.
|
||
|
|
-
|
||
|
|
-/**
|
||
|
|
-
|
||
|
|
-@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.
|
||
|
|
-
|
||
|
|
-*/
|
||
|
|
diff --git a/dep/recastnavigation/Detour/DetourNavMeshBuilder.cpp b/dep/recastnavigation/Detour/DetourNavMeshBuilder.cpp
|
||
|
|
index 9d8471b..f648571 100644
|
||
|
|
--- a/dep/recastnavigation/Detour/DetourNavMeshBuilder.cpp
|
||
|
|
+++ b/dep/recastnavigation/Detour/DetourNavMeshBuilder.cpp
|
||
|
|
@@ -20,7 +20,6 @@
|
||
|
|
#include <stdio.h>
|
||
|
|
#include <stdlib.h>
|
||
|
|
#include <string.h>
|
||
|
|
-#include <float.h>
|
||
|
|
#include "DetourNavMesh.h"
|
||
|
|
#include "DetourCommon.h"
|
||
|
|
#include "DetourNavMeshBuilder.h"
|
||
|
|
@@ -238,19 +237,11 @@ static unsigned char classifyOffMeshPoint(const float* pt, const float* bmin, co
|
||
|
|
case ZM: return 6;
|
||
|
|
case XP|ZM: return 7;
|
||
|
|
};
|
||
|
|
-
|
||
|
|
return 0xff;
|
||
|
|
}
|
||
|
|
|
||
|
|
// TODO: Better error handling.
|
||
|
|
|
||
|
|
-/// @par
|
||
|
|
-///
|
||
|
|
-/// The output data array is allocated using the detour allocator (dtAlloc()). The method
|
||
|
|
-/// used to free the memory will be determined by how the tile is added to the navigation
|
||
|
|
-/// mesh.
|
||
|
|
-///
|
||
|
|
-/// @see dtNavMesh, dtNavMesh::addTile()
|
||
|
|
bool dtCreateNavMeshData(dtNavMeshCreateParams* params, unsigned char** outData, int* outDataSize)
|
||
|
|
{
|
||
|
|
if (params->nvp > DT_VERTS_PER_POLYGON)
|
||
|
|
@@ -261,6 +252,8 @@ bool dtCreateNavMeshData(dtNavMeshCreateParams* params, unsigned char** outData,
|
||
|
|
return false;
|
||
|
|
if (!params->polyCount || !params->polys)
|
||
|
|
return false;
|
||
|
|
+ if (!params->detailMeshes || !params->detailVerts || !params->detailTris)
|
||
|
|
+ return false;
|
||
|
|
|
||
|
|
const int nvp = params->nvp;
|
||
|
|
|
||
|
|
@@ -276,50 +269,10 @@ bool dtCreateNavMeshData(dtNavMeshCreateParams* params, unsigned char** outData,
|
||
|
|
if (!offMeshConClass)
|
||
|
|
return false;
|
||
|
|
|
||
|
|
- // Find tight heigh bounds, used for culling out off-mesh start locations.
|
||
|
|
- float hmin = FLT_MAX;
|
||
|
|
- float hmax = -FLT_MAX;
|
||
|
|
-
|
||
|
|
- if (params->detailVerts && params->detailVertsCount)
|
||
|
|
- {
|
||
|
|
- for (int i = 0; i < params->detailVertsCount; ++i)
|
||
|
|
- {
|
||
|
|
- const float h = params->detailVerts[i*3+1];
|
||
|
|
- hmin = dtMin(hmin,h);
|
||
|
|
- hmax = dtMax(hmax,h);
|
||
|
|
- }
|
||
|
|
- }
|
||
|
|
- else
|
||
|
|
- {
|
||
|
|
- for (int i = 0; i < params->vertCount; ++i)
|
||
|
|
- {
|
||
|
|
- const unsigned short* iv = ¶ms->verts[i*3];
|
||
|
|
- const float h = params->bmin[1] + iv[1] * params->ch;
|
||
|
|
- hmin = dtMin(hmin,h);
|
||
|
|
- hmax = dtMax(hmax,h);
|
||
|
|
- }
|
||
|
|
- }
|
||
|
|
- hmin -= params->walkableClimb;
|
||
|
|
- hmax += params->walkableClimb;
|
||
|
|
- float bmin[3], bmax[3];
|
||
|
|
- dtVcopy(bmin, params->bmin);
|
||
|
|
- dtVcopy(bmax, params->bmax);
|
||
|
|
- bmin[1] = hmin;
|
||
|
|
- bmax[1] = hmax;
|
||
|
|
-
|
||
|
|
for (int i = 0; i < params->offMeshConCount; ++i)
|
||
|
|
{
|
||
|
|
- const float* p0 = ¶ms->offMeshConVerts[(i*2+0)*3];
|
||
|
|
- const float* p1 = ¶ms->offMeshConVerts[(i*2+1)*3];
|
||
|
|
- offMeshConClass[i*2+0] = classifyOffMeshPoint(p0, bmin, bmax);
|
||
|
|
- offMeshConClass[i*2+1] = classifyOffMeshPoint(p1, bmin, bmax);
|
||
|
|
-
|
||
|
|
- // Zero out off-mesh start positions which are not even potentially touching the mesh.
|
||
|
|
- if (offMeshConClass[i*2+0] == 0xff)
|
||
|
|
- {
|
||
|
|
- if (p0[1] < bmin[1] || p0[1] > bmax[1])
|
||
|
|
- offMeshConClass[i*2+0] = 0;
|
||
|
|
- }
|
||
|
|
+ offMeshConClass[i*2+0] = classifyOffMeshPoint(¶ms->offMeshConVerts[(i*2+0)*3], params->bmin, params->bmax);
|
||
|
|
+ offMeshConClass[i*2+1] = classifyOffMeshPoint(¶ms->offMeshConVerts[(i*2+1)*3], params->bmin, params->bmax);
|
||
|
|
|
||
|
|
// Cound how many links should be allocated for off-mesh connections.
|
||
|
|
if (offMeshConClass[i*2+0] == 0xff)
|
||
|
|
@@ -345,13 +298,23 @@ bool dtCreateNavMeshData(dtNavMeshCreateParams* params, unsigned char** outData,
|
||
|
|
for (int j = 0; j < nvp; ++j)
|
||
|
|
{
|
||
|
|
if (p[j] == MESH_NULL_IDX) break;
|
||
|
|
+ int nj = j+1;
|
||
|
|
+ if (nj >= nvp || p[nj] == MESH_NULL_IDX) nj = 0;
|
||
|
|
+ const unsigned short* va = ¶ms->verts[p[j]*3];
|
||
|
|
+ const unsigned short* vb = ¶ms->verts[p[nj]*3];
|
||
|
|
+
|
||
|
|
edgeCount++;
|
||
|
|
|
||
|
|
- if (p[nvp+j] & 0x8000)
|
||
|
|
+ if (params->tileSize > 0)
|
||
|
|
{
|
||
|
|
- unsigned short dir = p[nvp+j] & 0xf;
|
||
|
|
- if (dir != 0xf)
|
||
|
|
- portalCount++;
|
||
|
|
+ if (va[0] == params->tileSize && vb[0] == params->tileSize)
|
||
|
|
+ portalCount++; // x+
|
||
|
|
+ else if (va[2] == params->tileSize && vb[2] == params->tileSize)
|
||
|
|
+ portalCount++; // z+
|
||
|
|
+ else if (va[0] == 0 && vb[0] == 0)
|
||
|
|
+ portalCount++; // x-
|
||
|
|
+ else if (va[2] == 0 && vb[2] == 0)
|
||
|
|
+ portalCount++; // z-
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
@@ -360,41 +323,18 @@ bool dtCreateNavMeshData(dtNavMeshCreateParams* params, unsigned char** outData,
|
||
|
|
|
||
|
|
// Find unique detail vertices.
|
||
|
|
int uniqueDetailVertCount = 0;
|
||
|
|
- int detailTriCount = 0;
|
||
|
|
- if (params->detailMeshes)
|
||
|
|
- {
|
||
|
|
- // Has detail mesh, count unique detail vertex count and use input detail tri count.
|
||
|
|
- detailTriCount = params->detailTriCount;
|
||
|
|
- for (int i = 0; i < params->polyCount; ++i)
|
||
|
|
- {
|
||
|
|
- const unsigned short* p = ¶ms->polys[i*nvp*2];
|
||
|
|
- int ndv = params->detailMeshes[i*4+1];
|
||
|
|
- int nv = 0;
|
||
|
|
- for (int j = 0; j < nvp; ++j)
|
||
|
|
- {
|
||
|
|
- if (p[j] == MESH_NULL_IDX) break;
|
||
|
|
- nv++;
|
||
|
|
- }
|
||
|
|
- ndv -= nv;
|
||
|
|
- uniqueDetailVertCount += ndv;
|
||
|
|
- }
|
||
|
|
- }
|
||
|
|
- else
|
||
|
|
+ for (int i = 0; i < params->polyCount; ++i)
|
||
|
|
{
|
||
|
|
- // No input detail mesh, build detail mesh from nav polys.
|
||
|
|
- uniqueDetailVertCount = 0; // No extra detail verts.
|
||
|
|
- detailTriCount = 0;
|
||
|
|
- for (int i = 0; i < params->polyCount; ++i)
|
||
|
|
+ const unsigned short* p = ¶ms->polys[i*nvp*2];
|
||
|
|
+ int ndv = params->detailMeshes[i*4+1];
|
||
|
|
+ int nv = 0;
|
||
|
|
+ for (int j = 0; j < nvp; ++j)
|
||
|
|
{
|
||
|
|
- const unsigned short* p = ¶ms->polys[i*nvp*2];
|
||
|
|
- int nv = 0;
|
||
|
|
- for (int j = 0; j < nvp; ++j)
|
||
|
|
- {
|
||
|
|
- if (p[j] == MESH_NULL_IDX) break;
|
||
|
|
- nv++;
|
||
|
|
- }
|
||
|
|
- detailTriCount += nv-2;
|
||
|
|
+ if (p[j] == MESH_NULL_IDX) break;
|
||
|
|
+ nv++;
|
||
|
|
}
|
||
|
|
+ ndv -= nv;
|
||
|
|
+ uniqueDetailVertCount += ndv;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Calculate data size
|
||
|
|
@@ -404,8 +344,8 @@ bool dtCreateNavMeshData(dtNavMeshCreateParams* params, unsigned char** outData,
|
||
|
|
const int linksSize = dtAlign4(sizeof(dtLink)*maxLinkCount);
|
||
|
|
const int detailMeshesSize = dtAlign4(sizeof(dtPolyDetail)*params->polyCount);
|
||
|
|
const int detailVertsSize = dtAlign4(sizeof(float)*3*uniqueDetailVertCount);
|
||
|
|
- const int detailTrisSize = dtAlign4(sizeof(unsigned char)*4*detailTriCount);
|
||
|
|
- const int bvTreeSize = params->buildBvTree ? dtAlign4(sizeof(dtBVNode)*params->polyCount*2) : 0;
|
||
|
|
+ const int detailTrisSize = dtAlign4(sizeof(unsigned char)*4*params->detailTriCount);
|
||
|
|
+ const int bvTreeSize = dtAlign4(sizeof(dtBVNode)*params->polyCount*2);
|
||
|
|
const int offMeshConsSize = dtAlign4(sizeof(dtOffMeshConnection)*storedOffMeshConCount);
|
||
|
|
|
||
|
|
const int dataSize = headerSize + vertsSize + polysSize + linksSize +
|
||
|
|
@@ -437,7 +377,6 @@ bool dtCreateNavMeshData(dtNavMeshCreateParams* params, unsigned char** outData,
|
||
|
|
header->version = DT_NAVMESH_VERSION;
|
||
|
|
header->x = params->tileX;
|
||
|
|
header->y = params->tileY;
|
||
|
|
- header->layer = params->tileLayer;
|
||
|
|
header->userId = params->userId;
|
||
|
|
header->polyCount = totPolyCount;
|
||
|
|
header->vertCount = totVertCount;
|
||
|
|
@@ -446,14 +385,14 @@ bool dtCreateNavMeshData(dtNavMeshCreateParams* params, unsigned char** outData,
|
||
|
|
dtVcopy(header->bmax, params->bmax);
|
||
|
|
header->detailMeshCount = params->polyCount;
|
||
|
|
header->detailVertCount = uniqueDetailVertCount;
|
||
|
|
- header->detailTriCount = detailTriCount;
|
||
|
|
+ header->detailTriCount = params->detailTriCount;
|
||
|
|
header->bvQuantFactor = 1.0f / params->cs;
|
||
|
|
header->offMeshBase = params->polyCount;
|
||
|
|
header->walkableHeight = params->walkableHeight;
|
||
|
|
header->walkableRadius = params->walkableRadius;
|
||
|
|
header->walkableClimb = params->walkableClimb;
|
||
|
|
header->offMeshConCount = storedOffMeshConCount;
|
||
|
|
- header->bvNodeCount = params->buildBvTree ? params->polyCount*2 : 0;
|
||
|
|
+ header->bvNodeCount = params->polyCount*2;
|
||
|
|
|
||
|
|
const int offMeshVertsBase = params->vertCount;
|
||
|
|
const int offMeshPolyBase = params->polyCount;
|
||
|
|
@@ -497,27 +436,7 @@ bool dtCreateNavMeshData(dtNavMeshCreateParams* params, unsigned char** outData,
|
||
|
|
{
|
||
|
|
if (src[j] == MESH_NULL_IDX) break;
|
||
|
|
p->verts[j] = src[j];
|
||
|
|
- if (src[nvp+j] & 0x8000)
|
||
|
|
- {
|
||
|
|
- // Border or portal edge.
|
||
|
|
- unsigned short dir = src[nvp+j] & 0xf;
|
||
|
|
- if (dir == 0xf) // Border
|
||
|
|
- p->neis[j] = 0;
|
||
|
|
- else if (dir == 0) // Portal x-
|
||
|
|
- p->neis[j] = DT_EXT_LINK | 4;
|
||
|
|
- else if (dir == 1) // Portal z+
|
||
|
|
- p->neis[j] = DT_EXT_LINK | 2;
|
||
|
|
- else if (dir == 2) // Portal x+
|
||
|
|
- p->neis[j] = DT_EXT_LINK | 0;
|
||
|
|
- else if (dir == 3) // Portal z-
|
||
|
|
- p->neis[j] = DT_EXT_LINK | 6;
|
||
|
|
- }
|
||
|
|
- else
|
||
|
|
- {
|
||
|
|
- // Normal connection
|
||
|
|
- p->neis[j] = src[nvp+j]+1;
|
||
|
|
- }
|
||
|
|
-
|
||
|
|
+ p->neis[j] = (src[nvp+j]+1) & 0xffff;
|
||
|
|
p->vertCount++;
|
||
|
|
}
|
||
|
|
src += nvp*2;
|
||
|
|
@@ -539,68 +458,61 @@ bool dtCreateNavMeshData(dtNavMeshCreateParams* params, unsigned char** outData,
|
||
|
|
n++;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
-
|
||
|
|
- // Store detail meshes and vertices.
|
||
|
|
- // The nav polygon vertices are stored as the first vertices on each mesh.
|
||
|
|
- // We compress the mesh data by skipping them and using the navmesh coordinates.
|
||
|
|
- if (params->detailMeshes)
|
||
|
|
+
|
||
|
|
+ // Store portal edges.
|
||
|
|
+ if (params->tileSize > 0)
|
||
|
|
{
|
||
|
|
- unsigned short vbase = 0;
|
||
|
|
for (int i = 0; i < params->polyCount; ++i)
|
||
|
|
{
|
||
|
|
- dtPolyDetail& dtl = navDMeshes[i];
|
||
|
|
- const int vb = (int)params->detailMeshes[i*4+0];
|
||
|
|
- const int ndv = (int)params->detailMeshes[i*4+1];
|
||
|
|
- const int nv = navPolys[i].vertCount;
|
||
|
|
- dtl.vertBase = (unsigned int)vbase;
|
||
|
|
- dtl.vertCount = (unsigned char)(ndv-nv);
|
||
|
|
- dtl.triBase = (unsigned int)params->detailMeshes[i*4+2];
|
||
|
|
- dtl.triCount = (unsigned char)params->detailMeshes[i*4+3];
|
||
|
|
- // Copy vertices except the first 'nv' verts which are equal to nav poly verts.
|
||
|
|
- if (ndv-nv)
|
||
|
|
+ dtPoly* poly = &navPolys[i];
|
||
|
|
+ for (int j = 0; j < poly->vertCount; ++j)
|
||
|
|
{
|
||
|
|
- memcpy(&navDVerts[vbase*3], ¶ms->detailVerts[(vb+nv)*3], sizeof(float)*3*(ndv-nv));
|
||
|
|
- vbase += (unsigned short)(ndv-nv);
|
||
|
|
+ int nj = j+1;
|
||
|
|
+ if (nj >= poly->vertCount) nj = 0;
|
||
|
|
+
|
||
|
|
+ const unsigned short* va = ¶ms->verts[poly->verts[j]*3];
|
||
|
|
+ const unsigned short* vb = ¶ms->verts[poly->verts[nj]*3];
|
||
|
|
+
|
||
|
|
+ if (va[0] == params->tileSize && vb[0] == params->tileSize) // x+
|
||
|
|
+ poly->neis[j] = DT_EXT_LINK | 0;
|
||
|
|
+ else if (va[2] == params->tileSize && vb[2] == params->tileSize) // z+
|
||
|
|
+ poly->neis[j] = DT_EXT_LINK | 2;
|
||
|
|
+ else if (va[0] == 0 && vb[0] == 0) // x-
|
||
|
|
+ poly->neis[j] = DT_EXT_LINK | 4;
|
||
|
|
+ else if (va[2] == 0 && vb[2] == 0) // z-
|
||
|
|
+ poly->neis[j] = DT_EXT_LINK | 6;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
- // Store triangles.
|
||
|
|
- memcpy(navDTris, params->detailTris, sizeof(unsigned char)*4*params->detailTriCount);
|
||
|
|
}
|
||
|
|
- else
|
||
|
|
+
|
||
|
|
+ // Store detail meshes and vertices.
|
||
|
|
+ // The nav polygon vertices are stored as the first vertices on each mesh.
|
||
|
|
+ // We compress the mesh data by skipping them and using the navmesh coordinates.
|
||
|
|
+ unsigned short vbase = 0;
|
||
|
|
+ for (int i = 0; i < params->polyCount; ++i)
|
||
|
|
{
|
||
|
|
- // Create dummy detail mesh by triangulating polys.
|
||
|
|
- int tbase = 0;
|
||
|
|
- for (int i = 0; i < params->polyCount; ++i)
|
||
|
|
+ dtPolyDetail& dtl = navDMeshes[i];
|
||
|
|
+ const int vb = (int)params->detailMeshes[i*4+0];
|
||
|
|
+ const int ndv = (int)params->detailMeshes[i*4+1];
|
||
|
|
+ const int nv = navPolys[i].vertCount;
|
||
|
|
+ dtl.vertBase = (unsigned int)vbase;
|
||
|
|
+ dtl.vertCount = (unsigned char)(ndv-nv);
|
||
|
|
+ dtl.triBase = (unsigned int)params->detailMeshes[i*4+2];
|
||
|
|
+ dtl.triCount = (unsigned char)params->detailMeshes[i*4+3];
|
||
|
|
+ // Copy vertices except the first 'nv' verts which are equal to nav poly verts.
|
||
|
|
+ if (ndv-nv)
|
||
|
|
{
|
||
|
|
- dtPolyDetail& dtl = navDMeshes[i];
|
||
|
|
- const int nv = navPolys[i].vertCount;
|
||
|
|
- dtl.vertBase = 0;
|
||
|
|
- dtl.vertCount = 0;
|
||
|
|
- dtl.triBase = (unsigned int)tbase;
|
||
|
|
- dtl.triCount = (unsigned char)(nv-2);
|
||
|
|
- // Triangulate polygon (local indices).
|
||
|
|
- for (int j = 2; j < nv; ++j)
|
||
|
|
- {
|
||
|
|
- unsigned char* t = &navDTris[tbase*4];
|
||
|
|
- t[0] = 0;
|
||
|
|
- t[1] = (unsigned char)(j-1);
|
||
|
|
- t[2] = (unsigned char)j;
|
||
|
|
- // Bit for each edge that belongs to poly boundary.
|
||
|
|
- t[3] = (1<<2);
|
||
|
|
- if (j == 2) t[3] |= (1<<0);
|
||
|
|
- if (j == nv-1) t[3] |= (1<<4);
|
||
|
|
- tbase++;
|
||
|
|
- }
|
||
|
|
+ memcpy(&navDVerts[vbase*3], ¶ms->detailVerts[(vb+nv)*3], sizeof(float)*3*(ndv-nv));
|
||
|
|
+ vbase += (unsigned short)(ndv-nv);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
+ // Store triangles.
|
||
|
|
+ memcpy(navDTris, params->detailTris, sizeof(unsigned char)*4*params->detailTriCount);
|
||
|
|
|
||
|
|
// Store and create BVtree.
|
||
|
|
// TODO: take detail mesh into account! use byte per bbox extent?
|
||
|
|
- if (params->buildBvTree)
|
||
|
|
- {
|
||
|
|
- createBVTree(params->verts, params->vertCount, params->polys, params->polyCount,
|
||
|
|
- nvp, params->cs, params->ch, params->polyCount*2, navBvtree);
|
||
|
|
- }
|
||
|
|
+ createBVTree(params->verts, params->vertCount, params->polys, params->polyCount,
|
||
|
|
+ nvp, params->cs, params->ch, params->polyCount*2, navBvtree);
|
||
|
|
|
||
|
|
// Store Off-Mesh connections.
|
||
|
|
n = 0;
|
||
|
|
@@ -632,14 +544,51 @@ bool dtCreateNavMeshData(dtNavMeshCreateParams* params, unsigned char** outData,
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
+inline void swapByte(unsigned char* a, unsigned char* b)
|
||
|
|
+{
|
||
|
|
+ unsigned char tmp = *a;
|
||
|
|
+ *a = *b;
|
||
|
|
+ *b = tmp;
|
||
|
|
+}
|
||
|
|
+
|
||
|
|
+inline void swapEndian(unsigned short* v)
|
||
|
|
+{
|
||
|
|
+ unsigned char* x = (unsigned char*)v;
|
||
|
|
+ swapByte(x+0, x+1);
|
||
|
|
+}
|
||
|
|
+
|
||
|
|
+inline void swapEndian(short* v)
|
||
|
|
+{
|
||
|
|
+ unsigned char* x = (unsigned char*)v;
|
||
|
|
+ swapByte(x+0, x+1);
|
||
|
|
+}
|
||
|
|
+
|
||
|
|
+inline void swapEndian(unsigned int* v)
|
||
|
|
+{
|
||
|
|
+ unsigned char* x = (unsigned char*)v;
|
||
|
|
+ swapByte(x+0, x+3); swapByte(x+1, x+2);
|
||
|
|
+}
|
||
|
|
+
|
||
|
|
+inline void swapEndian(int* v)
|
||
|
|
+{
|
||
|
|
+ unsigned char* x = (unsigned char*)v;
|
||
|
|
+ swapByte(x+0, x+3); swapByte(x+1, x+2);
|
||
|
|
+}
|
||
|
|
+
|
||
|
|
+inline void swapEndian(float* v)
|
||
|
|
+{
|
||
|
|
+ unsigned char* x = (unsigned char*)v;
|
||
|
|
+ swapByte(x+0, x+3); swapByte(x+1, x+2);
|
||
|
|
+}
|
||
|
|
+
|
||
|
|
bool dtNavMeshHeaderSwapEndian(unsigned char* data, const int /*dataSize*/)
|
||
|
|
{
|
||
|
|
dtMeshHeader* header = (dtMeshHeader*)data;
|
||
|
|
|
||
|
|
int swappedMagic = DT_NAVMESH_MAGIC;
|
||
|
|
int swappedVersion = DT_NAVMESH_VERSION;
|
||
|
|
- dtSwapEndian(&swappedMagic);
|
||
|
|
- dtSwapEndian(&swappedVersion);
|
||
|
|
+ swapEndian(&swappedMagic);
|
||
|
|
+ swapEndian(&swappedVersion);
|
||
|
|
|
||
|
|
if ((header->magic != DT_NAVMESH_MAGIC || header->version != DT_NAVMESH_VERSION) &&
|
||
|
|
(header->magic != swappedMagic || header->version != swappedVersion))
|
||
|
|
@@ -647,43 +596,36 @@ bool dtNavMeshHeaderSwapEndian(unsigned char* data, const int /*dataSize*/)
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
- dtSwapEndian(&header->magic);
|
||
|
|
- dtSwapEndian(&header->version);
|
||
|
|
- dtSwapEndian(&header->x);
|
||
|
|
- dtSwapEndian(&header->y);
|
||
|
|
- dtSwapEndian(&header->layer);
|
||
|
|
- dtSwapEndian(&header->userId);
|
||
|
|
- dtSwapEndian(&header->polyCount);
|
||
|
|
- dtSwapEndian(&header->vertCount);
|
||
|
|
- dtSwapEndian(&header->maxLinkCount);
|
||
|
|
- dtSwapEndian(&header->detailMeshCount);
|
||
|
|
- dtSwapEndian(&header->detailVertCount);
|
||
|
|
- dtSwapEndian(&header->detailTriCount);
|
||
|
|
- dtSwapEndian(&header->bvNodeCount);
|
||
|
|
- dtSwapEndian(&header->offMeshConCount);
|
||
|
|
- dtSwapEndian(&header->offMeshBase);
|
||
|
|
- dtSwapEndian(&header->walkableHeight);
|
||
|
|
- dtSwapEndian(&header->walkableRadius);
|
||
|
|
- dtSwapEndian(&header->walkableClimb);
|
||
|
|
- dtSwapEndian(&header->bmin[0]);
|
||
|
|
- dtSwapEndian(&header->bmin[1]);
|
||
|
|
- dtSwapEndian(&header->bmin[2]);
|
||
|
|
- dtSwapEndian(&header->bmax[0]);
|
||
|
|
- dtSwapEndian(&header->bmax[1]);
|
||
|
|
- dtSwapEndian(&header->bmax[2]);
|
||
|
|
- dtSwapEndian(&header->bvQuantFactor);
|
||
|
|
+ swapEndian(&header->magic);
|
||
|
|
+ swapEndian(&header->version);
|
||
|
|
+ swapEndian(&header->x);
|
||
|
|
+ swapEndian(&header->y);
|
||
|
|
+ swapEndian(&header->userId);
|
||
|
|
+ swapEndian(&header->polyCount);
|
||
|
|
+ swapEndian(&header->vertCount);
|
||
|
|
+ swapEndian(&header->maxLinkCount);
|
||
|
|
+ swapEndian(&header->detailMeshCount);
|
||
|
|
+ swapEndian(&header->detailVertCount);
|
||
|
|
+ swapEndian(&header->detailTriCount);
|
||
|
|
+ swapEndian(&header->bvNodeCount);
|
||
|
|
+ swapEndian(&header->offMeshConCount);
|
||
|
|
+ swapEndian(&header->offMeshBase);
|
||
|
|
+ swapEndian(&header->walkableHeight);
|
||
|
|
+ swapEndian(&header->walkableRadius);
|
||
|
|
+ swapEndian(&header->walkableClimb);
|
||
|
|
+ swapEndian(&header->bmin[0]);
|
||
|
|
+ swapEndian(&header->bmin[1]);
|
||
|
|
+ swapEndian(&header->bmin[2]);
|
||
|
|
+ swapEndian(&header->bmax[0]);
|
||
|
|
+ swapEndian(&header->bmax[1]);
|
||
|
|
+ swapEndian(&header->bmax[2]);
|
||
|
|
+ swapEndian(&header->bvQuantFactor);
|
||
|
|
|
||
|
|
// Freelist index and pointers are updated when tile is added, no need to swap.
|
||
|
|
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
-/// @par
|
||
|
|
-///
|
||
|
|
-/// @warning This function assumes that the header is in the correct endianess already.
|
||
|
|
-/// Call #dtNavMeshHeaderSwapEndian() first on the data if the data is expected to be in wrong endianess
|
||
|
|
-/// to start with. Call #dtNavMeshHeaderSwapEndian() after the data has been swapped if converting from
|
||
|
|
-/// native to foreign endianess.
|
||
|
|
bool dtNavMeshDataSwapEndian(unsigned char* data, const int /*dataSize*/)
|
||
|
|
{
|
||
|
|
// Make sure the data is in right format.
|
||
|
|
@@ -717,7 +659,7 @@ bool dtNavMeshDataSwapEndian(unsigned char* data, const int /*dataSize*/)
|
||
|
|
// Vertices
|
||
|
|
for (int i = 0; i < header->vertCount*3; ++i)
|
||
|
|
{
|
||
|
|
- dtSwapEndian(&verts[i]);
|
||
|
|
+ swapEndian(&verts[i]);
|
||
|
|
}
|
||
|
|
|
||
|
|
// Polys
|
||
|
|
@@ -727,10 +669,10 @@ bool dtNavMeshDataSwapEndian(unsigned char* data, const int /*dataSize*/)
|
||
|
|
// poly->firstLink is update when tile is added, no need to swap.
|
||
|
|
for (int j = 0; j < DT_VERTS_PER_POLYGON; ++j)
|
||
|
|
{
|
||
|
|
- dtSwapEndian(&p->verts[j]);
|
||
|
|
- dtSwapEndian(&p->neis[j]);
|
||
|
|
+ swapEndian(&p->verts[j]);
|
||
|
|
+ swapEndian(&p->neis[j]);
|
||
|
|
}
|
||
|
|
- dtSwapEndian(&p->flags);
|
||
|
|
+ swapEndian(&p->flags);
|
||
|
|
}
|
||
|
|
|
||
|
|
// Links are rebuild when tile is added, no need to swap.
|
||
|
|
@@ -739,14 +681,14 @@ bool dtNavMeshDataSwapEndian(unsigned char* data, const int /*dataSize*/)
|
||
|
|
for (int i = 0; i < header->detailMeshCount; ++i)
|
||
|
|
{
|
||
|
|
dtPolyDetail* pd = &detailMeshes[i];
|
||
|
|
- dtSwapEndian(&pd->vertBase);
|
||
|
|
- dtSwapEndian(&pd->triBase);
|
||
|
|
+ swapEndian(&pd->vertBase);
|
||
|
|
+ swapEndian(&pd->triBase);
|
||
|
|
}
|
||
|
|
|
||
|
|
// Detail verts
|
||
|
|
for (int i = 0; i < header->detailVertCount*3; ++i)
|
||
|
|
{
|
||
|
|
- dtSwapEndian(&detailVerts[i]);
|
||
|
|
+ swapEndian(&detailVerts[i]);
|
||
|
|
}
|
||
|
|
|
||
|
|
// BV-tree
|
||
|
|
@@ -755,10 +697,10 @@ bool dtNavMeshDataSwapEndian(unsigned char* data, const int /*dataSize*/)
|
||
|
|
dtBVNode* node = &bvTree[i];
|
||
|
|
for (int j = 0; j < 3; ++j)
|
||
|
|
{
|
||
|
|
- dtSwapEndian(&node->bmin[j]);
|
||
|
|
- dtSwapEndian(&node->bmax[j]);
|
||
|
|
+ swapEndian(&node->bmin[j]);
|
||
|
|
+ swapEndian(&node->bmax[j]);
|
||
|
|
}
|
||
|
|
- dtSwapEndian(&node->i);
|
||
|
|
+ swapEndian(&node->i);
|
||
|
|
}
|
||
|
|
|
||
|
|
// Off-mesh Connections.
|
||
|
|
@@ -766,9 +708,9 @@ bool dtNavMeshDataSwapEndian(unsigned char* data, const int /*dataSize*/)
|
||
|
|
{
|
||
|
|
dtOffMeshConnection* con = &offMeshCons[i];
|
||
|
|
for (int j = 0; j < 6; ++j)
|
||
|
|
- dtSwapEndian(&con->pos[j]);
|
||
|
|
- dtSwapEndian(&con->rad);
|
||
|
|
- dtSwapEndian(&con->poly);
|
||
|
|
+ swapEndian(&con->pos[j]);
|
||
|
|
+ swapEndian(&con->rad);
|
||
|
|
+ swapEndian(&con->poly);
|
||
|
|
}
|
||
|
|
|
||
|
|
return true;
|
||
|
|
diff --git a/dep/recastnavigation/Detour/DetourNavMeshBuilder.h b/dep/recastnavigation/Detour/DetourNavMeshBuilder.h
|
||
|
|
index c80d171..8d8ef2e 100644
|
||
|
|
--- a/dep/recastnavigation/Detour/DetourNavMeshBuilder.h
|
||
|
|
+++ b/dep/recastnavigation/Detour/DetourNavMeshBuilder.h
|
||
|
|
@@ -21,128 +21,57 @@
|
||
|
|
|
||
|
|
#include "DetourAlloc.h"
|
||
|
|
|
||
|
|
-/// Represents the source data used to build an navigation mesh tile.
|
||
|
|
-/// @ingroup detour
|
||
|
|
+
|
||
|
|
+// The units of the parameters are specified in parenthesis as follows:
|
||
|
|
+// (vx) voxels, (wu) world units
|
||
|
|
struct dtNavMeshCreateParams
|
||
|
|
{
|
||
|
|
-
|
||
|
|
- /// @name Polygon Mesh Attributes
|
||
|
|
- /// Used to create the base navigation graph.
|
||
|
|
- /// See #rcPolyMesh for details related to these attributes.
|
||
|
|
- /// @{
|
||
|
|
-
|
||
|
|
- const unsigned short* verts; ///< The polygon mesh vertices. [(x, y, z) * #vertCount] [Unit: vx]
|
||
|
|
- int vertCount; ///< The number vertices in the polygon mesh. [Limit: >= 3]
|
||
|
|
- const unsigned short* polys; ///< The polygon data. [Size: #polyCount * 2 * #nvp]
|
||
|
|
- const unsigned short* polyFlags; ///< The user defined flags assigned to each polygon. [Size: #polyCount]
|
||
|
|
- const unsigned char* polyAreas; ///< The user defined area ids assigned to each polygon. [Size: #polyCount]
|
||
|
|
- int polyCount; ///< Number of polygons in the mesh. [Limit: >= 1]
|
||
|
|
- int nvp; ///< Number maximum number of vertices per polygon. [Limit: >= 3]
|
||
|
|
-
|
||
|
|
- /// @}
|
||
|
|
- /// @name Height Detail Attributes (Optional)
|
||
|
|
- /// See #rcPolyMeshDetail for details related to these attributes.
|
||
|
|
- /// @{
|
||
|
|
-
|
||
|
|
- const unsigned int* detailMeshes; ///< The height detail sub-mesh data. [Size: 4 * #polyCount]
|
||
|
|
- const float* detailVerts; ///< The detail mesh vertices. [Size: 3 * #detailVertsCount] [Unit: wu]
|
||
|
|
- int detailVertsCount; ///< The number of vertices in the detail mesh.
|
||
|
|
- const unsigned char* detailTris; ///< The detail mesh triangles. [Size: 4 * #detailTriCount]
|
||
|
|
- int detailTriCount; ///< The number of triangles in the detail mesh.
|
||
|
|
-
|
||
|
|
- /// @}
|
||
|
|
- /// @name Off-Mesh Connections Attributes (Optional)
|
||
|
|
- /// Used to define a custom point-to-point edge within the navigation graph, an
|
||
|
|
- /// off-mesh connection is a user defined traversable connection made up to two vertices,
|
||
|
|
- /// at least one of which resides within a navigation mesh polygon.
|
||
|
|
- /// @{
|
||
|
|
-
|
||
|
|
- /// Off-mesh connection vertices. [(ax, ay, az, bx, by, bz) * #offMeshConCount] [Unit: wu]
|
||
|
|
- const float* offMeshConVerts;
|
||
|
|
- /// Off-mesh connection radii. [Size: #offMeshConCount] [Unit: wu]
|
||
|
|
- const float* offMeshConRad;
|
||
|
|
- /// User defined flags assigned to the off-mesh connections. [Size: #offMeshConCount]
|
||
|
|
- const unsigned short* offMeshConFlags;
|
||
|
|
- /// User defined area ids assigned to the off-mesh connections. [Size: #offMeshConCount]
|
||
|
|
- const unsigned char* offMeshConAreas;
|
||
|
|
- /// The permitted travel direction of the off-mesh connections. [Size: #offMeshConCount]
|
||
|
|
- ///
|
||
|
|
- /// 0 = Travel only from endpoint A to endpoint B.<br/>
|
||
|
|
- /// #DT_OFFMESH_CON_BIDIR = Bidirectional travel.
|
||
|
|
- const unsigned char* offMeshConDir;
|
||
|
|
- /// The user defined ids of the off-mesh connection. [Size: #offMeshConCount]
|
||
|
|
- const unsigned int* offMeshConUserID;
|
||
|
|
- /// The number of off-mesh connections. [Limit: >= 0]
|
||
|
|
- int offMeshConCount;
|
||
|
|
-
|
||
|
|
- /// @}
|
||
|
|
- /// @name Tile Attributes
|
||
|
|
- /// @note The tile grid/layer data can be left at zero if the destination is a single tile mesh.
|
||
|
|
- /// @{
|
||
|
|
-
|
||
|
|
- unsigned int userId; ///< The user defined id of the tile.
|
||
|
|
- int tileX; ///< The tile's x-grid location within the multi-tile destination mesh. (Along the x-axis.)
|
||
|
|
- int tileY; ///< The tile's y-grid location within the multi-tile desitation mesh. (Along the z-axis.)
|
||
|
|
- int tileLayer; ///< The tile's layer within the layered destination mesh. [Limit: >= 0] (Along the y-axis.)
|
||
|
|
- float bmin[3]; ///< The minimum bounds of the tile. [(x, y, z)] [Unit: wu]
|
||
|
|
- float bmax[3]; ///< The maximum bounds of the tile. [(x, y, z)] [Unit: wu]
|
||
|
|
-
|
||
|
|
- /// @}
|
||
|
|
- /// @name General Configuration Attributes
|
||
|
|
- /// @{
|
||
|
|
-
|
||
|
|
- float walkableHeight; ///< The agent height. [Unit: wu]
|
||
|
|
- float walkableRadius; ///< The agent radius. [Unit: wu]
|
||
|
|
- float walkableClimb; ///< The agent maximum traversable ledge. (Up/Down) [Unit: wu]
|
||
|
|
- float cs; ///< The xz-plane cell size of the polygon mesh. [Limit: > 0] [Unit: wu]
|
||
|
|
- float ch; ///< The y-axis cell height of the polygon mesh. [Limit: > 0] [Unit: wu]
|
||
|
|
-
|
||
|
|
- /// True if a bounding volume tree should be built for the tile.
|
||
|
|
- /// @note The BVTree is not normally needed for layered navigation meshes.
|
||
|
|
- bool buildBvTree;
|
||
|
|
-
|
||
|
|
- /// @}
|
||
|
|
+ // Navmesh vertices.
|
||
|
|
+ const unsigned short* verts; // Array of vertices, each vertex has 3 components. (vx).
|
||
|
|
+ int vertCount; // Vertex count
|
||
|
|
+ // Navmesh polygons
|
||
|
|
+ const unsigned short* polys; // Array of polygons, uses same format as rcPolyMesh.
|
||
|
|
+ const unsigned short* polyFlags; // Array of flags per polygon.
|
||
|
|
+ const unsigned char* polyAreas; // Array of area ids per polygon.
|
||
|
|
+ int polyCount; // Number of polygons
|
||
|
|
+ int nvp; // Number of verts per polygon.
|
||
|
|
+ // Navmesh Detail
|
||
|
|
+ const unsigned int* detailMeshes; // Detail meshes, uses same format as rcPolyMeshDetail.
|
||
|
|
+ const float* detailVerts; // Detail mesh vertices, uses same format as rcPolyMeshDetail (wu).
|
||
|
|
+ int detailVertsCount; // Total number of detail vertices
|
||
|
|
+ const unsigned char* detailTris; // Array of detail tris per detail mesh.
|
||
|
|
+ int detailTriCount; // Total number of detail triangles.
|
||
|
|
+ // Off-Mesh Connections.
|
||
|
|
+ const float* offMeshConVerts; // Off-mesh connection vertices (wu).
|
||
|
|
+ const float* offMeshConRad; // Off-mesh connection radii (wu).
|
||
|
|
+ const unsigned short* offMeshConFlags; // Off-mesh connection flags.
|
||
|
|
+ const unsigned char* offMeshConAreas; // Off-mesh connection area ids.
|
||
|
|
+ const unsigned char* offMeshConDir; // Off-mesh connection direction flags (1 = bidir, 0 = oneway).
|
||
|
|
+ const unsigned int* offMeshConUserID; // Off-mesh connection user id (optional).
|
||
|
|
+ int offMeshConCount; // Number of off-mesh connections
|
||
|
|
+ // Tile location
|
||
|
|
+ unsigned int userId; // User ID bound to the tile.
|
||
|
|
+ int tileX, tileY; // Tile location (tile coords).
|
||
|
|
+ float bmin[3], bmax[3]; // Tile bounds (wu).
|
||
|
|
+ // Settings
|
||
|
|
+ float walkableHeight; // Agent height (wu).
|
||
|
|
+ float walkableRadius; // Agent radius (wu).
|
||
|
|
+ float walkableClimb; // Agent max climb (wu).
|
||
|
|
+ float cs; // Cell size (xz) (wu).
|
||
|
|
+ float ch; // Cell height (y) (wu).
|
||
|
|
+ int tileSize; // Tile size (width & height) (vx).
|
||
|
|
};
|
||
|
|
|
||
|
|
-/// Builds navigation mesh tile data from the provided tile creation data.
|
||
|
|
-/// @ingroup detour
|
||
|
|
-/// @param[in] params Tile creation data.
|
||
|
|
-/// @param[out] outData The resulting tile data.
|
||
|
|
-/// @param[out] outDataSize The size of the tile data array.
|
||
|
|
-/// @return True if the tile data was successfully created.
|
||
|
|
+// Build navmesh data from given input data.
|
||
|
|
bool dtCreateNavMeshData(dtNavMeshCreateParams* params, unsigned char** outData, int* outDataSize);
|
||
|
|
|
||
|
|
-/// Swaps the endianess of the tile data's header (#dtMeshHeader).
|
||
|
|
-/// @param[in,out] data The tile data array.
|
||
|
|
-/// @param[in] dataSize The size of the data array.
|
||
|
|
+// Swaps endianess of navmesh header.
|
||
|
|
bool dtNavMeshHeaderSwapEndian(unsigned char* data, const int dataSize);
|
||
|
|
|
||
|
|
-/// Swaps endianess of the tile data.
|
||
|
|
-/// @param[in,out] data The tile data array.
|
||
|
|
-/// @param[in] dataSize The size of the data array.
|
||
|
|
+// Swaps endianess of the navmesh data. This function assumes that the header is in correct
|
||
|
|
+// endianess already. Call dtNavMeshHeaderSwapEndian() first on the data if the data is
|
||
|
|
+// assumed to be in wrong endianess to start with. If converting from native endianess to foreign,
|
||
|
|
+// call dtNavMeshHeaderSwapEndian() after the data has been swapped.
|
||
|
|
bool dtNavMeshDataSwapEndian(unsigned char* data, const int dataSize);
|
||
|
|
|
||
|
|
#endif // DETOURNAVMESHBUILDER_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.
|
||
|
|
-
|
||
|
|
-/**
|
||
|
|
-
|
||
|
|
-@struct dtNavMeshCreateParams
|
||
|
|
-@par
|
||
|
|
-
|
||
|
|
-This structure is used to marshal data between the Recast mesh generation pipeline and Detour navigation components.
|
||
|
|
-
|
||
|
|
-See the rcPolyMesh and rcPolyMeshDetail documentation for detailed information related to mesh structure.
|
||
|
|
-
|
||
|
|
-Units are usually in voxels (vx) or world units (wu). The units for voxels, grid size, and cell size
|
||
|
|
-are all based on the values of #cs and #ch.
|
||
|
|
-
|
||
|
|
-The standard navigation mesh build process is to create tile data using dtCreateNavMeshData, then add the tile
|
||
|
|
-to a navigation mesh using either the dtNavMesh single tile <tt>init()</tt> function or the dtNavMesh::addTile()
|
||
|
|
-function.
|
||
|
|
-
|
||
|
|
-@see dtCreateNavMeshData
|
||
|
|
-
|
||
|
|
-*/
|
||
|
|
\ No newline at end of file
|
||
|
|
diff --git a/dep/recastnavigation/Detour/DetourNavMeshQuery.cpp b/dep/recastnavigation/Detour/DetourNavMeshQuery.cpp
|
||
|
|
index e6557cf..6a6eb94 100644
|
||
|
|
--- a/dep/recastnavigation/Detour/DetourNavMeshQuery.cpp
|
||
|
|
+++ b/dep/recastnavigation/Detour/DetourNavMeshQuery.cpp
|
||
|
|
@@ -27,38 +27,6 @@
|
||
|
|
#include "DetourAssert.h"
|
||
|
|
#include <new>
|
||
|
|
|
||
|
|
-/// @class dtQueryFilter
|
||
|
|
-///
|
||
|
|
-/// <b>The Default Implementation</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() :
|
||
|
|
m_includeFlags(0xffff),
|
||
|
|
@@ -81,7 +49,7 @@ float dtQueryFilter::getCost(const float* pa, const float* pb,
|
||
|
|
const dtPolyRef /*curRef*/, const dtMeshTile* /*curTile*/, const dtPoly* curPoly,
|
||
|
|
const dtPolyRef /*nextRef*/, const dtMeshTile* /*nextTile*/, const dtPoly* /*nextPoly*/) const
|
||
|
|
{
|
||
|
|
- return dtVdist(pa, pb) * m_areaCost[curPoly->getArea()];
|
||
|
|
+ return dtVdist(pa, pb) * m_areaCost[curPoly->area];
|
||
|
|
}
|
||
|
|
#else
|
||
|
|
inline bool dtQueryFilter::passFilter(const dtPolyRef /*ref*/,
|
||
|
|
@@ -99,9 +67,8 @@ inline float dtQueryFilter::getCost(const float* pa, const float* pb,
|
||
|
|
return dtVdist(pa, pb) * m_areaCost[curPoly->getArea()];
|
||
|
|
}
|
||
|
|
#endif
|
||
|
|
-
|
||
|
|
-// Edited by TC
|
||
|
|
-static const float H_SCALE = 2.0f; // Search heuristic scale.
|
||
|
|
+
|
||
|
|
+static const float H_SCALE = 2.0f; // Search heuristic scale.
|
||
|
|
|
||
|
|
|
||
|
|
dtNavMeshQuery* dtAllocNavMeshQuery()
|
||
|
|
@@ -119,25 +86,7 @@ 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() :
|
||
|
|
- m_nav(0),
|
||
|
|
m_tinyNodePool(0),
|
||
|
|
m_nodePool(0),
|
||
|
|
m_openList(0)
|
||
|
|
@@ -158,12 +107,6 @@ dtNavMeshQuery::~dtNavMeshQuery()
|
||
|
|
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)
|
||
|
|
{
|
||
|
|
m_nav = nav;
|
||
|
|
@@ -178,7 +121,7 @@ dtStatus dtNavMeshQuery::init(const dtNavMesh* nav, const int maxNodes)
|
||
|
|
}
|
||
|
|
m_nodePool = new (dtAlloc(sizeof(dtNodePool), DT_ALLOC_PERM)) dtNodePool(maxNodes, dtNextPow2(maxNodes/4));
|
||
|
|
if (!m_nodePool)
|
||
|
|
- return DT_FAILURE | DT_OUT_OF_MEMORY;
|
||
|
|
+ return DT_FAILURE_OUT_OF_MEMORY;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
@@ -189,7 +132,7 @@ dtStatus dtNavMeshQuery::init(const dtNavMesh* nav, const int maxNodes)
|
||
|
|
{
|
||
|
|
m_tinyNodePool = new (dtAlloc(sizeof(dtNodePool), DT_ALLOC_PERM)) dtNodePool(64, 32);
|
||
|
|
if (!m_tinyNodePool)
|
||
|
|
- return DT_FAILURE | DT_OUT_OF_MEMORY;
|
||
|
|
+ return DT_FAILURE_OUT_OF_MEMORY;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
@@ -207,7 +150,7 @@ dtStatus dtNavMeshQuery::init(const dtNavMesh* nav, const int maxNodes)
|
||
|
|
}
|
||
|
|
m_openList = new (dtAlloc(sizeof(dtNodeQueue), DT_ALLOC_PERM)) dtNodeQueue(maxNodes);
|
||
|
|
if (!m_openList)
|
||
|
|
- return DT_FAILURE | DT_OUT_OF_MEMORY;
|
||
|
|
+ return DT_FAILURE_OUT_OF_MEMORY;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
@@ -217,328 +160,33 @@ dtStatus dtNavMeshQuery::init(const dtNavMesh* nav, const int maxNodes)
|
||
|
|
return DT_SUCCESS;
|
||
|
|
}
|
||
|
|
|
||
|
|
-dtStatus dtNavMeshQuery::findRandomPoint(const dtQueryFilter* filter, float (*frand)(),
|
||
|
|
- dtPolyRef* randomRef, float* randomPt) const
|
||
|
|
-{
|
||
|
|
- dtAssert(m_nav);
|
||
|
|
-
|
||
|
|
- // Randomly pick one tile. Assume that all tiles cover roughly the same area.
|
||
|
|
- const dtMeshTile* tile = 0;
|
||
|
|
- float tsum = 0.0f;
|
||
|
|
- for (int i = 0; i < m_nav->getMaxTiles(); i++)
|
||
|
|
- {
|
||
|
|
- const dtMeshTile* t = m_nav->getTile(i);
|
||
|
|
- if (!t || !t->header) continue;
|
||
|
|
-
|
||
|
|
- // Choose random tile using reservoi sampling.
|
||
|
|
- const float area = 1.0f; // Could be tile area too.
|
||
|
|
- tsum += area;
|
||
|
|
- const float u = frand();
|
||
|
|
- if (u*tsum <= area)
|
||
|
|
- tile = t;
|
||
|
|
- }
|
||
|
|
- if (!tile)
|
||
|
|
- return DT_FAILURE;
|
||
|
|
-
|
||
|
|
- // Randomly pick one polygon weighted by polygon area.
|
||
|
|
- const dtPoly* poly = 0;
|
||
|
|
- dtPolyRef polyRef = 0;
|
||
|
|
- const dtPolyRef base = m_nav->getPolyRefBase(tile);
|
||
|
|
-
|
||
|
|
- float areaSum = 0.0f;
|
||
|
|
- for (int i = 0; i < tile->header->polyCount; ++i)
|
||
|
|
- {
|
||
|
|
- const dtPoly* p = &tile->polys[i];
|
||
|
|
- // Do not return off-mesh connection polygons.
|
||
|
|
- if (p->getType() != DT_POLYTYPE_GROUND)
|
||
|
|
- continue;
|
||
|
|
- // Must pass filter
|
||
|
|
- const dtPolyRef ref = base | (dtPolyRef)i;
|
||
|
|
- if (!filter->passFilter(ref, tile, p))
|
||
|
|
- continue;
|
||
|
|
-
|
||
|
|
- // Calc area of the polygon.
|
||
|
|
- float polyArea = 0.0f;
|
||
|
|
- for (int j = 2; j < p->vertCount; ++j)
|
||
|
|
- {
|
||
|
|
- const float* va = &tile->verts[p->verts[0]*3];
|
||
|
|
- const float* vb = &tile->verts[p->verts[j-1]*3];
|
||
|
|
- const float* vc = &tile->verts[p->verts[j]*3];
|
||
|
|
- polyArea += dtTriArea2D(va,vb,vc);
|
||
|
|
- }
|
||
|
|
-
|
||
|
|
- // Choose random polygon weighted by area, using reservoi sampling.
|
||
|
|
- areaSum += polyArea;
|
||
|
|
- const float u = frand();
|
||
|
|
- if (u*areaSum <= polyArea)
|
||
|
|
- {
|
||
|
|
- poly = p;
|
||
|
|
- polyRef = ref;
|
||
|
|
- }
|
||
|
|
- }
|
||
|
|
-
|
||
|
|
- if (!poly)
|
||
|
|
- return DT_FAILURE;
|
||
|
|
-
|
||
|
|
- // Randomly pick point on polygon.
|
||
|
|
- const float* v = &tile->verts[poly->verts[0]*3];
|
||
|
|
- float verts[3*DT_VERTS_PER_POLYGON];
|
||
|
|
- float areas[DT_VERTS_PER_POLYGON];
|
||
|
|
- dtVcopy(&verts[0*3],v);
|
||
|
|
- for (int j = 1; j < poly->vertCount; ++j)
|
||
|
|
- {
|
||
|
|
- v = &tile->verts[poly->verts[j]*3];
|
||
|
|
- dtVcopy(&verts[j*3],v);
|
||
|
|
- }
|
||
|
|
-
|
||
|
|
- const float s = frand();
|
||
|
|
- const float t = frand();
|
||
|
|
-
|
||
|
|
- float pt[3];
|
||
|
|
- dtRandomPointInConvexPoly(verts, poly->vertCount, areas, s, t, pt);
|
||
|
|
-
|
||
|
|
- float h = 0.0f;
|
||
|
|
- dtStatus status = getPolyHeight(polyRef, pt, &h);
|
||
|
|
- if (dtStatusFailed(status))
|
||
|
|
- return status;
|
||
|
|
- pt[1] = h;
|
||
|
|
-
|
||
|
|
- dtVcopy(randomPt, pt);
|
||
|
|
- *randomRef = polyRef;
|
||
|
|
-
|
||
|
|
- return DT_SUCCESS;
|
||
|
|
-}
|
||
|
|
-
|
||
|
|
-dtStatus dtNavMeshQuery::findRandomPointAroundCircle(dtPolyRef startRef, const float* centerPos, const float radius,
|
||
|
|
- const dtQueryFilter* filter, float (*frand)(),
|
||
|
|
- dtPolyRef* randomRef, float* randomPt) const
|
||
|
|
-{
|
||
|
|
- dtAssert(m_nav);
|
||
|
|
- dtAssert(m_nodePool);
|
||
|
|
- dtAssert(m_openList);
|
||
|
|
-
|
||
|
|
- // Validate input
|
||
|
|
- if (!startRef || !m_nav->isValidPolyRef(startRef))
|
||
|
|
- return DT_FAILURE | DT_INVALID_PARAM;
|
||
|
|
-
|
||
|
|
- const dtMeshTile* startTile = 0;
|
||
|
|
- const dtPoly* startPoly = 0;
|
||
|
|
- m_nav->getTileAndPolyByRefUnsafe(startRef, &startTile, &startPoly);
|
||
|
|
- if (!filter->passFilter(startRef, startTile, startPoly))
|
||
|
|
- return DT_FAILURE | DT_INVALID_PARAM;
|
||
|
|
-
|
||
|
|
- m_nodePool->clear();
|
||
|
|
- m_openList->clear();
|
||
|
|
-
|
||
|
|
- dtNode* startNode = m_nodePool->getNode(startRef);
|
||
|
|
- dtVcopy(startNode->pos, centerPos);
|
||
|
|
- startNode->pidx = 0;
|
||
|
|
- startNode->cost = 0;
|
||
|
|
- startNode->total = 0;
|
||
|
|
- startNode->id = startRef;
|
||
|
|
- startNode->flags = DT_NODE_OPEN;
|
||
|
|
- m_openList->push(startNode);
|
||
|
|
-
|
||
|
|
- dtStatus status = DT_SUCCESS;
|
||
|
|
-
|
||
|
|
- const float radiusSqr = dtSqr(radius);
|
||
|
|
- float areaSum = 0.0f;
|
||
|
|
-
|
||
|
|
- const dtMeshTile* randomTile = 0;
|
||
|
|
- const dtPoly* randomPoly = 0;
|
||
|
|
- dtPolyRef randomPolyRef = 0;
|
||
|
|
-
|
||
|
|
- while (!m_openList->empty())
|
||
|
|
- {
|
||
|
|
- dtNode* bestNode = m_openList->pop();
|
||
|
|
- bestNode->flags &= ~DT_NODE_OPEN;
|
||
|
|
- bestNode->flags |= DT_NODE_CLOSED;
|
||
|
|
-
|
||
|
|
- // Get poly and tile.
|
||
|
|
- // The API input has been cheked already, skip checking internal data.
|
||
|
|
- const dtPolyRef bestRef = bestNode->id;
|
||
|
|
- const dtMeshTile* bestTile = 0;
|
||
|
|
- const dtPoly* bestPoly = 0;
|
||
|
|
- m_nav->getTileAndPolyByRefUnsafe(bestRef, &bestTile, &bestPoly);
|
||
|
|
-
|
||
|
|
- // Place random locations on on ground.
|
||
|
|
- if (bestPoly->getType() == DT_POLYTYPE_GROUND)
|
||
|
|
- {
|
||
|
|
- // Calc area of the polygon.
|
||
|
|
- float polyArea = 0.0f;
|
||
|
|
- for (int j = 2; j < bestPoly->vertCount; ++j)
|
||
|
|
- {
|
||
|
|
- const float* va = &bestTile->verts[bestPoly->verts[0]*3];
|
||
|
|
- const float* vb = &bestTile->verts[bestPoly->verts[j-1]*3];
|
||
|
|
- const float* vc = &bestTile->verts[bestPoly->verts[j]*3];
|
||
|
|
- polyArea += dtTriArea2D(va,vb,vc);
|
||
|
|
- }
|
||
|
|
- // Choose random polygon weighted by area, using reservoi sampling.
|
||
|
|
- areaSum += polyArea;
|
||
|
|
- const float u = frand();
|
||
|
|
- if (u*areaSum <= polyArea)
|
||
|
|
- {
|
||
|
|
- randomTile = bestTile;
|
||
|
|
- randomPoly = bestPoly;
|
||
|
|
- randomPolyRef = bestRef;
|
||
|
|
- }
|
||
|
|
- }
|
||
|
|
-
|
||
|
|
-
|
||
|
|
- // Get parent poly and tile.
|
||
|
|
- dtPolyRef parentRef = 0;
|
||
|
|
- const dtMeshTile* parentTile = 0;
|
||
|
|
- const dtPoly* parentPoly = 0;
|
||
|
|
- if (bestNode->pidx)
|
||
|
|
- parentRef = m_nodePool->getNodeAtIdx(bestNode->pidx)->id;
|
||
|
|
- if (parentRef)
|
||
|
|
- m_nav->getTileAndPolyByRefUnsafe(parentRef, &parentTile, &parentPoly);
|
||
|
|
-
|
||
|
|
- for (unsigned int i = bestPoly->firstLink; i != DT_NULL_LINK; i = bestTile->links[i].next)
|
||
|
|
- {
|
||
|
|
- const dtLink* link = &bestTile->links[i];
|
||
|
|
- dtPolyRef neighbourRef = link->ref;
|
||
|
|
- // Skip invalid neighbours and do not follow back to parent.
|
||
|
|
- if (!neighbourRef || neighbourRef == parentRef)
|
||
|
|
- continue;
|
||
|
|
-
|
||
|
|
- // Expand to neighbour
|
||
|
|
- const dtMeshTile* neighbourTile = 0;
|
||
|
|
- const dtPoly* neighbourPoly = 0;
|
||
|
|
- m_nav->getTileAndPolyByRefUnsafe(neighbourRef, &neighbourTile, &neighbourPoly);
|
||
|
|
-
|
||
|
|
- // Do not advance if the polygon is excluded by the filter.
|
||
|
|
- if (!filter->passFilter(neighbourRef, neighbourTile, neighbourPoly))
|
||
|
|
- continue;
|
||
|
|
-
|
||
|
|
- // Find edge and calc distance to the edge.
|
||
|
|
- float va[3], vb[3];
|
||
|
|
- if (!getPortalPoints(bestRef, bestPoly, bestTile, neighbourRef, neighbourPoly, neighbourTile, va, vb))
|
||
|
|
- continue;
|
||
|
|
-
|
||
|
|
- // If the circle is not touching the next polygon, skip it.
|
||
|
|
- float tseg;
|
||
|
|
- float distSqr = dtDistancePtSegSqr2D(centerPos, va, vb, tseg);
|
||
|
|
- if (distSqr > radiusSqr)
|
||
|
|
- continue;
|
||
|
|
-
|
||
|
|
- dtNode* neighbourNode = m_nodePool->getNode(neighbourRef);
|
||
|
|
- if (!neighbourNode)
|
||
|
|
- {
|
||
|
|
- status |= DT_OUT_OF_NODES;
|
||
|
|
- continue;
|
||
|
|
- }
|
||
|
|
-
|
||
|
|
- if (neighbourNode->flags & DT_NODE_CLOSED)
|
||
|
|
- continue;
|
||
|
|
-
|
||
|
|
- // Cost
|
||
|
|
- if (neighbourNode->flags == 0)
|
||
|
|
- dtVlerp(neighbourNode->pos, va, vb, 0.5f);
|
||
|
|
-
|
||
|
|
- const float total = bestNode->total + dtVdist(bestNode->pos, neighbourNode->pos);
|
||
|
|
-
|
||
|
|
- // The node is already in open list and the new result is worse, skip.
|
||
|
|
- if ((neighbourNode->flags & DT_NODE_OPEN) && total >= neighbourNode->total)
|
||
|
|
- continue;
|
||
|
|
-
|
||
|
|
- neighbourNode->id = neighbourRef;
|
||
|
|
- neighbourNode->flags = (neighbourNode->flags & ~DT_NODE_CLOSED);
|
||
|
|
- neighbourNode->pidx = m_nodePool->getNodeIdx(bestNode);
|
||
|
|
- neighbourNode->total = total;
|
||
|
|
-
|
||
|
|
- if (neighbourNode->flags & DT_NODE_OPEN)
|
||
|
|
- {
|
||
|
|
- m_openList->modify(neighbourNode);
|
||
|
|
- }
|
||
|
|
- else
|
||
|
|
- {
|
||
|
|
- neighbourNode->flags = DT_NODE_OPEN;
|
||
|
|
- m_openList->push(neighbourNode);
|
||
|
|
- }
|
||
|
|
- }
|
||
|
|
- }
|
||
|
|
-
|
||
|
|
- if (!randomPoly)
|
||
|
|
- return DT_FAILURE;
|
||
|
|
-
|
||
|
|
- // Randomly pick point on polygon.
|
||
|
|
- const float* v = &randomTile->verts[randomPoly->verts[0]*3];
|
||
|
|
- float verts[3*DT_VERTS_PER_POLYGON];
|
||
|
|
- float areas[DT_VERTS_PER_POLYGON];
|
||
|
|
- dtVcopy(&verts[0*3],v);
|
||
|
|
- for (int j = 1; j < randomPoly->vertCount; ++j)
|
||
|
|
- {
|
||
|
|
- v = &randomTile->verts[randomPoly->verts[j]*3];
|
||
|
|
- dtVcopy(&verts[j*3],v);
|
||
|
|
- }
|
||
|
|
-
|
||
|
|
- const float s = frand();
|
||
|
|
- const float t = frand();
|
||
|
|
-
|
||
|
|
- float pt[3];
|
||
|
|
- dtRandomPointInConvexPoly(verts, randomPoly->vertCount, areas, s, t, pt);
|
||
|
|
-
|
||
|
|
- float h = 0.0f;
|
||
|
|
- dtStatus stat = getPolyHeight(randomPolyRef, pt, &h);
|
||
|
|
- if (dtStatusFailed(status))
|
||
|
|
- return stat;
|
||
|
|
- pt[1] = h;
|
||
|
|
-
|
||
|
|
- dtVcopy(randomPt, pt);
|
||
|
|
- *randomRef = randomPolyRef;
|
||
|
|
-
|
||
|
|
- return DT_SUCCESS;
|
||
|
|
-}
|
||
|
|
-
|
||
|
|
-
|
||
|
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||
|
|
-
|
||
|
|
-/// @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
|
||
|
|
{
|
||
|
|
dtAssert(m_nav);
|
||
|
|
const dtMeshTile* tile = 0;
|
||
|
|
const dtPoly* poly = 0;
|
||
|
|
- if (dtStatusFailed(m_nav->getTileAndPolyByRef(ref, &tile, &poly)))
|
||
|
|
- return DT_FAILURE | DT_INVALID_PARAM;
|
||
|
|
- if (!tile)
|
||
|
|
- return DT_FAILURE | DT_INVALID_PARAM;
|
||
|
|
+ if (m_nav->getTileAndPolyByRef(ref, &tile, &poly) != DT_SUCCESS)
|
||
|
|
+ return DT_FAILURE;
|
||
|
|
+ if (!tile) return DT_FAILURE;
|
||
|
|
|
||
|
|
- // Edited by TC
|
||
|
|
- if (poly->getType() == DT_POLYTYPE_OFFMESH_CONNECTION)
|
||
|
|
+ if (poly->getType() == DT_POLYTYPE_OFFMESH_CONNECTION)
|
||
|
|
return DT_FAILURE;
|
||
|
|
|
||
|
|
- closestPointOnPolyInTile(tile, poly, pos, closest);
|
||
|
|
-
|
||
|
|
+ if (closestPointOnPolyInTile(tile, poly, pos, closest) != DT_SUCCESS)
|
||
|
|
+ return DT_FAILURE;
|
||
|
|
return DT_SUCCESS;
|
||
|
|
}
|
||
|
|
|
||
|
|
-void dtNavMeshQuery::closestPointOnPolyInTile(const dtMeshTile* tile, const dtPoly* poly,
|
||
|
|
- const float* pos, float* closest) const
|
||
|
|
+dtStatus dtNavMeshQuery::closestPointOnPolyInTile(const dtMeshTile* tile, const dtPoly* poly,
|
||
|
|
+ const float* pos, float* closest) const
|
||
|
|
{
|
||
|
|
- // 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);
|
||
|
|
- return;
|
||
|
|
- }
|
||
|
|
-
|
||
|
|
const unsigned int ip = (unsigned int)(poly - tile->polys);
|
||
|
|
const dtPolyDetail* pd = &tile->detailMeshes[ip];
|
||
|
|
|
||
|
|
+ // TODO: The commented out version finds 'cylinder distance' instead of 'sphere distance' to the navmesh.
|
||
|
|
+ // Test and enable.
|
||
|
|
+/*
|
||
|
|
// Clamp point to be inside the polygon.
|
||
|
|
float verts[DT_VERTS_PER_POLYGON*3];
|
||
|
|
float edged[DT_VERTS_PER_POLYGON];
|
||
|
|
@@ -585,8 +233,8 @@ void dtNavMeshQuery::closestPointOnPolyInTile(const dtMeshTile* tile, const dtPo
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
-
|
||
|
|
-/* float closestDistSqr = FLT_MAX;
|
||
|
|
+*/
|
||
|
|
+ float closestDistSqr = FLT_MAX;
|
||
|
|
for (int j = 0; j < pd->triCount; ++j)
|
||
|
|
{
|
||
|
|
const unsigned char* t = &tile->detailTris[(pd->triBase+j)*4];
|
||
|
|
@@ -608,28 +256,19 @@ void dtNavMeshQuery::closestPointOnPolyInTile(const dtMeshTile* tile, const dtPo
|
||
|
|
dtVcopy(closest, pt);
|
||
|
|
closestDistSqr = d;
|
||
|
|
}
|
||
|
|
- }*/
|
||
|
|
+ }
|
||
|
|
+
|
||
|
|
+ return DT_SUCCESS;
|
||
|
|
}
|
||
|
|
|
||
|
|
-/// @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
|
||
|
|
{
|
||
|
|
dtAssert(m_nav);
|
||
|
|
|
||
|
|
const dtMeshTile* tile = 0;
|
||
|
|
const dtPoly* poly = 0;
|
||
|
|
- if (dtStatusFailed(m_nav->getTileAndPolyByRef(ref, &tile, &poly)))
|
||
|
|
- return DT_FAILURE | DT_INVALID_PARAM;
|
||
|
|
+ if (m_nav->getTileAndPolyByRef(ref, &tile, &poly) != DT_SUCCESS)
|
||
|
|
+ return DT_FAILURE;
|
||
|
|
|
||
|
|
// Collect vertices.
|
||
|
|
float verts[DT_VERTS_PER_POLYGON*3];
|
||
|
|
@@ -669,19 +308,15 @@ dtStatus dtNavMeshQuery::closestPointOnPolyBoundary(dtPolyRef ref, const float*
|
||
|
|
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
|
||
|
|
{
|
||
|
|
dtAssert(m_nav);
|
||
|
|
|
||
|
|
const dtMeshTile* tile = 0;
|
||
|
|
const dtPoly* poly = 0;
|
||
|
|
- if (dtStatusFailed(m_nav->getTileAndPolyByRef(ref, &tile, &poly)))
|
||
|
|
- return DT_FAILURE | DT_INVALID_PARAM;
|
||
|
|
+ if (m_nav->getTileAndPolyByRef(ref, &tile, &poly) != DT_SUCCESS)
|
||
|
|
+ return DT_FAILURE;
|
||
|
|
|
||
|
|
if (poly->getType() == DT_POLYTYPE_OFFMESH_CONNECTION)
|
||
|
|
{
|
||
|
|
@@ -719,18 +354,9 @@ dtStatus dtNavMeshQuery::getPolyHeight(dtPolyRef ref, const float* pos, float* h
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
- return DT_FAILURE | DT_INVALID_PARAM;
|
||
|
|
+ return DT_FAILURE;
|
||
|
|
}
|
||
|
|
|
||
|
|
-/// @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.
|
||
|
|
-///
|
||
|
|
-/// @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,
|
||
|
|
const dtQueryFilter* filter,
|
||
|
|
dtPolyRef* nearestRef, float* nearestPt) const
|
||
|
|
@@ -742,8 +368,8 @@ dtStatus dtNavMeshQuery::findNearestPoly(const float* center, const float* exten
|
||
|
|
// Get nearby polygons from proximity grid.
|
||
|
|
dtPolyRef polys[128];
|
||
|
|
int polyCount = 0;
|
||
|
|
- if (dtStatusFailed(queryPolygons(center, extents, filter, polys, &polyCount, 128)))
|
||
|
|
- return DT_FAILURE | DT_INVALID_PARAM;
|
||
|
|
+ if (queryPolygons(center, extents, filter, polys, &polyCount, 128) != DT_SUCCESS)
|
||
|
|
+ return DT_FAILURE;
|
||
|
|
|
||
|
|
// Find nearest polygon amongst the nearby polygons.
|
||
|
|
dtPolyRef nearest = 0;
|
||
|
|
@@ -752,7 +378,8 @@ dtStatus dtNavMeshQuery::findNearestPoly(const float* center, const float* exten
|
||
|
|
{
|
||
|
|
dtPolyRef ref = polys[i];
|
||
|
|
float closestPtPoly[3];
|
||
|
|
- closestPointOnPoly(ref, center, closestPtPoly);
|
||
|
|
+ if (closestPointOnPoly(ref, center, closestPtPoly) != DT_SUCCESS)
|
||
|
|
+ continue;
|
||
|
|
float d = dtVdistSqr(center, closestPtPoly);
|
||
|
|
if (d < nearestDistanceSqr)
|
||
|
|
{
|
||
|
|
@@ -790,7 +417,8 @@ dtPolyRef dtNavMeshQuery::findNearestPolyInTile(const dtMeshTile* tile, const fl
|
||
|
|
dtPolyRef ref = polys[i];
|
||
|
|
const dtPoly* poly = &tile->polys[m_nav->decodePolyIdPoly(ref)];
|
||
|
|
float closestPtPoly[3];
|
||
|
|
- closestPointOnPolyInTile(tile, poly, center, closestPtPoly);
|
||
|
|
+ if (closestPointOnPolyInTile(tile, poly, center, closestPtPoly) != DT_SUCCESS)
|
||
|
|
+ continue;
|
||
|
|
|
||
|
|
float d = dtVdistSqr(center, closestPtPoly);
|
||
|
|
if (d < nearestDistanceSqr)
|
||
|
|
@@ -872,15 +500,8 @@ int dtNavMeshQuery::queryPolygonsInTile(const dtMeshTile* tile, const float* qmi
|
||
|
|
const dtPolyRef base = m_nav->getPolyRefBase(tile);
|
||
|
|
for (int i = 0; i < tile->header->polyCount; ++i)
|
||
|
|
{
|
||
|
|
- const dtPoly* p = &tile->polys[i];
|
||
|
|
- // Do not return off-mesh connection polygons.
|
||
|
|
- if (p->getType() == DT_POLYTYPE_OFFMESH_CONNECTION)
|
||
|
|
- continue;
|
||
|
|
- // Must pass filter
|
||
|
|
- const dtPolyRef ref = base | (dtPolyRef)i;
|
||
|
|
- if (!filter->passFilter(ref, tile, p))
|
||
|
|
- continue;
|
||
|
|
// Calc polygon bounds.
|
||
|
|
+ dtPoly* p = &tile->polys[i];
|
||
|
|
const float* v = &tile->verts[p->verts[0]*3];
|
||
|
|
dtVcopy(bmin, v);
|
||
|
|
dtVcopy(bmax, v);
|
||
|
|
@@ -892,23 +513,18 @@ int dtNavMeshQuery::queryPolygonsInTile(const dtMeshTile* tile, const float* qmi
|
||
|
|
}
|
||
|
|
if (dtOverlapBounds(qmin,qmax, bmin,bmax))
|
||
|
|
{
|
||
|
|
- if (n < maxPolys)
|
||
|
|
- polys[n++] = ref;
|
||
|
|
+ const dtPolyRef ref = base | (dtPolyRef)i;
|
||
|
|
+ if (filter->passFilter(ref, tile, p))
|
||
|
|
+ {
|
||
|
|
+ if (n < maxPolys)
|
||
|
|
+ polys[n++] = ref;
|
||
|
|
+ }
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return n;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
-/// @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,
|
||
|
|
const dtQueryFilter* filter,
|
||
|
|
dtPolyRef* polys, int* polyCount, const int maxPolys) const
|
||
|
|
@@ -924,23 +540,18 @@ dtStatus dtNavMeshQuery::queryPolygons(const float* center, const float* extents
|
||
|
|
m_nav->calcTileLoc(bmin, &minx, &miny);
|
||
|
|
m_nav->calcTileLoc(bmax, &maxx, &maxy);
|
||
|
|
|
||
|
|
- static const int MAX_NEIS = 32;
|
||
|
|
- const dtMeshTile* neis[MAX_NEIS];
|
||
|
|
-
|
||
|
|
int n = 0;
|
||
|
|
for (int y = miny; y <= maxy; ++y)
|
||
|
|
{
|
||
|
|
for (int x = minx; x <= maxx; ++x)
|
||
|
|
{
|
||
|
|
- const int nneis = m_nav->getTilesAt(x,y,neis,MAX_NEIS);
|
||
|
|
- for (int j = 0; j < nneis; ++j)
|
||
|
|
+ const dtMeshTile* tile = m_nav->getTileAt(x,y);
|
||
|
|
+ if (!tile) continue;
|
||
|
|
+ n += queryPolygonsInTile(tile, bmin, bmax, filter, polys+n, maxPolys-n);
|
||
|
|
+ if (n >= maxPolys)
|
||
|
|
{
|
||
|
|
- n += queryPolygonsInTile(neis[j], bmin, bmax, filter, polys+n, maxPolys-n);
|
||
|
|
- if (n >= maxPolys)
|
||
|
|
- {
|
||
|
|
- *polyCount = n;
|
||
|
|
- return DT_SUCCESS | DT_BUFFER_TOO_SMALL;
|
||
|
|
- }
|
||
|
|
+ *polyCount = n;
|
||
|
|
+ return DT_SUCCESS;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
@@ -949,17 +560,6 @@ dtStatus dtNavMeshQuery::queryPolygons(const float* center, const float* extents
|
||
|
|
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,
|
||
|
|
const float* startPos, const float* endPos,
|
||
|
|
const dtQueryFilter* filter,
|
||
|
|
@@ -972,14 +572,14 @@ dtStatus dtNavMeshQuery::findPath(dtPolyRef startRef, dtPolyRef endRef,
|
||
|
|
*pathCount = 0;
|
||
|
|
|
||
|
|
if (!startRef || !endRef)
|
||
|
|
- return DT_FAILURE | DT_INVALID_PARAM;
|
||
|
|
+ return DT_FAILURE;
|
||
|
|
|
||
|
|
if (!maxPath)
|
||
|
|
- return DT_FAILURE | DT_INVALID_PARAM;
|
||
|
|
+ return DT_FAILURE;
|
||
|
|
|
||
|
|
// Validate input
|
||
|
|
if (!m_nav->isValidPolyRef(startRef) || !m_nav->isValidPolyRef(endRef))
|
||
|
|
- return DT_FAILURE | DT_INVALID_PARAM;
|
||
|
|
+ return DT_FAILURE;
|
||
|
|
|
||
|
|
if (startRef == endRef)
|
||
|
|
{
|
||
|
|
@@ -1003,8 +603,6 @@ dtStatus dtNavMeshQuery::findPath(dtPolyRef startRef, dtPolyRef endRef,
|
||
|
|
dtNode* lastBestNode = startNode;
|
||
|
|
float lastBestNodeCost = startNode->total;
|
||
|
|
|
||
|
|
- dtStatus status = DT_SUCCESS;
|
||
|
|
-
|
||
|
|
while (!m_openList->empty())
|
||
|
|
{
|
||
|
|
// Remove node from open list and put it in closed list.
|
||
|
|
@@ -1054,10 +652,7 @@ dtStatus dtNavMeshQuery::findPath(dtPolyRef startRef, dtPolyRef endRef,
|
||
|
|
|
||
|
|
dtNode* neighbourNode = m_nodePool->getNode(neighbourRef);
|
||
|
|
if (!neighbourNode)
|
||
|
|
- {
|
||
|
|
- status |= DT_OUT_OF_NODES;
|
||
|
|
continue;
|
||
|
|
- }
|
||
|
|
|
||
|
|
// If the node is visited the first time, calculate node position.
|
||
|
|
if (neighbourNode->flags == 0)
|
||
|
|
@@ -1110,7 +705,7 @@ dtStatus dtNavMeshQuery::findPath(dtPolyRef startRef, dtPolyRef endRef,
|
||
|
|
// Add or update the node.
|
||
|
|
neighbourNode->pidx = m_nodePool->getNodeIdx(bestNode);
|
||
|
|
neighbourNode->id = neighbourRef;
|
||
|
|
- neighbourNode->flags = (neighbourNode->flags & ~DT_NODE_CLOSED);
|
||
|
|
+ neighbourNode->flags &= ~DT_NODE_CLOSED;
|
||
|
|
neighbourNode->cost = cost;
|
||
|
|
neighbourNode->total = total;
|
||
|
|
|
||
|
|
@@ -1135,9 +730,6 @@ dtStatus dtNavMeshQuery::findPath(dtPolyRef startRef, dtPolyRef endRef,
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
- if (lastBestNode->id != endRef)
|
||
|
|
- status |= DT_PARTIAL_RESULT;
|
||
|
|
-
|
||
|
|
// Reverse the path.
|
||
|
|
dtNode* prev = 0;
|
||
|
|
dtNode* node = lastBestNode;
|
||
|
|
@@ -1156,28 +748,15 @@ dtStatus dtNavMeshQuery::findPath(dtPolyRef startRef, dtPolyRef endRef,
|
||
|
|
do
|
||
|
|
{
|
||
|
|
path[n++] = node->id;
|
||
|
|
- if (n >= maxPath)
|
||
|
|
- {
|
||
|
|
- status |= DT_BUFFER_TOO_SMALL;
|
||
|
|
- break;
|
||
|
|
- }
|
||
|
|
node = m_nodePool->getNodeAtIdx(node->pidx);
|
||
|
|
}
|
||
|
|
- while (node);
|
||
|
|
+ while (node && n < maxPath);
|
||
|
|
|
||
|
|
*pathCount = n;
|
||
|
|
|
||
|
|
- return status;
|
||
|
|
+ return DT_SUCCESS;
|
||
|
|
}
|
||
|
|
|
||
|
|
-/// @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,
|
||
|
|
const float* startPos, const float* endPos,
|
||
|
|
const dtQueryFilter* filter)
|
||
|
|
@@ -1196,11 +775,11 @@ dtStatus dtNavMeshQuery::initSlicedFindPath(dtPolyRef startRef, dtPolyRef endRef
|
||
|
|
m_query.filter = filter;
|
||
|
|
|
||
|
|
if (!startRef || !endRef)
|
||
|
|
- return DT_FAILURE | DT_INVALID_PARAM;
|
||
|
|
+ return DT_FAILURE;
|
||
|
|
|
||
|
|
// Validate input
|
||
|
|
if (!m_nav->isValidPolyRef(startRef) || !m_nav->isValidPolyRef(endRef))
|
||
|
|
- return DT_FAILURE | DT_INVALID_PARAM;
|
||
|
|
+ return DT_FAILURE;
|
||
|
|
|
||
|
|
if (startRef == endRef)
|
||
|
|
{
|
||
|
|
@@ -1227,9 +806,9 @@ dtStatus dtNavMeshQuery::initSlicedFindPath(dtPolyRef startRef, dtPolyRef endRef
|
||
|
|
return m_query.status;
|
||
|
|
}
|
||
|
|
|
||
|
|
-dtStatus dtNavMeshQuery::updateSlicedFindPath(const int maxIter, int* doneIters)
|
||
|
|
+dtStatus dtNavMeshQuery::updateSlicedFindPath(const int maxIter)
|
||
|
|
{
|
||
|
|
- if (!dtStatusInProgress(m_query.status))
|
||
|
|
+ if (m_query.status!= DT_IN_PROGRESS)
|
||
|
|
return m_query.status;
|
||
|
|
|
||
|
|
// Make sure the request is still valid.
|
||
|
|
@@ -1253,10 +832,7 @@ dtStatus dtNavMeshQuery::updateSlicedFindPath(const int maxIter, int* doneIters)
|
||
|
|
if (bestNode->id == m_query.endRef)
|
||
|
|
{
|
||
|
|
m_query.lastBestNode = bestNode;
|
||
|
|
- const dtStatus details = m_query.status & DT_STATUS_DETAIL_MASK;
|
||
|
|
- m_query.status = DT_SUCCESS | details;
|
||
|
|
- if (doneIters)
|
||
|
|
- *doneIters = iter;
|
||
|
|
+ m_query.status = DT_SUCCESS;
|
||
|
|
return m_query.status;
|
||
|
|
}
|
||
|
|
|
||
|
|
@@ -1265,12 +841,10 @@ dtStatus dtNavMeshQuery::updateSlicedFindPath(const int maxIter, int* doneIters)
|
||
|
|
const dtPolyRef bestRef = bestNode->id;
|
||
|
|
const dtMeshTile* bestTile = 0;
|
||
|
|
const dtPoly* bestPoly = 0;
|
||
|
|
- if (dtStatusFailed(m_nav->getTileAndPolyByRef(bestRef, &bestTile, &bestPoly)))
|
||
|
|
+ if (m_nav->getTileAndPolyByRef(bestRef, &bestTile, &bestPoly) != DT_SUCCESS)
|
||
|
|
{
|
||
|
|
// The polygon has disappeared during the sliced query, fail.
|
||
|
|
m_query.status = DT_FAILURE;
|
||
|
|
- if (doneIters)
|
||
|
|
- *doneIters = iter;
|
||
|
|
return m_query.status;
|
||
|
|
}
|
||
|
|
|
||
|
|
@@ -1282,12 +856,10 @@ dtStatus dtNavMeshQuery::updateSlicedFindPath(const int maxIter, int* doneIters)
|
||
|
|
parentRef = m_nodePool->getNodeAtIdx(bestNode->pidx)->id;
|
||
|
|
if (parentRef)
|
||
|
|
{
|
||
|
|
- if (dtStatusFailed(m_nav->getTileAndPolyByRef(parentRef, &parentTile, &parentPoly)))
|
||
|
|
+ if (m_nav->getTileAndPolyByRef(parentRef, &parentTile, &parentPoly) != DT_SUCCESS)
|
||
|
|
{
|
||
|
|
// The polygon has disappeared during the sliced query, fail.
|
||
|
|
m_query.status = DT_FAILURE;
|
||
|
|
- if (doneIters)
|
||
|
|
- *doneIters = iter;
|
||
|
|
return m_query.status;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
@@ -1311,10 +883,7 @@ dtStatus dtNavMeshQuery::updateSlicedFindPath(const int maxIter, int* doneIters)
|
||
|
|
|
||
|
|
dtNode* neighbourNode = m_nodePool->getNode(neighbourRef);
|
||
|
|
if (!neighbourNode)
|
||
|
|
- {
|
||
|
|
- m_query.status |= DT_OUT_OF_NODES;
|
||
|
|
continue;
|
||
|
|
- }
|
||
|
|
|
||
|
|
// If the node is visited the first time, calculate node position.
|
||
|
|
if (neighbourNode->flags == 0)
|
||
|
|
@@ -1367,7 +936,7 @@ dtStatus dtNavMeshQuery::updateSlicedFindPath(const int maxIter, int* doneIters)
|
||
|
|
// Add or update the node.
|
||
|
|
neighbourNode->pidx = m_nodePool->getNodeIdx(bestNode);
|
||
|
|
neighbourNode->id = neighbourRef;
|
||
|
|
- neighbourNode->flags = (neighbourNode->flags & ~DT_NODE_CLOSED);
|
||
|
|
+ neighbourNode->flags &= ~DT_NODE_CLOSED;
|
||
|
|
neighbourNode->cost = cost;
|
||
|
|
neighbourNode->total = total;
|
||
|
|
|
||
|
|
@@ -1394,13 +963,7 @@ dtStatus dtNavMeshQuery::updateSlicedFindPath(const int maxIter, int* doneIters)
|
||
|
|
|
||
|
|
// Exhausted all nodes, but could not find path.
|
||
|
|
if (m_openList->empty())
|
||
|
|
- {
|
||
|
|
- const dtStatus details = m_query.status & DT_STATUS_DETAIL_MASK;
|
||
|
|
- m_query.status = DT_SUCCESS | details;
|
||
|
|
- }
|
||
|
|
-
|
||
|
|
- if (doneIters)
|
||
|
|
- *doneIters = iter;
|
||
|
|
+ m_query.status = DT_SUCCESS;
|
||
|
|
|
||
|
|
return m_query.status;
|
||
|
|
}
|
||
|
|
@@ -1409,7 +972,7 @@ dtStatus dtNavMeshQuery::finalizeSlicedFindPath(dtPolyRef* path, int* pathCount,
|
||
|
|
{
|
||
|
|
*pathCount = 0;
|
||
|
|
|
||
|
|
- if (dtStatusFailed(m_query.status))
|
||
|
|
+ if (m_query.status != DT_SUCCESS)
|
||
|
|
{
|
||
|
|
// Reset query.
|
||
|
|
memset(&m_query, 0, sizeof(dtQueryData));
|
||
|
|
@@ -1427,10 +990,6 @@ dtStatus dtNavMeshQuery::finalizeSlicedFindPath(dtPolyRef* path, int* pathCount,
|
||
|
|
{
|
||
|
|
// Reverse the path.
|
||
|
|
dtAssert(m_query.lastBestNode);
|
||
|
|
-
|
||
|
|
- if (m_query.lastBestNode->id != m_query.endRef)
|
||
|
|
- m_query.status |= DT_PARTIAL_RESULT;
|
||
|
|
-
|
||
|
|
dtNode* prev = 0;
|
||
|
|
dtNode* node = m_query.lastBestNode;
|
||
|
|
do
|
||
|
|
@@ -1447,24 +1006,17 @@ dtStatus dtNavMeshQuery::finalizeSlicedFindPath(dtPolyRef* path, int* pathCount,
|
||
|
|
do
|
||
|
|
{
|
||
|
|
path[n++] = node->id;
|
||
|
|
- if (n >= maxPath)
|
||
|
|
- {
|
||
|
|
- m_query.status |= DT_BUFFER_TOO_SMALL;
|
||
|
|
- break;
|
||
|
|
- }
|
||
|
|
node = m_nodePool->getNodeAtIdx(node->pidx);
|
||
|
|
}
|
||
|
|
- while (node);
|
||
|
|
+ while (node && n < maxPath);
|
||
|
|
}
|
||
|
|
|
||
|
|
- const dtStatus details = m_query.status & DT_STATUS_DETAIL_MASK;
|
||
|
|
-
|
||
|
|
// Reset query.
|
||
|
|
memset(&m_query, 0, sizeof(dtQueryData));
|
||
|
|
|
||
|
|
*pathCount = n;
|
||
|
|
|
||
|
|
- return DT_SUCCESS | details;
|
||
|
|
+ return DT_SUCCESS;
|
||
|
|
}
|
||
|
|
|
||
|
|
dtStatus dtNavMeshQuery::finalizeSlicedFindPathPartial(const dtPolyRef* existing, const int existingSize,
|
||
|
|
@@ -1477,7 +1029,7 @@ dtStatus dtNavMeshQuery::finalizeSlicedFindPathPartial(const dtPolyRef* existing
|
||
|
|
return DT_FAILURE;
|
||
|
|
}
|
||
|
|
|
||
|
|
- if (dtStatusFailed(m_query.status))
|
||
|
|
+ if (m_query.status != DT_SUCCESS && m_query.status != DT_IN_PROGRESS)
|
||
|
|
{
|
||
|
|
// Reset query.
|
||
|
|
memset(&m_query, 0, sizeof(dtQueryData));
|
||
|
|
@@ -1505,9 +1057,7 @@ dtStatus dtNavMeshQuery::finalizeSlicedFindPathPartial(const dtPolyRef* existing
|
||
|
|
|
||
|
|
if (!node)
|
||
|
|
{
|
||
|
|
- m_query.status |= DT_PARTIAL_RESULT;
|
||
|
|
- dtAssert(m_query.lastBestNode);
|
||
|
|
- node = m_query.lastBestNode;
|
||
|
|
+ return DT_FAILURE;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Reverse the path.
|
||
|
|
@@ -1525,156 +1075,58 @@ dtStatus dtNavMeshQuery::finalizeSlicedFindPathPartial(const dtPolyRef* existing
|
||
|
|
do
|
||
|
|
{
|
||
|
|
path[n++] = node->id;
|
||
|
|
- if (n >= maxPath)
|
||
|
|
- {
|
||
|
|
- m_query.status |= DT_BUFFER_TOO_SMALL;
|
||
|
|
- break;
|
||
|
|
- }
|
||
|
|
node = m_nodePool->getNodeAtIdx(node->pidx);
|
||
|
|
}
|
||
|
|
- while (node);
|
||
|
|
+ while (node && n < maxPath);
|
||
|
|
}
|
||
|
|
|
||
|
|
- const dtStatus details = m_query.status & DT_STATUS_DETAIL_MASK;
|
||
|
|
-
|
||
|
|
// Reset query.
|
||
|
|
memset(&m_query, 0, sizeof(dtQueryData));
|
||
|
|
|
||
|
|
*pathCount = n;
|
||
|
|
|
||
|
|
- return DT_SUCCESS | details;
|
||
|
|
+ return DT_SUCCESS;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
-dtStatus dtNavMeshQuery::appendVertex(const float* pos, const unsigned char flags, const dtPolyRef ref,
|
||
|
|
- float* straightPath, unsigned char* straightPathFlags, dtPolyRef* straightPathRefs,
|
||
|
|
- int* straightPathCount, const int maxStraightPath) const
|
||
|
|
-{
|
||
|
|
- if ((*straightPathCount) > 0 && dtVequal(&straightPath[((*straightPathCount)-1)*3], pos))
|
||
|
|
- {
|
||
|
|
- // The vertices are equal, update flags and poly.
|
||
|
|
- if (straightPathFlags)
|
||
|
|
- straightPathFlags[(*straightPathCount)-1] = flags;
|
||
|
|
- if (straightPathRefs)
|
||
|
|
- straightPathRefs[(*straightPathCount)-1] = ref;
|
||
|
|
- }
|
||
|
|
- else
|
||
|
|
- {
|
||
|
|
- // Append new vertex.
|
||
|
|
- dtVcopy(&straightPath[(*straightPathCount)*3], pos);
|
||
|
|
- if (straightPathFlags)
|
||
|
|
- straightPathFlags[(*straightPathCount)] = flags;
|
||
|
|
- if (straightPathRefs)
|
||
|
|
- straightPathRefs[(*straightPathCount)] = ref;
|
||
|
|
- (*straightPathCount)++;
|
||
|
|
- // If reached end of path or there is no space to append more vertices, return.
|
||
|
|
- if (flags == DT_STRAIGHTPATH_END || (*straightPathCount) >= maxStraightPath)
|
||
|
|
- {
|
||
|
|
- return DT_SUCCESS | (((*straightPathCount) >= maxStraightPath) ? DT_BUFFER_TOO_SMALL : 0);
|
||
|
|
- }
|
||
|
|
- }
|
||
|
|
- return DT_IN_PROGRESS;
|
||
|
|
-}
|
||
|
|
-
|
||
|
|
-dtStatus dtNavMeshQuery::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 float* startPos = &straightPath[(*straightPathCount-1)*3];
|
||
|
|
- // Append or update last vertex
|
||
|
|
- dtStatus stat = 0;
|
||
|
|
- for (int i = startIdx; i < endIdx; i++)
|
||
|
|
- {
|
||
|
|
- // Calculate portal
|
||
|
|
- const dtPolyRef from = path[i];
|
||
|
|
- const dtMeshTile* fromTile = 0;
|
||
|
|
- const dtPoly* fromPoly = 0;
|
||
|
|
- if (dtStatusFailed(m_nav->getTileAndPolyByRef(from, &fromTile, &fromPoly)))
|
||
|
|
- return DT_FAILURE | DT_INVALID_PARAM;
|
||
|
|
-
|
||
|
|
- const dtPolyRef to = path[i+1];
|
||
|
|
- const dtMeshTile* toTile = 0;
|
||
|
|
- const dtPoly* toPoly = 0;
|
||
|
|
- if (dtStatusFailed(m_nav->getTileAndPolyByRef(to, &toTile, &toPoly)))
|
||
|
|
- return DT_FAILURE | DT_INVALID_PARAM;
|
||
|
|
-
|
||
|
|
- float left[3], right[3];
|
||
|
|
- if (dtStatusFailed(getPortalPoints(from, fromPoly, fromTile, to, toPoly, toTile, left, right)))
|
||
|
|
- break;
|
||
|
|
-
|
||
|
|
- if (options & DT_STRAIGHTPATH_AREA_CROSSINGS)
|
||
|
|
- {
|
||
|
|
- // Skip intersection if only area crossings are requested.
|
||
|
|
- if (fromPoly->getArea() == toPoly->getArea())
|
||
|
|
- continue;
|
||
|
|
- }
|
||
|
|
-
|
||
|
|
- // Append intersection
|
||
|
|
- float s,t;
|
||
|
|
- if (dtIntersectSegSeg2D(startPos, endPos, left, right, s, t))
|
||
|
|
- {
|
||
|
|
- float pt[3];
|
||
|
|
- dtVlerp(pt, left,right, t);
|
||
|
|
-
|
||
|
|
- stat = appendVertex(pt, 0, path[i+1],
|
||
|
|
- straightPath, straightPathFlags, straightPathRefs,
|
||
|
|
- straightPathCount, maxStraightPath);
|
||
|
|
- if (stat != DT_IN_PROGRESS)
|
||
|
|
- return stat;
|
||
|
|
- }
|
||
|
|
- }
|
||
|
|
- return DT_IN_PROGRESS;
|
||
|
|
-}
|
||
|
|
-
|
||
|
|
-/// @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,
|
||
|
|
const dtPolyRef* path, const int pathSize,
|
||
|
|
float* straightPath, unsigned char* straightPathFlags, dtPolyRef* straightPathRefs,
|
||
|
|
- int* straightPathCount, const int maxStraightPath, const int options) const
|
||
|
|
+ int* straightPathCount, const int maxStraightPath) const
|
||
|
|
{
|
||
|
|
dtAssert(m_nav);
|
||
|
|
|
||
|
|
*straightPathCount = 0;
|
||
|
|
|
||
|
|
if (!maxStraightPath)
|
||
|
|
- return DT_FAILURE | DT_INVALID_PARAM;
|
||
|
|
+ return DT_FAILURE;
|
||
|
|
|
||
|
|
if (!path[0])
|
||
|
|
- return DT_FAILURE | DT_INVALID_PARAM;
|
||
|
|
+ return DT_FAILURE;
|
||
|
|
|
||
|
|
- dtStatus stat = 0;
|
||
|
|
+ int n = 0;
|
||
|
|
|
||
|
|
// TODO: Should this be callers responsibility?
|
||
|
|
float closestStartPos[3];
|
||
|
|
- if (dtStatusFailed(closestPointOnPolyBoundary(path[0], startPos, closestStartPos)))
|
||
|
|
- return DT_FAILURE | DT_INVALID_PARAM;
|
||
|
|
-
|
||
|
|
- float closestEndPos[3];
|
||
|
|
- if (dtStatusFailed(closestPointOnPolyBoundary(path[pathSize-1], endPos, closestEndPos)))
|
||
|
|
- return DT_FAILURE | DT_INVALID_PARAM;
|
||
|
|
+ if (closestPointOnPolyBoundary(path[0], startPos, closestStartPos) != DT_SUCCESS)
|
||
|
|
+ return DT_FAILURE;
|
||
|
|
|
||
|
|
// Add start point.
|
||
|
|
- stat = appendVertex(closestStartPos, DT_STRAIGHTPATH_START, path[0],
|
||
|
|
- straightPath, straightPathFlags, straightPathRefs,
|
||
|
|
- straightPathCount, maxStraightPath);
|
||
|
|
- if (stat != DT_IN_PROGRESS)
|
||
|
|
- return stat;
|
||
|
|
+ dtVcopy(&straightPath[n*3], closestStartPos);
|
||
|
|
+ if (straightPathFlags)
|
||
|
|
+ straightPathFlags[n] = DT_STRAIGHTPATH_START;
|
||
|
|
+ if (straightPathRefs)
|
||
|
|
+ straightPathRefs[n] = path[0];
|
||
|
|
+ n++;
|
||
|
|
+ if (n >= maxStraightPath)
|
||
|
|
+ {
|
||
|
|
+ *straightPathCount = n;
|
||
|
|
+ return DT_SUCCESS;
|
||
|
|
+ }
|
||
|
|
+
|
||
|
|
+ float closestEndPos[3];
|
||
|
|
+ if (closestPointOnPolyBoundary(path[pathSize-1], endPos, closestEndPos) != DT_SUCCESS)
|
||
|
|
+ return DT_FAILURE;
|
||
|
|
|
||
|
|
if (pathSize > 1)
|
||
|
|
{
|
||
|
|
@@ -1700,30 +1152,19 @@ dtStatus dtNavMeshQuery::findStraightPath(const float* startPos, const float* en
|
||
|
|
if (i+1 < pathSize)
|
||
|
|
{
|
||
|
|
// Next portal.
|
||
|
|
- if (dtStatusFailed(getPortalPoints(path[i], path[i+1], left, right, fromType, toType)))
|
||
|
|
+ if (getPortalPoints(path[i], path[i+1], left, right, fromType, toType) != DT_SUCCESS)
|
||
|
|
{
|
||
|
|
- // Failed to get portal points, in practice this means that path[i+1] is invalid polygon.
|
||
|
|
- // Clamp the end point to path[i], and return the path so far.
|
||
|
|
+ if (closestPointOnPolyBoundary(path[i], endPos, closestEndPos) != DT_SUCCESS)
|
||
|
|
+ return DT_FAILURE;
|
||
|
|
|
||
|
|
- if (dtStatusFailed(closestPointOnPolyBoundary(path[i], endPos, closestEndPos)))
|
||
|
|
- {
|
||
|
|
- // This should only happen when the first polygon is invalid.
|
||
|
|
- return DT_FAILURE | DT_INVALID_PARAM;
|
||
|
|
- }
|
||
|
|
-
|
||
|
|
- // Apeend portals along the current straight path segment.
|
||
|
|
- if (options & (DT_STRAIGHTPATH_AREA_CROSSINGS | DT_STRAIGHTPATH_ALL_CROSSINGS))
|
||
|
|
- {
|
||
|
|
- stat = appendPortals(apexIndex, i, closestEndPos, path,
|
||
|
|
- straightPath, straightPathFlags, straightPathRefs,
|
||
|
|
- straightPathCount, maxStraightPath, options);
|
||
|
|
- }
|
||
|
|
-
|
||
|
|
- stat = appendVertex(closestEndPos, 0, path[i],
|
||
|
|
- straightPath, straightPathFlags, straightPathRefs,
|
||
|
|
- straightPathCount, maxStraightPath);
|
||
|
|
+ dtVcopy(&straightPath[n*3], closestEndPos);
|
||
|
|
+ if (straightPathFlags)
|
||
|
|
+ straightPathFlags[n] = 0;
|
||
|
|
+ if (straightPathRefs)
|
||
|
|
+ straightPathRefs[n] = path[i];
|
||
|
|
+ n++;
|
||
|
|
|
||
|
|
- return DT_SUCCESS | DT_PARTIAL_RESULT | ((*straightPathCount >= maxStraightPath) ? DT_BUFFER_TOO_SMALL : 0);
|
||
|
|
+ return DT_SUCCESS;
|
||
|
|
}
|
||
|
|
|
||
|
|
// If starting really close the portal, advance.
|
||
|
|
@@ -1755,16 +1196,6 @@ dtStatus dtNavMeshQuery::findStraightPath(const float* startPos, const float* en
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
- // Append portals along the current straight path segment.
|
||
|
|
- if (options & (DT_STRAIGHTPATH_AREA_CROSSINGS | DT_STRAIGHTPATH_ALL_CROSSINGS))
|
||
|
|
- {
|
||
|
|
- stat = appendPortals(apexIndex, leftIndex, portalLeft, path,
|
||
|
|
- straightPath, straightPathFlags, straightPathRefs,
|
||
|
|
- straightPathCount, maxStraightPath, options);
|
||
|
|
- if (stat != DT_IN_PROGRESS)
|
||
|
|
- return stat;
|
||
|
|
- }
|
||
|
|
-
|
||
|
|
dtVcopy(portalApex, portalLeft);
|
||
|
|
apexIndex = leftIndex;
|
||
|
|
|
||
|
|
@@ -1775,12 +1206,30 @@ dtStatus dtNavMeshQuery::findStraightPath(const float* startPos, const float* en
|
||
|
|
flags = DT_STRAIGHTPATH_OFFMESH_CONNECTION;
|
||
|
|
dtPolyRef ref = leftPolyRef;
|
||
|
|
|
||
|
|
- // Append or update vertex
|
||
|
|
- stat = appendVertex(portalApex, flags, ref,
|
||
|
|
- straightPath, straightPathFlags, straightPathRefs,
|
||
|
|
- straightPathCount, maxStraightPath);
|
||
|
|
- if (stat != DT_IN_PROGRESS)
|
||
|
|
- return stat;
|
||
|
|
+ if (!dtVequal(&straightPath[(n-1)*3], portalApex))
|
||
|
|
+ {
|
||
|
|
+ // Append new vertex.
|
||
|
|
+ dtVcopy(&straightPath[n*3], portalApex);
|
||
|
|
+ if (straightPathFlags)
|
||
|
|
+ straightPathFlags[n] = flags;
|
||
|
|
+ if (straightPathRefs)
|
||
|
|
+ straightPathRefs[n] = ref;
|
||
|
|
+ n++;
|
||
|
|
+ // If reached end of path or there is no space to append more vertices, return.
|
||
|
|
+ if (flags == DT_STRAIGHTPATH_END || n >= maxStraightPath)
|
||
|
|
+ {
|
||
|
|
+ *straightPathCount = n;
|
||
|
|
+ return DT_SUCCESS;
|
||
|
|
+ }
|
||
|
|
+ }
|
||
|
|
+ else
|
||
|
|
+ {
|
||
|
|
+ // The vertices are equal, update flags and poly.
|
||
|
|
+ if (straightPathFlags)
|
||
|
|
+ straightPathFlags[n-1] = flags;
|
||
|
|
+ if (straightPathRefs)
|
||
|
|
+ straightPathRefs[n-1] = ref;
|
||
|
|
+ }
|
||
|
|
|
||
|
|
dtVcopy(portalLeft, portalApex);
|
||
|
|
dtVcopy(portalRight, portalApex);
|
||
|
|
@@ -1806,16 +1255,6 @@ dtStatus dtNavMeshQuery::findStraightPath(const float* startPos, const float* en
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
- // Append portals along the current straight path segment.
|
||
|
|
- if (options & (DT_STRAIGHTPATH_AREA_CROSSINGS | DT_STRAIGHTPATH_ALL_CROSSINGS))
|
||
|
|
- {
|
||
|
|
- stat = appendPortals(apexIndex, rightIndex, portalRight, path,
|
||
|
|
- straightPath, straightPathFlags, straightPathRefs,
|
||
|
|
- straightPathCount, maxStraightPath, options);
|
||
|
|
- if (stat != DT_IN_PROGRESS)
|
||
|
|
- return stat;
|
||
|
|
- }
|
||
|
|
-
|
||
|
|
dtVcopy(portalApex, portalRight);
|
||
|
|
apexIndex = rightIndex;
|
||
|
|
|
||
|
|
@@ -1825,13 +1264,31 @@ dtStatus dtNavMeshQuery::findStraightPath(const float* startPos, const float* en
|
||
|
|
else if (rightPolyType == DT_POLYTYPE_OFFMESH_CONNECTION)
|
||
|
|
flags = DT_STRAIGHTPATH_OFFMESH_CONNECTION;
|
||
|
|
dtPolyRef ref = rightPolyRef;
|
||
|
|
-
|
||
|
|
- // Append or update vertex
|
||
|
|
- stat = appendVertex(portalApex, flags, ref,
|
||
|
|
- straightPath, straightPathFlags, straightPathRefs,
|
||
|
|
- straightPathCount, maxStraightPath);
|
||
|
|
- if (stat != DT_IN_PROGRESS)
|
||
|
|
- return stat;
|
||
|
|
+
|
||
|
|
+ if (!dtVequal(&straightPath[(n-1)*3], portalApex))
|
||
|
|
+ {
|
||
|
|
+ // Append new vertex.
|
||
|
|
+ dtVcopy(&straightPath[n*3], portalApex);
|
||
|
|
+ if (straightPathFlags)
|
||
|
|
+ straightPathFlags[n] = flags;
|
||
|
|
+ if (straightPathRefs)
|
||
|
|
+ straightPathRefs[n] = ref;
|
||
|
|
+ n++;
|
||
|
|
+ // If reached end of path or there is no space to append more vertices, return.
|
||
|
|
+ if (flags == DT_STRAIGHTPATH_END || n >= maxStraightPath)
|
||
|
|
+ {
|
||
|
|
+ *straightPathCount = n;
|
||
|
|
+ return DT_SUCCESS;
|
||
|
|
+ }
|
||
|
|
+ }
|
||
|
|
+ else
|
||
|
|
+ {
|
||
|
|
+ // The vertices are equal, update flags and poly.
|
||
|
|
+ if (straightPathFlags)
|
||
|
|
+ straightPathFlags[n-1] = flags;
|
||
|
|
+ if (straightPathRefs)
|
||
|
|
+ straightPathRefs[n-1] = ref;
|
||
|
|
+ }
|
||
|
|
|
||
|
|
dtVcopy(portalLeft, portalApex);
|
||
|
|
dtVcopy(portalRight, portalApex);
|
||
|
|
@@ -1845,45 +1302,27 @@ dtStatus dtNavMeshQuery::findStraightPath(const float* startPos, const float* en
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
-
|
||
|
|
- // Append portals along the current straight path segment.
|
||
|
|
- if (options & (DT_STRAIGHTPATH_AREA_CROSSINGS | DT_STRAIGHTPATH_ALL_CROSSINGS))
|
||
|
|
- {
|
||
|
|
- stat = appendPortals(apexIndex, pathSize-1, closestEndPos, path,
|
||
|
|
- straightPath, straightPathFlags, straightPathRefs,
|
||
|
|
- straightPathCount, maxStraightPath, options);
|
||
|
|
- if (stat != DT_IN_PROGRESS)
|
||
|
|
- return stat;
|
||
|
|
- }
|
||
|
|
}
|
||
|
|
-
|
||
|
|
- stat = appendVertex(closestEndPos, DT_STRAIGHTPATH_END, 0,
|
||
|
|
- straightPath, straightPathFlags, straightPathRefs,
|
||
|
|
- straightPathCount, maxStraightPath);
|
||
|
|
|
||
|
|
- return DT_SUCCESS | ((*straightPathCount >= maxStraightPath) ? DT_BUFFER_TOO_SMALL : 0);
|
||
|
|
+ // If the point already exists, remove it and add reappend the actual end location.
|
||
|
|
+ if (n > 0 && dtVequal(&straightPath[(n-1)*3], closestEndPos))
|
||
|
|
+ n--;
|
||
|
|
+
|
||
|
|
+ // Add end point.
|
||
|
|
+ if (n < maxStraightPath)
|
||
|
|
+ {
|
||
|
|
+ dtVcopy(&straightPath[n*3], closestEndPos);
|
||
|
|
+ if (straightPathFlags)
|
||
|
|
+ straightPathFlags[n] = DT_STRAIGHTPATH_END;
|
||
|
|
+ if (straightPathRefs)
|
||
|
|
+ straightPathRefs[n] = 0;
|
||
|
|
+ n++;
|
||
|
|
+ }
|
||
|
|
+
|
||
|
|
+ *straightPathCount = n;
|
||
|
|
+ return DT_SUCCESS;
|
||
|
|
}
|
||
|
|
|
||
|
|
-/// @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,
|
||
|
|
const dtQueryFilter* filter,
|
||
|
|
float* resultPos, dtPolyRef* visited, int* visitedCount, const int maxVisitedSize) const
|
||
|
|
@@ -1894,12 +1333,8 @@ dtStatus dtNavMeshQuery::moveAlongSurface(dtPolyRef startRef, const float* start
|
||
|
|
*visitedCount = 0;
|
||
|
|
|
||
|
|
// Validate input
|
||
|
|
- if (!startRef)
|
||
|
|
- return DT_FAILURE | DT_INVALID_PARAM;
|
||
|
|
- if (!m_nav->isValidPolyRef(startRef))
|
||
|
|
- return DT_FAILURE | DT_INVALID_PARAM;
|
||
|
|
-
|
||
|
|
- dtStatus status = DT_SUCCESS;
|
||
|
|
+ if (!startRef) return DT_FAILURE;
|
||
|
|
+ if (!m_nav->isValidPolyRef(startRef)) return DT_FAILURE;
|
||
|
|
|
||
|
|
static const int MAX_STACK = 48;
|
||
|
|
dtNode* stack[MAX_STACK];
|
||
|
|
@@ -2064,21 +1499,16 @@ dtStatus dtNavMeshQuery::moveAlongSurface(dtPolyRef startRef, const float* start
|
||
|
|
do
|
||
|
|
{
|
||
|
|
visited[n++] = node->id;
|
||
|
|
- if (n >= maxVisitedSize)
|
||
|
|
- {
|
||
|
|
- status |= DT_BUFFER_TOO_SMALL;
|
||
|
|
- break;
|
||
|
|
- }
|
||
|
|
node = m_tinyNodePool->getNodeAtIdx(node->pidx);
|
||
|
|
}
|
||
|
|
- while (node);
|
||
|
|
+ while (node && n < maxVisitedSize);
|
||
|
|
}
|
||
|
|
|
||
|
|
dtVcopy(resultPos, bestPos);
|
||
|
|
|
||
|
|
*visitedCount = n;
|
||
|
|
|
||
|
|
- return status;
|
||
|
|
+ return DT_SUCCESS;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
@@ -2089,14 +1519,14 @@ dtStatus dtNavMeshQuery::getPortalPoints(dtPolyRef from, dtPolyRef to, float* le
|
||
|
|
|
||
|
|
const dtMeshTile* fromTile = 0;
|
||
|
|
const dtPoly* fromPoly = 0;
|
||
|
|
- if (dtStatusFailed(m_nav->getTileAndPolyByRef(from, &fromTile, &fromPoly)))
|
||
|
|
- return DT_FAILURE | DT_INVALID_PARAM;
|
||
|
|
+ if (m_nav->getTileAndPolyByRef(from, &fromTile, &fromPoly) != DT_SUCCESS)
|
||
|
|
+ return DT_FAILURE;
|
||
|
|
fromType = fromPoly->getType();
|
||
|
|
|
||
|
|
const dtMeshTile* toTile = 0;
|
||
|
|
const dtPoly* toPoly = 0;
|
||
|
|
- if (dtStatusFailed(m_nav->getTileAndPolyByRef(to, &toTile, &toPoly)))
|
||
|
|
- return DT_FAILURE | DT_INVALID_PARAM;
|
||
|
|
+ if (m_nav->getTileAndPolyByRef(to, &toTile, &toPoly) != DT_SUCCESS)
|
||
|
|
+ return DT_FAILURE;
|
||
|
|
toType = toPoly->getType();
|
||
|
|
|
||
|
|
return getPortalPoints(from, fromPoly, fromTile, to, toPoly, toTile, left, right);
|
||
|
|
@@ -2118,7 +1548,7 @@ dtStatus dtNavMeshQuery::getPortalPoints(dtPolyRef from, const dtPoly* fromPoly,
|
||
|
|
}
|
||
|
|
}
|
||
|
|
if (!link)
|
||
|
|
- return DT_FAILURE | DT_INVALID_PARAM;
|
||
|
|
+ return DT_FAILURE;
|
||
|
|
|
||
|
|
// Handle off-mesh connections.
|
||
|
|
if (fromPoly->getType() == DT_POLYTYPE_OFFMESH_CONNECTION)
|
||
|
|
@@ -2134,7 +1564,7 @@ dtStatus dtNavMeshQuery::getPortalPoints(dtPolyRef from, const dtPoly* fromPoly,
|
||
|
|
return DT_SUCCESS;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
- return DT_FAILURE | DT_INVALID_PARAM;
|
||
|
|
+ return DT_FAILURE;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (toPoly->getType() == DT_POLYTYPE_OFFMESH_CONNECTION)
|
||
|
|
@@ -2149,7 +1579,7 @@ dtStatus dtNavMeshQuery::getPortalPoints(dtPolyRef from, const dtPoly* fromPoly,
|
||
|
|
return DT_SUCCESS;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
- return DT_FAILURE | DT_INVALID_PARAM;
|
||
|
|
+ return DT_FAILURE;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Find portal vertices.
|
||
|
|
@@ -2181,8 +1611,7 @@ dtStatus dtNavMeshQuery::getEdgeMidPoint(dtPolyRef from, dtPolyRef to, float* mi
|
||
|
|
{
|
||
|
|
float left[3], right[3];
|
||
|
|
unsigned char fromType, toType;
|
||
|
|
- if (dtStatusFailed(getPortalPoints(from, to, left,right, fromType, toType)))
|
||
|
|
- return DT_FAILURE | DT_INVALID_PARAM;
|
||
|
|
+ if (!getPortalPoints(from, to, left,right, fromType, toType)) return DT_FAILURE;
|
||
|
|
mid[0] = (left[0]+right[0])*0.5f;
|
||
|
|
mid[1] = (left[1]+right[1])*0.5f;
|
||
|
|
mid[2] = (left[2]+right[2])*0.5f;
|
||
|
|
@@ -2194,52 +1623,14 @@ dtStatus dtNavMeshQuery::getEdgeMidPoint(dtPolyRef from, const dtPoly* fromPoly,
|
||
|
|
float* mid) const
|
||
|
|
{
|
||
|
|
float left[3], right[3];
|
||
|
|
- if (dtStatusFailed(getPortalPoints(from, fromPoly, fromTile, to, toPoly, toTile, left, right)))
|
||
|
|
- return DT_FAILURE | DT_INVALID_PARAM;
|
||
|
|
+ if (getPortalPoints(from, fromPoly, fromTile, to, toPoly, toTile, left, right) != DT_SUCCESS)
|
||
|
|
+ return DT_FAILURE;
|
||
|
|
mid[0] = (left[0]+right[0])*0.5f;
|
||
|
|
mid[1] = (left[1]+right[1])*0.5f;
|
||
|
|
mid[2] = (left[2]+right[2])*0.5f;
|
||
|
|
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,
|
||
|
|
const dtQueryFilter* filter,
|
||
|
|
float* t, float* hitNormal, dtPolyRef* path, int* pathCount, const int maxPath) const
|
||
|
|
@@ -2252,7 +1643,7 @@ dtStatus dtNavMeshQuery::raycast(dtPolyRef startRef, const float* startPos, cons
|
||
|
|
|
||
|
|
// Validate input
|
||
|
|
if (!startRef || !m_nav->isValidPolyRef(startRef))
|
||
|
|
- return DT_FAILURE | DT_INVALID_PARAM;
|
||
|
|
+ return DT_FAILURE;
|
||
|
|
|
||
|
|
dtPolyRef curRef = startRef;
|
||
|
|
float verts[DT_VERTS_PER_POLYGON*3];
|
||
|
|
@@ -2262,8 +1653,6 @@ dtStatus dtNavMeshQuery::raycast(dtPolyRef startRef, const float* startPos, cons
|
||
|
|
hitNormal[1] = 0;
|
||
|
|
hitNormal[2] = 0;
|
||
|
|
|
||
|
|
- dtStatus status = DT_SUCCESS;
|
||
|
|
-
|
||
|
|
while (curRef)
|
||
|
|
{
|
||
|
|
// Cast ray against current polygon.
|
||
|
|
@@ -2288,7 +1677,7 @@ dtStatus dtNavMeshQuery::raycast(dtPolyRef startRef, const float* startPos, cons
|
||
|
|
// Could not hit the polygon, keep the old t and report hit.
|
||
|
|
if (pathCount)
|
||
|
|
*pathCount = n;
|
||
|
|
- return status;
|
||
|
|
+ return DT_SUCCESS;
|
||
|
|
}
|
||
|
|
// Keep track of furthest t so far.
|
||
|
|
if (tmax > *t)
|
||
|
|
@@ -2297,8 +1686,6 @@ dtStatus dtNavMeshQuery::raycast(dtPolyRef startRef, const float* startPos, cons
|
||
|
|
// Store visited polygons.
|
||
|
|
if (n < maxPath)
|
||
|
|
path[n++] = curRef;
|
||
|
|
- else
|
||
|
|
- status |= DT_BUFFER_TOO_SMALL;
|
||
|
|
|
||
|
|
// Ray end is completely inside the polygon.
|
||
|
|
if (segMax == -1)
|
||
|
|
@@ -2306,7 +1693,7 @@ dtStatus dtNavMeshQuery::raycast(dtPolyRef startRef, const float* startPos, cons
|
||
|
|
*t = FLT_MAX;
|
||
|
|
if (pathCount)
|
||
|
|
*pathCount = n;
|
||
|
|
- return status;
|
||
|
|
+ return DT_SUCCESS;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Follow neighbours.
|
||
|
|
@@ -2408,7 +1795,7 @@ dtStatus dtNavMeshQuery::raycast(dtPolyRef startRef, const float* startPos, cons
|
||
|
|
|
||
|
|
if (pathCount)
|
||
|
|
*pathCount = n;
|
||
|
|
- return status;
|
||
|
|
+ return DT_SUCCESS;
|
||
|
|
}
|
||
|
|
|
||
|
|
// No hit, advance to neighbour polygon.
|
||
|
|
@@ -2418,38 +1805,9 @@ dtStatus dtNavMeshQuery::raycast(dtPolyRef startRef, const float* startPos, cons
|
||
|
|
if (pathCount)
|
||
|
|
*pathCount = n;
|
||
|
|
|
||
|
|
- return status;
|
||
|
|
+ return DT_SUCCESS;
|
||
|
|
}
|
||
|
|
|
||
|
|
-/// @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,
|
||
|
|
const dtQueryFilter* filter,
|
||
|
|
dtPolyRef* resultRef, dtPolyRef* resultParent, float* resultCost,
|
||
|
|
@@ -2462,8 +1820,8 @@ dtStatus dtNavMeshQuery::findPolysAroundCircle(dtPolyRef startRef, const float*
|
||
|
|
*resultCount = 0;
|
||
|
|
|
||
|
|
// Validate input
|
||
|
|
- if (!startRef || !m_nav->isValidPolyRef(startRef))
|
||
|
|
- return DT_FAILURE | DT_INVALID_PARAM;
|
||
|
|
+ if (!startRef) return DT_FAILURE;
|
||
|
|
+ if (!m_nav->isValidPolyRef(startRef)) return DT_FAILURE;
|
||
|
|
|
||
|
|
m_nodePool->clear();
|
||
|
|
m_openList->clear();
|
||
|
|
@@ -2477,8 +1835,6 @@ dtStatus dtNavMeshQuery::findPolysAroundCircle(dtPolyRef startRef, const float*
|
||
|
|
startNode->flags = DT_NODE_OPEN;
|
||
|
|
m_openList->push(startNode);
|
||
|
|
|
||
|
|
- dtStatus status = DT_SUCCESS;
|
||
|
|
-
|
||
|
|
int n = 0;
|
||
|
|
if (n < maxResult)
|
||
|
|
{
|
||
|
|
@@ -2490,10 +1846,6 @@ dtStatus dtNavMeshQuery::findPolysAroundCircle(dtPolyRef startRef, const float*
|
||
|
|
resultCost[n] = 0;
|
||
|
|
++n;
|
||
|
|
}
|
||
|
|
- else
|
||
|
|
- {
|
||
|
|
- status |= DT_BUFFER_TOO_SMALL;
|
||
|
|
- }
|
||
|
|
|
||
|
|
const float radiusSqr = dtSqr(radius);
|
||
|
|
|
||
|
|
@@ -2549,10 +1901,7 @@ dtStatus dtNavMeshQuery::findPolysAroundCircle(dtPolyRef startRef, const float*
|
||
|
|
|
||
|
|
dtNode* neighbourNode = m_nodePool->getNode(neighbourRef);
|
||
|
|
if (!neighbourNode)
|
||
|
|
- {
|
||
|
|
- status |= DT_OUT_OF_NODES;
|
||
|
|
continue;
|
||
|
|
- }
|
||
|
|
|
||
|
|
if (neighbourNode->flags & DT_NODE_CLOSED)
|
||
|
|
continue;
|
||
|
|
@@ -2568,7 +1917,7 @@ dtStatus dtNavMeshQuery::findPolysAroundCircle(dtPolyRef startRef, const float*
|
||
|
|
continue;
|
||
|
|
|
||
|
|
neighbourNode->id = neighbourRef;
|
||
|
|
- neighbourNode->flags = (neighbourNode->flags & ~DT_NODE_CLOSED);
|
||
|
|
+ neighbourNode->flags &= ~DT_NODE_CLOSED;
|
||
|
|
neighbourNode->pidx = m_nodePool->getNodeIdx(bestNode);
|
||
|
|
neighbourNode->total = total;
|
||
|
|
|
||
|
|
@@ -2588,10 +1937,6 @@ dtStatus dtNavMeshQuery::findPolysAroundCircle(dtPolyRef startRef, const float*
|
||
|
|
resultCost[n] = neighbourNode->total;
|
||
|
|
++n;
|
||
|
|
}
|
||
|
|
- else
|
||
|
|
- {
|
||
|
|
- status |= DT_BUFFER_TOO_SMALL;
|
||
|
|
- }
|
||
|
|
neighbourNode->flags = DT_NODE_OPEN;
|
||
|
|
m_openList->push(neighbourNode);
|
||
|
|
}
|
||
|
|
@@ -2600,31 +1945,9 @@ dtStatus dtNavMeshQuery::findPolysAroundCircle(dtPolyRef startRef, const float*
|
||
|
|
|
||
|
|
*resultCount = n;
|
||
|
|
|
||
|
|
- return status;
|
||
|
|
+ return DT_SUCCESS;
|
||
|
|
}
|
||
|
|
|
||
|
|
-/// @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,
|
||
|
|
const dtQueryFilter* filter,
|
||
|
|
dtPolyRef* resultRef, dtPolyRef* resultParent, float* resultCost,
|
||
|
|
@@ -2637,8 +1960,8 @@ dtStatus dtNavMeshQuery::findPolysAroundShape(dtPolyRef startRef, const float* v
|
||
|
|
*resultCount = 0;
|
||
|
|
|
||
|
|
// Validate input
|
||
|
|
- if (!startRef || !m_nav->isValidPolyRef(startRef))
|
||
|
|
- return DT_FAILURE | DT_INVALID_PARAM;
|
||
|
|
+ if (!startRef) return DT_FAILURE;
|
||
|
|
+ if (!m_nav->isValidPolyRef(startRef)) return DT_FAILURE;
|
||
|
|
|
||
|
|
m_nodePool->clear();
|
||
|
|
m_openList->clear();
|
||
|
|
@@ -2657,8 +1980,6 @@ dtStatus dtNavMeshQuery::findPolysAroundShape(dtPolyRef startRef, const float* v
|
||
|
|
startNode->flags = DT_NODE_OPEN;
|
||
|
|
m_openList->push(startNode);
|
||
|
|
|
||
|
|
- dtStatus status = DT_SUCCESS;
|
||
|
|
-
|
||
|
|
int n = 0;
|
||
|
|
if (n < maxResult)
|
||
|
|
{
|
||
|
|
@@ -2670,10 +1991,6 @@ dtStatus dtNavMeshQuery::findPolysAroundShape(dtPolyRef startRef, const float* v
|
||
|
|
resultCost[n] = 0;
|
||
|
|
++n;
|
||
|
|
}
|
||
|
|
- else
|
||
|
|
- {
|
||
|
|
- status |= DT_BUFFER_TOO_SMALL;
|
||
|
|
- }
|
||
|
|
|
||
|
|
while (!m_openList->empty())
|
||
|
|
{
|
||
|
|
@@ -2729,10 +2046,7 @@ dtStatus dtNavMeshQuery::findPolysAroundShape(dtPolyRef startRef, const float* v
|
||
|
|
|
||
|
|
dtNode* neighbourNode = m_nodePool->getNode(neighbourRef);
|
||
|
|
if (!neighbourNode)
|
||
|
|
- {
|
||
|
|
- status |= DT_OUT_OF_NODES;
|
||
|
|
continue;
|
||
|
|
- }
|
||
|
|
|
||
|
|
if (neighbourNode->flags & DT_NODE_CLOSED)
|
||
|
|
continue;
|
||
|
|
@@ -2748,7 +2062,7 @@ dtStatus dtNavMeshQuery::findPolysAroundShape(dtPolyRef startRef, const float* v
|
||
|
|
continue;
|
||
|
|
|
||
|
|
neighbourNode->id = neighbourRef;
|
||
|
|
- neighbourNode->flags = (neighbourNode->flags & ~DT_NODE_CLOSED);
|
||
|
|
+ neighbourNode->flags &= ~DT_NODE_CLOSED;
|
||
|
|
neighbourNode->pidx = m_nodePool->getNodeIdx(bestNode);
|
||
|
|
neighbourNode->total = total;
|
||
|
|
|
||
|
|
@@ -2768,10 +2082,6 @@ dtStatus dtNavMeshQuery::findPolysAroundShape(dtPolyRef startRef, const float* v
|
||
|
|
resultCost[n] = neighbourNode->total;
|
||
|
|
++n;
|
||
|
|
}
|
||
|
|
- else
|
||
|
|
- {
|
||
|
|
- status |= DT_BUFFER_TOO_SMALL;
|
||
|
|
- }
|
||
|
|
neighbourNode->flags = DT_NODE_OPEN;
|
||
|
|
m_openList->push(neighbourNode);
|
||
|
|
}
|
||
|
|
@@ -2780,31 +2090,9 @@ dtStatus dtNavMeshQuery::findPolysAroundShape(dtPolyRef startRef, const float* v
|
||
|
|
|
||
|
|
*resultCount = n;
|
||
|
|
|
||
|
|
- return status;
|
||
|
|
+ return DT_SUCCESS;
|
||
|
|
}
|
||
|
|
|
||
|
|
-/// @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,
|
||
|
|
const dtQueryFilter* filter,
|
||
|
|
dtPolyRef* resultRef, dtPolyRef* resultParent,
|
||
|
|
@@ -2816,8 +2104,8 @@ dtStatus dtNavMeshQuery::findLocalNeighbourhood(dtPolyRef startRef, const float*
|
||
|
|
*resultCount = 0;
|
||
|
|
|
||
|
|
// Validate input
|
||
|
|
- if (!startRef || !m_nav->isValidPolyRef(startRef))
|
||
|
|
- return DT_FAILURE | DT_INVALID_PARAM;
|
||
|
|
+ if (!startRef) return DT_FAILURE;
|
||
|
|
+ if (!m_nav->isValidPolyRef(startRef)) return DT_FAILURE;
|
||
|
|
|
||
|
|
static const int MAX_STACK = 48;
|
||
|
|
dtNode* stack[MAX_STACK];
|
||
|
|
@@ -2836,8 +2124,6 @@ dtStatus dtNavMeshQuery::findLocalNeighbourhood(dtPolyRef startRef, const float*
|
||
|
|
float pa[DT_VERTS_PER_POLYGON*3];
|
||
|
|
float pb[DT_VERTS_PER_POLYGON*3];
|
||
|
|
|
||
|
|
- dtStatus status = DT_SUCCESS;
|
||
|
|
-
|
||
|
|
int n = 0;
|
||
|
|
if (n < maxResult)
|
||
|
|
{
|
||
|
|
@@ -2846,10 +2132,6 @@ dtStatus dtNavMeshQuery::findLocalNeighbourhood(dtPolyRef startRef, const float*
|
||
|
|
resultParent[n] = 0;
|
||
|
|
++n;
|
||
|
|
}
|
||
|
|
- else
|
||
|
|
- {
|
||
|
|
- status |= DT_BUFFER_TOO_SMALL;
|
||
|
|
- }
|
||
|
|
|
||
|
|
while (nstack)
|
||
|
|
{
|
||
|
|
@@ -2963,10 +2245,6 @@ dtStatus dtNavMeshQuery::findLocalNeighbourhood(dtPolyRef startRef, const float*
|
||
|
|
resultParent[n] = curRef;
|
||
|
|
++n;
|
||
|
|
}
|
||
|
|
- else
|
||
|
|
- {
|
||
|
|
- status |= DT_BUFFER_TOO_SMALL;
|
||
|
|
- }
|
||
|
|
|
||
|
|
if (nstack < MAX_STACK)
|
||
|
|
{
|
||
|
|
@@ -2977,18 +2255,17 @@ dtStatus dtNavMeshQuery::findLocalNeighbourhood(dtPolyRef startRef, const float*
|
||
|
|
|
||
|
|
*resultCount = n;
|
||
|
|
|
||
|
|
- return status;
|
||
|
|
+ return DT_SUCCESS;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
struct dtSegInterval
|
||
|
|
{
|
||
|
|
- dtPolyRef ref;
|
||
|
|
short tmin, tmax;
|
||
|
|
};
|
||
|
|
|
||
|
|
static void insertInterval(dtSegInterval* ints, int& nints, const int maxInts,
|
||
|
|
- const short tmin, const short tmax, const dtPolyRef ref)
|
||
|
|
+ const short tmin, const short tmax)
|
||
|
|
{
|
||
|
|
if (nints+1 > maxInts) return;
|
||
|
|
// Find insertion point.
|
||
|
|
@@ -3003,26 +2280,13 @@ static void insertInterval(dtSegInterval* ints, int& nints, const int maxInts,
|
||
|
|
if (nints-idx)
|
||
|
|
memmove(ints+idx+1, ints+idx, sizeof(dtSegInterval)*(nints-idx));
|
||
|
|
// Store
|
||
|
|
- ints[idx].ref = ref;
|
||
|
|
ints[idx].tmin = tmin;
|
||
|
|
ints[idx].tmax = tmax;
|
||
|
|
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,
|
||
|
|
- float* segmentVerts, dtPolyRef* segmentRefs, int* segmentCount,
|
||
|
|
- const int maxSegments) const
|
||
|
|
+ float* segments, int* segmentCount, const int maxSegments) const
|
||
|
|
{
|
||
|
|
dtAssert(m_nav);
|
||
|
|
|
||
|
|
@@ -3030,18 +2294,14 @@ dtStatus dtNavMeshQuery::getPolyWallSegments(dtPolyRef ref, const dtQueryFilter*
|
||
|
|
|
||
|
|
const dtMeshTile* tile = 0;
|
||
|
|
const dtPoly* poly = 0;
|
||
|
|
- if (dtStatusFailed(m_nav->getTileAndPolyByRef(ref, &tile, &poly)))
|
||
|
|
- return DT_FAILURE | DT_INVALID_PARAM;
|
||
|
|
+ if (m_nav->getTileAndPolyByRef(ref, &tile, &poly) != DT_SUCCESS)
|
||
|
|
+ return DT_FAILURE;
|
||
|
|
|
||
|
|
int n = 0;
|
||
|
|
static const int MAX_INTERVAL = 16;
|
||
|
|
dtSegInterval ints[MAX_INTERVAL];
|
||
|
|
int nints;
|
||
|
|
|
||
|
|
- const bool storePortals = segmentRefs != 0;
|
||
|
|
-
|
||
|
|
- dtStatus status = DT_SUCCESS;
|
||
|
|
-
|
||
|
|
for (int i = 0, j = (int)poly->vertCount-1; i < (int)poly->vertCount; j = i++)
|
||
|
|
{
|
||
|
|
// Skip non-solid edges.
|
||
|
|
@@ -3061,95 +2321,54 @@ dtStatus dtNavMeshQuery::getPolyWallSegments(dtPolyRef ref, const dtQueryFilter*
|
||
|
|
m_nav->getTileAndPolyByRefUnsafe(link->ref, &neiTile, &neiPoly);
|
||
|
|
if (filter->passFilter(link->ref, neiTile, neiPoly))
|
||
|
|
{
|
||
|
|
- insertInterval(ints, nints, MAX_INTERVAL, link->bmin, link->bmax, link->ref);
|
||
|
|
+ insertInterval(ints, nints, MAX_INTERVAL, link->bmin, link->bmax);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
- else
|
||
|
|
+ else if (poly->neis[j])
|
||
|
|
{
|
||
|
|
// Internal edge
|
||
|
|
- dtPolyRef neiRef = 0;
|
||
|
|
- if (poly->neis[j])
|
||
|
|
- {
|
||
|
|
- const unsigned int idx = (unsigned int)(poly->neis[j]-1);
|
||
|
|
- neiRef = m_nav->getPolyRefBase(tile) | idx;
|
||
|
|
- if (!filter->passFilter(neiRef, tile, &tile->polys[idx]))
|
||
|
|
- neiRef = 0;
|
||
|
|
- }
|
||
|
|
-
|
||
|
|
- // If the edge leads to another polygon and portals are not stored, skip.
|
||
|
|
- if (neiRef != 0 && !storePortals)
|
||
|
|
+ const unsigned int idx = (unsigned int)(poly->neis[j]-1);
|
||
|
|
+ const dtPolyRef ref = m_nav->getPolyRefBase(tile) | idx;
|
||
|
|
+ if (filter->passFilter(ref, tile, &tile->polys[idx]))
|
||
|
|
continue;
|
||
|
|
-
|
||
|
|
- if (n < maxSegments)
|
||
|
|
- {
|
||
|
|
- const float* vj = &tile->verts[poly->verts[j]*3];
|
||
|
|
- const float* vi = &tile->verts[poly->verts[i]*3];
|
||
|
|
- float* seg = &segmentVerts[n*6];
|
||
|
|
- dtVcopy(seg+0, vj);
|
||
|
|
- dtVcopy(seg+3, vi);
|
||
|
|
- if (segmentRefs)
|
||
|
|
- segmentRefs[n] = neiRef;
|
||
|
|
- n++;
|
||
|
|
- }
|
||
|
|
- else
|
||
|
|
- {
|
||
|
|
- status |= DT_BUFFER_TOO_SMALL;
|
||
|
|
- }
|
||
|
|
-
|
||
|
|
- continue;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Add sentinels
|
||
|
|
- insertInterval(ints, nints, MAX_INTERVAL, -1, 0, 0);
|
||
|
|
- insertInterval(ints, nints, MAX_INTERVAL, 255, 256, 0);
|
||
|
|
+ insertInterval(ints, nints, MAX_INTERVAL, -1, 0);
|
||
|
|
+ insertInterval(ints, nints, MAX_INTERVAL, 255, 256);
|
||
|
|
|
||
|
|
- // Store segments.
|
||
|
|
+ // Store segment.
|
||
|
|
const float* vj = &tile->verts[poly->verts[j]*3];
|
||
|
|
const float* vi = &tile->verts[poly->verts[i]*3];
|
||
|
|
for (int k = 1; k < nints; ++k)
|
||
|
|
{
|
||
|
|
- // Portal segment.
|
||
|
|
- if (storePortals && ints[k].ref)
|
||
|
|
+ // Find the space inbetween the opening areas.
|
||
|
|
+ const int imin = ints[k-1].tmax;
|
||
|
|
+ const int imax = ints[k].tmin;
|
||
|
|
+ if (imin == imax) continue;
|
||
|
|
+ if (imin == 0 && imax == 255)
|
||
|
|
{
|
||
|
|
- const float tmin = ints[k].tmin/255.0f;
|
||
|
|
- const float tmax = ints[k].tmax/255.0f;
|
||
|
|
if (n < maxSegments)
|
||
|
|
{
|
||
|
|
- float* seg = &segmentVerts[n*6];
|
||
|
|
- dtVlerp(seg+0, vj,vi, tmin);
|
||
|
|
- dtVlerp(seg+3, vj,vi, tmax);
|
||
|
|
- if (segmentRefs)
|
||
|
|
- segmentRefs[n] = ints[k].ref;
|
||
|
|
+ float* seg = &segments[n*6];
|
||
|
|
n++;
|
||
|
|
- }
|
||
|
|
- else
|
||
|
|
- {
|
||
|
|
- status |= DT_BUFFER_TOO_SMALL;
|
||
|
|
+ dtVcopy(seg+0, vj);
|
||
|
|
+ dtVcopy(seg+3, vi);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
-
|
||
|
|
- // Wall segment.
|
||
|
|
- const int imin = ints[k-1].tmax;
|
||
|
|
- const int imax = ints[k].tmin;
|
||
|
|
- if (imin != imax)
|
||
|
|
+ else
|
||
|
|
{
|
||
|
|
const float tmin = imin/255.0f;
|
||
|
|
const float tmax = imax/255.0f;
|
||
|
|
if (n < maxSegments)
|
||
|
|
{
|
||
|
|
- float* seg = &segmentVerts[n*6];
|
||
|
|
+ float* seg = &segments[n*6];
|
||
|
|
+ n++;
|
||
|
|
dtVlerp(seg+0, vj,vi, tmin);
|
||
|
|
dtVlerp(seg+3, vj,vi, tmax);
|
||
|
|
- if (segmentRefs)
|
||
|
|
- segmentRefs[n] = 0;
|
||
|
|
- n++;
|
||
|
|
- }
|
||
|
|
- else
|
||
|
|
- {
|
||
|
|
- status |= DT_BUFFER_TOO_SMALL;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
@@ -3157,19 +2376,9 @@ dtStatus dtNavMeshQuery::getPolyWallSegments(dtPolyRef ref, const dtQueryFilter*
|
||
|
|
|
||
|
|
*segmentCount = n;
|
||
|
|
|
||
|
|
- return status;
|
||
|
|
+ return DT_SUCCESS;
|
||
|
|
}
|
||
|
|
|
||
|
|
-/// @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,
|
||
|
|
const dtQueryFilter* filter,
|
||
|
|
float* hitDist, float* hitPos, float* hitNormal) const
|
||
|
|
@@ -3179,8 +2388,8 @@ dtStatus dtNavMeshQuery::findDistanceToWall(dtPolyRef startRef, const float* cen
|
||
|
|
dtAssert(m_openList);
|
||
|
|
|
||
|
|
// Validate input
|
||
|
|
- if (!startRef || !m_nav->isValidPolyRef(startRef))
|
||
|
|
- return DT_FAILURE | DT_INVALID_PARAM;
|
||
|
|
+ if (!startRef) return DT_FAILURE;
|
||
|
|
+ if (!m_nav->isValidPolyRef(startRef)) return DT_FAILURE;
|
||
|
|
|
||
|
|
m_nodePool->clear();
|
||
|
|
m_openList->clear();
|
||
|
|
@@ -3196,8 +2405,6 @@ dtStatus dtNavMeshQuery::findDistanceToWall(dtPolyRef startRef, const float* cen
|
||
|
|
|
||
|
|
float radiusSqr = dtSqr(maxRadius);
|
||
|
|
|
||
|
|
- dtStatus status = DT_SUCCESS;
|
||
|
|
-
|
||
|
|
while (!m_openList->empty())
|
||
|
|
{
|
||
|
|
dtNode* bestNode = m_openList->pop();
|
||
|
|
@@ -3305,10 +2512,7 @@ dtStatus dtNavMeshQuery::findDistanceToWall(dtPolyRef startRef, const float* cen
|
||
|
|
|
||
|
|
dtNode* neighbourNode = m_nodePool->getNode(neighbourRef);
|
||
|
|
if (!neighbourNode)
|
||
|
|
- {
|
||
|
|
- status |= DT_OUT_OF_NODES;
|
||
|
|
continue;
|
||
|
|
- }
|
||
|
|
|
||
|
|
if (neighbourNode->flags & DT_NODE_CLOSED)
|
||
|
|
continue;
|
||
|
|
@@ -3327,7 +2531,7 @@ dtStatus dtNavMeshQuery::findDistanceToWall(dtPolyRef startRef, const float* cen
|
||
|
|
continue;
|
||
|
|
|
||
|
|
neighbourNode->id = neighbourRef;
|
||
|
|
- neighbourNode->flags = (neighbourNode->flags & ~DT_NODE_CLOSED);
|
||
|
|
+ neighbourNode->flags &= ~DT_NODE_CLOSED;
|
||
|
|
neighbourNode->pidx = m_nodePool->getNodeIdx(bestNode);
|
||
|
|
neighbourNode->total = total;
|
||
|
|
|
||
|
|
@@ -3347,30 +2551,11 @@ dtStatus dtNavMeshQuery::findDistanceToWall(dtPolyRef startRef, const float* cen
|
||
|
|
dtVsub(hitNormal, centerPos, hitPos);
|
||
|
|
dtVnormalize(hitNormal);
|
||
|
|
|
||
|
|
- *hitDist = dtSqrt(radiusSqr);
|
||
|
|
+ *hitDist = sqrtf(radiusSqr);
|
||
|
|
|
||
|
|
- return status;
|
||
|
|
-}
|
||
|
|
-
|
||
|
|
-bool dtNavMeshQuery::isValidPolyRef(dtPolyRef ref, const dtQueryFilter* filter) const
|
||
|
|
-{
|
||
|
|
- const dtMeshTile* tile = 0;
|
||
|
|
- const dtPoly* poly = 0;
|
||
|
|
- dtStatus status = m_nav->getTileAndPolyByRef(ref, &tile, &poly);
|
||
|
|
- // If cannot get polygon, assume it does not exists and boundary is invalid.
|
||
|
|
- if (dtStatusFailed(status))
|
||
|
|
- return false;
|
||
|
|
- // If cannot pass filter, assume flags has changed and boundary is invalid.
|
||
|
|
- if (!filter->passFilter(ref, tile, poly))
|
||
|
|
- return false;
|
||
|
|
- return true;
|
||
|
|
+ return DT_SUCCESS;
|
||
|
|
}
|
||
|
|
|
||
|
|
-/// @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
|
||
|
|
{
|
||
|
|
if (!m_nodePool) return false;
|
||
|
|
diff --git a/dep/recastnavigation/Detour/DetourNavMeshQuery.h b/dep/recastnavigation/Detour/DetourNavMeshQuery.h
|
||
|
|
index d431bf1..f5046d8 100644
|
||
|
|
--- a/dep/recastnavigation/Detour/DetourNavMeshQuery.h
|
||
|
|
+++ b/dep/recastnavigation/Detour/DetourNavMeshQuery.h
|
||
|
|
@@ -20,31 +20,39 @@
|
||
|
|
#define DETOURNAVMESHQUERY_H
|
||
|
|
|
||
|
|
#include "DetourNavMesh.h"
|
||
|
|
-#include "DetourStatus.h"
|
||
|
|
|
||
|
|
|
||
|
|
// 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
|
||
|
|
-// setting is to use non-virtual functions, the actual implementations of the functions
|
||
|
|
+// setting is to use non-virtual functions, the actualy implementations of the functions
|
||
|
|
// are declared as inline for maximum speed.
|
||
|
|
|
||
|
|
//#define DT_VIRTUAL_QUERYFILTER 1
|
||
|
|
|
||
|
|
-/// Defines polygon filtering and traversal costs for navigation mesh query operations.
|
||
|
|
-/// @ingroup detour
|
||
|
|
+// Class for polygon filtering and cost calculation during query operations.
|
||
|
|
+// - It is possible to derive a custom query filter from dtQueryFilter by overriding
|
||
|
|
+// 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
|
||
|
|
{
|
||
|
|
- float m_areaCost[DT_MAX_AREAS]; ///< Cost per area type. (Used by default implementation.)
|
||
|
|
- unsigned short m_includeFlags; ///< Flags for polygons that can be visited. (Used by default implementation.)
|
||
|
|
- unsigned short m_excludeFlags; ///< Flags for polygons that should not be visted. (Used by default implementation.)
|
||
|
|
+ float m_areaCost[DT_MAX_AREAS]; // Array storing cost per area type, used by default implementation.
|
||
|
|
+ unsigned short m_includeFlags; // Include poly flags, used by default implementation.
|
||
|
|
+ unsigned short m_excludeFlags; // Exclude poly flags, used by default implementation.
|
||
|
|
|
||
|
|
public:
|
||
|
|
dtQueryFilter();
|
||
|
|
|
||
|
|
- /// 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.
|
||
|
|
- /// @param[in] poly The polygon to test.
|
||
|
|
+ // Returns true if the polygon is can visited.
|
||
|
|
+ // Params:
|
||
|
|
+ // ref - (in) reference to the polygon test.
|
||
|
|
+ // tile - (in) pointer to the tile of the polygon test.
|
||
|
|
+ // poly - (in) pointer to the polygon test.
|
||
|
|
#ifdef DT_VIRTUAL_QUERYFILTER
|
||
|
|
virtual bool passFilter(const dtPolyRef ref,
|
||
|
|
const dtMeshTile* tile,
|
||
|
|
@@ -55,19 +63,16 @@ public:
|
||
|
|
const dtPoly* poly) const;
|
||
|
|
#endif
|
||
|
|
|
||
|
|
- /// Returns cost to move from the beginning to the end of a line segment
|
||
|
|
- /// that is fully contained within a polygon.
|
||
|
|
- /// @param[in] pa The start position on the edge of the previous and current polygon. [(x, y, z)]
|
||
|
|
- /// @param[in] pb The end position on the edge of the current and next polygon. [(x, y, z)]
|
||
|
|
- /// @param[in] prevRef The reference id of the previous polygon. [opt]
|
||
|
|
- /// @param[in] prevTile The tile containing the previous polygon. [opt]
|
||
|
|
- /// @param[in] prevPoly The previous polygon. [opt]
|
||
|
|
- /// @param[in] curRef The reference id of the current polygon.
|
||
|
|
- /// @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]
|
||
|
|
+ // Returns cost to travel from 'pa' to 'pb'.'
|
||
|
|
+ // The segment is fully contained inside 'cur'.
|
||
|
|
+ // 'pa' lies on the edge between 'prev' and 'cur',
|
||
|
|
+ // 'pb' lies on the edge between 'cur' and 'next'.
|
||
|
|
+ // Params:
|
||
|
|
+ // pa - (in) segment start position.
|
||
|
|
+ // pb - (in) segment end position.
|
||
|
|
+ // prevRef, prevTile, prevPoly - (in) data describing the previous polygon, can be null.
|
||
|
|
+ // curRef, curTile, curPoly - (in) data describing the current polygon.
|
||
|
|
+ // nextRef, nextTile, nextPoly - (in) data describing the next polygon, can be null.
|
||
|
|
#ifdef DT_VIRTUAL_QUERYFILTER
|
||
|
|
virtual float getCost(const float* pa, const float* pb,
|
||
|
|
const dtPolyRef prevRef, const dtMeshTile* prevTile, const dtPoly* prevPoly,
|
||
|
|
@@ -79,385 +84,305 @@ public:
|
||
|
|
const dtPolyRef curRef, const dtMeshTile* curTile, const dtPoly* curPoly,
|
||
|
|
const dtPolyRef nextRef, const dtMeshTile* nextTile, const dtPoly* nextPoly) const;
|
||
|
|
#endif
|
||
|
|
-
|
||
|
|
- /// @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.
|
||
|
|
+
|
||
|
|
+ // Getters and setters for the default implementation data.
|
||
|
|
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; }
|
||
|
|
|
||
|
|
- /// 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; }
|
||
|
|
-
|
||
|
|
- /// Sets the include flags for the filter.
|
||
|
|
- /// @param[in] flags The new 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; }
|
||
|
|
-
|
||
|
|
- /// Sets the exclude flags for the filter.
|
||
|
|
- /// @param[in] flags The new 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
|
||
|
|
{
|
||
|
|
public:
|
||
|
|
dtNavMeshQuery();
|
||
|
|
~dtNavMeshQuery();
|
||
|
|
|
||
|
|
- /// 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]
|
||
|
|
- /// @returns The status flags for the query.
|
||
|
|
+ // Initializes the nav mesh query.
|
||
|
|
+ // Params:
|
||
|
|
+ // nav - (in) pointer to navigation mesh data.
|
||
|
|
+ // maxNodes - (in) Maximum number of search nodes to use (max 65536).
|
||
|
|
+ // Returns: True if succeed, else false.
|
||
|
|
dtStatus init(const dtNavMesh* nav, const int maxNodes);
|
||
|
|
|
||
|
|
- /// @name Standard Pathfinding Functions
|
||
|
|
- // /@{
|
||
|
|
-
|
||
|
|
- /// Finds a path from the start polygon to the end polygon.
|
||
|
|
- /// @param[in] startRef The refrence id of the start polygon.
|
||
|
|
- /// @param[in] endRef The reference id of the end polygon.
|
||
|
|
- /// @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[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 maximum number of polygons the @p path array can hold. [Limit: >= 1]
|
||
|
|
+ // Finds the nearest navigation polygon around the center location.
|
||
|
|
+ // Params:
|
||
|
|
+ // center[3] - (in) The center of the search box.
|
||
|
|
+ // extents[3] - (in) The extents of the search box.
|
||
|
|
+ // filter - (in) path polygon filter.
|
||
|
|
+ // nearestRef - (out) Reference to the nearest polygon.
|
||
|
|
+ // nearestPt[3] - (out, opt) The nearest point on found polygon, null if not needed.
|
||
|
|
+ // Returns: Reference identifier for the polygon, or 0 if no polygons found.
|
||
|
|
+ dtStatus findNearestPoly(const float* center, const float* extents,
|
||
|
|
+ const dtQueryFilter* filter,
|
||
|
|
+ dtPolyRef* nearestRef, float* nearestPt) const;
|
||
|
|
+
|
||
|
|
+ // Returns polygons which overlap the query box.
|
||
|
|
+ // Params:
|
||
|
|
+ // center[3] - (in) the center of the search box.
|
||
|
|
+ // extents[3] - (in) the extents of the search box.
|
||
|
|
+ // filter - (in) path polygon filter.
|
||
|
|
+ // polys - (out) array holding the search result.
|
||
|
|
+ // polyCount - (out) Number of polygons in search result array.
|
||
|
|
+ // maxPolys - (in) The max number of polygons the polys array can hold.
|
||
|
|
+ dtStatus queryPolygons(const float* center, const float* extents,
|
||
|
|
+ const dtQueryFilter* filter,
|
||
|
|
+ dtPolyRef* polys, int* polyCount, const int maxPolys) const;
|
||
|
|
+
|
||
|
|
+ // 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.
|
||
|
|
+ // Params:
|
||
|
|
+ // startRef - (in) ref to path start polygon.
|
||
|
|
+ // endRef - (in) ref to path end polygon.
|
||
|
|
+ // startPos[3] - (in) Path start location.
|
||
|
|
+ // endPos[3] - (in) Path end location.
|
||
|
|
+ // filter - (in) path polygon filter.
|
||
|
|
+ // path - (out) array holding the search result.
|
||
|
|
+ // pathCount - (out) Number of polygons in search result array.
|
||
|
|
+ // maxPath - (in) The max number of polygons the path array can hold. Must be at least 1.
|
||
|
|
dtStatus findPath(dtPolyRef startRef, dtPolyRef endRef,
|
||
|
|
const float* startPos, const float* endPos,
|
||
|
|
const dtQueryFilter* filter,
|
||
|
|
dtPolyRef* path, int* pathCount, const int maxPath) const;
|
||
|
|
|
||
|
|
- /// Finds the straight path from the start to the end position within the polygon corridor.
|
||
|
|
- /// @param[in] startPos Path start position. [(x, y, z)]
|
||
|
|
- /// @param[in] endPos Path end position. [(x, y, z)]
|
||
|
|
- /// @param[in] path An array of polygon references that represent the path corridor.
|
||
|
|
- /// @param[in] pathSize The number of polygons in the @p path array.
|
||
|
|
- /// @param[out] straightPath Points describing the straight path. [(x, y, z) * @p straightPathCount].
|
||
|
|
- /// @param[out] straightPathFlags Flags describing each point. (See: #dtStraightPathFlags) [opt]
|
||
|
|
- /// @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 options = 0) const;
|
||
|
|
-
|
||
|
|
- ///@}
|
||
|
|
- /// @name Sliced Pathfinding Functions
|
||
|
|
- /// Common use case:
|
||
|
|
- /// -# Call initSlicedFindPath() to initialize the sliced path query.
|
||
|
|
- /// -# Call updateSlicedFindPath() until it returns complete.
|
||
|
|
- /// -# Call finalizeSlicedFindPath() to get the path.
|
||
|
|
- ///@{
|
||
|
|
-
|
||
|
|
- /// Intializes a sliced path query.
|
||
|
|
- /// @param[in] startRef The refrence id of the start polygon.
|
||
|
|
- /// @param[in] endRef The reference id of the end polygon.
|
||
|
|
- /// @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.
|
||
|
|
- /// @returns The status flags for the query.
|
||
|
|
+ // Intializes sliced path find query.
|
||
|
|
+ // Note 1: calling any other dtNavMeshQuery method before calling findPathEnd()
|
||
|
|
+ // may results in corrupted data!
|
||
|
|
+ // Note 2: The pointer to filter is store, and used in subsequent
|
||
|
|
+ // calls to updateSlicedFindPath().
|
||
|
|
+ // Params:
|
||
|
|
+ // startRef - (in) ref to path start polygon.
|
||
|
|
+ // endRef - (in) ref to path end polygon.
|
||
|
|
+ // startPos[3] - (in) Path start location.
|
||
|
|
+ // endPos[3] - (in) Path end location.
|
||
|
|
+ // filter - (in) path polygon filter.
|
||
|
|
dtStatus initSlicedFindPath(dtPolyRef startRef, dtPolyRef endRef,
|
||
|
|
const float* startPos, const float* endPos,
|
||
|
|
const dtQueryFilter* filter);
|
||
|
|
|
||
|
|
- /// Updates an in-progress sliced path query.
|
||
|
|
- /// @param[in] maxIter The maximum number of iterations to perform.
|
||
|
|
- /// @param[out] doneIters The actual number of iterations completed. [opt]
|
||
|
|
- /// @returns The status flags for the query.
|
||
|
|
- dtStatus updateSlicedFindPath(const int maxIter, int* doneIters);
|
||
|
|
+ // Updates sliced path find query.
|
||
|
|
+ // Params:
|
||
|
|
+ // maxIter - (in) max number of iterations to update.
|
||
|
|
+ // Returns: Path query state.
|
||
|
|
+ dtStatus updateSlicedFindPath(const int maxIter);
|
||
|
|
|
||
|
|
- /// Finalizes and returns the results of a sliced path query.
|
||
|
|
- /// @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 path array can hold. [Limit: >= 1]
|
||
|
|
- /// @returns The status flags for the query.
|
||
|
|
+ // Finalizes sliced path find query and returns found path.
|
||
|
|
+ // path - (out) array holding the search result.
|
||
|
|
+ // pathCount - (out) Number of polygons in search result array.
|
||
|
|
+ // maxPath - (in) The max number of polygons the path array can hold.
|
||
|
|
dtStatus finalizeSlicedFindPath(dtPolyRef* path, int* pathCount, const int maxPath);
|
||
|
|
|
||
|
|
- /// 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[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.
|
||
|
|
+ // Finalizes partial sliced path find query and returns path to the furthest
|
||
|
|
+ // polygon on the existing path that was visited during the search.
|
||
|
|
+ // existing - (out) Array of polygons in the existing path.
|
||
|
|
+ // existingSize - (out) Number of polygons in existing path array.
|
||
|
|
+ // path - (out) array holding the search result.
|
||
|
|
+ // pathCount - (out) Number of polygons in search result array.
|
||
|
|
+ // 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);
|
||
|
|
-
|
||
|
|
- ///@}
|
||
|
|
- /// @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.
|
||
|
|
+
|
||
|
|
+ // 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.
|
||
|
|
+ // Params:
|
||
|
|
+ // startPos[3] - (in) Path start location.
|
||
|
|
+ // endPo[3] - (in) Path end location.
|
||
|
|
+ // path - (in) Array of connected polygons describing the corridor.
|
||
|
|
+ // pathSize - (in) Number of polygons in path array.
|
||
|
|
+ // straightPath - (out) Points describing the straight path.
|
||
|
|
+ // straightPathFlags - (out, opt) Flags describing each point type, see dtStraightPathFlags.
|
||
|
|
+ // straightPathRefs - (out, opt) References to polygons at point locations.
|
||
|
|
+ // straightPathCount - (out) Number of points in the path.
|
||
|
|
+ // 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,
|
||
|
|
+ const dtPolyRef* path, const int pathSize,
|
||
|
|
+ float* straightPath, unsigned char* straightPathFlags, dtPolyRef* straightPathRefs,
|
||
|
|
+ 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,
|
||
|
|
+ // or else the resultPos will be the nearest point in navmesh.
|
||
|
|
+ // Note: The resulting point is not projected to the ground, use getPolyHeight() to get height.
|
||
|
|
+ // Note: The algorithm is optimized for small delta movement and small number of polygons.
|
||
|
|
+ // Params:
|
||
|
|
+ // startRef - (in) ref to the polygon where startPos lies.
|
||
|
|
+ // startPos[3] - (in) start position of the mover.
|
||
|
|
+ // endPos[3] - (in) desired end position of the mover.
|
||
|
|
+ // filter - (in) path polygon filter.
|
||
|
|
+ // resultPos[3] - (out) new position of the mover.
|
||
|
|
+ // visited - (out) array of visited polygons.
|
||
|
|
+ // visitedCount - (out) Number of entries in the visited array.
|
||
|
|
+ // 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.
|
||
|
|
+ // Params:
|
||
|
|
+ // startRef - (in) ref to the polygon where the start lies.
|
||
|
|
+ // startPos[3] - (in) start position of the query.
|
||
|
|
+ // endPos[3] - (in) end position of the query.
|
||
|
|
+ // t - (out) hit parameter along the segment, FLT_MAX if no hit.
|
||
|
|
+ // hitNormal[3] - (out) normal of the nearest hit.
|
||
|
|
+ // filter - (in) path polygon filter.
|
||
|
|
+ // path - (out,opt) visited path polygons.
|
||
|
|
+ // pathCount - (out,opt) Number of polygons visited.
|
||
|
|
+ // maxPath - (in) max number of polygons in the path array.
|
||
|
|
+ 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.
|
||
|
|
+ // Params:
|
||
|
|
+ // startRef - (in) ref to the polygon where the center lies.
|
||
|
|
+ // centerPos[3] - (in) center if the query circle.
|
||
|
|
+ // maxRadius - (in) max search radius.
|
||
|
|
+ // filter - (in) path polygon filter.
|
||
|
|
+ // hitDist - (out) distance to nearest wall from the test location.
|
||
|
|
+ // hitPos[3] - (out) location of the nearest hit.
|
||
|
|
+ // 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.
|
||
|
|
+ // Params:
|
||
|
|
+ // startRef - (in) ref to the polygon where the search starts.
|
||
|
|
+ // centerPos[3] - (in) center if the query circle.
|
||
|
|
+ // radius - (in) radius of the query circle.
|
||
|
|
+ // filter - (in) path polygon filter.
|
||
|
|
+ // resultRef - (out, opt) refs to the polygons touched by the circle.
|
||
|
|
+ // resultParent - (out, opt) parent of each result polygon.
|
||
|
|
+ // resultCost - (out, opt) search cost at each result polygon.
|
||
|
|
+ // resultCount - (out, opt) Number of results.
|
||
|
|
+ // maxResult - (int) maximum capacity of search results.
|
||
|
|
dtStatus findPolysAroundCircle(dtPolyRef startRef, const float* centerPos, const float radius,
|
||
|
|
const dtQueryFilter* filter,
|
||
|
|
dtPolyRef* resultRef, dtPolyRef* resultParent, float* resultCost,
|
||
|
|
int* resultCount, const int maxResult) const;
|
||
|
|
|
||
|
|
- /// Finds the polygons along the naviation graph that touch the specified convex polygon.
|
||
|
|
- /// @param[in] startRef The reference id of the polygon where the search starts.
|
||
|
|
- /// @param[in] verts The vertices describing the convex polygon. (CCW)
|
||
|
|
- /// [(x, y, z) * @p nverts]
|
||
|
|
- /// @param[in] nverts The number of vertices in the polygon.
|
||
|
|
- /// @param[in] filter The polygon filter to apply to the query.
|
||
|
|
- /// @param[out] resultRef The reference ids of the polygons touched by the search polygon. [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 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.
|
||
|
|
+ // Finds polygons found along the navigation graph which touch the convex polygon shape.
|
||
|
|
+ // Params:
|
||
|
|
+ // startRef - (in) ref to the polygon where the search starts.
|
||
|
|
+ // verts[3*n] - (in) vertices describing convex polygon shape (CCW).
|
||
|
|
+ // nverts - (in) number of vertices in the polygon.
|
||
|
|
+ // filter - (in) path polygon filter.
|
||
|
|
+ // resultRef - (out, opt) refs to the polygons touched by the circle.
|
||
|
|
+ // resultParent - (out, opt) parent of each result polygon.
|
||
|
|
+ // resultCost - (out, opt) search cost at each result polygon.
|
||
|
|
+ // resultCount - (out) number of results.
|
||
|
|
+ // maxResult - (int) maximum capacity of search results.
|
||
|
|
dtStatus findPolysAroundShape(dtPolyRef startRef, const float* verts, const int nverts,
|
||
|
|
const dtQueryFilter* filter,
|
||
|
|
dtPolyRef* resultRef, dtPolyRef* resultParent, float* resultCost,
|
||
|
|
int* resultCount, const int maxResult) const;
|
||
|
|
|
||
|
|
- /// @}
|
||
|
|
- /// @name Local Query Functions
|
||
|
|
- ///@{
|
||
|
|
-
|
||
|
|
- /// Finds the polygon nearest to the specified center point.
|
||
|
|
- /// @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] nearestRef The reference id of the nearest polygon.
|
||
|
|
- /// @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.
|
||
|
|
+ // Finds non-overlapping local neighbourhood around center location.
|
||
|
|
+ // Note: The algorithm is optimized for small query radius and small number of polygons.
|
||
|
|
+ // Params:
|
||
|
|
+ // startRef - (in) ref to the polygon where the search starts.
|
||
|
|
+ // centerPos[3] - (in) center if the query circle.
|
||
|
|
+ // radius - (in) radius of the query circle.
|
||
|
|
+ // filter - (in) path polygon filter.
|
||
|
|
+ // resultRef - (out) refs to the polygons touched by the circle.
|
||
|
|
+ // resultParent - (out, opt) parent of each result polygon.
|
||
|
|
+ // resultCount - (out) number of results.
|
||
|
|
+ // maxResult - (int) maximum capacity of search results.
|
||
|
|
dtStatus findLocalNeighbourhood(dtPolyRef startRef, const float* centerPos, const float radius,
|
||
|
|
const dtQueryFilter* filter,
|
||
|
|
dtPolyRef* resultRef, dtPolyRef* resultParent,
|
||
|
|
int* resultCount, const int maxResult) const;
|
||
|
|
-
|
||
|
|
- /// Moves from the start to the end position constrained to the navigation mesh.
|
||
|
|
- /// @param[in] startRef The reference id of the start polygon.
|
||
|
|
- /// @param[in] startPos A position of the mover within the start polygon. [(x, y, x)]
|
||
|
|
- /// @param[in] endPos The desired end position of the mover. [(x, y, z)]
|
||
|
|
- /// @param[in] filter The polygon filter to apply to the query.
|
||
|
|
- /// @param[out] resultPos The result position of the mover. [(x, y, z)]
|
||
|
|
- /// @param[out] visited The reference ids of the polygons visited during the move.
|
||
|
|
- /// @param[out] visitedCount The number of polygons visited during the move.
|
||
|
|
- /// @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.
|
||
|
|
+ // Returns wall segments of specified polygon.
|
||
|
|
+ // Params:
|
||
|
|
+ // ref - (in) ref to the polygon.
|
||
|
|
+ // filter - (in) path polygon filter.
|
||
|
|
+ // segments[6*maxSegments] - (out) wall segments (2 endpoints per segment).
|
||
|
|
+ // segmentCount - (out) number of wall segments.
|
||
|
|
+ // maxSegments - (in) max number of segments that can be stored in 'segments'.
|
||
|
|
dtStatus getPolyWallSegments(dtPolyRef ref, const dtQueryFilter* filter,
|
||
|
|
- float* segmentVerts, dtPolyRef* segmentRefs, int* segmentCount,
|
||
|
|
- const int maxSegments) const;
|
||
|
|
-
|
||
|
|
- /// Returns random location on navmesh.
|
||
|
|
- /// Polygons are chosen weighted by area. The search runs in linear related to number of polygon.
|
||
|
|
- /// @param[in] filter The polygon filter to apply to the query.
|
||
|
|
- /// @param[in] frand Function returning a random number [0..1).
|
||
|
|
- /// @param[out] randomRef The reference id of the random location.
|
||
|
|
- /// @param[out] randomPt The random location.
|
||
|
|
- /// @returns The status flags for the query.
|
||
|
|
- dtStatus findRandomPoint(const dtQueryFilter* filter, float (*frand)(),
|
||
|
|
- dtPolyRef* randomRef, float* randomPt) const;
|
||
|
|
-
|
||
|
|
- /// Returns random location on navmesh within the reach of specified location.
|
||
|
|
- /// Polygons are chosen weighted by area. The search runs in linear related to number of polygon.
|
||
|
|
- /// The location is not exactly constrained by the circle, but it limits the visited polygons.
|
||
|
|
- /// @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] filter The polygon filter to apply to the query.
|
||
|
|
- /// @param[in] frand Function returning a random number [0..1).
|
||
|
|
- /// @param[out] randomRef The reference id of the random location.
|
||
|
|
- /// @param[out] randomPt The random location. [(x, y, z)]
|
||
|
|
- /// @returns The status flags for the query.
|
||
|
|
- dtStatus findRandomPointAroundCircle(dtPolyRef startRef, const float* centerPos, const float maxRadius,
|
||
|
|
- const dtQueryFilter* filter, float (*frand)(),
|
||
|
|
- dtPolyRef* randomRef, float* randomPt) const;
|
||
|
|
+ float* segments, int* segmentCount, const int maxSegments) const;
|
||
|
|
|
||
|
|
- /// Finds the closest point on the specified polygon.
|
||
|
|
- /// @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)]
|
||
|
|
- /// @returns The status flags for the query.
|
||
|
|
+ // Returns closest point on navigation polygon.
|
||
|
|
+ // Uses detail polygons to find the closest point to the navigation polygon surface.
|
||
|
|
+ // Params:
|
||
|
|
+ // ref - (in) ref to the polygon.
|
||
|
|
+ // pos[3] - (in) the point to check.
|
||
|
|
+ // closest[3] - (out) closest point.
|
||
|
|
+ // Returns: true if closest point found.
|
||
|
|
dtStatus closestPointOnPoly(dtPolyRef ref, const float* pos, float* closest) const;
|
||
|
|
|
||
|
|
- /// Returns a point on the boundary closest to the source point if the source point is outside the
|
||
|
|
- /// polygon's xz-bounds.
|
||
|
|
- /// @param[in] ref The reference id to the polygon.
|
||
|
|
- /// @param[in] pos The position to check. [(x, y, z)]
|
||
|
|
- /// @param[out] closest The closest point. [(x, y, z)]
|
||
|
|
- /// @returns The status flags for the query.
|
||
|
|
+ // Returns closest point on navigation polygon boundary.
|
||
|
|
+ // Uses the navigation polygon boundary to snap the point to poly boundary
|
||
|
|
+ // if it is outside the polygon. Much faster than closestPointToPoly. Does not affect height.
|
||
|
|
+ // Params:
|
||
|
|
+ // ref - (in) ref to the polygon.
|
||
|
|
+ // pos[3] - (in) the point to check.
|
||
|
|
+ // closest[3] - (out) closest point.
|
||
|
|
+ // Returns: true if closest point found.
|
||
|
|
dtStatus closestPointOnPolyBoundary(dtPolyRef ref, const float* pos, float* closest) const;
|
||
|
|
|
||
|
|
- /// Gets the height of the polygon at the provided position using the height detail. (Most accurate.)
|
||
|
|
- /// @param[in] ref The reference id of the polygon.
|
||
|
|
- /// @param[in] pos A position within the xz-bounds of the polygon. [(x, y, z)]
|
||
|
|
- /// @param[out] height The height at the surface of the polygon.
|
||
|
|
- /// @returns The status flags for the query.
|
||
|
|
+ // Returns start and end location of an off-mesh link polygon.
|
||
|
|
+ // Params:
|
||
|
|
+ // prevRef - (in) ref to the polygon before the link (used to select direction).
|
||
|
|
+ // polyRef - (in) ref to the off-mesh link polygon.
|
||
|
|
+ // startPos[3] - (out) start point of the link.
|
||
|
|
+ // endPos[3] - (out) end point of the link.
|
||
|
|
+ // Returns: true if link is found.
|
||
|
|
+ dtStatus getOffMeshConnectionPolyEndPoints(dtPolyRef prevRef, dtPolyRef polyRef, float* startPos, float* endPos) const;
|
||
|
|
+
|
||
|
|
+ // Returns height of the polygon at specified location.
|
||
|
|
+ // Params:
|
||
|
|
+ // ref - (in) ref to the polygon.
|
||
|
|
+ // pos[3] - (in) the point where to locate the height.
|
||
|
|
+ // height - (out) height at the location.
|
||
|
|
+ // Returns: true if over polygon.
|
||
|
|
dtStatus getPolyHeight(dtPolyRef ref, const float* pos, float* height) const;
|
||
|
|
-
|
||
|
|
- /// @}
|
||
|
|
- /// @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;
|
||
|
|
-
|
||
|
|
- /// 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.
|
||
|
|
+
|
||
|
|
+ // Returns true if poly reference ins in closed list.
|
||
|
|
bool isInClosedList(dtPolyRef ref) const;
|
||
|
|
|
||
|
|
- /// Gets the node pool.
|
||
|
|
- /// @returns The node pool.
|
||
|
|
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; }
|
||
|
|
-
|
||
|
|
- /// @}
|
||
|
|
-
|
||
|
|
private:
|
||
|
|
|
||
|
|
- /// Returns neighbour tile based on side.
|
||
|
|
+ // Returns neighbour tile based on side.
|
||
|
|
dtMeshTile* getNeighbourTileAt(int x, int y, int side) const;
|
||
|
|
|
||
|
|
- /// Queries polygons within a tile.
|
||
|
|
+ // 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.
|
||
|
|
+ // 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 closest point on polygon.
|
||
|
|
+ dtStatus closestPointOnPolyInTile(const dtMeshTile* tile, const dtPoly* poly, const float* pos, float* closest) const;
|
||
|
|
|
||
|
|
- /// Returns portal points between two polygons.
|
||
|
|
+ // Returns portal points between two polygons.
|
||
|
|
dtStatus getPortalPoints(dtPolyRef from, dtPolyRef to, float* left, float* right,
|
||
|
|
unsigned char& fromType, unsigned char& toType) const;
|
||
|
|
dtStatus getPortalPoints(dtPolyRef from, const dtPoly* fromPoly, const dtMeshTile* fromTile,
|
||
|
|
dtPolyRef to, const dtPoly* toPoly, const dtMeshTile* toTile,
|
||
|
|
float* left, float* right) const;
|
||
|
|
|
||
|
|
- /// Returns edge mid point between two polygons.
|
||
|
|
+ // Returns edge mid point between two polygons.
|
||
|
|
dtStatus getEdgeMidPoint(dtPolyRef from, dtPolyRef to, float* mid) const;
|
||
|
|
dtStatus getEdgeMidPoint(dtPolyRef from, const dtPoly* fromPoly, const dtMeshTile* fromTile,
|
||
|
|
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.
|
||
|
|
+ const dtNavMesh* m_nav; // Pointer to navmesh data.
|
||
|
|
|
||
|
|
struct dtQueryData
|
||
|
|
{
|
||
|
|
@@ -468,21 +393,15 @@ private:
|
||
|
|
float startPos[3], endPos[3];
|
||
|
|
const dtQueryFilter* filter;
|
||
|
|
};
|
||
|
|
- dtQueryData m_query; ///< Sliced query state.
|
||
|
|
+ dtQueryData m_query; // Sliced query state.
|
||
|
|
|
||
|
|
- class dtNodePool* m_tinyNodePool; ///< Pointer to small node pool.
|
||
|
|
- class dtNodePool* m_nodePool; ///< Pointer to node pool.
|
||
|
|
- class dtNodeQueue* m_openList; ///< Pointer to open list queue.
|
||
|
|
+ class dtNodePool* m_tinyNodePool; // Pointer to small node pool.
|
||
|
|
+ class dtNodePool* m_nodePool; // Pointer to node pool.
|
||
|
|
+ class dtNodeQueue* m_openList; // Pointer to open list queue.
|
||
|
|
};
|
||
|
|
|
||
|
|
-/// Allocates a query object using the Detour allocator.
|
||
|
|
-/// @return An allocated query object, or null on failure.
|
||
|
|
-/// @ingroup detour
|
||
|
|
+// Helper function to allocate navmesh query class using Detour allocator.
|
||
|
|
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);
|
||
|
|
|
||
|
|
#endif // DETOURNAVMESHQUERY_H
|
||
|
|
diff --git a/dep/recastnavigation/Detour/DetourNode.cpp b/dep/recastnavigation/Detour/DetourNode.cpp
|
||
|
|
index 4c8215e..0d1af83 100644
|
||
|
|
--- a/dep/recastnavigation/Detour/DetourNode.cpp
|
||
|
|
+++ b/dep/recastnavigation/Detour/DetourNode.cpp
|
||
|
|
@@ -24,7 +24,6 @@
|
||
|
|
|
||
|
|
inline unsigned int dtHashRef(dtPolyRef a)
|
||
|
|
{
|
||
|
|
- // Edited by TC
|
||
|
|
a = (~a) + (a << 18);
|
||
|
|
a = a ^ (a >> 31);
|
||
|
|
a = a * 21;
|
||
|
|
@@ -47,15 +46,15 @@ dtNodePool::dtNodePool(int maxNodes, int hashSize) :
|
||
|
|
dtAssert(m_maxNodes > 0);
|
||
|
|
|
||
|
|
m_nodes = (dtNode*)dtAlloc(sizeof(dtNode)*m_maxNodes, DT_ALLOC_PERM);
|
||
|
|
- m_next = (dtNodeIndex*)dtAlloc(sizeof(dtNodeIndex)*m_maxNodes, DT_ALLOC_PERM);
|
||
|
|
- m_first = (dtNodeIndex*)dtAlloc(sizeof(dtNodeIndex)*hashSize, DT_ALLOC_PERM);
|
||
|
|
+ m_next = (unsigned short*)dtAlloc(sizeof(unsigned short)*m_maxNodes, DT_ALLOC_PERM);
|
||
|
|
+ m_first = (unsigned short*)dtAlloc(sizeof(unsigned short)*hashSize, DT_ALLOC_PERM);
|
||
|
|
|
||
|
|
dtAssert(m_nodes);
|
||
|
|
dtAssert(m_next);
|
||
|
|
dtAssert(m_first);
|
||
|
|
|
||
|
|
- memset(m_first, 0xff, sizeof(dtNodeIndex)*m_hashSize);
|
||
|
|
- memset(m_next, 0xff, sizeof(dtNodeIndex)*m_maxNodes);
|
||
|
|
+ memset(m_first, 0xff, sizeof(unsigned short)*m_hashSize);
|
||
|
|
+ memset(m_next, 0xff, sizeof(unsigned short)*m_maxNodes);
|
||
|
|
}
|
||
|
|
|
||
|
|
dtNodePool::~dtNodePool()
|
||
|
|
@@ -67,14 +66,14 @@ dtNodePool::~dtNodePool()
|
||
|
|
|
||
|
|
void dtNodePool::clear()
|
||
|
|
{
|
||
|
|
- memset(m_first, 0xff, sizeof(dtNodeIndex)*m_hashSize);
|
||
|
|
+ memset(m_first, 0xff, sizeof(unsigned short)*m_hashSize);
|
||
|
|
m_nodeCount = 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
dtNode* dtNodePool::findNode(dtPolyRef id)
|
||
|
|
{
|
||
|
|
unsigned int bucket = dtHashRef(id) & (m_hashSize-1);
|
||
|
|
- dtNodeIndex i = m_first[bucket];
|
||
|
|
+ unsigned short i = m_first[bucket];
|
||
|
|
while (i != DT_NULL_IDX)
|
||
|
|
{
|
||
|
|
if (m_nodes[i].id == id)
|
||
|
|
@@ -87,7 +86,7 @@ dtNode* dtNodePool::findNode(dtPolyRef id)
|
||
|
|
dtNode* dtNodePool::getNode(dtPolyRef id)
|
||
|
|
{
|
||
|
|
unsigned int bucket = dtHashRef(id) & (m_hashSize-1);
|
||
|
|
- dtNodeIndex i = m_first[bucket];
|
||
|
|
+ unsigned short i = m_first[bucket];
|
||
|
|
dtNode* node = 0;
|
||
|
|
while (i != DT_NULL_IDX)
|
||
|
|
{
|
||
|
|
@@ -99,7 +98,7 @@ dtNode* dtNodePool::getNode(dtPolyRef id)
|
||
|
|
if (m_nodeCount >= m_maxNodes)
|
||
|
|
return 0;
|
||
|
|
|
||
|
|
- i = (dtNodeIndex)m_nodeCount;
|
||
|
|
+ i = (unsigned short)m_nodeCount;
|
||
|
|
m_nodeCount++;
|
||
|
|
|
||
|
|
// Init node
|
||
|
|
diff --git a/dep/recastnavigation/Detour/DetourNode.h b/dep/recastnavigation/Detour/DetourNode.h
|
||
|
|
index b68c922..e893f78 100644
|
||
|
|
--- a/dep/recastnavigation/Detour/DetourNode.h
|
||
|
|
+++ b/dep/recastnavigation/Detour/DetourNode.h
|
||
|
|
@@ -27,20 +27,18 @@ enum dtNodeFlags
|
||
|
|
DT_NODE_CLOSED = 0x02,
|
||
|
|
};
|
||
|
|
|
||
|
|
-typedef unsigned short dtNodeIndex;
|
||
|
|
-static const dtNodeIndex DT_NULL_IDX = (dtNodeIndex)~0;
|
||
|
|
+static const unsigned short DT_NULL_IDX = 0xffff;
|
||
|
|
|
||
|
|
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 : 30; // Index to parent node.
|
||
|
|
+ unsigned int flags : 2; // Node flags 0/open/closed.
|
||
|
|
+ dtPolyRef id; // Polygon ref the node corresponds to.
|
||
|
|
};
|
||
|
|
|
||
|
|
-
|
||
|
|
class dtNodePool
|
||
|
|
{
|
||
|
|
public:
|
||
|
|
@@ -72,22 +70,22 @@ public:
|
||
|
|
inline int getMemUsed() const
|
||
|
|
{
|
||
|
|
return sizeof(*this) +
|
||
|
|
- sizeof(dtNode)*m_maxNodes +
|
||
|
|
- sizeof(dtNodeIndex)*m_maxNodes +
|
||
|
|
- sizeof(dtNodeIndex)*m_hashSize;
|
||
|
|
+ sizeof(dtNode)*m_maxNodes +
|
||
|
|
+ sizeof(unsigned short)*m_maxNodes +
|
||
|
|
+ sizeof(unsigned short)*m_hashSize;
|
||
|
|
}
|
||
|
|
|
||
|
|
inline int getMaxNodes() const { return m_maxNodes; }
|
||
|
|
|
||
|
|
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 unsigned short getFirst(int bucket) const { return m_first[bucket]; }
|
||
|
|
+ inline unsigned short getNext(int i) const { return m_next[i]; }
|
||
|
|
|
||
|
|
private:
|
||
|
|
|
||
|
|
dtNode* m_nodes;
|
||
|
|
- dtNodeIndex* m_first;
|
||
|
|
- dtNodeIndex* m_next;
|
||
|
|
+ unsigned short* m_first;
|
||
|
|
+ unsigned short* m_next;
|
||
|
|
const int m_maxNodes;
|
||
|
|
const int m_hashSize;
|
||
|
|
int m_nodeCount;
|
||
|
|
@@ -156,4 +154,4 @@ private:
|
||
|
|
};
|
||
|
|
|
||
|
|
|
||
|
|
-#endif // DETOURNODE_H
|
||
|
|
+#endif // DETOURNODE_H
|
||
|
|
\ No newline at end of file
|
||
|
|
diff --git a/dep/recastnavigation/Detour/DetourStatus.h b/dep/recastnavigation/Detour/DetourStatus.h
|
||
|
|
deleted file mode 100644
|
||
|
|
index af822c4..0000000
|
||
|
|
--- a/dep/recastnavigation/Detour/DetourStatus.h
|
||
|
|
+++ /dev/null
|
||
|
|
@@ -1,64 +0,0 @@
|
||
|
|
-//
|
||
|
|
-// Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||
|
|
-//
|
||
|
|
-// This software is provided 'as-is', without any express or implied
|
||
|
|
-// warranty. In no event will the authors be held liable for any damages
|
||
|
|
-// arising from the use of this software.
|
||
|
|
-// Permission is granted to anyone to use this software for any purpose,
|
||
|
|
-// including commercial applications, and to alter it and redistribute it
|
||
|
|
-// freely, subject to the following restrictions:
|
||
|
|
-// 1. The origin of this software must not be misrepresented; you must not
|
||
|
|
-// claim that you wrote the original software. If you use this software
|
||
|
|
-// in a product, an acknowledgment in the product documentation would be
|
||
|
|
-// appreciated but is not required.
|
||
|
|
-// 2. Altered source versions must be plainly marked as such, and must not be
|
||
|
|
-// misrepresented as being the original software.
|
||
|
|
-// 3. This notice may not be removed or altered from any source distribution.
|
||
|
|
-//
|
||
|
|
-
|
||
|
|
-#ifndef DETOURSTATUS_H
|
||
|
|
-#define DETOURSTATUS_H
|
||
|
|
-
|
||
|
|
-typedef unsigned int dtStatus;
|
||
|
|
-
|
||
|
|
-// High level status.
|
||
|
|
-static const unsigned int DT_FAILURE = 1u << 31; // Operation failed.
|
||
|
|
-static const unsigned int DT_SUCCESS = 1u << 30; // Operation succeed.
|
||
|
|
-static const unsigned int DT_IN_PROGRESS = 1u << 29; // Operation still in progress.
|
||
|
|
-
|
||
|
|
-// Detail information for status.
|
||
|
|
-static const unsigned int DT_STATUS_DETAIL_MASK = 0x0ffffff;
|
||
|
|
-static const unsigned int DT_WRONG_MAGIC = 1 << 0; // Input data is not recognized.
|
||
|
|
-static const unsigned int DT_WRONG_VERSION = 1 << 1; // Input data is in wrong version.
|
||
|
|
-static const unsigned int DT_OUT_OF_MEMORY = 1 << 2; // Operation ran out of memory.
|
||
|
|
-static const unsigned int DT_INVALID_PARAM = 1 << 3; // An input parameter was invalid.
|
||
|
|
-static const unsigned int DT_BUFFER_TOO_SMALL = 1 << 4; // Result buffer for the query was too small to store all results.
|
||
|
|
-static const unsigned int DT_OUT_OF_NODES = 1 << 5; // Query ran out of nodes during search.
|
||
|
|
-static const unsigned int DT_PARTIAL_RESULT = 1 << 6; // Query did not reach the end location, returning best guess.
|
||
|
|
-
|
||
|
|
-
|
||
|
|
-// Returns true of status is success.
|
||
|
|
-inline bool dtStatusSucceed(dtStatus status)
|
||
|
|
-{
|
||
|
|
- return (status & DT_SUCCESS) != 0;
|
||
|
|
-}
|
||
|
|
-
|
||
|
|
-// Returns true of status is failure.
|
||
|
|
-inline bool dtStatusFailed(dtStatus status)
|
||
|
|
-{
|
||
|
|
- return (status & DT_FAILURE) != 0;
|
||
|
|
-}
|
||
|
|
-
|
||
|
|
-// Returns true of status is in progress.
|
||
|
|
-inline bool dtStatusInProgress(dtStatus status)
|
||
|
|
-{
|
||
|
|
- return (status & DT_IN_PROGRESS) != 0;
|
||
|
|
-}
|
||
|
|
-
|
||
|
|
-// Returns true if specific detail is set.
|
||
|
|
-inline bool dtStatusDetail(dtStatus status, unsigned int detail)
|
||
|
|
-{
|
||
|
|
- return (status & detail) != 0;
|
||
|
|
-}
|
||
|
|
-
|
||
|
|
-#endif // DETOURSTATUS_H
|
||
|
|
diff --git a/dep/recastnavigation/Recast/CMakeLists.txt b/dep/recastnavigation/Recast/CMakeLists.txt
|
||
|
|
index 5f466a4..726aff7 100644
|
||
|
|
--- a/dep/recastnavigation/Recast/CMakeLists.txt
|
||
|
|
+++ b/dep/recastnavigation/Recast/CMakeLists.txt
|
||
|
|
@@ -14,7 +14,6 @@ set(Recast_STAT_SRCS
|
||
|
|
RecastArea.cpp
|
||
|
|
RecastContour.cpp
|
||
|
|
RecastFilter.cpp
|
||
|
|
- RecastLayers.cpp
|
||
|
|
RecastMesh.cpp
|
||
|
|
RecastMeshDetail.cpp
|
||
|
|
RecastRasterization.cpp
|
||
|
|
diff --git a/dep/recastnavigation/Recast/Recast.cpp b/dep/recastnavigation/Recast/Recast.cpp
|
||
|
|
index 803daac..d051418 100644
|
||
|
|
--- a/dep/recastnavigation/Recast/Recast.cpp
|
||
|
|
+++ b/dep/recastnavigation/Recast/Recast.cpp
|
||
|
|
@@ -32,26 +32,7 @@ float rcSqrt(float x)
|
||
|
|
return sqrtf(x);
|
||
|
|
}
|
||
|
|
|
||
|
|
-/// @class rcContext
|
||
|
|
-/// @par
|
||
|
|
-///
|
||
|
|
-/// This class does not provide logging or timer functionality on its
|
||
|
|
-/// own. Both must be provided by a concrete implementation
|
||
|
|
-/// by overriding the protected member functions. Also, this class does not
|
||
|
|
-/// provide an interface for extracting log messages. (Only adding them.)
|
||
|
|
-/// So concrete implementations must provide one.
|
||
|
|
-///
|
||
|
|
-/// If no logging or timers are required, just pass an instance of this
|
||
|
|
-/// class through the Recast build process.
|
||
|
|
-///
|
||
|
|
|
||
|
|
-/// @par
|
||
|
|
-///
|
||
|
|
-/// Example:
|
||
|
|
-/// @code
|
||
|
|
-/// // Where ctx is an instance of rcContext and filepath is a char array.
|
||
|
|
-/// ctx->log(RC_LOG_ERROR, "buildTiledNavigation: Could not load '%s'", filepath);
|
||
|
|
-/// @endcode
|
||
|
|
void rcContext::log(const rcLogCategory category, const char* format, ...)
|
||
|
|
{
|
||
|
|
if (!m_logEnabled)
|
||
|
|
@@ -109,28 +90,6 @@ void rcFreeCompactHeightfield(rcCompactHeightfield* chf)
|
||
|
|
rcFree(chf);
|
||
|
|
}
|
||
|
|
|
||
|
|
-
|
||
|
|
-rcHeightfieldLayerSet* rcAllocHeightfieldLayerSet()
|
||
|
|
-{
|
||
|
|
- rcHeightfieldLayerSet* lset = (rcHeightfieldLayerSet*)rcAlloc(sizeof(rcHeightfieldLayerSet), RC_ALLOC_PERM);
|
||
|
|
- memset(lset, 0, sizeof(rcHeightfieldLayerSet));
|
||
|
|
- return lset;
|
||
|
|
-}
|
||
|
|
-
|
||
|
|
-void rcFreeHeightfieldLayerSet(rcHeightfieldLayerSet* lset)
|
||
|
|
-{
|
||
|
|
- if (!lset) return;
|
||
|
|
- for (int i = 0; i < lset->nlayers; ++i)
|
||
|
|
- {
|
||
|
|
- rcFree(lset->layers[i].heights);
|
||
|
|
- rcFree(lset->layers[i].areas);
|
||
|
|
- rcFree(lset->layers[i].cons);
|
||
|
|
- }
|
||
|
|
- rcFree(lset->layers);
|
||
|
|
- rcFree(lset);
|
||
|
|
-}
|
||
|
|
-
|
||
|
|
-
|
||
|
|
rcContourSet* rcAllocContourSet()
|
||
|
|
{
|
||
|
|
rcContourSet* cset = (rcContourSet*)rcAlloc(sizeof(rcContourSet), RC_ALLOC_PERM);
|
||
|
|
@@ -184,6 +143,7 @@ void rcFreePolyMeshDetail(rcPolyMeshDetail* dmesh)
|
||
|
|
rcFree(dmesh);
|
||
|
|
}
|
||
|
|
|
||
|
|
+
|
||
|
|
void rcCalcBounds(const float* verts, int nv, float* bmin, float* bmax)
|
||
|
|
{
|
||
|
|
// Calculate bounding box.
|
||
|
|
@@ -203,11 +163,6 @@ void rcCalcGridSize(const float* bmin, const float* bmax, float cs, int* w, int*
|
||
|
|
*h = (int)((bmax[2] - bmin[2])/cs+0.5f);
|
||
|
|
}
|
||
|
|
|
||
|
|
-/// @par
|
||
|
|
-///
|
||
|
|
-/// See the #rcConfig documentation for more information on the configuration parameters.
|
||
|
|
-///
|
||
|
|
-/// @see rcAllocHeightfield, rcHeightfield
|
||
|
|
bool rcCreateHeightfield(rcContext* /*ctx*/, rcHeightfield& hf, int width, int height,
|
||
|
|
const float* bmin, const float* bmax,
|
||
|
|
float cs, float ch)
|
||
|
|
@@ -237,14 +192,6 @@ static void calcTriNormal(const float* v0, const float* v1, const float* v2, flo
|
||
|
|
rcVnormalize(norm);
|
||
|
|
}
|
||
|
|
|
||
|
|
-/// @par
|
||
|
|
-///
|
||
|
|
-/// Only sets the aread id's for the walkable triangles. Does not alter the
|
||
|
|
-/// area id's for unwalkable triangles.
|
||
|
|
-///
|
||
|
|
-/// See the #rcConfig documentation for more information on the configuration parameters.
|
||
|
|
-///
|
||
|
|
-/// @see rcHeightfield, rcClearUnwalkableTriangles, rcRasterizeTriangles
|
||
|
|
void rcMarkWalkableTriangles(rcContext* /*ctx*/, const float walkableSlopeAngle,
|
||
|
|
const float* verts, int /*nv*/,
|
||
|
|
const int* tris, int nt,
|
||
|
|
@@ -267,14 +214,6 @@ void rcMarkWalkableTriangles(rcContext* /*ctx*/, const float walkableSlopeAngle,
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
-/// @par
|
||
|
|
-///
|
||
|
|
-/// Only sets the aread id's for the unwalkable triangles. Does not alter the
|
||
|
|
-/// area id's for walkable triangles.
|
||
|
|
-///
|
||
|
|
-/// See the #rcConfig documentation for more information on the configuration parameters.
|
||
|
|
-///
|
||
|
|
-/// @see rcHeightfield, rcClearUnwalkableTriangles, rcRasterizeTriangles
|
||
|
|
void rcClearUnwalkableTriangles(rcContext* /*ctx*/, const float walkableSlopeAngle,
|
||
|
|
const float* verts, int /*nv*/,
|
||
|
|
const int* tris, int nt,
|
||
|
|
@@ -319,15 +258,6 @@ int rcGetHeightFieldSpanCount(rcContext* /*ctx*/, rcHeightfield& hf)
|
||
|
|
return spanCount;
|
||
|
|
}
|
||
|
|
|
||
|
|
-/// @par
|
||
|
|
-///
|
||
|
|
-/// This is just the beginning of the process of fully building a compact heightfield.
|
||
|
|
-/// Various filters may be applied applied, then the distance field and regions built.
|
||
|
|
-/// E.g: #rcBuildDistanceField and #rcBuildRegions
|
||
|
|
-///
|
||
|
|
-/// See the #rcConfig documentation for more information on the configuration parameters.
|
||
|
|
-///
|
||
|
|
-/// @see rcAllocCompactHeightfield, rcHeightfield, rcCompactHeightfield, rcConfig
|
||
|
|
bool rcBuildCompactHeightfield(rcContext* ctx, const int walkableHeight, const int walkableClimb,
|
||
|
|
rcHeightfield& hf, rcCompactHeightfield& chf)
|
||
|
|
{
|
||
|
|
@@ -439,13 +369,13 @@ bool rcBuildCompactHeightfield(rcContext* ctx, const int walkableHeight, const i
|
||
|
|
if ((top - bot) >= walkableHeight && rcAbs((int)ns.y - (int)s.y) <= walkableClimb)
|
||
|
|
{
|
||
|
|
// Mark direction as walkable.
|
||
|
|
- const int lidx = k - (int)nc.index;
|
||
|
|
- if (lidx < 0 || lidx > MAX_LAYERS)
|
||
|
|
+ const int idx = k - (int)nc.index;
|
||
|
|
+ if (idx < 0 || idx > MAX_LAYERS)
|
||
|
|
{
|
||
|
|
- tooHighNeighbour = rcMax(tooHighNeighbour, lidx);
|
||
|
|
+ tooHighNeighbour = rcMax(tooHighNeighbour, idx);
|
||
|
|
continue;
|
||
|
|
}
|
||
|
|
- rcSetCon(s, dir, lidx);
|
||
|
|
+ rcSetCon(s, dir, idx);
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
diff --git a/dep/recastnavigation/Recast/Recast.h b/dep/recastnavigation/Recast/Recast.h
|
||
|
|
index fb36aa4..0e5f074 100644
|
||
|
|
--- a/dep/recastnavigation/Recast/Recast.h
|
||
|
|
+++ b/dep/recastnavigation/Recast/Recast.h
|
||
|
|
@@ -19,583 +19,327 @@
|
||
|
|
#ifndef RECAST_H
|
||
|
|
#define RECAST_H
|
||
|
|
|
||
|
|
-/// The value of PI used by Recast.
|
||
|
|
+// Some math headers don't have PI defined.
|
||
|
|
static const float RC_PI = 3.14159265f;
|
||
|
|
|
||
|
|
-/// Recast log categories.
|
||
|
|
-/// @see rcContext
|
||
|
|
enum rcLogCategory
|
||
|
|
{
|
||
|
|
- RC_LOG_PROGRESS = 1, ///< A progress log entry.
|
||
|
|
- RC_LOG_WARNING, ///< A warning log entry.
|
||
|
|
- RC_LOG_ERROR, ///< An error log entry.
|
||
|
|
+ RC_LOG_PROGRESS = 1,
|
||
|
|
+ RC_LOG_WARNING,
|
||
|
|
+ RC_LOG_ERROR,
|
||
|
|
};
|
||
|
|
|
||
|
|
-/// Recast performance timer categories.
|
||
|
|
-/// @see rcContext
|
||
|
|
enum rcTimerLabel
|
||
|
|
{
|
||
|
|
- /// The user defined total time of the build.
|
||
|
|
RC_TIMER_TOTAL,
|
||
|
|
- /// A user defined build time.
|
||
|
|
RC_TIMER_TEMP,
|
||
|
|
- /// The time to rasterize the triangles. (See: #rcRasterizeTriangle)
|
||
|
|
RC_TIMER_RASTERIZE_TRIANGLES,
|
||
|
|
- /// The time to build the compact heightfield. (See: #rcBuildCompactHeightfield)
|
||
|
|
RC_TIMER_BUILD_COMPACTHEIGHTFIELD,
|
||
|
|
- /// The total time to build the contours. (See: #rcBuildContours)
|
||
|
|
RC_TIMER_BUILD_CONTOURS,
|
||
|
|
- /// The time to trace the boundaries of the contours. (See: #rcBuildContours)
|
||
|
|
RC_TIMER_BUILD_CONTOURS_TRACE,
|
||
|
|
- /// The time to simplify the contours. (See: #rcBuildContours)
|
||
|
|
RC_TIMER_BUILD_CONTOURS_SIMPLIFY,
|
||
|
|
- /// The time to filter ledge spans. (See: #rcFilterLedgeSpans)
|
||
|
|
RC_TIMER_FILTER_BORDER,
|
||
|
|
- /// The time to filter low height spans. (See: #rcFilterWalkableLowHeightSpans)
|
||
|
|
RC_TIMER_FILTER_WALKABLE,
|
||
|
|
- /// The time to apply the median filter. (See: #rcMedianFilterWalkableArea)
|
||
|
|
RC_TIMER_MEDIAN_AREA,
|
||
|
|
- /// The time to filter low obstacles. (See: #rcFilterLowHangingWalkableObstacles)
|
||
|
|
RC_TIMER_FILTER_LOW_OBSTACLES,
|
||
|
|
- /// The time to build the polygon mesh. (See: #rcBuildPolyMesh)
|
||
|
|
RC_TIMER_BUILD_POLYMESH,
|
||
|
|
- /// The time to merge polygon meshes. (See: #rcMergePolyMeshes)
|
||
|
|
RC_TIMER_MERGE_POLYMESH,
|
||
|
|
- /// The time to erode the walkable area. (See: #rcErodeWalkableArea)
|
||
|
|
RC_TIMER_ERODE_AREA,
|
||
|
|
- /// The time to mark a box area. (See: #rcMarkBoxArea)
|
||
|
|
RC_TIMER_MARK_BOX_AREA,
|
||
|
|
- /// The time to mark a cylinder area. (See: #rcMarkCylinderArea)
|
||
|
|
- RC_TIMER_MARK_CYLINDER_AREA,
|
||
|
|
- /// The time to mark a convex polygon area. (See: #rcMarkConvexPolyArea)
|
||
|
|
RC_TIMER_MARK_CONVEXPOLY_AREA,
|
||
|
|
- /// The total time to build the distance field. (See: #rcBuildDistanceField)
|
||
|
|
RC_TIMER_BUILD_DISTANCEFIELD,
|
||
|
|
- /// The time to build the distances of the distance field. (See: #rcBuildDistanceField)
|
||
|
|
RC_TIMER_BUILD_DISTANCEFIELD_DIST,
|
||
|
|
- /// The time to blur the distance field. (See: #rcBuildDistanceField)
|
||
|
|
RC_TIMER_BUILD_DISTANCEFIELD_BLUR,
|
||
|
|
- /// The total time to build the regions. (See: #rcBuildRegions, #rcBuildRegionsMonotone)
|
||
|
|
RC_TIMER_BUILD_REGIONS,
|
||
|
|
- /// The total time to apply the watershed algorithm. (See: #rcBuildRegions)
|
||
|
|
RC_TIMER_BUILD_REGIONS_WATERSHED,
|
||
|
|
- /// The time to expand regions while applying the watershed algorithm. (See: #rcBuildRegions)
|
||
|
|
RC_TIMER_BUILD_REGIONS_EXPAND,
|
||
|
|
- /// The time to flood regions while applying the watershed algorithm. (See: #rcBuildRegions)
|
||
|
|
RC_TIMER_BUILD_REGIONS_FLOOD,
|
||
|
|
- /// The time to filter out small regions. (See: #rcBuildRegions, #rcBuildRegionsMonotone)
|
||
|
|
RC_TIMER_BUILD_REGIONS_FILTER,
|
||
|
|
- /// The time to build heightfield layers. (See: #rcBuildHeightfieldLayers)
|
||
|
|
- RC_TIMER_BUILD_LAYERS,
|
||
|
|
- /// The time to build the polygon mesh detail. (See: #rcBuildPolyMeshDetail)
|
||
|
|
RC_TIMER_BUILD_POLYMESHDETAIL,
|
||
|
|
- /// The time to merge polygon mesh details. (See: #rcMergePolyMeshDetails)
|
||
|
|
RC_TIMER_MERGE_POLYMESHDETAIL,
|
||
|
|
- /// The maximum number of timers. (Used for iterating timers.)
|
||
|
|
RC_MAX_TIMERS
|
||
|
|
};
|
||
|
|
|
||
|
|
-/// Provides an interface for optional logging and performance tracking of the Recast
|
||
|
|
-/// build process.
|
||
|
|
-/// @ingroup recast
|
||
|
|
+// Build context provides several optional utilities needed for the build process,
|
||
|
|
+// such as timing, logging, and build time collecting.
|
||
|
|
class rcContext
|
||
|
|
{
|
||
|
|
public:
|
||
|
|
-
|
||
|
|
- /// Contructor.
|
||
|
|
- /// @param[in] state TRUE if the logging and performance timers should be enabled. [Default: true]
|
||
|
|
inline rcContext(bool state = true) : m_logEnabled(state), m_timerEnabled(state) {}
|
||
|
|
virtual ~rcContext() {}
|
||
|
|
|
||
|
|
- /// Enables or disables logging.
|
||
|
|
- /// @param[in] state TRUE if logging should be enabled.
|
||
|
|
+ // Enables or disables logging.
|
||
|
|
inline void enableLog(bool state) { m_logEnabled = state; }
|
||
|
|
-
|
||
|
|
- /// Clears all log entries.
|
||
|
|
+ // Resets log.
|
||
|
|
inline void resetLog() { if (m_logEnabled) doResetLog(); }
|
||
|
|
-
|
||
|
|
- /// Logs a message.
|
||
|
|
- /// @param[in] category The category of the message.
|
||
|
|
- /// @param[in] format The message.
|
||
|
|
+ // Logs a message.
|
||
|
|
void log(const rcLogCategory category, const char* format, ...);
|
||
|
|
|
||
|
|
- /// Enables or disables the performance timers.
|
||
|
|
- /// @param[in] state TRUE if timers should be enabled.
|
||
|
|
+ // Enables or disables timer.
|
||
|
|
inline void enableTimer(bool state) { m_timerEnabled = state; }
|
||
|
|
-
|
||
|
|
- /// Clears all peformance timers. (Resets all to unused.)
|
||
|
|
+ // Resets all timers.
|
||
|
|
inline void resetTimers() { if (m_timerEnabled) doResetTimers(); }
|
||
|
|
-
|
||
|
|
- /// Starts the specified performance timer.
|
||
|
|
- /// @param label The category of timer.
|
||
|
|
+ // Starts timer, used for performance timing.
|
||
|
|
inline void startTimer(const rcTimerLabel label) { if (m_timerEnabled) doStartTimer(label); }
|
||
|
|
-
|
||
|
|
- /// Stops the specified performance timer.
|
||
|
|
- /// @param label The category of the timer.
|
||
|
|
+ // Stops timer, used for performance timing.
|
||
|
|
inline void stopTimer(const rcTimerLabel label) { if (m_timerEnabled) doStopTimer(label); }
|
||
|
|
-
|
||
|
|
- /// Returns the total accumulated time of the specified performance timer.
|
||
|
|
- /// @param label The category of the timer.
|
||
|
|
- /// @return The accumulated time of the timer, or -1 if timers are disabled or the timer has never been started.
|
||
|
|
+ // Returns time accumulated between timer start/stop.
|
||
|
|
inline int getAccumulatedTime(const rcTimerLabel label) const { return m_timerEnabled ? doGetAccumulatedTime(label) : -1; }
|
||
|
|
|
||
|
|
protected:
|
||
|
|
-
|
||
|
|
- /// Clears all log entries.
|
||
|
|
+ // Virtual functions to override for custom implementations.
|
||
|
|
virtual void doResetLog() {}
|
||
|
|
-
|
||
|
|
- /// Logs a message.
|
||
|
|
- /// @param[in] category The category of the message.
|
||
|
|
- /// @param[in] msg The formatted message.
|
||
|
|
- /// @param[in] len The length of the formatted message.
|
||
|
|
virtual void doLog(const rcLogCategory /*category*/, const char* /*msg*/, const int /*len*/) {}
|
||
|
|
-
|
||
|
|
- /// Clears all timers. (Resets all to unused.)
|
||
|
|
virtual void doResetTimers() {}
|
||
|
|
-
|
||
|
|
- /// Starts the specified performance timer.
|
||
|
|
- /// @param[in] label The category of timer.
|
||
|
|
virtual void doStartTimer(const rcTimerLabel /*label*/) {}
|
||
|
|
-
|
||
|
|
- /// Stops the specified performance timer.
|
||
|
|
- /// @param[in] label The category of the timer.
|
||
|
|
virtual void doStopTimer(const rcTimerLabel /*label*/) {}
|
||
|
|
-
|
||
|
|
- /// Returns the total accumulated time of the specified performance timer.
|
||
|
|
- /// @param[in] label The category of the timer.
|
||
|
|
- /// @return The accumulated time of the timer, or -1 if timers are disabled or the timer has never been started.
|
||
|
|
virtual int doGetAccumulatedTime(const rcTimerLabel /*label*/) const { return -1; }
|
||
|
|
|
||
|
|
- /// True if logging is enabled.
|
||
|
|
bool m_logEnabled;
|
||
|
|
-
|
||
|
|
- /// True if the performance timers are enabled.
|
||
|
|
bool m_timerEnabled;
|
||
|
|
};
|
||
|
|
|
||
|
|
-/// Specifies a configuration to use when performing Recast builds.
|
||
|
|
-/// @ingroup recast
|
||
|
|
+
|
||
|
|
+// The units of the parameters are specified in parenthesis as follows:
|
||
|
|
+// (vx) voxels, (wu) world units
|
||
|
|
struct rcConfig
|
||
|
|
{
|
||
|
|
- /// The width of the field along the x-axis. [Limit: >= 0] [Units: vx]
|
||
|
|
- int width;
|
||
|
|
-
|
||
|
|
- /// The height of the field along the z-axis. [Limit: >= 0] [Units: vx]
|
||
|
|
- int height;
|
||
|
|
-
|
||
|
|
- /// The width/height size of tile's on the xz-plane. [Limit: >= 0] [Units: vx]
|
||
|
|
- int tileSize;
|
||
|
|
-
|
||
|
|
- /// The size of the non-navigable border around the heightfield. [Limit: >=0] [Units: vx]
|
||
|
|
- int borderSize;
|
||
|
|
-
|
||
|
|
- /// The xz-plane cell size to use for fields. [Limit: > 0] [Units: wu]
|
||
|
|
- float cs;
|
||
|
|
-
|
||
|
|
- /// The y-axis cell size to use for fields. [Limit: > 0] [Units: wu]
|
||
|
|
- float ch;
|
||
|
|
-
|
||
|
|
- /// The minimum bounds of the field's AABB. [(x, y, z)] [Units: wu]
|
||
|
|
- float bmin[3];
|
||
|
|
-
|
||
|
|
- /// The maximum bounds of the field's AABB. [(x, y, z)] [Units: wu]
|
||
|
|
- float bmax[3];
|
||
|
|
-
|
||
|
|
- /// The maximum slope that is considered walkable. [Limits: 0 <= value < 90] [Units: Degrees]
|
||
|
|
- float walkableSlopeAngle;
|
||
|
|
-
|
||
|
|
- /// Minimum floor to 'ceiling' height that will still allow the floor area to
|
||
|
|
- /// be considered walkable. [Limit: >= 3] [Units: vx]
|
||
|
|
- int walkableHeight;
|
||
|
|
-
|
||
|
|
- /// Maximum ledge height that is considered to still be traversable. [Limit: >=0] [Units: vx]
|
||
|
|
- int walkableClimb;
|
||
|
|
-
|
||
|
|
- /// The distance to erode/shrink the walkable area of the heightfield away from
|
||
|
|
- /// obstructions. [Limit: >=0] [Units: vx]
|
||
|
|
- int walkableRadius;
|
||
|
|
-
|
||
|
|
- /// The maximum allowed length for contour edges along the border of the mesh. [Limit: >=0] [Units: vx]
|
||
|
|
- int maxEdgeLen;
|
||
|
|
-
|
||
|
|
- /// The maximum distance a simplfied contour's border edges should deviate
|
||
|
|
- /// the original raw contour. [Limit: >=0] [Units: wu]
|
||
|
|
- float maxSimplificationError;
|
||
|
|
-
|
||
|
|
- /// The minimum number of cells allowed to form isolated island areas. [Limit: >=0] [Units: vx]
|
||
|
|
- int minRegionArea;
|
||
|
|
-
|
||
|
|
- /// Any regions with a span count smaller than this value will, if possible,
|
||
|
|
- /// be merged with larger regions. [Limit: >=0] [Units: vx]
|
||
|
|
- int mergeRegionArea;
|
||
|
|
-
|
||
|
|
- /// The maximum number of vertices allowed for polygons generated during the
|
||
|
|
- /// contour to polygon conversion process. [Limit: >= 3]
|
||
|
|
- int maxVertsPerPoly;
|
||
|
|
-
|
||
|
|
- /// Sets the sampling distance to use when generating the detail mesh.
|
||
|
|
- /// (For height detail only.) [Limits: 0 or >= 0.9] [Units: wu]
|
||
|
|
- float detailSampleDist;
|
||
|
|
-
|
||
|
|
- /// The maximum distance the detail mesh surface should deviate from heightfield
|
||
|
|
- /// data. (For height detail only.) [Limit: >=0] [Units: wu]
|
||
|
|
- float detailSampleMaxError;
|
||
|
|
+ int width, height; // Dimensions of the rasterized heightfield (vx)
|
||
|
|
+ int tileSize; // Width and Height of a tile (vx)
|
||
|
|
+ int borderSize; // Non-navigable Border around the heightfield (vx)
|
||
|
|
+ float cs, ch; // Grid cell size and height (wu)
|
||
|
|
+ float bmin[3], bmax[3]; // Grid bounds (wu)
|
||
|
|
+ float walkableSlopeAngle; // Maximum walkable slope angle in degrees.
|
||
|
|
+ int walkableHeight; // Minimum height where the agent can still walk (vx)
|
||
|
|
+ int walkableClimb; // Maximum height between grid cells the agent can climb (vx)
|
||
|
|
+ int walkableRadius; // Radius of the agent in cells (vx)
|
||
|
|
+ int maxEdgeLen; // Maximum contour edge length (vx)
|
||
|
|
+ float maxSimplificationError; // Maximum distance error from contour to cells (vx)
|
||
|
|
+ int minRegionArea; // Regions whose area is smaller than this threshold will be removed. (vx)
|
||
|
|
+ int mergeRegionArea; // Regions whose area is smaller than this threshold will be merged (vx)
|
||
|
|
+ int maxVertsPerPoly; // Max number of vertices per polygon
|
||
|
|
+ float detailSampleDist; // Detail mesh sample spacing.
|
||
|
|
+ float detailSampleMaxError; // Detail mesh simplification max sample error.
|
||
|
|
};
|
||
|
|
|
||
|
|
-/// Defines the number of bits allocated to rcSpan::smin and rcSpan::smax.
|
||
|
|
-static const int RC_SPAN_HEIGHT_BITS = 16; // EDITED BY TC
|
||
|
|
-/// Defines the maximum value for rcSpan::smin and rcSpan::smax.
|
||
|
|
+// Define number of bits in the above structure for smin/smax.
|
||
|
|
+// The max height is used for clamping rasterized values.
|
||
|
|
+static const int RC_SPAN_HEIGHT_BITS = 16;
|
||
|
|
static const int RC_SPAN_MAX_HEIGHT = (1<<RC_SPAN_HEIGHT_BITS)-1;
|
||
|
|
|
||
|
|
-/// The number of spans allocated per span spool.
|
||
|
|
-/// @see rcSpanPool
|
||
|
|
-static const int RC_SPANS_PER_POOL = 2048;
|
||
|
|
-
|
||
|
|
-/// Represents a span in a heightfield.
|
||
|
|
-/// @see rcHeightfield
|
||
|
|
+// Heightfield span.
|
||
|
|
struct rcSpan
|
||
|
|
{
|
||
|
|
- unsigned int smin : 16; ///< The lower limit of the span. [Limit: < #smax]
|
||
|
|
- unsigned int smax : 16; ///< The upper limit of the span. [Limit: <= #RC_SPAN_MAX_HEIGHT]
|
||
|
|
- unsigned char area; ///< The area id assigned to the span.
|
||
|
|
- rcSpan* next; ///< The next span higher up in column.
|
||
|
|
+ unsigned int smin : 16; // Span min height.
|
||
|
|
+ unsigned int smax : 16; // Span max height.
|
||
|
|
+ unsigned char area; // Span area type.
|
||
|
|
+ rcSpan* next; // Next span in column.
|
||
|
|
};
|
||
|
|
|
||
|
|
-/// A memory pool used for quick allocation of spans within a heightfield.
|
||
|
|
-/// @see rcHeightfield
|
||
|
|
+// Number of spans allocated per pool.
|
||
|
|
+static const int RC_SPANS_PER_POOL = 2048;
|
||
|
|
+
|
||
|
|
+// Memory pool used for quick span allocation.
|
||
|
|
struct rcSpanPool
|
||
|
|
{
|
||
|
|
- rcSpanPool* next; ///< The next span pool.
|
||
|
|
- rcSpan items[RC_SPANS_PER_POOL]; ///< Array of spans in the pool.
|
||
|
|
+ rcSpanPool* next; // Pointer to next pool.
|
||
|
|
+ rcSpan items[RC_SPANS_PER_POOL]; // Array of spans.
|
||
|
|
};
|
||
|
|
|
||
|
|
-/// A dynamic heightfield representing obstructed space.
|
||
|
|
-/// @ingroup recast
|
||
|
|
+// Dynamic span-heightfield.
|
||
|
|
struct rcHeightfield
|
||
|
|
{
|
||
|
|
- int width; ///< The width of the heightfield. (Along the x-axis in cell units.)
|
||
|
|
- int height; ///< The height of the heightfield. (Along the z-axis in cell units.)
|
||
|
|
- float bmin[3]; ///< The minimum bounds in world space. [(x, y, z)]
|
||
|
|
- float bmax[3]; ///< The maximum bounds in world space. [(x, y, z)]
|
||
|
|
- float cs; ///< The size of each cell. (On the xz-plane.)
|
||
|
|
- float ch; ///< The height of each cell. (The minimum increment along the y-axis.)
|
||
|
|
- rcSpan** spans; ///< Heightfield of spans (width*height).
|
||
|
|
- rcSpanPool* pools; ///< Linked list of span pools.
|
||
|
|
- rcSpan* freelist; ///< The next free span.
|
||
|
|
+ int width, height; // Dimension of the heightfield.
|
||
|
|
+ float bmin[3], bmax[3]; // Bounding box of the heightfield
|
||
|
|
+ float cs, ch; // Cell size and height.
|
||
|
|
+ rcSpan** spans; // Heightfield of spans (width*height).
|
||
|
|
+ rcSpanPool* pools; // Linked list of span pools.
|
||
|
|
+ rcSpan* freelist; // Pointer to next free span.
|
||
|
|
};
|
||
|
|
|
||
|
|
-/// Provides information on the content of a cell column in a compact heightfield.
|
||
|
|
+rcHeightfield* rcAllocHeightfield();
|
||
|
|
+void rcFreeHeightField(rcHeightfield* hf);
|
||
|
|
+
|
||
|
|
+
|
||
|
|
struct rcCompactCell
|
||
|
|
{
|
||
|
|
- unsigned int index : 24; ///< Index to the first span in the column.
|
||
|
|
- unsigned int count : 8; ///< Number of spans in the column.
|
||
|
|
+ unsigned int index : 24; // Index to first span in column.
|
||
|
|
+ unsigned int count : 8; // Number of spans in this column.
|
||
|
|
};
|
||
|
|
|
||
|
|
-/// Represents a span of unobstructed space within a compact heightfield.
|
||
|
|
struct rcCompactSpan
|
||
|
|
{
|
||
|
|
- unsigned short y; ///< The lower extent of the span. (Measured from the heightfield's base.)
|
||
|
|
- unsigned short reg; ///< The id of the region the span belongs to. (Or zero if not in a region.)
|
||
|
|
- unsigned int con : 24; ///< Packed neighbor connection data.
|
||
|
|
- unsigned int h : 8; ///< The height of the span. (Measured from #y.)
|
||
|
|
+ unsigned short y; // Bottom coordinate of the span.
|
||
|
|
+ unsigned short reg;
|
||
|
|
+ unsigned int con : 24; // Connections to neighbour cells.
|
||
|
|
+ unsigned int h : 8; // Height of the span.
|
||
|
|
};
|
||
|
|
|
||
|
|
-/// A compact, static heightfield representing unobstructed space.
|
||
|
|
-/// @ingroup recast
|
||
|
|
+// Compact static heightfield.
|
||
|
|
struct rcCompactHeightfield
|
||
|
|
{
|
||
|
|
- int width; ///< The width of the heightfield. (Along the x-axis in cell units.)
|
||
|
|
- int height; ///< The height of the heightfield. (Along the z-axis in cell units.)
|
||
|
|
- int spanCount; ///< The number of spans in the heightfield.
|
||
|
|
- int walkableHeight; ///< The walkable height used during the build of the field. (See: rcConfig::walkableHeight)
|
||
|
|
- int walkableClimb; ///< The walkable climb used during the build of the field. (See: rcConfig::walkableClimb)
|
||
|
|
- int borderSize; ///< The AABB border size used during the build of the field. (See: rcConfig::borderSize)
|
||
|
|
- unsigned short maxDistance; ///< The maximum distance value of any span within the field.
|
||
|
|
- unsigned short maxRegions; ///< The maximum region id of any span within the field.
|
||
|
|
- float bmin[3]; ///< The minimum bounds in world space. [(x, y, z)]
|
||
|
|
- float bmax[3]; ///< The maximum bounds in world space. [(x, y, z)]
|
||
|
|
- float cs; ///< The size of each cell. (On the xz-plane.)
|
||
|
|
- float ch; ///< The height of each cell. (The minimum increment along the y-axis.)
|
||
|
|
- rcCompactCell* cells; ///< Array of cells. [Size: #width*#height]
|
||
|
|
- rcCompactSpan* spans; ///< Array of spans. [Size: #spanCount]
|
||
|
|
- unsigned short* dist; ///< Array containing border distance data. [Size: #spanCount]
|
||
|
|
- unsigned char* areas; ///< Array containing area id data. [Size: #spanCount]
|
||
|
|
+ int width, height; // Width and height of the heightfield.
|
||
|
|
+ int spanCount; // Number of spans in the heightfield.
|
||
|
|
+ int walkableHeight, walkableClimb; // Agent properties.
|
||
|
|
+ unsigned short maxDistance; // Maximum distance value stored in heightfield.
|
||
|
|
+ unsigned short maxRegions; // Maximum Region Id stored in heightfield.
|
||
|
|
+ float bmin[3], bmax[3]; // Bounding box of the heightfield.
|
||
|
|
+ float cs, ch; // Cell size and height.
|
||
|
|
+ rcCompactCell* cells; // Pointer to width*height cells.
|
||
|
|
+ rcCompactSpan* spans; // Pointer to spans.
|
||
|
|
+ unsigned short* dist; // Pointer to per span distance to border.
|
||
|
|
+ unsigned char* areas; // Pointer to per span area ID.
|
||
|
|
};
|
||
|
|
|
||
|
|
-/// Represents a heightfield layer within a layer set.
|
||
|
|
-/// @see rcHeightfieldLayerSet
|
||
|
|
-struct rcHeightfieldLayer
|
||
|
|
-{
|
||
|
|
- float bmin[3]; ///< The minimum bounds in world space. [(x, y, z)]
|
||
|
|
- float bmax[3]; ///< The maximum bounds in world space. [(x, y, z)]
|
||
|
|
- float cs; ///< The size of each cell. (On the xz-plane.)
|
||
|
|
- float ch; ///< The height of each cell. (The minimum increment along the y-axis.)
|
||
|
|
- int width; ///< The width of the heightfield. (Along the x-axis in cell units.)
|
||
|
|
- int height; ///< The height of the heightfield. (Along the z-axis in cell units.)
|
||
|
|
- int minx; ///< The minimum x-bounds of usable data.
|
||
|
|
- int maxx; ///< The maximum x-bounds of usable data.
|
||
|
|
- int miny; ///< The minimum y-bounds of usable data. (Along the z-axis.)
|
||
|
|
- int maxy; ///< The maximum y-bounds of usable data. (Along the z-axis.)
|
||
|
|
- int hmin; ///< The minimum height bounds of usable data. (Along the y-axis.)
|
||
|
|
- int hmax; ///< The maximum height bounds of usable data. (Along the y-axis.)
|
||
|
|
- unsigned char* heights; ///< The heightfield. [Size: (width - borderSize*2) * (h - borderSize*2)]
|
||
|
|
- unsigned char* areas; ///< Area ids. [Size: Same as #heights]
|
||
|
|
- unsigned char* cons; ///< Packed neighbor connection information. [Size: Same as #heights]
|
||
|
|
-};
|
||
|
|
+rcCompactHeightfield* rcAllocCompactHeightfield();
|
||
|
|
+void rcFreeCompactHeightfield(rcCompactHeightfield* chf);
|
||
|
|
|
||
|
|
-/// Represents a set of heightfield layers.
|
||
|
|
-/// @ingroup recast
|
||
|
|
-/// @see rcAllocHeightfieldLayerSet, rcFreeHeightfieldLayerSet
|
||
|
|
-struct rcHeightfieldLayerSet
|
||
|
|
-{
|
||
|
|
- rcHeightfieldLayer* layers; ///< The layers in the set. [Size: #nlayers]
|
||
|
|
- int nlayers; ///< The number of layers in the set.
|
||
|
|
-};
|
||
|
|
|
||
|
|
-/// Represents a simple, non-overlapping contour in field space.
|
||
|
|
struct rcContour
|
||
|
|
{
|
||
|
|
- int* verts; ///< Simplified contour vertex and connection data. [Size: 4 * #nverts]
|
||
|
|
- int nverts; ///< The number of vertices in the simplified contour.
|
||
|
|
- int* rverts; ///< Raw contour vertex and connection data. [Size: 4 * #nrverts]
|
||
|
|
- int nrverts; ///< The number of vertices in the raw contour.
|
||
|
|
- unsigned short reg; ///< The region id of the contour.
|
||
|
|
- unsigned char area; ///< The area id of the contour.
|
||
|
|
+ int* verts; // Vertex coordinates, each vertex contains 4 components.
|
||
|
|
+ int nverts; // Number of vertices.
|
||
|
|
+ int* rverts; // Raw vertex coordinates, each vertex contains 4 components.
|
||
|
|
+ int nrverts; // Number of raw vertices.
|
||
|
|
+ unsigned short reg; // Region ID of the contour.
|
||
|
|
+ unsigned char area; // Area ID of the contour.
|
||
|
|
};
|
||
|
|
|
||
|
|
-/// Represents a group of related contours.
|
||
|
|
-/// @ingroup recast
|
||
|
|
struct rcContourSet
|
||
|
|
{
|
||
|
|
- rcContour* conts; ///< An array of the contours in the set. [Size: #nconts]
|
||
|
|
- int nconts; ///< The number of contours in the set.
|
||
|
|
- float bmin[3]; ///< The minimum bounds in world space. [(x, y, z)]
|
||
|
|
- float bmax[3]; ///< The maximum bounds in world space. [(x, y, z)]
|
||
|
|
- float cs; ///< The size of each cell. (On the xz-plane.)
|
||
|
|
- float ch; ///< The height of each cell. (The minimum increment along the y-axis.)
|
||
|
|
- int width; ///< The width of the set. (Along the x-axis in cell units.)
|
||
|
|
- int height; ///< The height of the set. (Along the z-axis in cell units.)
|
||
|
|
- int borderSize; ///< The AABB border size used to generate the source data from which the contours were derived.
|
||
|
|
-};
|
||
|
|
-
|
||
|
|
-/// Represents a polygon mesh suitable for use in building a navigation mesh.
|
||
|
|
-/// @ingroup recast
|
||
|
|
-struct rcPolyMesh
|
||
|
|
-{
|
||
|
|
- unsigned short* verts; ///< The mesh vertices. [Form: (x, y, z) * #nverts]
|
||
|
|
- unsigned short* polys; ///< Polygon and neighbor data. [Length: #maxpolys * 2 * #nvp]
|
||
|
|
- unsigned short* regs; ///< The region id assigned to each polygon. [Length: #maxpolys]
|
||
|
|
- unsigned short* flags; ///< The user defined flags for each polygon. [Length: #maxpolys]
|
||
|
|
- unsigned char* areas; ///< The area id assigned to each polygon. [Length: #maxpolys]
|
||
|
|
- int nverts; ///< The number of vertices.
|
||
|
|
- int npolys; ///< The number of polygons.
|
||
|
|
- int maxpolys; ///< The number of allocated polygons.
|
||
|
|
- int nvp; ///< The maximum number of vertices per polygon.
|
||
|
|
- float bmin[3]; ///< The minimum bounds in world space. [(x, y, z)]
|
||
|
|
- float bmax[3]; ///< The maximum bounds in world space. [(x, y, z)]
|
||
|
|
- float cs; ///< The size of each cell. (On the xz-plane.)
|
||
|
|
- float ch; ///< The height of each cell. (The minimum increment along the y-axis.)
|
||
|
|
- int borderSize; ///< The AABB border size used to generate the source data from which the mesh was derived.
|
||
|
|
-};
|
||
|
|
-
|
||
|
|
-/// Contains triangle meshes that represent detailed height data associated
|
||
|
|
-/// with the polygons in its associated polygon mesh object.
|
||
|
|
-/// @ingroup recast
|
||
|
|
-struct rcPolyMeshDetail
|
||
|
|
-{
|
||
|
|
- unsigned int* meshes; ///< The sub-mesh data. [Size: 4*#nmeshes]
|
||
|
|
- float* verts; ///< The mesh vertices. [Size: 3*#nverts]
|
||
|
|
- unsigned char* tris; ///< The mesh triangles. [Size: 4*#ntris]
|
||
|
|
- int nmeshes; ///< The number of sub-meshes defined by #meshes.
|
||
|
|
- int nverts; ///< The number of vertices in #verts.
|
||
|
|
- int ntris; ///< The number of triangles in #tris.
|
||
|
|
+ rcContour* conts; // Pointer to all contours.
|
||
|
|
+ int nconts; // Number of contours.
|
||
|
|
+ float bmin[3], bmax[3]; // Bounding box of the heightfield.
|
||
|
|
+ float cs, ch; // Cell size and height.
|
||
|
|
};
|
||
|
|
|
||
|
|
-/// @name Allocation Functions
|
||
|
|
-/// Functions used to allocate and de-allocate Recast objects.
|
||
|
|
-/// @see rcAllocSetCustom
|
||
|
|
-/// @{
|
||
|
|
-
|
||
|
|
-/// Allocates a heightfield object using the Recast allocator.
|
||
|
|
-/// @return A heightfield that is ready for initialization, or null on failure.
|
||
|
|
-/// @ingroup recast
|
||
|
|
-/// @see rcCreateHeightfield, rcFreeHeightField
|
||
|
|
-rcHeightfield* rcAllocHeightfield();
|
||
|
|
+rcContourSet* rcAllocContourSet();
|
||
|
|
+void rcFreeContourSet(rcContourSet* cset);
|
||
|
|
|
||
|
|
-/// Frees the specified heightfield object using the Recast allocator.
|
||
|
|
-/// @param[in] hf A heightfield allocated using #rcAllocHeightfield
|
||
|
|
-/// @ingroup recast
|
||
|
|
-/// @see rcAllocHeightfield
|
||
|
|
-void rcFreeHeightField(rcHeightfield* hf);
|
||
|
|
|
||
|
|
-/// Allocates a compact heightfield object using the Recast allocator.
|
||
|
|
-/// @return A compact heightfield that is ready for initialization, or null on failure.
|
||
|
|
-/// @ingroup recast
|
||
|
|
-/// @see rcBuildCompactHeightfield, rcFreeCompactHeightfield
|
||
|
|
-rcCompactHeightfield* rcAllocCompactHeightfield();
|
||
|
|
-
|
||
|
|
-/// Frees the specified compact heightfield object using the Recast allocator.
|
||
|
|
-/// @param[in] chf A compact heightfield allocated using #rcAllocCompactHeightfield
|
||
|
|
-/// @ingroup recast
|
||
|
|
-/// @see rcAllocCompactHeightfield
|
||
|
|
-void rcFreeCompactHeightfield(rcCompactHeightfield* chf);
|
||
|
|
+// Polymesh store a connected mesh of polygons.
|
||
|
|
+// The polygons are store in an array where each polygons takes
|
||
|
|
+// 'nvp*2' elements. The first 'nvp' elements are indices to vertices
|
||
|
|
+// and the second 'nvp' elements are indices to neighbour polygons.
|
||
|
|
+// If a polygon has less than 'bvp' vertices, the remaining indices
|
||
|
|
+// are set to RC_MESH_NULL_IDX. If an polygon edge does not have a neighbour
|
||
|
|
+// the neighbour index is set to RC_MESH_NULL_IDX.
|
||
|
|
+// Vertices can be transformed into world space as follows:
|
||
|
|
+// x = bmin[0] + verts[i*3+0]*cs;
|
||
|
|
+// y = bmin[1] + verts[i*3+1]*ch;
|
||
|
|
+// z = bmin[2] + verts[i*3+2]*cs;
|
||
|
|
+struct rcPolyMesh
|
||
|
|
+{
|
||
|
|
+ unsigned short* verts; // Vertices of the mesh, 3 elements per vertex.
|
||
|
|
+ unsigned short* polys; // Polygons of the mesh, nvp*2 elements per polygon.
|
||
|
|
+ unsigned short* regs; // Region ID of the polygons.
|
||
|
|
+ unsigned short* flags; // Per polygon flags.
|
||
|
|
+ unsigned char* areas; // Area ID of polygons.
|
||
|
|
+ int nverts; // Number of vertices.
|
||
|
|
+ int npolys; // Number of polygons.
|
||
|
|
+ int maxpolys; // Number of allocated polygons.
|
||
|
|
+ int nvp; // Max number of vertices per polygon.
|
||
|
|
+ float bmin[3], bmax[3]; // Bounding box of the mesh.
|
||
|
|
+ float cs, ch; // Cell size and height.
|
||
|
|
+};
|
||
|
|
|
||
|
|
-/// Allocates a heightfield layer set using the Recast allocator.
|
||
|
|
-/// @return A heightfield layer set that is ready for initialization, or null on failure.
|
||
|
|
-/// @ingroup recast
|
||
|
|
-/// @see rcBuildHeightfieldLayers, rcFreeHeightfieldLayerSet
|
||
|
|
-rcHeightfieldLayerSet* rcAllocHeightfieldLayerSet();
|
||
|
|
-
|
||
|
|
-/// Frees the specified heightfield layer set using the Recast allocator.
|
||
|
|
-/// @param[in] lset A heightfield layer set allocated using #rcAllocHeightfieldLayerSet
|
||
|
|
-/// @ingroup recast
|
||
|
|
-/// @see rcAllocHeightfieldLayerSet
|
||
|
|
-void rcFreeHeightfieldLayerSet(rcHeightfieldLayerSet* lset);
|
||
|
|
-
|
||
|
|
-/// Allocates a contour set object using the Recast allocator.
|
||
|
|
-/// @return A contour set that is ready for initialization, or null on failure.
|
||
|
|
-/// @ingroup recast
|
||
|
|
-/// @see rcBuildContours, rcFreeContourSet
|
||
|
|
-rcContourSet* rcAllocContourSet();
|
||
|
|
+rcPolyMesh* rcAllocPolyMesh();
|
||
|
|
+void rcFreePolyMesh(rcPolyMesh* pmesh);
|
||
|
|
|
||
|
|
-/// Frees the specified contour set using the Recast allocator.
|
||
|
|
-/// @param[in] cset A contour set allocated using #rcAllocContourSet
|
||
|
|
-/// @ingroup recast
|
||
|
|
-/// @see rcAllocContourSet
|
||
|
|
-void rcFreeContourSet(rcContourSet* cset);
|
||
|
|
|
||
|
|
-/// Allocates a polygon mesh object using the Recast allocator.
|
||
|
|
-/// @return A polygon mesh that is ready for initialization, or null on failure.
|
||
|
|
-/// @ingroup recast
|
||
|
|
-/// @see rcBuildPolyMesh, rcFreePolyMesh
|
||
|
|
-rcPolyMesh* rcAllocPolyMesh();
|
||
|
|
+// Detail mesh generated from a rcPolyMesh.
|
||
|
|
+// Each submesh represents a polygon in the polymesh and they are stored in
|
||
|
|
+// exactly same order. Each submesh is described as 4 values:
|
||
|
|
+// base vertex, vertex count, base triangle, triangle count. That is,
|
||
|
|
+// const unsigned char* t = &dmesh.tris[(tbase+i)*3]; and
|
||
|
|
+// const float* v = &dmesh.verts[(vbase+t[j])*3];
|
||
|
|
+// If the input polygon has 'n' vertices, those vertices are first in the
|
||
|
|
+// submesh vertex list. This allows to compres the mesh by not storing the
|
||
|
|
+// first vertices and using the polymesh vertices instead.
|
||
|
|
+// Max number of vertices per submesh is 127 and
|
||
|
|
+// max number of triangles per submesh is 255.
|
||
|
|
|
||
|
|
-/// Frees the specified polygon mesh using the Recast allocator.
|
||
|
|
-/// @param[in] pmesh A polygon mesh allocated using #rcAllocPolyMesh
|
||
|
|
-/// @ingroup recast
|
||
|
|
-/// @see rcAllocPolyMesh
|
||
|
|
-void rcFreePolyMesh(rcPolyMesh* pmesh);
|
||
|
|
+struct rcPolyMeshDetail
|
||
|
|
+{
|
||
|
|
+ unsigned int* meshes; // Pointer to all mesh data.
|
||
|
|
+ float* verts; // Pointer to all vertex data.
|
||
|
|
+ unsigned char* tris; // Pointer to all triangle data.
|
||
|
|
+ int nmeshes; // Number of meshes.
|
||
|
|
+ int nverts; // Number of total vertices.
|
||
|
|
+ int ntris; // Number of triangles.
|
||
|
|
+};
|
||
|
|
|
||
|
|
-/// Allocates a detail mesh object using the Recast allocator.
|
||
|
|
-/// @return A detail mesh that is ready for initialization, or null on failure.
|
||
|
|
-/// @ingroup recast
|
||
|
|
-/// @see rcBuildPolyMeshDetail, rcFreePolyMeshDetail
|
||
|
|
rcPolyMeshDetail* rcAllocPolyMeshDetail();
|
||
|
|
-
|
||
|
|
-/// Frees the specified detail mesh using the Recast allocator.
|
||
|
|
-/// @param[in] dmesh A detail mesh allocated using #rcAllocPolyMeshDetail
|
||
|
|
-/// @ingroup recast
|
||
|
|
-/// @see rcAllocPolyMeshDetail
|
||
|
|
void rcFreePolyMeshDetail(rcPolyMeshDetail* dmesh);
|
||
|
|
|
||
|
|
-/// @}
|
||
|
|
|
||
|
|
-/// Heighfield border flag.
|
||
|
|
-/// If a heightfield region ID has this bit set, then the region is a border
|
||
|
|
-/// region and its spans are considered unwalkable.
|
||
|
|
-/// (Used during the region and contour build process.)
|
||
|
|
-/// @see rcCompactSpan::reg
|
||
|
|
+// If heightfield region ID has the following bit set, the region is on border area
|
||
|
|
+// and excluded from many calculations.
|
||
|
|
static const unsigned short RC_BORDER_REG = 0x8000;
|
||
|
|
|
||
|
|
-/// Border vertex flag.
|
||
|
|
-/// If a region ID has this bit set, then the associated element lies on
|
||
|
|
-/// a tile border. If a contour vertex's region ID has this bit set, the
|
||
|
|
-/// vertex will later be removed in order to match the segments and vertices
|
||
|
|
-/// at tile boundaries.
|
||
|
|
-/// (Used during the build process.)
|
||
|
|
-/// @see rcCompactSpan::reg, #rcContour::verts, #rcContour::rverts
|
||
|
|
+// If contour region ID has the following bit set, the vertex will be later
|
||
|
|
+// removed in order to match the segments and vertices at tile boundaries.
|
||
|
|
static const int RC_BORDER_VERTEX = 0x10000;
|
||
|
|
|
||
|
|
-/// Area border flag.
|
||
|
|
-/// If a region ID has this bit set, then the associated element lies on
|
||
|
|
-/// the border of an area.
|
||
|
|
-/// (Used during the region and contour build process.)
|
||
|
|
-/// @see rcCompactSpan::reg, #rcContour::verts, #rcContour::rverts
|
||
|
|
static const int RC_AREA_BORDER = 0x20000;
|
||
|
|
|
||
|
|
-/// Contour build flags.
|
||
|
|
-/// @see rcBuildContours
|
||
|
|
enum rcBuildContoursFlags
|
||
|
|
{
|
||
|
|
- RC_CONTOUR_TESS_WALL_EDGES = 0x01, ///< Tessellate solid (impassable) edges during contour simplification.
|
||
|
|
- RC_CONTOUR_TESS_AREA_EDGES = 0x02, ///< Tessellate edges between areas during contour simplification.
|
||
|
|
+ RC_CONTOUR_TESS_WALL_EDGES = 0x01, // Tessellate wall edges
|
||
|
|
+ RC_CONTOUR_TESS_AREA_EDGES = 0x02, // Tessellate edges between areas.
|
||
|
|
};
|
||
|
|
|
||
|
|
-/// Applied to the region id field of contour vertices in order to extract the region id.
|
||
|
|
-/// The region id field of a vertex may have several flags applied to it. So the
|
||
|
|
-/// fields value can't be used directly.
|
||
|
|
-/// @see rcContour::verts, rcContour::rverts
|
||
|
|
+// Mask used with contours to extract region id.
|
||
|
|
static const int RC_CONTOUR_REG_MASK = 0xffff;
|
||
|
|
|
||
|
|
-/// An value which indicates an invalid index within a mesh.
|
||
|
|
-/// @note This does not necessarily indicate an error.
|
||
|
|
-/// @see rcPolyMesh::polys
|
||
|
|
+// Null index which is used with meshes to mark unset or invalid indices.
|
||
|
|
static const unsigned short RC_MESH_NULL_IDX = 0xffff;
|
||
|
|
|
||
|
|
-/// Represents the null area.
|
||
|
|
-/// When a data element is given this value it is considered to no longer be
|
||
|
|
-/// assigned to a usable area. (E.g. It is unwalkable.)
|
||
|
|
+// Area ID that is considered empty.
|
||
|
|
static const unsigned char RC_NULL_AREA = 0;
|
||
|
|
|
||
|
|
-/// The default area id used to indicate a walkable polygon.
|
||
|
|
-/// This is also the maximum allowed area id, and the only non-null area id
|
||
|
|
-/// recognized by some steps in the build process.
|
||
|
|
+// Area ID that is considered generally walkable.
|
||
|
|
static const unsigned char RC_WALKABLE_AREA = 63;
|
||
|
|
|
||
|
|
-/// The value returned by #rcGetCon if the specified direction is not connected
|
||
|
|
-/// to another span. (Has no neighbor.)
|
||
|
|
+// Value returned by rcGetCon() if the direction is not connected.
|
||
|
|
static const int RC_NOT_CONNECTED = 0x3f;
|
||
|
|
|
||
|
|
-/// @name General helper functions
|
||
|
|
-/// @{
|
||
|
|
+// Compact span neighbour helpers.
|
||
|
|
+inline void rcSetCon(rcCompactSpan& s, int dir, int i)
|
||
|
|
+{
|
||
|
|
+ const unsigned int shift = (unsigned int)dir*6;
|
||
|
|
+ unsigned int con = s.con;
|
||
|
|
+ s.con = (con & ~(0x3f << shift)) | (((unsigned int)i & 0x3f) << shift);
|
||
|
|
+}
|
||
|
|
|
||
|
|
-/// Swaps the values of the two parameters.
|
||
|
|
-/// @param[in,out] a Value A
|
||
|
|
-/// @param[in,out] b Value B
|
||
|
|
-template<class T> inline void rcSwap(T& a, T& b) { T t = a; a = b; b = t; }
|
||
|
|
+inline int rcGetCon(const rcCompactSpan& s, int dir)
|
||
|
|
+{
|
||
|
|
+ const unsigned int shift = (unsigned int)dir*6;
|
||
|
|
+ return (s.con >> shift) & 0x3f;
|
||
|
|
+}
|
||
|
|
|
||
|
|
-/// 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 rcMin(T a, T b) { return a < b ? a : b; }
|
||
|
|
+inline int rcGetDirOffsetX(int dir)
|
||
|
|
+{
|
||
|
|
+ const int offset[4] = { -1, 0, 1, 0, };
|
||
|
|
+ return offset[dir&0x03];
|
||
|
|
+}
|
||
|
|
|
||
|
|
-/// 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 rcMax(T a, T b) { return a > b ? a : b; }
|
||
|
|
+inline int rcGetDirOffsetY(int dir)
|
||
|
|
+{
|
||
|
|
+ const int offset[4] = { 0, 1, 0, -1 };
|
||
|
|
+ return offset[dir&0x03];
|
||
|
|
+}
|
||
|
|
|
||
|
|
-/// Returns the absolute value.
|
||
|
|
-/// @param[in] a The value.
|
||
|
|
-/// @return The absolute value of the specified value.
|
||
|
|
+// Common helper functions
|
||
|
|
+template<class T> inline void rcSwap(T& a, T& b) { T t = a; a = b; b = t; }
|
||
|
|
+template<class T> inline T rcMin(T a, T b) { return a < b ? a : b; }
|
||
|
|
+template<class T> inline T rcMax(T a, T b) { return a > b ? a : b; }
|
||
|
|
template<class T> inline T rcAbs(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 rcSqr(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 rcClamp(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 rcSqrt(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)]
|
||
|
|
+// Common vector helper functions.
|
||
|
|
inline void rcVcross(float* dest, const float* v1, const float* v2)
|
||
|
|
{
|
||
|
|
dest[0] = v1[1]*v2[2] - v1[2]*v2[1];
|
||
|
|
@@ -603,20 +347,11 @@ inline void rcVcross(float* dest, const float* v1, const float* v2)
|
||
|
|
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 rcVdot(const float* v1, const float* v2)
|
||
|
|
{
|
||
|
|
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 rcVmad(float* dest, const float* v1, const float* v2, const float s)
|
||
|
|
{
|
||
|
|
dest[0] = v1[0]+v2[0]*s;
|
||
|
|
@@ -624,10 +359,6 @@ inline void rcVmad(float* dest, const float* v1, const float* v2, const float s)
|
||
|
|
dest[2] = v1[2]+v2[2]*s;
|
||
|
|
}
|
||
|
|
|
||
|
|
-/// 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 rcVadd(float* dest, const float* v1, const float* v2)
|
||
|
|
{
|
||
|
|
dest[0] = v1[0]+v2[0];
|
||
|
|
@@ -635,10 +366,6 @@ inline void rcVadd(float* dest, const float* v1, const float* v2)
|
||
|
|
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 rcVsub(float* dest, const float* v1, const float* v2)
|
||
|
|
{
|
||
|
|
dest[0] = v1[0]-v2[0];
|
||
|
|
@@ -646,9 +373,6 @@ inline void rcVsub(float* dest, const float* v1, const float* v2)
|
||
|
|
dest[2] = v1[2]-v2[2];
|
||
|
|
}
|
||
|
|
|
||
|
|
-/// 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 rcVmin(float* mn, const float* v)
|
||
|
|
{
|
||
|
|
mn[0] = rcMin(mn[0], v[0]);
|
||
|
|
@@ -656,9 +380,6 @@ inline void rcVmin(float* mn, const float* v)
|
||
|
|
mn[2] = rcMin(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 rcVmax(float* mx, const float* v)
|
||
|
|
{
|
||
|
|
mx[0] = rcMax(mx[0], v[0]);
|
||
|
|
@@ -666,9 +387,6 @@ inline void rcVmax(float* mx, const float* v)
|
||
|
|
mx[2] = rcMax(mx[2], v[2]);
|
||
|
|
}
|
||
|
|
|
||
|
|
-/// Performs a vector copy.
|
||
|
|
-/// @param[out] dest The result. [(x, y, z)]
|
||
|
|
-/// @param[in] v The vector to copy. [(x, y, z)]
|
||
|
|
inline void rcVcopy(float* dest, const float* v)
|
||
|
|
{
|
||
|
|
dest[0] = v[0];
|
||
|
|
@@ -676,10 +394,6 @@ inline void rcVcopy(float* dest, const float* v)
|
||
|
|
dest[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 rcVdist(const float* v1, const float* v2)
|
||
|
|
{
|
||
|
|
float dx = v2[0] - v1[0];
|
||
|
|
@@ -688,10 +402,6 @@ inline float rcVdist(const float* v1, const float* v2)
|
||
|
|
return rcSqrt(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 rcVdistSqr(const float* v1, const float* v2)
|
||
|
|
{
|
||
|
|
float dx = v2[0] - v1[0];
|
||
|
|
@@ -700,8 +410,6 @@ inline float rcVdistSqr(const float* v1, const float* v2)
|
||
|
|
return dx*dx + dy*dy + dz*dz;
|
||
|
|
}
|
||
|
|
|
||
|
|
-/// Normalizes the vector.
|
||
|
|
-/// @param[in,out] v The vector to normalize. [(x, y, z)]
|
||
|
|
inline void rcVnormalize(float* v)
|
||
|
|
{
|
||
|
|
float d = 1.0f / rcSqrt(rcSqr(v[0]) + rcSqr(v[1]) + rcSqr(v[2]));
|
||
|
|
@@ -710,421 +418,271 @@ inline void rcVnormalize(float* v)
|
||
|
|
v[2] *= d;
|
||
|
|
}
|
||
|
|
|
||
|
|
-/// @}
|
||
|
|
-/// @name Heightfield Functions
|
||
|
|
-/// @see rcHeightfield
|
||
|
|
-/// @{
|
||
|
|
-
|
||
|
|
-/// Calculates the bounding box of an array of vertices.
|
||
|
|
-/// @ingroup recast
|
||
|
|
-/// @param[in] verts An array of vertices. [(x, y, z) * @p nv]
|
||
|
|
-/// @param[in] nv The number of vertices in the @p verts array.
|
||
|
|
-/// @param[out] bmin The minimum bounds of the AABB. [(x, y, z)] [Units: wu]
|
||
|
|
-/// @param[out] bmax The maximum bounds of the AABB. [(x, y, z)] [Units: wu]
|
||
|
|
+inline bool rcVequal(const float* p0, const float* p1)
|
||
|
|
+{
|
||
|
|
+ static const float thr = rcSqr(1.0f/16384.0f);
|
||
|
|
+ const float d = rcVdistSqr(p0, p1);
|
||
|
|
+ return d < thr;
|
||
|
|
+}
|
||
|
|
+
|
||
|
|
+// Calculated bounding box of array of vertices.
|
||
|
|
+// Params:
|
||
|
|
+// verts - (in) array of vertices
|
||
|
|
+// nv - (in) vertex count
|
||
|
|
+// bmin, bmax - (out) bounding box
|
||
|
|
void rcCalcBounds(const float* verts, int nv, float* bmin, float* bmax);
|
||
|
|
|
||
|
|
-/// Calculates the grid size based on the bounding box and grid cell size.
|
||
|
|
-/// @ingroup recast
|
||
|
|
-/// @param[in] bmin The minimum bounds of the AABB. [(x, y, z)] [Units: wu]
|
||
|
|
-/// @param[in] bmax The maximum bounds of the AABB. [(x, y, z)] [Units: wu]
|
||
|
|
-/// @param[in] cs The xz-plane cell size. [Limit: > 0] [Units: wu]
|
||
|
|
-/// @param[out] w The width along the x-axis. [Limit: >= 0] [Units: vx]
|
||
|
|
-/// @param[out] h The height along the z-axis. [Limit: >= 0] [Units: vx]
|
||
|
|
+// Calculates grid size based on bounding box and grid cell size.
|
||
|
|
+// Params:
|
||
|
|
+// bmin, bmax - (in) bounding box
|
||
|
|
+// cs - (in) grid cell size
|
||
|
|
+// w - (out) grid width
|
||
|
|
+// h - (out) grid height
|
||
|
|
void rcCalcGridSize(const float* bmin, const float* bmax, float cs, int* w, int* h);
|
||
|
|
|
||
|
|
-/// Initializes a new heightfield.
|
||
|
|
-/// @ingroup recast
|
||
|
|
-/// @param[in,out] ctx The build context to use during the operation.
|
||
|
|
-/// @param[in,out] hf The allocated heightfield to initialize.
|
||
|
|
-/// @param[in] width The width of the field along the x-axis. [Limit: >= 0] [Units: vx]
|
||
|
|
-/// @param[in] height The height of the field along the z-axis. [Limit: >= 0] [Units: vx]
|
||
|
|
-/// @param[in] bmin The minimum bounds of the field's AABB. [(x, y, z)] [Units: wu]
|
||
|
|
-/// @param[in] bmax The maximum bounds of the field's AABB. [(x, y, z)] [Units: wu]
|
||
|
|
-/// @param[in] cs The xz-plane cell size to use for the field. [Limit: > 0] [Units: wu]
|
||
|
|
-/// @param[in] ch The y-axis cell size to use for field. [Limit: > 0] [Units: wu]
|
||
|
|
+// Creates and initializes new heightfield.
|
||
|
|
+// Params:
|
||
|
|
+// hf - (in/out) heightfield to initialize.
|
||
|
|
+// width - (in) width of the heightfield.
|
||
|
|
+// height - (in) height of the heightfield.
|
||
|
|
+// bmin, bmax - (in) bounding box of the heightfield
|
||
|
|
+// cs - (in) grid cell size
|
||
|
|
+// ch - (in) grid cell height
|
||
|
|
bool rcCreateHeightfield(rcContext* ctx, rcHeightfield& hf, int width, int height,
|
||
|
|
const float* bmin, const float* bmax,
|
||
|
|
float cs, float ch);
|
||
|
|
|
||
|
|
-/// Sets the area id of all triangles with a slope below the specified value
|
||
|
|
-/// to #RC_WALKABLE_AREA.
|
||
|
|
-/// @ingroup recast
|
||
|
|
-/// @param[in,out] ctx The build context to use during the operation.
|
||
|
|
-/// @param[in] walkableSlopeAngle The maximum slope that is considered walkable.
|
||
|
|
-/// [Limits: 0 <= value < 90] [Units: Degrees]
|
||
|
|
-/// @param[in] verts The vertices. [(x, y, z) * @p nv]
|
||
|
|
-/// @param[in] nv The number of vertices.
|
||
|
|
-/// @param[in] tris The triangle vertex indices. [(vertA, vertB, vertC) * @p nt]
|
||
|
|
-/// @param[in] nt The number of triangles.
|
||
|
|
-/// @param[out] areas The triangle area ids. [Length: >= @p nt]
|
||
|
|
+// Sets the RC_WALKABLE_AREA for every triangle whose slope is below
|
||
|
|
+// the maximum walkable slope angle.
|
||
|
|
+// Params:
|
||
|
|
+// walkableSlopeAngle - (in) maximum slope angle in degrees.
|
||
|
|
+// verts - (in) array of vertices
|
||
|
|
+// nv - (in) vertex count
|
||
|
|
+// tris - (in) array of triangle vertex indices
|
||
|
|
+// nt - (in) triangle count
|
||
|
|
+// areas - (out) array of triangle area types
|
||
|
|
void rcMarkWalkableTriangles(rcContext* ctx, const float walkableSlopeAngle, const float* verts, int nv,
|
||
|
|
const int* tris, int nt, unsigned char* areas);
|
||
|
|
|
||
|
|
-/// Sets the area id of all triangles with a slope greater than or equal to the specified value to #RC_NULL_AREA.
|
||
|
|
-/// @ingroup recast
|
||
|
|
-/// @param[in,out] ctx The build context to use during the operation.
|
||
|
|
-/// @param[in] walkableSlopeAngle The maximum slope that is considered walkable.
|
||
|
|
-/// [Limits: 0 <= value < 90] [Units: Degrees]
|
||
|
|
-/// @param[in] verts The vertices. [(x, y, z) * @p nv]
|
||
|
|
-/// @param[in] nv The number of vertices.
|
||
|
|
-/// @param[in] tris The triangle vertex indices. [(vertA, vertB, vertC) * @p nt]
|
||
|
|
-/// @param[in] nt The number of triangles.
|
||
|
|
-/// @param[out] areas The triangle area ids. [Length: >= @p nt]
|
||
|
|
+// Sets the RC_NULL_AREA for every triangle whose slope is steeper than
|
||
|
|
+// the maximum walkable slope angle.
|
||
|
|
+// Params:
|
||
|
|
+// walkableSlopeAngle - (in) maximum slope angle in degrees.
|
||
|
|
+// verts - (in) array of vertices
|
||
|
|
+// nv - (in) vertex count
|
||
|
|
+// tris - (in) array of triangle vertex indices
|
||
|
|
+// nt - (in) triangle count
|
||
|
|
+// areas - (out) array of triangle are types
|
||
|
|
void rcClearUnwalkableTriangles(rcContext* ctx, const float walkableSlopeAngle, const float* verts, int nv,
|
||
|
|
const int* tris, int nt, unsigned char* areas);
|
||
|
|
|
||
|
|
-/// Adds a span to the specified heightfield.
|
||
|
|
-/// @ingroup recast
|
||
|
|
-/// @param[in,out] ctx The build context to use during the operation.
|
||
|
|
-/// @param[in,out] hf An initialized heightfield.
|
||
|
|
-/// @param[in] x The width index where the span is to be added.
|
||
|
|
-/// [Limits: 0 <= value < rcHeightfield::width]
|
||
|
|
-/// @param[in] y The height index where the span is to be added.
|
||
|
|
-/// [Limits: 0 <= value < rcHeightfield::height]
|
||
|
|
-/// @param[in] smin The minimum height of the span. [Limit: < @p smax] [Units: vx]
|
||
|
|
-/// @param[in] smax The maximum height of the span. [Limit: <= #RC_SPAN_MAX_HEIGHT] [Units: vx]
|
||
|
|
-/// @param[in] area The area id of the span. [Limit: <= #RC_WALKABLE_AREA)
|
||
|
|
-/// @param[in] flagMergeThr The merge theshold. [Limit: >= 0] [Units: vx]
|
||
|
|
-void rcAddSpan(rcContext* ctx, rcHeightfield& hf, const int x, const int y,
|
||
|
|
+// Adds span to heightfield.
|
||
|
|
+// The span addition can set to favor flags. If the span is merged to
|
||
|
|
+// another span and the new smax is within 'flagMergeThr' units away
|
||
|
|
+// from the existing span the span flags are merged and stored.
|
||
|
|
+// Params:
|
||
|
|
+// solid - (in) heightfield where the spans is added to
|
||
|
|
+// x,y - (in) location on the heightfield where the span is added
|
||
|
|
+// smin,smax - (in) spans min/max height
|
||
|
|
+// flags - (in) span flags (zero or WALKABLE)
|
||
|
|
+// flagMergeThr - (in) merge threshold.
|
||
|
|
+void rcAddSpan(rcContext* ctx, rcHeightfield& solid, const int x, const int y,
|
||
|
|
const unsigned short smin, const unsigned short smax,
|
||
|
|
- const unsigned char area, const int flagMergeThr);
|
||
|
|
-
|
||
|
|
-/// Rasterizes a triangle into the specified heightfield.
|
||
|
|
-/// @ingroup recast
|
||
|
|
-/// @param[in,out] ctx The build context to use during the operation.
|
||
|
|
-/// @param[in] v0 Triangle vertex 0 [(x, y, z)]
|
||
|
|
-/// @param[in] v1 Triangle vertex 1 [(x, y, z)]
|
||
|
|
-/// @param[in] v2 Triangle vertex 2 [(x, y, z)]
|
||
|
|
-/// @param[in] area The area id of the triangle. [Limit: <= #RC_WALKABLE_AREA]
|
||
|
|
-/// @param[in,out] solid An initialized heightfield.
|
||
|
|
-/// @param[in] flagMergeThr The distance where the walkable flag is favored over the non-walkable flag.
|
||
|
|
-/// [Limit: >= 0] [Units: vx]
|
||
|
|
+ const unsigned short area, const int flagMergeThr);
|
||
|
|
+
|
||
|
|
+// Rasterizes a triangle into heightfield spans.
|
||
|
|
+// Params:
|
||
|
|
+// v0,v1,v2 - (in) the vertices of the triangle.
|
||
|
|
+// area - (in) area type of the triangle.
|
||
|
|
+// solid - (in) heightfield where the triangle is rasterized
|
||
|
|
+// flagMergeThr - (in) distance in voxel where walkable flag is favored over non-walkable.
|
||
|
|
void rcRasterizeTriangle(rcContext* ctx, const float* v0, const float* v1, const float* v2,
|
||
|
|
const unsigned char area, rcHeightfield& solid,
|
||
|
|
const int flagMergeThr = 1);
|
||
|
|
|
||
|
|
-/// Rasterizes an indexed triangle mesh into the specified heightfield.
|
||
|
|
-/// @ingroup recast
|
||
|
|
-/// @param[in,out] ctx The build context to use during the operation.
|
||
|
|
-/// @param[in] verts The vertices. [(x, y, z) * @p nv]
|
||
|
|
-/// @param[in] nv The number of vertices.
|
||
|
|
-/// @param[in] tris The triangle indices. [(vertA, vertB, vertC) * @p nt]
|
||
|
|
-/// @param[in] areas The area id's of the triangles. [Limit: <= #RC_WALKABLE_AREA] [Size: @p nt]
|
||
|
|
-/// @param[in] nt The number of triangles.
|
||
|
|
-/// @param[in,out] solid An initialized heightfield.
|
||
|
|
-/// @param[in] flagMergeThr The distance where the walkable flag is favored over the non-walkable flag.
|
||
|
|
-/// [Limit: >= 0] [Units: vx]
|
||
|
|
+// Rasterizes indexed triangle mesh into heightfield spans.
|
||
|
|
+// Params:
|
||
|
|
+// verts - (in) array of vertices
|
||
|
|
+// nv - (in) vertex count
|
||
|
|
+// tris - (in) array of triangle vertex indices
|
||
|
|
+// area - (in) array of triangle area types.
|
||
|
|
+// nt - (in) triangle count
|
||
|
|
+// solid - (in) heightfield where the triangles are rasterized
|
||
|
|
+// flagMergeThr - (in) distance in voxel where walkable flag is favored over non-walkable.
|
||
|
|
void rcRasterizeTriangles(rcContext* ctx, const float* verts, const int nv,
|
||
|
|
const int* tris, const unsigned char* areas, const int nt,
|
||
|
|
rcHeightfield& solid, const int flagMergeThr = 1);
|
||
|
|
|
||
|
|
-/// Rasterizes an indexed triangle mesh into the specified heightfield.
|
||
|
|
-/// @ingroup recast
|
||
|
|
-/// @param[in,out] ctx The build context to use during the operation.
|
||
|
|
-/// @param[in] verts The vertices. [(x, y, z) * @p nv]
|
||
|
|
-/// @param[in] nv The number of vertices.
|
||
|
|
-/// @param[in] tris The triangle indices. [(vertA, vertB, vertC) * @p nt]
|
||
|
|
-/// @param[in] areas The area id's of the triangles. [Limit: <= #RC_WALKABLE_AREA] [Size: @p nt]
|
||
|
|
-/// @param[in] nt The number of triangles.
|
||
|
|
-/// @param[in,out] solid An initialized heightfield.
|
||
|
|
-/// @param[in] flagMergeThr The distance where the walkable flag is favored over the non-walkable flag.
|
||
|
|
-/// [Limit: >= 0] [Units: vx]
|
||
|
|
+// Rasterizes indexed triangle mesh into heightfield spans.
|
||
|
|
+// Params:
|
||
|
|
+// verts - (in) array of vertices
|
||
|
|
+// nv - (in) vertex count
|
||
|
|
+// tris - (in) array of triangle vertex indices
|
||
|
|
+// area - (in) array of triangle area types.
|
||
|
|
+// nt - (in) triangle count
|
||
|
|
+// solid - (in) heightfield where the triangles are rasterized
|
||
|
|
+// flagMergeThr - (in) distance in voxel where walkable flag is favored over non-walkable.
|
||
|
|
void rcRasterizeTriangles(rcContext* ctx, const float* verts, const int nv,
|
||
|
|
const unsigned short* tris, const unsigned char* areas, const int nt,
|
||
|
|
rcHeightfield& solid, const int flagMergeThr = 1);
|
||
|
|
|
||
|
|
-/// Rasterizes triangles into the specified heightfield.
|
||
|
|
-/// @ingroup recast
|
||
|
|
-/// @param[in,out] ctx The build context to use during the operation.
|
||
|
|
-/// @param[in] verts The triangle vertices. [(ax, ay, az, bx, by, bz, cx, by, cx) * @p nt]
|
||
|
|
-/// @param[in] areas The area id's of the triangles. [Limit: <= #RC_WALKABLE_AREA] [Size: @p nt]
|
||
|
|
-/// @param[in] nt The number of triangles.
|
||
|
|
-/// @param[in,out] solid An initialized heightfield.
|
||
|
|
-/// @param[in] flagMergeThr The distance where the walkable flag is favored over the non-walkable flag.
|
||
|
|
-/// [Limit: >= 0] [Units: vx]
|
||
|
|
+// Rasterizes the triangles into heightfield spans.
|
||
|
|
+// Params:
|
||
|
|
+// verts - (in) array of vertices
|
||
|
|
+// area - (in) array of triangle area types.
|
||
|
|
+// nt - (in) triangle count
|
||
|
|
+// solid - (in) heightfield where the triangles are rasterized
|
||
|
|
void rcRasterizeTriangles(rcContext* ctx, const float* verts, const unsigned char* areas, const int nt,
|
||
|
|
rcHeightfield& solid, const int flagMergeThr = 1);
|
||
|
|
|
||
|
|
-/// Marks non-walkable spans as walkable if their maximum is within @p walkableClimp of a walkable neihbor.
|
||
|
|
-/// @ingroup recast
|
||
|
|
-/// @param[in,out] ctx The build context to use during the operation.
|
||
|
|
-/// @param[in] walkableClimb Maximum ledge height that is considered to still be traversable.
|
||
|
|
-/// [Limit: >=0] [Units: vx]
|
||
|
|
-/// @param[in,out] solid A fully built heightfield. (All spans have been added.)
|
||
|
|
+// Marks non-walkable low obstacles as walkable if they are closer than walkableClimb
|
||
|
|
+// from a walkable surface. Applying this filter allows to step over low hanging
|
||
|
|
+// low obstacles.
|
||
|
|
+// Params:
|
||
|
|
+// walkableHeight - (in) minimum height where the agent can still walk
|
||
|
|
+// solid - (in/out) heightfield describing the solid space
|
||
|
|
+// TODO: Missuses ledge flag, must be called before rcFilterLedgeSpans!
|
||
|
|
void rcFilterLowHangingWalkableObstacles(rcContext* ctx, const int walkableClimb, rcHeightfield& solid);
|
||
|
|
|
||
|
|
-/// Marks spans that are ledges as not-walkable.
|
||
|
|
-/// @ingroup recast
|
||
|
|
-/// @param[in,out] ctx The build context to use during the operation.
|
||
|
|
-/// @param[in] walkableHeight Minimum floor to 'ceiling' height that will still allow the floor area to
|
||
|
|
-/// be considered walkable. [Limit: >= 3] [Units: vx]
|
||
|
|
-/// @param[in] walkableClimb Maximum ledge height that is considered to still be traversable.
|
||
|
|
-/// [Limit: >=0] [Units: vx]
|
||
|
|
-/// @param[in,out] solid A fully built heightfield. (All spans have been added.)
|
||
|
|
+// Removes WALKABLE flag from all spans that are at ledges. This filtering
|
||
|
|
+// removes possible overestimation of the conservative voxelization so that
|
||
|
|
+// the resulting mesh will not have regions hanging in air over ledges.
|
||
|
|
+// Params:
|
||
|
|
+// walkableHeight - (in) minimum height where the agent can still walk
|
||
|
|
+// walkableClimb - (in) maximum height between grid cells the agent can climb
|
||
|
|
+// solid - (in/out) heightfield describing the solid space
|
||
|
|
void rcFilterLedgeSpans(rcContext* ctx, const int walkableHeight,
|
||
|
|
const int walkableClimb, rcHeightfield& solid);
|
||
|
|
|
||
|
|
-/// Marks walkable spans as not walkable if the clearence above the span is less than the specified height.
|
||
|
|
-/// @ingroup recast
|
||
|
|
-/// @param[in,out] ctx The build context to use during the operation.
|
||
|
|
-/// @param[in] walkableHeight Minimum floor to 'ceiling' height that will still allow the floor area to
|
||
|
|
-/// be considered walkable. [Limit: >= 3] [Units: vx]
|
||
|
|
-/// @param[in,out] solid A fully built heightfield. (All spans have been added.)
|
||
|
|
+// Removes WALKABLE flag from all spans which have smaller than
|
||
|
|
+// 'walkableHeight' clearance above them.
|
||
|
|
+// Params:
|
||
|
|
+// walkableHeight - (in) minimum height where the agent can still walk
|
||
|
|
+// solid - (in/out) heightfield describing the solid space
|
||
|
|
void rcFilterWalkableLowHeightSpans(rcContext* ctx, int walkableHeight, rcHeightfield& solid);
|
||
|
|
|
||
|
|
-/// Returns the number of spans contained in the specified heightfield.
|
||
|
|
-/// @ingroup recast
|
||
|
|
-/// @param[in,out] ctx The build context to use during the operation.
|
||
|
|
-/// @param[in] hf An initialized heightfield.
|
||
|
|
-/// @returns The number of spans in the heightfield.
|
||
|
|
+// Returns number of spans contained in a heightfield.
|
||
|
|
+// Params:
|
||
|
|
+// hf - (in) heightfield to be compacted
|
||
|
|
+// Returns number of spans.
|
||
|
|
int rcGetHeightFieldSpanCount(rcContext* ctx, rcHeightfield& hf);
|
||
|
|
|
||
|
|
-/// @}
|
||
|
|
-/// @name Compact Heightfield Functions
|
||
|
|
-/// @see rcCompactHeightfield
|
||
|
|
-/// @{
|
||
|
|
-
|
||
|
|
-/// Builds a compact heightfield representing open space, from a heightfield representing solid space.
|
||
|
|
-/// @ingroup recast
|
||
|
|
-/// @param[in,out] ctx The build context to use during the operation.
|
||
|
|
-/// @param[in] walkableHeight Minimum floor to 'ceiling' height that will still allow the floor area
|
||
|
|
-/// to be considered walkable. [Limit: >= 3] [Units: vx]
|
||
|
|
-/// @param[in] walkableClimb Maximum ledge height that is considered to still be traversable.
|
||
|
|
-/// [Limit: >=0] [Units: vx]
|
||
|
|
-/// @param[in] hf The heightfield to be compacted.
|
||
|
|
-/// @param[out] chf The resulting compact heightfield. (Must be pre-allocated.)
|
||
|
|
-/// @returns True if the operation completed successfully.
|
||
|
|
+// Builds compact representation of the heightfield.
|
||
|
|
+// Params:
|
||
|
|
+// walkableHeight - (in) minimum height where the agent can still walk
|
||
|
|
+// walkableClimb - (in) maximum height between grid cells the agent can climb
|
||
|
|
+// flags - (in) require flags for a cell to be included in the compact heightfield.
|
||
|
|
+// hf - (in) heightfield to be compacted
|
||
|
|
+// chf - (out) compact heightfield representing the open space.
|
||
|
|
+// Returns false if operation ran out of memory.
|
||
|
|
bool rcBuildCompactHeightfield(rcContext* ctx, const int walkableHeight, const int walkableClimb,
|
||
|
|
rcHeightfield& hf, rcCompactHeightfield& chf);
|
||
|
|
|
||
|
|
-/// Erodes the walkable area within the heightfield by the specified radius.
|
||
|
|
-/// @ingroup recast
|
||
|
|
-/// @param[in,out] ctx The build context to use during the operation.
|
||
|
|
-/// @param[in] radius The radius of erosion. [Limits: 0 < value < 255] [Units: vx]
|
||
|
|
-/// @param[in,out] chf The populated compact heightfield to erode.
|
||
|
|
-/// @returns True if the operation completed successfully.
|
||
|
|
+// Erodes walkable area.
|
||
|
|
+// Params:
|
||
|
|
+// radius - (in) radius of erosion (max 255).
|
||
|
|
+// chf - (in/out) compact heightfield to erode.
|
||
|
|
+// Returns false if operation ran out of memory.
|
||
|
|
bool rcErodeWalkableArea(rcContext* ctx, int radius, rcCompactHeightfield& chf);
|
||
|
|
|
||
|
|
-/// Applies a median filter to walkable area types (based on area id), removing noise.
|
||
|
|
-/// @ingroup recast
|
||
|
|
-/// @param[in,out] ctx The build context to use during the operation.
|
||
|
|
-/// @param[in,out] chf A populated compact heightfield.
|
||
|
|
-/// @returns True if the operation completed successfully.
|
||
|
|
+// Applies median filter to walkable area types, removing noise.
|
||
|
|
+// Params:
|
||
|
|
+// chf - (in/out) compact heightfield to erode.
|
||
|
|
+// Returns false if operation ran out of memory.
|
||
|
|
bool rcMedianFilterWalkableArea(rcContext* ctx, rcCompactHeightfield& chf);
|
||
|
|
|
||
|
|
-/// Applies an area id to all spans within the specified bounding box. (AABB)
|
||
|
|
-/// @ingroup recast
|
||
|
|
-/// @param[in,out] ctx The build context to use during the operation.
|
||
|
|
-/// @param[in] bmin The minimum of the bounding box. [(x, y, z)]
|
||
|
|
-/// @param[in] bmax The maximum of the bounding box. [(x, y, z)]
|
||
|
|
-/// @param[in] areaId The area id to apply. [Limit: <= #RC_WALKABLE_AREA]
|
||
|
|
-/// @param[in,out] chf A populated compact heightfield.
|
||
|
|
+// Marks the area of the convex polygon into the area type of the compact heightfield.
|
||
|
|
+// Params:
|
||
|
|
+// bmin/bmax - (in) bounds of the axis aligned box.
|
||
|
|
+// areaId - (in) area ID to mark.
|
||
|
|
+// chf - (in/out) compact heightfield to mark.
|
||
|
|
void rcMarkBoxArea(rcContext* ctx, const float* bmin, const float* bmax, unsigned char areaId,
|
||
|
|
rcCompactHeightfield& chf);
|
||
|
|
|
||
|
|
-/// Applies the area id to the all spans within the specified convex polygon.
|
||
|
|
-/// @ingroup recast
|
||
|
|
-/// @param[in,out] ctx The build context to use during the operation.
|
||
|
|
-/// @param[in] verts The vertices of the polygon [Fomr: (x, y, z) * @p nverts]
|
||
|
|
-/// @param[in] nverts The number of vertices in the polygon.
|
||
|
|
-/// @param[in] hmin The height of the base of the polygon.
|
||
|
|
-/// @param[in] hmax The height of the top of the polygon.
|
||
|
|
-/// @param[in] areaId The area id to apply. [Limit: <= #RC_WALKABLE_AREA]
|
||
|
|
-/// @param[in,out] chf A populated compact heightfield.
|
||
|
|
+// Marks the area of the convex polygon into the area type of the compact heightfield.
|
||
|
|
+// Params:
|
||
|
|
+// verts - (in) vertices of the convex polygon.
|
||
|
|
+// nverts - (in) number of vertices in the polygon.
|
||
|
|
+// hmin/hmax - (in) min and max height of the polygon.
|
||
|
|
+// areaId - (in) area ID to mark.
|
||
|
|
+// chf - (in/out) compact heightfield to mark.
|
||
|
|
void rcMarkConvexPolyArea(rcContext* ctx, const float* verts, const int nverts,
|
||
|
|
const float hmin, const float hmax, unsigned char areaId,
|
||
|
|
rcCompactHeightfield& chf);
|
||
|
|
|
||
|
|
-/// Helper function to offset voncex polygons for rcMarkConvexPolyArea.
|
||
|
|
-/// @ingroup recast
|
||
|
|
-/// @param[in] verts The vertices of the polygon [Form: (x, y, z) * @p nverts]
|
||
|
|
-/// @param[in] nverts The number of vertices in the polygon.
|
||
|
|
-/// @param[out] outVerts The offset vertices (should hold up to 2 * @p nverts) [Form: (x, y, z) * return value]
|
||
|
|
-/// @param[in] maxOutVerts The max number of vertices that can be stored to @p outVerts.
|
||
|
|
-/// @returns Number of vertices in the offset polygon or 0 if too few vertices in @p outVerts.
|
||
|
|
-int rcOffsetPoly(const float* verts, const int nverts, const float offset,
|
||
|
|
- float* outVerts, const int maxOutVerts);
|
||
|
|
-
|
||
|
|
-/// Applies the area id to all spans within the specified cylinder.
|
||
|
|
-/// @ingroup recast
|
||
|
|
-/// @param[in,out] ctx The build context to use during the operation.
|
||
|
|
-/// @param[in] pos The center of the base of the cylinder. [Form: (x, y, z)]
|
||
|
|
-/// @param[in] r The radius of the cylinder.
|
||
|
|
-/// @param[in] h The height of the cylinder.
|
||
|
|
-/// @param[in] areaId The area id to apply. [Limit: <= #RC_WALKABLE_AREA]
|
||
|
|
-/// @param[in,out] chf A populated compact heightfield.
|
||
|
|
-void rcMarkCylinderArea(rcContext* ctx, const float* pos,
|
||
|
|
- const float r, const float h, unsigned char areaId,
|
||
|
|
- rcCompactHeightfield& chf);
|
||
|
|
-
|
||
|
|
-/// Builds the distance field for the specified compact heightfield.
|
||
|
|
-/// @ingroup recast
|
||
|
|
-/// @param[in,out] ctx The build context to use during the operation.
|
||
|
|
-/// @param[in,out] chf A populated compact heightfield.
|
||
|
|
-/// @returns True if the operation completed successfully.
|
||
|
|
+// Builds distance field and stores it into the combat heightfield.
|
||
|
|
+// Params:
|
||
|
|
+// chf - (in/out) compact heightfield representing the open space.
|
||
|
|
+// Returns false if operation ran out of memory.
|
||
|
|
bool rcBuildDistanceField(rcContext* ctx, rcCompactHeightfield& chf);
|
||
|
|
|
||
|
|
-/// Builds region data for the heightfield using watershed partitioning.
|
||
|
|
-/// @ingroup recast
|
||
|
|
-/// @param[in,out] ctx The build context to use during the operation.
|
||
|
|
-/// @param[in,out] chf A populated compact heightfield.
|
||
|
|
-/// @param[in] borderSize The size of the non-navigable border around the heightfield.
|
||
|
|
-/// [Limit: >=0] [Units: vx]
|
||
|
|
-/// @param[in] minRegionArea The minimum number of cells allowed to form isolated island areas.
|
||
|
|
-/// [Limit: >=0] [Units: vx].
|
||
|
|
-/// @param[in] mergeRegionArea Any regions with a span count smaller than this value will, if possible,
|
||
|
|
-/// be merged with larger regions. [Limit: >=0] [Units: vx]
|
||
|
|
-/// @returns True if the operation completed successfully.
|
||
|
|
+// Divides the walkable heighfied into simple regions using watershed partitioning.
|
||
|
|
+// Each region has only one contour and no overlaps.
|
||
|
|
+// The regions are stored in the compact heightfield 'reg' field.
|
||
|
|
+// The process sometimes creates small regions. If the area of a regions is
|
||
|
|
+// smaller than 'mergeRegionArea' then the region will be merged with a neighbour
|
||
|
|
+// region if possible. If multiple regions form an area which is smaller than
|
||
|
|
+// 'minRegionArea' all the regions belonging to that area will be removed.
|
||
|
|
+// Here area means the count of spans in an area.
|
||
|
|
+// Params:
|
||
|
|
+// chf - (in/out) compact heightfield representing the open space.
|
||
|
|
+// minRegionArea - (in) the smallest allowed region area.
|
||
|
|
+// maxMergeRegionArea - (in) the largest allowed region area which can be merged.
|
||
|
|
+// Returns false if operation ran out of memory.
|
||
|
|
bool rcBuildRegions(rcContext* ctx, rcCompactHeightfield& chf,
|
||
|
|
const int borderSize, const int minRegionArea, const int mergeRegionArea);
|
||
|
|
|
||
|
|
-/// Builds region data for the heightfield using simple monotone partitioning.
|
||
|
|
-/// @ingroup recast
|
||
|
|
-/// @param[in,out] ctx The build context to use during the operation.
|
||
|
|
-/// @param[in,out] chf A populated compact heightfield.
|
||
|
|
-/// @param[in] borderSize The size of the non-navigable border around the heightfield.
|
||
|
|
-/// [Limit: >=0] [Units: vx]
|
||
|
|
-/// @param[in] minRegionArea The minimum number of cells allowed to form isolated island areas.
|
||
|
|
-/// [Limit: >=0] [Units: vx].
|
||
|
|
-/// @param[in] mergeRegionArea Any regions with a span count smaller than this value will, if possible,
|
||
|
|
-/// be merged with larger regions. [Limit: >=0] [Units: vx]
|
||
|
|
-/// @returns True if the operation completed successfully.
|
||
|
|
+// Divides the walkable heighfied into simple regions using simple monotone partitioning.
|
||
|
|
+// Each region has only one contour and no overlaps.
|
||
|
|
+// The regions are stored in the compact heightfield 'reg' field.
|
||
|
|
+// The process sometimes creates small regions. If the area of a regions is
|
||
|
|
+// smaller than 'mergeRegionArea' then the region will be merged with a neighbour
|
||
|
|
+// region if possible. If multiple regions form an area which is smaller than
|
||
|
|
+// 'minRegionArea' all the regions belonging to that area will be removed.
|
||
|
|
+// Here area means the count of spans in an area.
|
||
|
|
+// Params:
|
||
|
|
+// chf - (in/out) compact heightfield representing the open space.
|
||
|
|
+// minRegionArea - (in) the smallest allowed regions size.
|
||
|
|
+// maxMergeRegionArea - (in) the largest allowed regions size which can be merged.
|
||
|
|
+// Returns false if operation ran out of memory.
|
||
|
|
bool rcBuildRegionsMonotone(rcContext* ctx, rcCompactHeightfield& chf,
|
||
|
|
const int borderSize, const int minRegionArea, const int mergeRegionArea);
|
||
|
|
|
||
|
|
-
|
||
|
|
-/// Sets the neighbor connection data for the specified direction.
|
||
|
|
-/// @param[in] s The span to update.
|
||
|
|
-/// @param[in] dir The direction to set. [Limits: 0 <= value < 4]
|
||
|
|
-/// @param[in] i The index of the neighbor span.
|
||
|
|
-inline void rcSetCon(rcCompactSpan& s, int dir, int i)
|
||
|
|
-{
|
||
|
|
- const unsigned int shift = (unsigned int)dir*6;
|
||
|
|
- unsigned int con = s.con;
|
||
|
|
- s.con = (con & ~(0x3f << shift)) | (((unsigned int)i & 0x3f) << shift);
|
||
|
|
-}
|
||
|
|
-
|
||
|
|
-/// Gets neighbor connection data for the specified direction.
|
||
|
|
-/// @param[in] s The span to check.
|
||
|
|
-/// @param[in] dir The direction to check. [Limits: 0 <= value < 4]
|
||
|
|
-/// @return The neighbor connection data for the specified direction,
|
||
|
|
-/// or #RC_NOT_CONNECTED if there is no connection.
|
||
|
|
-inline int rcGetCon(const rcCompactSpan& s, int dir)
|
||
|
|
-{
|
||
|
|
- const unsigned int shift = (unsigned int)dir*6;
|
||
|
|
- return (s.con >> shift) & 0x3f;
|
||
|
|
-}
|
||
|
|
-
|
||
|
|
-/// Gets the standard width (x-axis) offset for the specified direction.
|
||
|
|
-/// @param[in] dir The direction. [Limits: 0 <= value < 4]
|
||
|
|
-/// @return The width offset to apply to the current cell position to move
|
||
|
|
-/// in the direction.
|
||
|
|
-inline int rcGetDirOffsetX(int dir)
|
||
|
|
-{
|
||
|
|
- const int offset[4] = { -1, 0, 1, 0, };
|
||
|
|
- return offset[dir&0x03];
|
||
|
|
-}
|
||
|
|
-
|
||
|
|
-/// Gets the standard height (z-axis) offset for the specified direction.
|
||
|
|
-/// @param[in] dir The direction. [Limits: 0 <= value < 4]
|
||
|
|
-/// @return The height offset to apply to the current cell position to move
|
||
|
|
-/// in the direction.
|
||
|
|
-inline int rcGetDirOffsetY(int dir)
|
||
|
|
-{
|
||
|
|
- const int offset[4] = { 0, 1, 0, -1 };
|
||
|
|
- return offset[dir&0x03];
|
||
|
|
-}
|
||
|
|
-
|
||
|
|
-/// @}
|
||
|
|
-/// @name Layer, Contour, Polymesh, and Detail Mesh Functions
|
||
|
|
-/// @see rcHeightfieldLayer, rcContourSet, rcPolyMesh, rcPolyMeshDetail
|
||
|
|
-/// @{
|
||
|
|
-
|
||
|
|
-/// Builds a layer set from the specified compact heightfield.
|
||
|
|
-/// @ingroup recast
|
||
|
|
-/// @param[in,out] ctx The build context to use during the operation.
|
||
|
|
-/// @param[in] chf A fully built compact heightfield.
|
||
|
|
-/// @param[in] borderSize The size of the non-navigable border around the heightfield. [Limit: >=0]
|
||
|
|
-/// [Units: vx]
|
||
|
|
-/// @param[in] walkableHeight Minimum floor to 'ceiling' height that will still allow the floor area
|
||
|
|
-/// to be considered walkable. [Limit: >= 3] [Units: vx]
|
||
|
|
-/// @param[out] lset The resulting layer set. (Must be pre-allocated.)
|
||
|
|
-/// @returns True if the operation completed successfully.
|
||
|
|
-bool rcBuildHeightfieldLayers(rcContext* ctx, rcCompactHeightfield& chf,
|
||
|
|
- const int borderSize, const int walkableHeight,
|
||
|
|
- rcHeightfieldLayerSet& lset);
|
||
|
|
-
|
||
|
|
-/// Builds a contour set from the region outlines in the provided compact heightfield.
|
||
|
|
-/// @ingroup recast
|
||
|
|
-/// @param[in,out] ctx The build context to use during the operation.
|
||
|
|
-/// @param[in] chf A fully built compact heightfield.
|
||
|
|
-/// @param[in] maxError The maximum distance a simplfied contour's border edges should deviate
|
||
|
|
-/// the original raw contour. [Limit: >=0] [Units: wu]
|
||
|
|
-/// @param[in] maxEdgeLen The maximum allowed length for contour edges along the border of the mesh.
|
||
|
|
-/// [Limit: >=0] [Units: vx]
|
||
|
|
-/// @param[out] cset The resulting contour set. (Must be pre-allocated.)
|
||
|
|
-/// @param[in] buildFlags The build flags. (See: #rcBuildContoursFlags)
|
||
|
|
-/// @returns True if the operation completed successfully.
|
||
|
|
+// Builds simplified contours from the regions outlines.
|
||
|
|
+// Params:
|
||
|
|
+// chf - (in) compact heightfield which has regions set.
|
||
|
|
+// maxError - (in) maximum allowed distance between simplified contour and cells.
|
||
|
|
+// maxEdgeLen - (in) maximum allowed contour edge length in cells.
|
||
|
|
+// cset - (out) Resulting contour set.
|
||
|
|
+// flags - (in) build flags, see rcBuildContoursFlags.
|
||
|
|
+// Returns false if operation ran out of memory.
|
||
|
|
bool rcBuildContours(rcContext* ctx, rcCompactHeightfield& chf,
|
||
|
|
const float maxError, const int maxEdgeLen,
|
||
|
|
rcContourSet& cset, const int flags = RC_CONTOUR_TESS_WALL_EDGES);
|
||
|
|
|
||
|
|
-/// Builds a polygon mesh from the provided contours.
|
||
|
|
-/// @ingroup recast
|
||
|
|
-/// @param[in,out] ctx The build context to use during the operation.
|
||
|
|
-/// @param[in] cset A fully built contour set.
|
||
|
|
-/// @param[in] nvp The maximum number of vertices allowed for polygons generated during the
|
||
|
|
-/// contour to polygon conversion process. [Limit: >= 3]
|
||
|
|
-/// @param[out] mesh The resulting polygon mesh. (Must be re-allocated.)
|
||
|
|
-/// @returns True if the operation completed successfully.
|
||
|
|
-bool rcBuildPolyMesh(rcContext* ctx, rcContourSet& cset, const int nvp, rcPolyMesh& mesh);
|
||
|
|
-
|
||
|
|
-/// Merges multiple polygon meshes into a single mesh.
|
||
|
|
-/// @ingroup recast
|
||
|
|
-/// @param[in,out] ctx The build context to use during the operation.
|
||
|
|
-/// @param[in] meshes An array of polygon meshes to merge. [Size: @p nmeshes]
|
||
|
|
-/// @param[in] nmeshes The number of polygon meshes in the meshes array.
|
||
|
|
-/// @param[in] mesh The resulting polygon mesh. (Must be pre-allocated.)
|
||
|
|
-/// @returns True if the operation completed successfully.
|
||
|
|
+// Builds connected convex polygon mesh from contour polygons.
|
||
|
|
+// Params:
|
||
|
|
+// cset - (in) contour set.
|
||
|
|
+// nvp - (in) maximum number of vertices per polygon.
|
||
|
|
+// mesh - (out) poly mesh.
|
||
|
|
+// Returns false if operation ran out of memory.
|
||
|
|
+bool rcBuildPolyMesh(rcContext* ctx, rcContourSet& cset, int nvp, rcPolyMesh& mesh);
|
||
|
|
+
|
||
|
|
bool rcMergePolyMeshes(rcContext* ctx, rcPolyMesh** meshes, const int nmeshes, rcPolyMesh& mesh);
|
||
|
|
|
||
|
|
-/// Builds a detail mesh from the provided polygon mesh.
|
||
|
|
-/// @ingroup recast
|
||
|
|
-/// @param[in,out] ctx The build context to use during the operation.
|
||
|
|
-/// @param[in] mesh A fully built polygon mesh.
|
||
|
|
-/// @param[in] chf The compact heightfield used to build the polygon mesh.
|
||
|
|
-/// @param[in] sampleDist Sets the distance to use when samping the heightfield. [Limit: >=0] [Units: wu]
|
||
|
|
-/// @param[in] sampleMaxError The maximum distance the detail mesh surface should deviate from
|
||
|
|
-/// heightfield data. [Limit: >=0] [Units: wu]
|
||
|
|
-/// @param[out] dmesh The resulting detail mesh. (Must be pre-allocated.)
|
||
|
|
-/// @returns True if the operation completed successfully.
|
||
|
|
+// Builds detail triangle mesh for each polygon in the poly mesh.
|
||
|
|
+// Params:
|
||
|
|
+// mesh - (in) poly mesh to detail.
|
||
|
|
+// chf - (in) compact height field, used to query height for new vertices.
|
||
|
|
+// sampleDist - (in) spacing between height samples used to generate more detail into mesh.
|
||
|
|
+// sampleMaxError - (in) maximum allowed distance between simplified detail mesh and height sample.
|
||
|
|
+// pmdtl - (out) detail mesh.
|
||
|
|
+// Returns false if operation ran out of memory.
|
||
|
|
bool rcBuildPolyMeshDetail(rcContext* ctx, const rcPolyMesh& mesh, const rcCompactHeightfield& chf,
|
||
|
|
const float sampleDist, const float sampleMaxError,
|
||
|
|
rcPolyMeshDetail& dmesh);
|
||
|
|
|
||
|
|
-/// Copies the poly mesh data from src to dst.
|
||
|
|
-/// @ingroup recast
|
||
|
|
-/// @param[in,out] ctx The build context to use during the operation.
|
||
|
|
-/// @param[in] src The source mesh to copy from.
|
||
|
|
-/// @param[out] dst The resulting detail mesh. (Must be pre-allocated, must be empty mesh.)
|
||
|
|
-/// @returns True if the operation completed successfully.
|
||
|
|
-bool rcCopyPolyMesh(rcContext* ctx, const rcPolyMesh& src, rcPolyMesh& dst);
|
||
|
|
-
|
||
|
|
-/// Merges multiple detail meshes into a single detail mesh.
|
||
|
|
-/// @ingroup recast
|
||
|
|
-/// @param[in,out] ctx The build context to use during the operation.
|
||
|
|
-/// @param[in] meshes An array of detail meshes to merge. [Size: @p nmeshes]
|
||
|
|
-/// @param[in] nmeshes The number of detail meshes in the meshes array.
|
||
|
|
-/// @param[out] mesh The resulting detail mesh. (Must be pre-allocated.)
|
||
|
|
-/// @returns True if the operation completed successfully.
|
||
|
|
bool rcMergePolyMeshDetails(rcContext* ctx, rcPolyMeshDetail** meshes, const int nmeshes, rcPolyMeshDetail& mesh);
|
||
|
|
|
||
|
|
-/// @}
|
||
|
|
|
||
|
|
#endif // RECAST_H
|
||
|
|
-
|
||
|
|
-///////////////////////////////////////////////////////////////////////////
|
||
|
|
-
|
||
|
|
-// Due to the large amount of detail documentation for this file,
|
||
|
|
-// the content normally located at the end of the header file has been separated
|
||
|
|
-// out to a file in /Docs/Extern.
|
||
|
|
diff --git a/dep/recastnavigation/Recast/RecastAlloc.cpp b/dep/recastnavigation/Recast/RecastAlloc.cpp
|
||
|
|
index b5ec151..2c7396a 100644
|
||
|
|
--- a/dep/recastnavigation/Recast/RecastAlloc.cpp
|
||
|
|
+++ b/dep/recastnavigation/Recast/RecastAlloc.cpp
|
||
|
|
@@ -33,45 +33,24 @@ static void rcFreeDefault(void *ptr)
|
||
|
|
static rcAllocFunc* sRecastAllocFunc = rcAllocDefault;
|
||
|
|
static rcFreeFunc* sRecastFreeFunc = rcFreeDefault;
|
||
|
|
|
||
|
|
-/// @see rcAlloc, rcFree
|
||
|
|
void rcAllocSetCustom(rcAllocFunc *allocFunc, rcFreeFunc *freeFunc)
|
||
|
|
{
|
||
|
|
sRecastAllocFunc = allocFunc ? allocFunc : rcAllocDefault;
|
||
|
|
sRecastFreeFunc = freeFunc ? freeFunc : rcFreeDefault;
|
||
|
|
}
|
||
|
|
|
||
|
|
-/// @see rcAllocSetCustom
|
||
|
|
void* rcAlloc(int size, rcAllocHint hint)
|
||
|
|
{
|
||
|
|
return sRecastAllocFunc(size, hint);
|
||
|
|
}
|
||
|
|
|
||
|
|
-/// @par
|
||
|
|
-///
|
||
|
|
-/// @warning This function leaves the value of @p ptr unchanged. So it still
|
||
|
|
-/// points to the same (now invalid) location, and not to null.
|
||
|
|
-///
|
||
|
|
-/// @see rcAllocSetCustom
|
||
|
|
void rcFree(void* ptr)
|
||
|
|
{
|
||
|
|
if (ptr)
|
||
|
|
sRecastFreeFunc(ptr);
|
||
|
|
}
|
||
|
|
|
||
|
|
-/// @class rcIntArray
|
||
|
|
-///
|
||
|
|
-/// While it is possible to pre-allocate a specific array size during
|
||
|
|
-/// construction or by using the #resize method, certain methods will
|
||
|
|
-/// automatically resize the array as needed.
|
||
|
|
-///
|
||
|
|
-/// @warning The array memory is not initialized to zero when the size is
|
||
|
|
-/// manually set during construction or when using #resize.
|
||
|
|
|
||
|
|
-/// @par
|
||
|
|
-///
|
||
|
|
-/// Using this method ensures the array is at least large enough to hold
|
||
|
|
-/// the specified number of elements. This can improve performance by
|
||
|
|
-/// avoiding auto-resizing during use.
|
||
|
|
void rcIntArray::resize(int n)
|
||
|
|
{
|
||
|
|
if (n > m_cap)
|
||
|
|
diff --git a/dep/recastnavigation/Recast/RecastAlloc.h b/dep/recastnavigation/Recast/RecastAlloc.h
|
||
|
|
index 438be9e..9a31637 100644
|
||
|
|
--- a/dep/recastnavigation/Recast/RecastAlloc.h
|
||
|
|
+++ b/dep/recastnavigation/Recast/RecastAlloc.h
|
||
|
|
@@ -19,45 +19,23 @@
|
||
|
|
#ifndef RECASTALLOC_H
|
||
|
|
#define RECASTALLOC_H
|
||
|
|
|
||
|
|
-/// Provides hint values to the memory allocator on how long the
|
||
|
|
-/// memory is expected to be used.
|
||
|
|
enum rcAllocHint
|
||
|
|
{
|
||
|
|
- RC_ALLOC_PERM, ///< Memory will persist after a function call.
|
||
|
|
- RC_ALLOC_TEMP ///< Memory used temporarily within a function.
|
||
|
|
+ RC_ALLOC_PERM, // Memory persist after a function call.
|
||
|
|
+ RC_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 rcAllocSetCustom
|
||
|
|
typedef void* (rcAllocFunc)(int size, rcAllocHint hint);
|
||
|
|
-
|
||
|
|
-/// A memory deallocation function.
|
||
|
|
-/// @param[in] ptr A pointer to a memory block previously allocated using #rcAllocFunc.
|
||
|
|
-/// @see rcAllocSetCustom
|
||
|
|
typedef void (rcFreeFunc)(void* ptr);
|
||
|
|
|
||
|
|
-/// Sets the base custom allocation functions to be used by Recast.
|
||
|
|
-/// @param[in] allocFunc The memory allocation function to be used by #rcAlloc
|
||
|
|
-/// @param[in] freeFunc The memory de-allocation function to be used by #rcFree
|
||
|
|
void rcAllocSetCustom(rcAllocFunc *allocFunc, rcFreeFunc *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 rcFree
|
||
|
|
void* rcAlloc(int size, rcAllocHint hint);
|
||
|
|
-
|
||
|
|
-/// Deallocates a memory block.
|
||
|
|
-/// @param[in] ptr A pointer to a memory block previously allocated using #rcAlloc.
|
||
|
|
-/// @see rcAlloc
|
||
|
|
void rcFree(void* ptr);
|
||
|
|
|
||
|
|
|
||
|
|
-/// A simple dynamic array of integers.
|
||
|
|
+
|
||
|
|
+// Simple dynamic array ints.
|
||
|
|
class rcIntArray
|
||
|
|
{
|
||
|
|
int* m_data;
|
||
|
|
@@ -65,59 +43,26 @@ class rcIntArray
|
||
|
|
inline rcIntArray(const rcIntArray&);
|
||
|
|
inline rcIntArray& operator=(const rcIntArray&);
|
||
|
|
public:
|
||
|
|
-
|
||
|
|
- /// Constructs an instance with an initial array size of zero.
|
||
|
|
inline rcIntArray() : m_data(0), m_size(0), m_cap(0) {}
|
||
|
|
-
|
||
|
|
- /// Constructs an instance initialized to the specified size.
|
||
|
|
- /// @param[in] n The initial size of the integer array.
|
||
|
|
inline rcIntArray(int n) : m_data(0), m_size(0), m_cap(0) { resize(n); }
|
||
|
|
inline ~rcIntArray() { rcFree(m_data); }
|
||
|
|
-
|
||
|
|
- /// Specifies the new size of the integer array.
|
||
|
|
- /// @param[in] n The new size of the integer array.
|
||
|
|
void resize(int n);
|
||
|
|
-
|
||
|
|
- /// Push the specified integer onto the end of the array and increases the size by one.
|
||
|
|
- /// @param[in] item The new value.
|
||
|
|
inline void push(int item) { resize(m_size+1); m_data[m_size-1] = item; }
|
||
|
|
-
|
||
|
|
- /// Returns the value at the end of the array and reduces the size by one.
|
||
|
|
- /// @return The value at the end of the array.
|
||
|
|
inline int pop() { if (m_size > 0) m_size--; return m_data[m_size]; }
|
||
|
|
-
|
||
|
|
- /// The value at the specified array index.
|
||
|
|
- /// @warning Does not provide overflow protection.
|
||
|
|
- /// @param[in] i The index of the value.
|
||
|
|
inline const int& operator[](int i) const { return m_data[i]; }
|
||
|
|
-
|
||
|
|
- /// The value at the specified array index.
|
||
|
|
- /// @warning Does not provide overflow protection.
|
||
|
|
- /// @param[in] i The index of the value.
|
||
|
|
inline int& operator[](int i) { return m_data[i]; }
|
||
|
|
-
|
||
|
|
- /// The current size of the integer array.
|
||
|
|
inline int size() const { return m_size; }
|
||
|
|
};
|
||
|
|
|
||
|
|
-/// A simple helper class used to delete an array when it goes out of scope.
|
||
|
|
-/// @note This class is rarely if ever used by the end user.
|
||
|
|
+// Simple internal helper class to delete array in scope
|
||
|
|
template<class T> class rcScopedDelete
|
||
|
|
{
|
||
|
|
T* ptr;
|
||
|
|
inline T* operator=(T* p);
|
||
|
|
public:
|
||
|
|
-
|
||
|
|
- /// Constructs an instance with a null pointer.
|
||
|
|
inline rcScopedDelete() : ptr(0) {}
|
||
|
|
-
|
||
|
|
- /// Constructs an instance with the specified pointer.
|
||
|
|
- /// @param[in] p An pointer to an allocated array.
|
||
|
|
inline rcScopedDelete(T* p) : ptr(p) {}
|
||
|
|
inline ~rcScopedDelete() { rcFree(ptr); }
|
||
|
|
-
|
||
|
|
- /// The root array pointer.
|
||
|
|
- /// @return The root array pointer.
|
||
|
|
inline operator T*() { return ptr; }
|
||
|
|
};
|
||
|
|
|
||
|
|
diff --git a/dep/recastnavigation/Recast/RecastArea.cpp b/dep/recastnavigation/Recast/RecastArea.cpp
|
||
|
|
index 1a338cd..e89caee 100644
|
||
|
|
--- a/dep/recastnavigation/Recast/RecastArea.cpp
|
||
|
|
+++ b/dep/recastnavigation/Recast/RecastArea.cpp
|
||
|
|
@@ -26,14 +26,7 @@
|
||
|
|
#include "RecastAlloc.h"
|
||
|
|
#include "RecastAssert.h"
|
||
|
|
|
||
|
|
-/// @par
|
||
|
|
-///
|
||
|
|
-/// Basically, any spans that are closer to a boundary or obstruction than the specified radius
|
||
|
|
-/// are marked as unwalkable.
|
||
|
|
-///
|
||
|
|
-/// This method is usually called immediately after the heightfield has been built.
|
||
|
|
-///
|
||
|
|
-/// @see rcCompactHeightfield, rcBuildCompactHeightfield, rcConfig::walkableRadius
|
||
|
|
+
|
||
|
|
bool rcErodeWalkableArea(rcContext* ctx, int radius, rcCompactHeightfield& chf)
|
||
|
|
{
|
||
|
|
rcAssert(ctx);
|
||
|
|
@@ -61,26 +54,14 @@ bool rcErodeWalkableArea(rcContext* ctx, int radius, rcCompactHeightfield& chf)
|
||
|
|
const rcCompactCell& c = chf.cells[x+y*w];
|
||
|
|
for (int i = (int)c.index, ni = (int)(c.index+c.count); i < ni; ++i)
|
||
|
|
{
|
||
|
|
- if (chf.areas[i] == RC_NULL_AREA)
|
||
|
|
- {
|
||
|
|
- dist[i] = 0;
|
||
|
|
- }
|
||
|
|
- else
|
||
|
|
+ if (chf.areas[i] != RC_NULL_AREA)
|
||
|
|
{
|
||
|
|
const rcCompactSpan& s = chf.spans[i];
|
||
|
|
int nc = 0;
|
||
|
|
for (int dir = 0; dir < 4; ++dir)
|
||
|
|
{
|
||
|
|
if (rcGetCon(s, dir) != RC_NOT_CONNECTED)
|
||
|
|
- {
|
||
|
|
- const int nx = x + rcGetDirOffsetX(dir);
|
||
|
|
- const int ny = y + rcGetDirOffsetY(dir);
|
||
|
|
- const int nidx = (int)chf.cells[nx+ny*w].index + rcGetCon(s, dir);
|
||
|
|
- if (chf.areas[nidx] != RC_NULL_AREA)
|
||
|
|
- {
|
||
|
|
- nc++;
|
||
|
|
- }
|
||
|
|
- }
|
||
|
|
+ nc++;
|
||
|
|
}
|
||
|
|
// At least one missing neighbour.
|
||
|
|
if (nc != 4)
|
||
|
|
@@ -232,12 +213,7 @@ static void insertSort(unsigned char* a, const int n)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
-/// @par
|
||
|
|
-///
|
||
|
|
-/// This filter is usually applied after applying area id's using functions
|
||
|
|
-/// such as #rcMarkBoxArea, #rcMarkConvexPolyArea, and #rcMarkCylinderArea.
|
||
|
|
-///
|
||
|
|
-/// @see rcCompactHeightfield
|
||
|
|
+
|
||
|
|
bool rcMedianFilterWalkableArea(rcContext* ctx, rcCompactHeightfield& chf)
|
||
|
|
{
|
||
|
|
rcAssert(ctx);
|
||
|
|
@@ -312,11 +288,6 @@ bool rcMedianFilterWalkableArea(rcContext* ctx, rcCompactHeightfield& chf)
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
-/// @par
|
||
|
|
-///
|
||
|
|
-/// The value of spacial parameters are in world units.
|
||
|
|
-///
|
||
|
|
-/// @see rcCompactHeightfield, rcMedianFilterWalkableArea
|
||
|
|
void rcMarkBoxArea(rcContext* ctx, const float* bmin, const float* bmax, unsigned char areaId,
|
||
|
|
rcCompactHeightfield& chf)
|
||
|
|
{
|
||
|
|
@@ -351,8 +322,7 @@ void rcMarkBoxArea(rcContext* ctx, const float* bmin, const float* bmax, unsigne
|
||
|
|
rcCompactSpan& s = chf.spans[i];
|
||
|
|
if ((int)s.y >= miny && (int)s.y <= maxy)
|
||
|
|
{
|
||
|
|
- if (chf.areas[i] != RC_NULL_AREA)
|
||
|
|
- chf.areas[i] = areaId;
|
||
|
|
+ chf.areas[i] = areaId;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
@@ -377,14 +347,6 @@ static int pointInPoly(int nvert, const float* verts, const float* p)
|
||
|
|
return c;
|
||
|
|
}
|
||
|
|
|
||
|
|
-/// @par
|
||
|
|
-///
|
||
|
|
-/// The value of spacial parameters are in world units.
|
||
|
|
-///
|
||
|
|
-/// The y-values of the polygon vertices are ignored. So the polygon is effectively
|
||
|
|
-/// projected onto the xz-plane at @p hmin, then extruded to @p hmax.
|
||
|
|
-///
|
||
|
|
-/// @see rcCompactHeightfield, rcMedianFilterWalkableArea
|
||
|
|
void rcMarkConvexPolyArea(rcContext* ctx, const float* verts, const int nverts,
|
||
|
|
const float hmin, const float hmax, unsigned char areaId,
|
||
|
|
rcCompactHeightfield& chf)
|
||
|
|
@@ -431,8 +393,6 @@ void rcMarkConvexPolyArea(rcContext* ctx, const float* verts, const int nverts,
|
||
|
|
for (int i = (int)c.index, ni = (int)(c.index+c.count); i < ni; ++i)
|
||
|
|
{
|
||
|
|
rcCompactSpan& s = chf.spans[i];
|
||
|
|
- if (chf.areas[i] == RC_NULL_AREA)
|
||
|
|
- continue;
|
||
|
|
if ((int)s.y >= miny && (int)s.y <= maxy)
|
||
|
|
{
|
||
|
|
float p[3];
|
||
|
|
@@ -451,152 +411,3 @@ void rcMarkConvexPolyArea(rcContext* ctx, const float* verts, const int nverts,
|
||
|
|
|
||
|
|
ctx->stopTimer(RC_TIMER_MARK_CONVEXPOLY_AREA);
|
||
|
|
}
|
||
|
|
-
|
||
|
|
-int rcOffsetPoly(const float* verts, const int nverts, const float offset,
|
||
|
|
- float* outVerts, const int maxOutVerts)
|
||
|
|
-{
|
||
|
|
- const float MITER_LIMIT = 1.20f;
|
||
|
|
-
|
||
|
|
- int n = 0;
|
||
|
|
-
|
||
|
|
- for (int i = 0; i < nverts; i++)
|
||
|
|
- {
|
||
|
|
- const int a = (i+nverts-1) % nverts;
|
||
|
|
- const int b = i;
|
||
|
|
- const int c = (i+1) % nverts;
|
||
|
|
- const float* va = &verts[a*3];
|
||
|
|
- const float* vb = &verts[b*3];
|
||
|
|
- const float* vc = &verts[c*3];
|
||
|
|
- float dx0 = vb[0] - va[0];
|
||
|
|
- float dy0 = vb[2] - va[2];
|
||
|
|
- float d0 = dx0*dx0 + dy0*dy0;
|
||
|
|
- if (d0 > 1e-6f)
|
||
|
|
- {
|
||
|
|
- d0 = 1.0f/rcSqrt(d0);
|
||
|
|
- dx0 *= d0;
|
||
|
|
- dy0 *= d0;
|
||
|
|
- }
|
||
|
|
- float dx1 = vc[0] - vb[0];
|
||
|
|
- float dy1 = vc[2] - vb[2];
|
||
|
|
- float d1 = dx1*dx1 + dy1*dy1;
|
||
|
|
- if (d1 > 1e-6f)
|
||
|
|
- {
|
||
|
|
- d1 = 1.0f/rcSqrt(d1);
|
||
|
|
- dx1 *= d1;
|
||
|
|
- dy1 *= d1;
|
||
|
|
- }
|
||
|
|
- const float dlx0 = -dy0;
|
||
|
|
- const float dly0 = dx0;
|
||
|
|
- const float dlx1 = -dy1;
|
||
|
|
- const float dly1 = dx1;
|
||
|
|
- float cross = dx1*dy0 - dx0*dy1;
|
||
|
|
- float dmx = (dlx0 + dlx1) * 0.5f;
|
||
|
|
- float dmy = (dly0 + dly1) * 0.5f;
|
||
|
|
- float dmr2 = dmx*dmx + dmy*dmy;
|
||
|
|
- bool bevel = dmr2 * MITER_LIMIT*MITER_LIMIT < 1.0f;
|
||
|
|
- if (dmr2 > 1e-6f)
|
||
|
|
- {
|
||
|
|
- const float scale = 1.0f / dmr2;
|
||
|
|
- dmx *= scale;
|
||
|
|
- dmy *= scale;
|
||
|
|
- }
|
||
|
|
-
|
||
|
|
- if (bevel && cross < 0.0f)
|
||
|
|
- {
|
||
|
|
- if (n+2 >= maxOutVerts)
|
||
|
|
- return 0;
|
||
|
|
- float d = (1.0f - (dx0*dx1 + dy0*dy1))*0.5f;
|
||
|
|
- outVerts[n*3+0] = vb[0] + (-dlx0+dx0*d)*offset;
|
||
|
|
- outVerts[n*3+1] = vb[1];
|
||
|
|
- outVerts[n*3+2] = vb[2] + (-dly0+dy0*d)*offset;
|
||
|
|
- n++;
|
||
|
|
- outVerts[n*3+0] = vb[0] + (-dlx1-dx1*d)*offset;
|
||
|
|
- outVerts[n*3+1] = vb[1];
|
||
|
|
- outVerts[n*3+2] = vb[2] + (-dly1-dy1*d)*offset;
|
||
|
|
- n++;
|
||
|
|
- }
|
||
|
|
- else
|
||
|
|
- {
|
||
|
|
- if (n+1 >= maxOutVerts)
|
||
|
|
- return 0;
|
||
|
|
- outVerts[n*3+0] = vb[0] - dmx*offset;
|
||
|
|
- outVerts[n*3+1] = vb[1];
|
||
|
|
- outVerts[n*3+2] = vb[2] - dmy*offset;
|
||
|
|
- n++;
|
||
|
|
- }
|
||
|
|
- }
|
||
|
|
-
|
||
|
|
- return n;
|
||
|
|
-}
|
||
|
|
-
|
||
|
|
-
|
||
|
|
-/// @par
|
||
|
|
-///
|
||
|
|
-/// The value of spacial parameters are in world units.
|
||
|
|
-///
|
||
|
|
-/// @see rcCompactHeightfield, rcMedianFilterWalkableArea
|
||
|
|
-void rcMarkCylinderArea(rcContext* ctx, const float* pos,
|
||
|
|
- const float r, const float h, unsigned char areaId,
|
||
|
|
- rcCompactHeightfield& chf)
|
||
|
|
-{
|
||
|
|
- rcAssert(ctx);
|
||
|
|
-
|
||
|
|
- ctx->startTimer(RC_TIMER_MARK_CYLINDER_AREA);
|
||
|
|
-
|
||
|
|
- float bmin[3], bmax[3];
|
||
|
|
- bmin[0] = pos[0] - r;
|
||
|
|
- bmin[1] = pos[1];
|
||
|
|
- bmin[2] = pos[2] - r;
|
||
|
|
- bmax[0] = pos[0] + r;
|
||
|
|
- bmax[1] = pos[1] + h;
|
||
|
|
- bmax[2] = pos[2] + r;
|
||
|
|
- const float r2 = r*r;
|
||
|
|
-
|
||
|
|
- int minx = (int)((bmin[0]-chf.bmin[0])/chf.cs);
|
||
|
|
- int miny = (int)((bmin[1]-chf.bmin[1])/chf.ch);
|
||
|
|
- int minz = (int)((bmin[2]-chf.bmin[2])/chf.cs);
|
||
|
|
- int maxx = (int)((bmax[0]-chf.bmin[0])/chf.cs);
|
||
|
|
- int maxy = (int)((bmax[1]-chf.bmin[1])/chf.ch);
|
||
|
|
- int maxz = (int)((bmax[2]-chf.bmin[2])/chf.cs);
|
||
|
|
-
|
||
|
|
- if (maxx < 0) return;
|
||
|
|
- if (minx >= chf.width) return;
|
||
|
|
- if (maxz < 0) return;
|
||
|
|
- if (minz >= chf.height) return;
|
||
|
|
-
|
||
|
|
- if (minx < 0) minx = 0;
|
||
|
|
- if (maxx >= chf.width) maxx = chf.width-1;
|
||
|
|
- if (minz < 0) minz = 0;
|
||
|
|
- if (maxz >= chf.height) maxz = chf.height-1;
|
||
|
|
-
|
||
|
|
-
|
||
|
|
- for (int z = minz; z <= maxz; ++z)
|
||
|
|
- {
|
||
|
|
- for (int x = minx; x <= maxx; ++x)
|
||
|
|
- {
|
||
|
|
- const rcCompactCell& c = chf.cells[x+z*chf.width];
|
||
|
|
- for (int i = (int)c.index, ni = (int)(c.index+c.count); i < ni; ++i)
|
||
|
|
- {
|
||
|
|
- rcCompactSpan& s = chf.spans[i];
|
||
|
|
-
|
||
|
|
- if (chf.areas[i] == RC_NULL_AREA)
|
||
|
|
- continue;
|
||
|
|
-
|
||
|
|
- if ((int)s.y >= miny && (int)s.y <= maxy)
|
||
|
|
- {
|
||
|
|
- const float sx = chf.bmin[0] + (x+0.5f)*chf.cs;
|
||
|
|
- const float sz = chf.bmin[2] + (z+0.5f)*chf.cs;
|
||
|
|
- const float dx = sx - pos[0];
|
||
|
|
- const float dz = sz - pos[2];
|
||
|
|
-
|
||
|
|
- if (dx*dx + dz*dz < r2)
|
||
|
|
- {
|
||
|
|
- chf.areas[i] = areaId;
|
||
|
|
- }
|
||
|
|
- }
|
||
|
|
- }
|
||
|
|
- }
|
||
|
|
- }
|
||
|
|
-
|
||
|
|
- ctx->stopTimer(RC_TIMER_MARK_CYLINDER_AREA);
|
||
|
|
-}
|
||
|
|
diff --git a/dep/recastnavigation/Recast/RecastAssert.h b/dep/recastnavigation/Recast/RecastAssert.h
|
||
|
|
index 2aca0d9..b58b8fc 100644
|
||
|
|
--- a/dep/recastnavigation/Recast/RecastAssert.h
|
||
|
|
+++ b/dep/recastnavigation/Recast/RecastAssert.h
|
||
|
|
@@ -24,7 +24,7 @@
|
||
|
|
|
||
|
|
#ifdef NDEBUG
|
||
|
|
// From http://cnicholson.net/2009/02/stupid-c-tricks-adventures-in-assert/
|
||
|
|
-# define rcAssert(x) do { (void)sizeof(x); } while((void)(__LINE__==-1),false)
|
||
|
|
+# define rcAssert(x) do { (void)sizeof(x); } while(__LINE__==-1,false)
|
||
|
|
#else
|
||
|
|
# include <assert.h>
|
||
|
|
# define rcAssert assert
|
||
|
|
diff --git a/dep/recastnavigation/Recast/RecastContour.cpp b/dep/recastnavigation/Recast/RecastContour.cpp
|
||
|
|
index 5c324bc..1906b6e 100644
|
||
|
|
--- a/dep/recastnavigation/Recast/RecastContour.cpp
|
||
|
|
+++ b/dep/recastnavigation/Recast/RecastContour.cpp
|
||
|
|
@@ -340,7 +340,7 @@ static void simplifyContour(rcIntArray& points, rcIntArray& simplified,
|
||
|
|
endi = ai;
|
||
|
|
}
|
||
|
|
|
||
|
|
- // Tessellate only outer edges or edges between areas.
|
||
|
|
+ // Tessellate only outer edges oredges between areas.
|
||
|
|
if ((points[ci*4+3] & RC_CONTOUR_REG_MASK) == 0 ||
|
||
|
|
(points[ci*4+3] & RC_AREA_BORDER))
|
||
|
|
{
|
||
|
|
@@ -420,13 +420,15 @@ static void simplifyContour(rcIntArray& points, rcIntArray& simplified,
|
||
|
|
// Round based on the segments in lexilogical order so that the
|
||
|
|
// max tesselation is consistent regardles in which direction
|
||
|
|
// segments are traversed.
|
||
|
|
- const int n = bi < ai ? (bi+pn - ai) : (bi - ai);
|
||
|
|
- if (n > 1)
|
||
|
|
+ if (bx > ax || (bx == ax && bz > az))
|
||
|
|
{
|
||
|
|
- if (bx > ax || (bx == ax && bz > az))
|
||
|
|
- maxi = (ai + n/2) % pn;
|
||
|
|
- else
|
||
|
|
- maxi = (ai + (n+1)/2) % pn;
|
||
|
|
+ const int n = bi < ai ? (bi+pn - ai) : (bi - ai);
|
||
|
|
+ maxi = (ai + n/2) % pn;
|
||
|
|
+ }
|
||
|
|
+ else
|
||
|
|
+ {
|
||
|
|
+ const int n = bi < ai ? (bi+pn - ai) : (bi - ai);
|
||
|
|
+ maxi = (ai + (n+1)/2) % pn;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
@@ -464,7 +466,7 @@ static void simplifyContour(rcIntArray& points, rcIntArray& simplified,
|
||
|
|
// and the neighbour region is take from the next raw point.
|
||
|
|
const int ai = (simplified[i*4+3]+1) % pn;
|
||
|
|
const int bi = simplified[i*4+3];
|
||
|
|
- simplified[i*4+3] = (points[ai*4+3] & (RC_CONTOUR_REG_MASK|RC_AREA_BORDER)) | (points[bi*4+3] & RC_BORDER_VERTEX);
|
||
|
|
+ simplified[i*4+3] = (points[ai*4+3] & RC_CONTOUR_REG_MASK) | (points[bi*4+3] & RC_BORDER_VERTEX);
|
||
|
|
}
|
||
|
|
|
||
|
|
}
|
||
|
|
@@ -590,19 +592,6 @@ static bool mergeContours(rcContour& ca, rcContour& cb, int ia, int ib)
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
-/// @par
|
||
|
|
-///
|
||
|
|
-/// The raw contours will match the region outlines exactly. The @p maxError and @p maxEdgeLen
|
||
|
|
-/// parameters control how closely the simplified contours will match the raw contours.
|
||
|
|
-///
|
||
|
|
-/// Simplified contours are generated such that the vertices for portals between areas match up.
|
||
|
|
-/// (They are considered mandatory vertices.)
|
||
|
|
-///
|
||
|
|
-/// Setting @p maxEdgeLength to zero will disabled the edge length feature.
|
||
|
|
-///
|
||
|
|
-/// See the #rcConfig documentation for more information on the configuration parameters.
|
||
|
|
-///
|
||
|
|
-/// @see rcAllocContourSet, rcCompactHeightfield, rcContourSet, rcConfig
|
||
|
|
bool rcBuildContours(rcContext* ctx, rcCompactHeightfield& chf,
|
||
|
|
const float maxError, const int maxEdgeLen,
|
||
|
|
rcContourSet& cset, const int buildFlags)
|
||
|
|
@@ -611,26 +600,13 @@ bool rcBuildContours(rcContext* ctx, rcCompactHeightfield& chf,
|
||
|
|
|
||
|
|
const int w = chf.width;
|
||
|
|
const int h = chf.height;
|
||
|
|
- const int borderSize = chf.borderSize;
|
||
|
|
|
||
|
|
ctx->startTimer(RC_TIMER_BUILD_CONTOURS);
|
||
|
|
|
||
|
|
rcVcopy(cset.bmin, chf.bmin);
|
||
|
|
rcVcopy(cset.bmax, chf.bmax);
|
||
|
|
- if (borderSize > 0)
|
||
|
|
- {
|
||
|
|
- // If the heightfield was build with bordersize, remove the offset.
|
||
|
|
- const float pad = borderSize*chf.cs;
|
||
|
|
- cset.bmin[0] += pad;
|
||
|
|
- cset.bmin[2] += pad;
|
||
|
|
- cset.bmax[0] -= pad;
|
||
|
|
- cset.bmax[2] -= pad;
|
||
|
|
- }
|
||
|
|
cset.cs = chf.cs;
|
||
|
|
cset.ch = chf.ch;
|
||
|
|
- cset.width = chf.width - chf.borderSize*2;
|
||
|
|
- cset.height = chf.height - chf.borderSize*2;
|
||
|
|
- cset.borderSize = chf.borderSize;
|
||
|
|
|
||
|
|
int maxContours = rcMax((int)chf.maxRegions, 8);
|
||
|
|
cset.conts = (rcContour*)rcAlloc(sizeof(rcContour)*maxContours, RC_ALLOC_PERM);
|
||
|
|
@@ -682,6 +658,8 @@ bool rcBuildContours(rcContext* ctx, rcCompactHeightfield& chf,
|
||
|
|
|
||
|
|
ctx->stopTimer(RC_TIMER_BUILD_CONTOURS_TRACE);
|
||
|
|
|
||
|
|
+ ctx->startTimer(RC_TIMER_BUILD_CONTOURS_SIMPLIFY);
|
||
|
|
+
|
||
|
|
rcIntArray verts(256);
|
||
|
|
rcIntArray simplified(64);
|
||
|
|
|
||
|
|
@@ -704,17 +682,10 @@ bool rcBuildContours(rcContext* ctx, rcCompactHeightfield& chf,
|
||
|
|
|
||
|
|
verts.resize(0);
|
||
|
|
simplified.resize(0);
|
||
|
|
-
|
||
|
|
- ctx->startTimer(RC_TIMER_BUILD_CONTOURS_TRACE);
|
||
|
|
walkContour(x, y, i, chf, flags, verts);
|
||
|
|
- ctx->stopTimer(RC_TIMER_BUILD_CONTOURS_TRACE);
|
||
|
|
-
|
||
|
|
- ctx->startTimer(RC_TIMER_BUILD_CONTOURS_SIMPLIFY);
|
||
|
|
simplifyContour(verts, simplified, maxError, maxEdgeLen, buildFlags);
|
||
|
|
removeDegenerateSegments(simplified);
|
||
|
|
- ctx->stopTimer(RC_TIMER_BUILD_CONTOURS_SIMPLIFY);
|
||
|
|
|
||
|
|
-
|
||
|
|
// Store region->contour remap info.
|
||
|
|
// Create contour.
|
||
|
|
if (simplified.size()/4 >= 3)
|
||
|
|
@@ -749,16 +720,6 @@ bool rcBuildContours(rcContext* ctx, rcCompactHeightfield& chf,
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
memcpy(cont->verts, &simplified[0], sizeof(int)*cont->nverts*4);
|
||
|
|
- if (borderSize > 0)
|
||
|
|
- {
|
||
|
|
- // If the heightfield was build with bordersize, remove the offset.
|
||
|
|
- for (int j = 0; j < cont->nverts; ++j)
|
||
|
|
- {
|
||
|
|
- int* v = &cont->verts[j*4];
|
||
|
|
- v[0] -= borderSize;
|
||
|
|
- v[2] -= borderSize;
|
||
|
|
- }
|
||
|
|
- }
|
||
|
|
|
||
|
|
cont->nrverts = verts.size()/4;
|
||
|
|
cont->rverts = (int*)rcAlloc(sizeof(int)*cont->nrverts*4, RC_ALLOC_PERM);
|
||
|
|
@@ -768,16 +729,6 @@ bool rcBuildContours(rcContext* ctx, rcCompactHeightfield& chf,
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
memcpy(cont->rverts, &verts[0], sizeof(int)*cont->nrverts*4);
|
||
|
|
- if (borderSize > 0)
|
||
|
|
- {
|
||
|
|
- // If the heightfield was build with bordersize, remove the offset.
|
||
|
|
- for (int j = 0; j < cont->nrverts; ++j)
|
||
|
|
- {
|
||
|
|
- int* v = &cont->rverts[j*4];
|
||
|
|
- v[0] -= borderSize;
|
||
|
|
- v[2] -= borderSize;
|
||
|
|
- }
|
||
|
|
- }
|
||
|
|
|
||
|
|
/* cont->cx = cont->cy = cont->cz = 0;
|
||
|
|
for (int i = 0; i < cont->nverts; ++i)
|
||
|
|
@@ -845,6 +796,8 @@ bool rcBuildContours(rcContext* ctx, rcCompactHeightfield& chf,
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
+ ctx->stopTimer(RC_TIMER_BUILD_CONTOURS_SIMPLIFY);
|
||
|
|
+
|
||
|
|
ctx->stopTimer(RC_TIMER_BUILD_CONTOURS);
|
||
|
|
|
||
|
|
return true;
|
||
|
|
diff --git a/dep/recastnavigation/Recast/RecastFilter.cpp b/dep/recastnavigation/Recast/RecastFilter.cpp
|
||
|
|
index bf985c3..d01808a 100644
|
||
|
|
--- a/dep/recastnavigation/Recast/RecastFilter.cpp
|
||
|
|
+++ b/dep/recastnavigation/Recast/RecastFilter.cpp
|
||
|
|
@@ -22,17 +22,7 @@
|
||
|
|
#include "Recast.h"
|
||
|
|
#include "RecastAssert.h"
|
||
|
|
|
||
|
|
-/// @par
|
||
|
|
-///
|
||
|
|
-/// Allows the formation of walkable regions that will flow over low lying
|
||
|
|
-/// objects such as curbs, and up structures such as stairways.
|
||
|
|
-///
|
||
|
|
-/// Two neighboring spans are walkable if: <tt>rcAbs(currentSpan.smax - neighborSpan.smax) < waklableClimb</tt>
|
||
|
|
-///
|
||
|
|
-/// @warning Will override the effect of #rcFilterLedgeSpans. So if both filters are used, call
|
||
|
|
-/// #rcFilterLedgeSpans after calling this filter.
|
||
|
|
-///
|
||
|
|
-/// @see rcHeightfield, rcConfig
|
||
|
|
+
|
||
|
|
void rcFilterLowHangingWalkableObstacles(rcContext* ctx, const int walkableClimb, rcHeightfield& solid)
|
||
|
|
{
|
||
|
|
rcAssert(ctx);
|
||
|
|
@@ -48,7 +38,6 @@ void rcFilterLowHangingWalkableObstacles(rcContext* ctx, const int walkableClimb
|
||
|
|
{
|
||
|
|
rcSpan* ps = 0;
|
||
|
|
bool previousWalkable = false;
|
||
|
|
- unsigned char previousArea = RC_NULL_AREA;
|
||
|
|
|
||
|
|
for (rcSpan* s = solid.spans[x + y*w]; s; ps = s, s = s->next)
|
||
|
|
{
|
||
|
|
@@ -58,29 +47,18 @@ void rcFilterLowHangingWalkableObstacles(rcContext* ctx, const int walkableClimb
|
||
|
|
if (!walkable && previousWalkable)
|
||
|
|
{
|
||
|
|
if (rcAbs((int)s->smax - (int)ps->smax) <= walkableClimb)
|
||
|
|
- s->area = previousArea;
|
||
|
|
+ s->area = RC_NULL_AREA;
|
||
|
|
}
|
||
|
|
// Copy walkable flag so that it cannot propagate
|
||
|
|
// past multiple non-walkable objects.
|
||
|
|
previousWalkable = walkable;
|
||
|
|
- previousArea = s->area;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
ctx->stopTimer(RC_TIMER_FILTER_LOW_OBSTACLES);
|
||
|
|
}
|
||
|
|
-
|
||
|
|
-/// @par
|
||
|
|
-///
|
||
|
|
-/// A ledge is a span with one or more neighbors whose maximum is further away than @p walkableClimb
|
||
|
|
-/// from the current span's maximum.
|
||
|
|
-/// This method removes the impact of the overestimation of conservative voxelization
|
||
|
|
-/// so the resulting mesh will not have regions hanging in the air over ledges.
|
||
|
|
-///
|
||
|
|
-/// A span is a ledge if: <tt>rcAbs(currentSpan.smax - neighborSpan.smax) > walkableClimb</tt>
|
||
|
|
-///
|
||
|
|
-/// @see rcHeightfield, rcConfig
|
||
|
|
+
|
||
|
|
void rcFilterLedgeSpans(rcContext* ctx, const int walkableHeight, const int walkableClimb,
|
||
|
|
rcHeightfield& solid)
|
||
|
|
{
|
||
|
|
@@ -171,12 +149,6 @@ void rcFilterLedgeSpans(rcContext* ctx, const int walkableHeight, const int walk
|
||
|
|
ctx->stopTimer(RC_TIMER_FILTER_BORDER);
|
||
|
|
}
|
||
|
|
|
||
|
|
-/// @par
|
||
|
|
-///
|
||
|
|
-/// For this filter, the clearance above the span is the distance from the span's
|
||
|
|
-/// maximum to the next higher span's minimum. (Same grid column.)
|
||
|
|
-///
|
||
|
|
-/// @see rcHeightfield, rcConfig
|
||
|
|
void rcFilterWalkableLowHeightSpans(rcContext* ctx, int walkableHeight, rcHeightfield& solid)
|
||
|
|
{
|
||
|
|
rcAssert(ctx);
|
||
|
|
diff --git a/dep/recastnavigation/Recast/RecastLayers.cpp b/dep/recastnavigation/Recast/RecastLayers.cpp
|
||
|
|
deleted file mode 100644
|
||
|
|
index 5ea6cb7..0000000
|
||
|
|
--- a/dep/recastnavigation/Recast/RecastLayers.cpp
|
||
|
|
+++ /dev/null
|
||
|
|
@@ -1,620 +0,0 @@
|
||
|
|
-//
|
||
|
|
-// Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||
|
|
-//
|
||
|
|
-// This software is provided 'as-is', without any express or implied
|
||
|
|
-// warranty. In no event will the authors be held liable for any damages
|
||
|
|
-// arising from the use of this software.
|
||
|
|
-// Permission is granted to anyone to use this software for any purpose,
|
||
|
|
-// including commercial applications, and to alter it and redistribute it
|
||
|
|
-// freely, subject to the following restrictions:
|
||
|
|
-// 1. The origin of this software must not be misrepresented; you must not
|
||
|
|
-// claim that you wrote the original software. If you use this software
|
||
|
|
-// in a product, an acknowledgment in the product documentation would be
|
||
|
|
-// appreciated but is not required.
|
||
|
|
-// 2. Altered source versions must be plainly marked as such, and must not be
|
||
|
|
-// misrepresented as being the original software.
|
||
|
|
-// 3. This notice may not be removed or altered from any source distribution.
|
||
|
|
-//
|
||
|
|
-
|
||
|
|
-#include <float.h>
|
||
|
|
-#define _USE_MATH_DEFINES
|
||
|
|
-#include <math.h>
|
||
|
|
-#include <string.h>
|
||
|
|
-#include <stdlib.h>
|
||
|
|
-#include <stdio.h>
|
||
|
|
-#include "Recast.h"
|
||
|
|
-#include "RecastAlloc.h"
|
||
|
|
-#include "RecastAssert.h"
|
||
|
|
-
|
||
|
|
-
|
||
|
|
-static const int RC_MAX_LAYERS = RC_NOT_CONNECTED;
|
||
|
|
-static const int RC_MAX_NEIS = 16;
|
||
|
|
-
|
||
|
|
-struct rcLayerRegion
|
||
|
|
-{
|
||
|
|
- unsigned char layers[RC_MAX_LAYERS];
|
||
|
|
- unsigned char neis[RC_MAX_NEIS];
|
||
|
|
- unsigned short ymin, ymax;
|
||
|
|
- unsigned char layerId; // Layer ID
|
||
|
|
- unsigned char nlayers; // Layer count
|
||
|
|
- unsigned char nneis; // Neighbour count
|
||
|
|
- unsigned char base; // Flag indicating if the region is hte base of merged regions.
|
||
|
|
-};
|
||
|
|
-
|
||
|
|
-
|
||
|
|
-static void addUnique(unsigned char* a, unsigned char& an, unsigned char v)
|
||
|
|
-{
|
||
|
|
- const int n = (int)an;
|
||
|
|
- for (int i = 0; i < n; ++i)
|
||
|
|
- if (a[i] == v)
|
||
|
|
- return;
|
||
|
|
- a[an] = v;
|
||
|
|
- an++;
|
||
|
|
-}
|
||
|
|
-
|
||
|
|
-static bool contains(const unsigned char* a, const unsigned char an, const unsigned char v)
|
||
|
|
-{
|
||
|
|
- const int n = (int)an;
|
||
|
|
- for (int i = 0; i < n; ++i)
|
||
|
|
- if (a[i] == v)
|
||
|
|
- return true;
|
||
|
|
- return false;
|
||
|
|
-}
|
||
|
|
-
|
||
|
|
-inline bool overlapRange(const unsigned short amin, const unsigned short amax,
|
||
|
|
- const unsigned short bmin, const unsigned short bmax)
|
||
|
|
-{
|
||
|
|
- return (amin > bmax || amax < bmin) ? false : true;
|
||
|
|
-}
|
||
|
|
-
|
||
|
|
-
|
||
|
|
-
|
||
|
|
-struct rcLayerSweepSpan
|
||
|
|
-{
|
||
|
|
- unsigned short ns; // number samples
|
||
|
|
- unsigned char id; // region id
|
||
|
|
- unsigned char nei; // neighbour id
|
||
|
|
-};
|
||
|
|
-
|
||
|
|
-/// @par
|
||
|
|
-///
|
||
|
|
-/// See the #rcConfig documentation for more information on the configuration parameters.
|
||
|
|
-///
|
||
|
|
-/// @see rcAllocHeightfieldLayerSet, rcCompactHeightfield, rcHeightfieldLayerSet, rcConfig
|
||
|
|
-bool rcBuildHeightfieldLayers(rcContext* ctx, rcCompactHeightfield& chf,
|
||
|
|
- const int borderSize, const int walkableHeight,
|
||
|
|
- rcHeightfieldLayerSet& lset)
|
||
|
|
-{
|
||
|
|
- rcAssert(ctx);
|
||
|
|
-
|
||
|
|
- ctx->startTimer(RC_TIMER_BUILD_LAYERS);
|
||
|
|
-
|
||
|
|
- const int w = chf.width;
|
||
|
|
- const int h = chf.height;
|
||
|
|
-
|
||
|
|
- rcScopedDelete<unsigned char> srcReg = (unsigned char*)rcAlloc(sizeof(unsigned char)*chf.spanCount, RC_ALLOC_TEMP);
|
||
|
|
- if (!srcReg)
|
||
|
|
- {
|
||
|
|
- ctx->log(RC_LOG_ERROR, "rcBuildHeightfieldLayers: Out of memory 'srcReg' (%d).", chf.spanCount);
|
||
|
|
- return false;
|
||
|
|
- }
|
||
|
|
- memset(srcReg,0xff,sizeof(unsigned char)*chf.spanCount);
|
||
|
|
-
|
||
|
|
- const int nsweeps = chf.width;
|
||
|
|
- rcScopedDelete<rcLayerSweepSpan> sweeps = (rcLayerSweepSpan*)rcAlloc(sizeof(rcLayerSweepSpan)*nsweeps, RC_ALLOC_TEMP);
|
||
|
|
- if (!sweeps)
|
||
|
|
- {
|
||
|
|
- ctx->log(RC_LOG_ERROR, "rcBuildHeightfieldLayers: Out of memory 'sweeps' (%d).", nsweeps);
|
||
|
|
- return false;
|
||
|
|
- }
|
||
|
|
-
|
||
|
|
-
|
||
|
|
- // Partition walkable area into monotone regions.
|
||
|
|
- int prevCount[256];
|
||
|
|
- unsigned char regId = 0;
|
||
|
|
-
|
||
|
|
- for (int y = borderSize; y < h-borderSize; ++y)
|
||
|
|
- {
|
||
|
|
- memset(prevCount,0,sizeof(int)*regId);
|
||
|
|
- unsigned char sweepId = 0;
|
||
|
|
-
|
||
|
|
- for (int x = borderSize; x < w-borderSize; ++x)
|
||
|
|
- {
|
||
|
|
- const rcCompactCell& c = chf.cells[x+y*w];
|
||
|
|
-
|
||
|
|
- for (int i = (int)c.index, ni = (int)(c.index+c.count); i < ni; ++i)
|
||
|
|
- {
|
||
|
|
- const rcCompactSpan& s = chf.spans[i];
|
||
|
|
- if (chf.areas[i] == RC_NULL_AREA) continue;
|
||
|
|
-
|
||
|
|
- unsigned char sid = 0xff;
|
||
|
|
-
|
||
|
|
- // -x
|
||
|
|
- if (rcGetCon(s, 0) != RC_NOT_CONNECTED)
|
||
|
|
- {
|
||
|
|
- const int ax = x + rcGetDirOffsetX(0);
|
||
|
|
- const int ay = y + rcGetDirOffsetY(0);
|
||
|
|
- const int ai = (int)chf.cells[ax+ay*w].index + rcGetCon(s, 0);
|
||
|
|
- if (chf.areas[ai] != RC_NULL_AREA && srcReg[ai] != 0xff)
|
||
|
|
- sid = srcReg[ai];
|
||
|
|
- }
|
||
|
|
-
|
||
|
|
- if (sid == 0xff)
|
||
|
|
- {
|
||
|
|
- sid = sweepId++;
|
||
|
|
- sweeps[sid].nei = 0xff;
|
||
|
|
- sweeps[sid].ns = 0;
|
||
|
|
- }
|
||
|
|
-
|
||
|
|
- // -y
|
||
|
|
- if (rcGetCon(s,3) != RC_NOT_CONNECTED)
|
||
|
|
- {
|
||
|
|
- const int ax = x + rcGetDirOffsetX(3);
|
||
|
|
- const int ay = y + rcGetDirOffsetY(3);
|
||
|
|
- const int ai = (int)chf.cells[ax+ay*w].index + rcGetCon(s, 3);
|
||
|
|
- const unsigned char nr = srcReg[ai];
|
||
|
|
- if (nr != 0xff)
|
||
|
|
- {
|
||
|
|
- // Set neighbour when first valid neighbour is encoutered.
|
||
|
|
- if (sweeps[sid].ns == 0)
|
||
|
|
- sweeps[sid].nei = nr;
|
||
|
|
-
|
||
|
|
- if (sweeps[sid].nei == nr)
|
||
|
|
- {
|
||
|
|
- // Update existing neighbour
|
||
|
|
- sweeps[sid].ns++;
|
||
|
|
- prevCount[nr]++;
|
||
|
|
- }
|
||
|
|
- else
|
||
|
|
- {
|
||
|
|
- // This is hit if there is nore than one neighbour.
|
||
|
|
- // Invalidate the neighbour.
|
||
|
|
- sweeps[sid].nei = 0xff;
|
||
|
|
- }
|
||
|
|
- }
|
||
|
|
- }
|
||
|
|
-
|
||
|
|
- srcReg[i] = sid;
|
||
|
|
- }
|
||
|
|
- }
|
||
|
|
-
|
||
|
|
- // Create unique ID.
|
||
|
|
- for (int i = 0; i < sweepId; ++i)
|
||
|
|
- {
|
||
|
|
- // If the neighbour is set and there is only one continuous connection to it,
|
||
|
|
- // the sweep will be merged with the previous one, else new region is created.
|
||
|
|
- if (sweeps[i].nei != 0xff && prevCount[sweeps[i].nei] == (int)sweeps[i].ns)
|
||
|
|
- {
|
||
|
|
- sweeps[i].id = sweeps[i].nei;
|
||
|
|
- }
|
||
|
|
- else
|
||
|
|
- {
|
||
|
|
- if (regId == 255)
|
||
|
|
- {
|
||
|
|
- ctx->log(RC_LOG_ERROR, "rcBuildHeightfieldLayers: Region ID overflow.");
|
||
|
|
- return false;
|
||
|
|
- }
|
||
|
|
- sweeps[i].id = regId++;
|
||
|
|
- }
|
||
|
|
- }
|
||
|
|
-
|
||
|
|
- // Remap local sweep ids to region ids.
|
||
|
|
- for (int x = borderSize; x < w-borderSize; ++x)
|
||
|
|
- {
|
||
|
|
- const rcCompactCell& c = chf.cells[x+y*w];
|
||
|
|
- for (int i = (int)c.index, ni = (int)(c.index+c.count); i < ni; ++i)
|
||
|
|
- {
|
||
|
|
- if (srcReg[i] != 0xff)
|
||
|
|
- srcReg[i] = sweeps[srcReg[i]].id;
|
||
|
|
- }
|
||
|
|
- }
|
||
|
|
- }
|
||
|
|
-
|
||
|
|
- // Allocate and init layer regions.
|
||
|
|
- const int nregs = (int)regId;
|
||
|
|
- rcScopedDelete<rcLayerRegion> regs = (rcLayerRegion*)rcAlloc(sizeof(rcLayerRegion)*nregs, RC_ALLOC_TEMP);
|
||
|
|
- if (!regs)
|
||
|
|
- {
|
||
|
|
- ctx->log(RC_LOG_ERROR, "rcBuildHeightfieldLayers: Out of memory 'regs' (%d).", nregs);
|
||
|
|
- return false;
|
||
|
|
- }
|
||
|
|
- memset(regs, 0, sizeof(rcLayerRegion)*nregs);
|
||
|
|
- for (int i = 0; i < nregs; ++i)
|
||
|
|
- {
|
||
|
|
- regs[i].layerId = 0xff;
|
||
|
|
- regs[i].ymin = 0xffff;
|
||
|
|
- regs[i].ymax = 0;
|
||
|
|
- }
|
||
|
|
-
|
||
|
|
- // Find region neighbours and overlapping regions.
|
||
|
|
- for (int y = 0; y < h; ++y)
|
||
|
|
- {
|
||
|
|
- for (int x = 0; x < w; ++x)
|
||
|
|
- {
|
||
|
|
- const rcCompactCell& c = chf.cells[x+y*w];
|
||
|
|
-
|
||
|
|
- unsigned char lregs[RC_MAX_LAYERS];
|
||
|
|
- int nlregs = 0;
|
||
|
|
-
|
||
|
|
- for (int i = (int)c.index, ni = (int)(c.index+c.count); i < ni; ++i)
|
||
|
|
- {
|
||
|
|
- const rcCompactSpan& s = chf.spans[i];
|
||
|
|
- const unsigned char ri = srcReg[i];
|
||
|
|
- if (ri == 0xff) continue;
|
||
|
|
-
|
||
|
|
- regs[ri].ymin = rcMin(regs[ri].ymin, s.y);
|
||
|
|
- regs[ri].ymax = rcMax(regs[ri].ymax, s.y);
|
||
|
|
-
|
||
|
|
- // Collect all region layers.
|
||
|
|
- if (nlregs < RC_MAX_LAYERS)
|
||
|
|
- lregs[nlregs++] = ri;
|
||
|
|
-
|
||
|
|
- // Update neighbours
|
||
|
|
- for (int dir = 0; dir < 4; ++dir)
|
||
|
|
- {
|
||
|
|
- if (rcGetCon(s, dir) != RC_NOT_CONNECTED)
|
||
|
|
- {
|
||
|
|
- const int ax = x + rcGetDirOffsetX(dir);
|
||
|
|
- const int ay = y + rcGetDirOffsetY(dir);
|
||
|
|
- const int ai = (int)chf.cells[ax+ay*w].index + rcGetCon(s, dir);
|
||
|
|
- const unsigned char rai = srcReg[ai];
|
||
|
|
- if (rai != 0xff && rai != ri)
|
||
|
|
- addUnique(regs[ri].neis, regs[ri].nneis, rai);
|
||
|
|
- }
|
||
|
|
- }
|
||
|
|
-
|
||
|
|
- }
|
||
|
|
-
|
||
|
|
- // Update overlapping regions.
|
||
|
|
- for (int i = 0; i < nlregs-1; ++i)
|
||
|
|
- {
|
||
|
|
- for (int j = i+1; j < nlregs; ++j)
|
||
|
|
- {
|
||
|
|
- if (lregs[i] != lregs[j])
|
||
|
|
- {
|
||
|
|
- rcLayerRegion& ri = regs[lregs[i]];
|
||
|
|
- rcLayerRegion& rj = regs[lregs[j]];
|
||
|
|
- addUnique(ri.layers, ri.nlayers, lregs[j]);
|
||
|
|
- addUnique(rj.layers, rj.nlayers, lregs[i]);
|
||
|
|
- }
|
||
|
|
- }
|
||
|
|
- }
|
||
|
|
-
|
||
|
|
- }
|
||
|
|
- }
|
||
|
|
-
|
||
|
|
- // Create 2D layers from regions.
|
||
|
|
- unsigned char layerId = 0;
|
||
|
|
-
|
||
|
|
- static const int MAX_STACK = 64;
|
||
|
|
- unsigned char stack[MAX_STACK];
|
||
|
|
- int nstack = 0;
|
||
|
|
-
|
||
|
|
- for (int i = 0; i < nregs; ++i)
|
||
|
|
- {
|
||
|
|
- rcLayerRegion& root = regs[i];
|
||
|
|
- // Skip alreadu visited.
|
||
|
|
- if (root.layerId != 0xff)
|
||
|
|
- continue;
|
||
|
|
-
|
||
|
|
- // Start search.
|
||
|
|
- root.layerId = layerId;
|
||
|
|
- root.base = 1;
|
||
|
|
-
|
||
|
|
- nstack = 0;
|
||
|
|
- stack[nstack++] = (unsigned char)i;
|
||
|
|
-
|
||
|
|
- while (nstack)
|
||
|
|
- {
|
||
|
|
- // Pop front
|
||
|
|
- rcLayerRegion& reg = regs[stack[0]];
|
||
|
|
- nstack--;
|
||
|
|
- for (int j = 0; j < nstack; ++j)
|
||
|
|
- stack[j] = stack[j+1];
|
||
|
|
-
|
||
|
|
- const int nneis = (int)reg.nneis;
|
||
|
|
- for (int j = 0; j < nneis; ++j)
|
||
|
|
- {
|
||
|
|
- const unsigned char nei = reg.neis[j];
|
||
|
|
- rcLayerRegion& regn = regs[nei];
|
||
|
|
- // Skip already visited.
|
||
|
|
- if (regn.layerId != 0xff)
|
||
|
|
- continue;
|
||
|
|
- // Skip if the neighbour is overlapping root region.
|
||
|
|
- if (contains(root.layers, root.nlayers, nei))
|
||
|
|
- continue;
|
||
|
|
- // Skip if the height range would become too large.
|
||
|
|
- const int ymin = rcMin(root.ymin, regn.ymin);
|
||
|
|
- const int ymax = rcMax(root.ymax, regn.ymax); // Edited by TC
|
||
|
|
- if ((ymax - ymin) >= 255)
|
||
|
|
- continue;
|
||
|
|
-
|
||
|
|
- if (nstack < MAX_STACK)
|
||
|
|
- {
|
||
|
|
- // Deepen
|
||
|
|
- stack[nstack++] = (unsigned char)nei;
|
||
|
|
-
|
||
|
|
- // Mark layer id
|
||
|
|
- regn.layerId = layerId;
|
||
|
|
- // Merge current layers to root.
|
||
|
|
- for (int k = 0; k < regn.nlayers; ++k)
|
||
|
|
- addUnique(root.layers, root.nlayers, regn.layers[k]);
|
||
|
|
- root.ymin = rcMin(root.ymin, regn.ymin);
|
||
|
|
- root.ymax = rcMax(root.ymax, regn.ymax);
|
||
|
|
- }
|
||
|
|
- }
|
||
|
|
- }
|
||
|
|
-
|
||
|
|
- layerId++;
|
||
|
|
- }
|
||
|
|
-
|
||
|
|
- // Merge non-overlapping regions that are close in height.
|
||
|
|
- const unsigned short mergeHeight = (unsigned short)walkableHeight * 4;
|
||
|
|
-
|
||
|
|
- for (int i = 0; i < nregs; ++i)
|
||
|
|
- {
|
||
|
|
- rcLayerRegion& ri = regs[i];
|
||
|
|
- if (!ri.base) continue;
|
||
|
|
-
|
||
|
|
- unsigned char newId = ri.layerId;
|
||
|
|
-
|
||
|
|
- for (;;)
|
||
|
|
- {
|
||
|
|
- unsigned char oldId = 0xff;
|
||
|
|
-
|
||
|
|
- for (int j = 0; j < nregs; ++j)
|
||
|
|
- {
|
||
|
|
- if (i == j) continue;
|
||
|
|
- rcLayerRegion& rj = regs[j];
|
||
|
|
- if (!rj.base) continue;
|
||
|
|
-
|
||
|
|
- // Skip if teh regions are not close to each other.
|
||
|
|
- if (!overlapRange(ri.ymin,ri.ymax+mergeHeight, rj.ymin,rj.ymax+mergeHeight))
|
||
|
|
- continue;
|
||
|
|
- // Skip if the height range would become too large.
|
||
|
|
- const int ymin = rcMin(ri.ymin, rj.ymin);
|
||
|
|
- const int ymax = rcMax(ri.ymax, rj.ymax); // Edited by TC
|
||
|
|
- if ((ymax - ymin) >= 255)
|
||
|
|
- continue;
|
||
|
|
-
|
||
|
|
- // Make sure that there is no overlap when mergin 'ri' and 'rj'.
|
||
|
|
- bool overlap = false;
|
||
|
|
- // Iterate over all regions which have the same layerId as 'rj'
|
||
|
|
- for (int k = 0; k < nregs; ++k)
|
||
|
|
- {
|
||
|
|
- if (regs[k].layerId != rj.layerId)
|
||
|
|
- continue;
|
||
|
|
- // Check if region 'k' is overlapping region 'ri'
|
||
|
|
- // Index to 'regs' is the same as region id.
|
||
|
|
- if (contains(ri.layers,ri.nlayers, (unsigned char)k))
|
||
|
|
- {
|
||
|
|
- overlap = true;
|
||
|
|
- break;
|
||
|
|
- }
|
||
|
|
- }
|
||
|
|
- // Cannot merge of regions overlap.
|
||
|
|
- if (overlap)
|
||
|
|
- continue;
|
||
|
|
-
|
||
|
|
- // Can merge i and j.
|
||
|
|
- oldId = rj.layerId;
|
||
|
|
- break;
|
||
|
|
- }
|
||
|
|
-
|
||
|
|
- // Could not find anything to merge with, stop.
|
||
|
|
- if (oldId == 0xff)
|
||
|
|
- break;
|
||
|
|
-
|
||
|
|
- // Merge
|
||
|
|
- for (int j = 0; j < nregs; ++j)
|
||
|
|
- {
|
||
|
|
- rcLayerRegion& rj = regs[j];
|
||
|
|
- if (rj.layerId == oldId)
|
||
|
|
- {
|
||
|
|
- rj.base = 0;
|
||
|
|
- // Remap layerIds.
|
||
|
|
- rj.layerId = newId;
|
||
|
|
- // Add overlaid layers from 'rj' to 'ri'.
|
||
|
|
- for (int k = 0; k < rj.nlayers; ++k)
|
||
|
|
- addUnique(ri.layers, ri.nlayers, rj.layers[k]);
|
||
|
|
- // Update heigh bounds.
|
||
|
|
- ri.ymin = rcMin(ri.ymin, rj.ymin);
|
||
|
|
- ri.ymax = rcMax(ri.ymax, rj.ymax);
|
||
|
|
- }
|
||
|
|
- }
|
||
|
|
- }
|
||
|
|
- }
|
||
|
|
-
|
||
|
|
- // Compact layerIds
|
||
|
|
- unsigned char remap[256];
|
||
|
|
- memset(remap, 0, 256);
|
||
|
|
-
|
||
|
|
- // Find number of unique layers.
|
||
|
|
- layerId = 0;
|
||
|
|
- for (int i = 0; i < nregs; ++i)
|
||
|
|
- remap[regs[i].layerId] = 1;
|
||
|
|
- for (int i = 0; i < 256; ++i)
|
||
|
|
- {
|
||
|
|
- if (remap[i])
|
||
|
|
- remap[i] = layerId++;
|
||
|
|
- else
|
||
|
|
- remap[i] = 0xff;
|
||
|
|
- }
|
||
|
|
- // Remap ids.
|
||
|
|
- for (int i = 0; i < nregs; ++i)
|
||
|
|
- regs[i].layerId = remap[regs[i].layerId];
|
||
|
|
-
|
||
|
|
- // No layers, return empty.
|
||
|
|
- if (layerId == 0)
|
||
|
|
- {
|
||
|
|
- ctx->stopTimer(RC_TIMER_BUILD_LAYERS);
|
||
|
|
- return true;
|
||
|
|
- }
|
||
|
|
-
|
||
|
|
- // Create layers.
|
||
|
|
- rcAssert(lset.layers == 0);
|
||
|
|
-
|
||
|
|
- const int lw = w - borderSize*2;
|
||
|
|
- const int lh = h - borderSize*2;
|
||
|
|
-
|
||
|
|
- // Build contracted bbox for layers.
|
||
|
|
- float bmin[3], bmax[3];
|
||
|
|
- rcVcopy(bmin, chf.bmin);
|
||
|
|
- rcVcopy(bmax, chf.bmax);
|
||
|
|
- bmin[0] += borderSize*chf.cs;
|
||
|
|
- bmin[2] += borderSize*chf.cs;
|
||
|
|
- bmax[0] -= borderSize*chf.cs;
|
||
|
|
- bmax[2] -= borderSize*chf.cs;
|
||
|
|
-
|
||
|
|
- lset.nlayers = (int)layerId;
|
||
|
|
-
|
||
|
|
- lset.layers = (rcHeightfieldLayer*)rcAlloc(sizeof(rcHeightfieldLayer)*lset.nlayers, RC_ALLOC_PERM);
|
||
|
|
- if (!lset.layers)
|
||
|
|
- {
|
||
|
|
- ctx->log(RC_LOG_ERROR, "rcBuildHeightfieldLayers: Out of memory 'layers' (%d).", lset.nlayers);
|
||
|
|
- return false;
|
||
|
|
- }
|
||
|
|
- memset(lset.layers, 0, sizeof(rcHeightfieldLayer)*lset.nlayers);
|
||
|
|
-
|
||
|
|
-
|
||
|
|
- // Store layers.
|
||
|
|
- for (int i = 0; i < lset.nlayers; ++i)
|
||
|
|
- {
|
||
|
|
- unsigned char curId = (unsigned char)i;
|
||
|
|
-
|
||
|
|
- // Allocate memory for the current layer.
|
||
|
|
- rcHeightfieldLayer* layer = &lset.layers[i];
|
||
|
|
- memset(layer, 0, sizeof(rcHeightfieldLayer));
|
||
|
|
-
|
||
|
|
- const int gridSize = sizeof(unsigned char)*lw*lh;
|
||
|
|
-
|
||
|
|
- layer->heights = (unsigned char*)rcAlloc(gridSize, RC_ALLOC_PERM);
|
||
|
|
- if (!layer->heights)
|
||
|
|
- {
|
||
|
|
- ctx->log(RC_LOG_ERROR, "rcBuildHeightfieldLayers: Out of memory 'heights' (%d).", gridSize);
|
||
|
|
- return false;
|
||
|
|
- }
|
||
|
|
- memset(layer->heights, 0xff, gridSize);
|
||
|
|
-
|
||
|
|
- layer->areas = (unsigned char*)rcAlloc(gridSize, RC_ALLOC_PERM);
|
||
|
|
- if (!layer->areas)
|
||
|
|
- {
|
||
|
|
- ctx->log(RC_LOG_ERROR, "rcBuildHeightfieldLayers: Out of memory 'areas' (%d).", gridSize);
|
||
|
|
- return false;
|
||
|
|
- }
|
||
|
|
- memset(layer->areas, 0, gridSize);
|
||
|
|
-
|
||
|
|
- layer->cons = (unsigned char*)rcAlloc(gridSize, RC_ALLOC_PERM);
|
||
|
|
- if (!layer->cons)
|
||
|
|
- {
|
||
|
|
- ctx->log(RC_LOG_ERROR, "rcBuildHeightfieldLayers: Out of memory 'cons' (%d).", gridSize);
|
||
|
|
- return false;
|
||
|
|
- }
|
||
|
|
- memset(layer->cons, 0, gridSize);
|
||
|
|
-
|
||
|
|
- // Find layer height bounds.
|
||
|
|
- int hmin = 0, hmax = 0;
|
||
|
|
- for (int j = 0; j < nregs; ++j)
|
||
|
|
- {
|
||
|
|
- if (regs[j].base && regs[j].layerId == curId)
|
||
|
|
- {
|
||
|
|
- hmin = (int)regs[j].ymin;
|
||
|
|
- hmax = (int)regs[j].ymax;
|
||
|
|
- }
|
||
|
|
- }
|
||
|
|
-
|
||
|
|
- layer->width = lw;
|
||
|
|
- layer->height = lh;
|
||
|
|
- layer->cs = chf.cs;
|
||
|
|
- layer->ch = chf.ch;
|
||
|
|
-
|
||
|
|
- // Adjust the bbox to fit the heighfield.
|
||
|
|
- rcVcopy(layer->bmin, bmin);
|
||
|
|
- rcVcopy(layer->bmax, bmax);
|
||
|
|
- layer->bmin[1] = bmin[1] + hmin*chf.ch;
|
||
|
|
- layer->bmax[1] = bmin[1] + hmax*chf.ch;
|
||
|
|
- layer->hmin = hmin;
|
||
|
|
- layer->hmax = hmax;
|
||
|
|
-
|
||
|
|
- // Update usable data region.
|
||
|
|
- layer->minx = layer->width;
|
||
|
|
- layer->maxx = 0;
|
||
|
|
- layer->miny = layer->height;
|
||
|
|
- layer->maxy = 0;
|
||
|
|
-
|
||
|
|
- // Copy height and area from compact heighfield.
|
||
|
|
- for (int y = 0; y < lh; ++y)
|
||
|
|
- {
|
||
|
|
- for (int x = 0; x < lw; ++x)
|
||
|
|
- {
|
||
|
|
- const int cx = borderSize+x;
|
||
|
|
- const int cy = borderSize+y;
|
||
|
|
- const rcCompactCell& c = chf.cells[cx+cy*w];
|
||
|
|
- for (int j = (int)c.index, nj = (int)(c.index+c.count); j < nj; ++j)
|
||
|
|
- {
|
||
|
|
- const rcCompactSpan& s = chf.spans[j];
|
||
|
|
- // Skip unassigned regions.
|
||
|
|
- if (srcReg[j] == 0xff)
|
||
|
|
- continue;
|
||
|
|
- // Skip of does nto belong to current layer.
|
||
|
|
- unsigned char lid = regs[srcReg[j]].layerId;
|
||
|
|
- if (lid != curId)
|
||
|
|
- continue;
|
||
|
|
-
|
||
|
|
- // Update data bounds.
|
||
|
|
- layer->minx = rcMin(layer->minx, x);
|
||
|
|
- layer->maxx = rcMax(layer->maxx, x);
|
||
|
|
- layer->miny = rcMin(layer->miny, y);
|
||
|
|
- layer->maxy = rcMax(layer->maxy, y);
|
||
|
|
-
|
||
|
|
- // Store height and area type.
|
||
|
|
- const int idx = x+y*lw;
|
||
|
|
- layer->heights[idx] = (unsigned char)(s.y - hmin);
|
||
|
|
- layer->areas[idx] = chf.areas[j];
|
||
|
|
-
|
||
|
|
- // Check connection.
|
||
|
|
- unsigned char portal = 0;
|
||
|
|
- unsigned char con = 0;
|
||
|
|
- for (int dir = 0; dir < 4; ++dir)
|
||
|
|
- {
|
||
|
|
- if (rcGetCon(s, dir) != RC_NOT_CONNECTED)
|
||
|
|
- {
|
||
|
|
- const int ax = cx + rcGetDirOffsetX(dir);
|
||
|
|
- const int ay = cy + rcGetDirOffsetY(dir);
|
||
|
|
- const int ai = (int)chf.cells[ax+ay*w].index + rcGetCon(s, dir);
|
||
|
|
- unsigned char alid = srcReg[ai] != 0xff ? regs[srcReg[ai]].layerId : 0xff;
|
||
|
|
- // Portal mask
|
||
|
|
- if (chf.areas[ai] != RC_NULL_AREA && lid != alid)
|
||
|
|
- {
|
||
|
|
- portal |= (unsigned char)(1<<dir);
|
||
|
|
- // Update height so that it matches on both sides of the portal.
|
||
|
|
- const rcCompactSpan& as = chf.spans[ai];
|
||
|
|
- if (as.y > hmin)
|
||
|
|
- layer->heights[idx] = rcMax(layer->heights[idx], (unsigned char)(as.y - hmin));
|
||
|
|
- }
|
||
|
|
- // Valid connection mask
|
||
|
|
- if (chf.areas[ai] != RC_NULL_AREA && lid == alid)
|
||
|
|
- {
|
||
|
|
- const int nx = ax - borderSize;
|
||
|
|
- const int ny = ay - borderSize;
|
||
|
|
- if (nx >= 0 && ny >= 0 && nx < lw && ny < lh)
|
||
|
|
- con |= (unsigned char)(1<<dir);
|
||
|
|
- }
|
||
|
|
- }
|
||
|
|
- }
|
||
|
|
-
|
||
|
|
- layer->cons[idx] = (portal << 4) | con;
|
||
|
|
- }
|
||
|
|
- }
|
||
|
|
- }
|
||
|
|
-
|
||
|
|
- if (layer->minx > layer->maxx)
|
||
|
|
- layer->minx = layer->maxx = 0;
|
||
|
|
- if (layer->miny > layer->maxy)
|
||
|
|
- layer->miny = layer->maxy = 0;
|
||
|
|
- }
|
||
|
|
-
|
||
|
|
- ctx->stopTimer(RC_TIMER_BUILD_LAYERS);
|
||
|
|
-
|
||
|
|
- return true;
|
||
|
|
-}
|
||
|
|
diff --git a/dep/recastnavigation/Recast/RecastMesh.cpp b/dep/recastnavigation/Recast/RecastMesh.cpp
|
||
|
|
index 13aad2a..4b33c10 100644
|
||
|
|
--- a/dep/recastnavigation/Recast/RecastMesh.cpp
|
||
|
|
+++ b/dep/recastnavigation/Recast/RecastMesh.cpp
|
||
|
|
@@ -59,7 +59,6 @@ static bool buildMeshAdjacency(unsigned short* polys, const int npolys,
|
||
|
|
unsigned short* t = &polys[i*vertsPerPoly*2];
|
||
|
|
for (int j = 0; j < vertsPerPoly; ++j)
|
||
|
|
{
|
||
|
|
- if (t[j] == RC_MESH_NULL_IDX) break;
|
||
|
|
unsigned short v0 = t[j];
|
||
|
|
unsigned short v1 = (j+1 >= vertsPerPoly || t[j+1] == RC_MESH_NULL_IDX) ? t[0] : t[j+1];
|
||
|
|
if (v0 < v1)
|
||
|
|
@@ -84,7 +83,6 @@ static bool buildMeshAdjacency(unsigned short* polys, const int npolys,
|
||
|
|
unsigned short* t = &polys[i*vertsPerPoly*2];
|
||
|
|
for (int j = 0; j < vertsPerPoly; ++j)
|
||
|
|
{
|
||
|
|
- if (t[j] == RC_MESH_NULL_IDX) break;
|
||
|
|
unsigned short v0 = t[j];
|
||
|
|
unsigned short v1 = (j+1 >= vertsPerPoly || t[j+1] == RC_MESH_NULL_IDX) ? t[0] : t[j+1];
|
||
|
|
if (v0 > v1)
|
||
|
|
@@ -197,7 +195,7 @@ inline bool collinear(const int* a, const int* b, const int* c)
|
||
|
|
// Returns true iff ab properly intersects cd: they share
|
||
|
|
// a point interior to both segments. The properness of the
|
||
|
|
// intersection is ensured by using strict leftness.
|
||
|
|
-static bool intersectProp(const int* a, const int* b, const int* c, const int* d)
|
||
|
|
+bool intersectProp(const int* a, const int* b, const int* c, const int* d)
|
||
|
|
{
|
||
|
|
// Eliminate improper cases.
|
||
|
|
if (collinear(a,b,c) || collinear(a,b,d) ||
|
||
|
|
@@ -472,7 +470,6 @@ static void mergePolys(unsigned short* pa, unsigned short* pb, int ea, int eb,
|
||
|
|
memcpy(pa, tmp, sizeof(unsigned short)*nvp);
|
||
|
|
}
|
||
|
|
|
||
|
|
-
|
||
|
|
static void pushFront(int v, int* arr, int& an)
|
||
|
|
{
|
||
|
|
an++;
|
||
|
|
@@ -550,9 +547,9 @@ static bool canRemoveVertex(rcContext* ctx, rcPolyMesh& mesh, const unsigned sho
|
||
|
|
|
||
|
|
// Check if the edge exists
|
||
|
|
bool exists = false;
|
||
|
|
- for (int m = 0; m < nedges; ++m)
|
||
|
|
+ for (int k = 0; k < nedges; ++k)
|
||
|
|
{
|
||
|
|
- int* e = &edges[m*3];
|
||
|
|
+ int* e = &edges[k*3];
|
||
|
|
if (e[1] == b)
|
||
|
|
{
|
||
|
|
// Exists, increment vertex share count.
|
||
|
|
@@ -895,13 +892,8 @@ static bool removeVertex(rcContext* ctx, rcPolyMesh& mesh, const unsigned short
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
-/// @par
|
||
|
|
-///
|
||
|
|
-/// @note If the mesh data is to be used to construct a Detour navigation mesh, then the upper
|
||
|
|
-/// limit must be retricted to <= #DT_VERTS_PER_POLYGON.
|
||
|
|
-///
|
||
|
|
-/// @see rcAllocPolyMesh, rcContourSet, rcPolyMesh, rcConfig
|
||
|
|
-bool rcBuildPolyMesh(rcContext* ctx, rcContourSet& cset, const int nvp, rcPolyMesh& mesh)
|
||
|
|
+
|
||
|
|
+bool rcBuildPolyMesh(rcContext* ctx, rcContourSet& cset, int nvp, rcPolyMesh& mesh)
|
||
|
|
{
|
||
|
|
rcAssert(ctx);
|
||
|
|
|
||
|
|
@@ -911,7 +903,6 @@ bool rcBuildPolyMesh(rcContext* ctx, rcContourSet& cset, const int nvp, rcPolyMe
|
||
|
|
rcVcopy(mesh.bmax, cset.bmax);
|
||
|
|
mesh.cs = cset.cs;
|
||
|
|
mesh.ch = cset.ch;
|
||
|
|
- mesh.borderSize = cset.borderSize;
|
||
|
|
|
||
|
|
int maxVertices = 0;
|
||
|
|
int maxTris = 0;
|
||
|
|
@@ -934,7 +925,7 @@ bool rcBuildPolyMesh(rcContext* ctx, rcContourSet& cset, const int nvp, rcPolyMe
|
||
|
|
rcScopedDelete<unsigned char> vflags = (unsigned char*)rcAlloc(sizeof(unsigned char)*maxVertices, RC_ALLOC_TEMP);
|
||
|
|
if (!vflags)
|
||
|
|
{
|
||
|
|
- ctx->log(RC_LOG_ERROR, "rcBuildPolyMesh: Out of memory 'vflags' (%d).", maxVertices);
|
||
|
|
+ ctx->log(RC_LOG_ERROR, "rcBuildPolyMesh: Out of memory 'mesh.verts' (%d).", maxVertices);
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
memset(vflags, 0, maxVertices);
|
||
|
|
@@ -945,7 +936,7 @@ bool rcBuildPolyMesh(rcContext* ctx, rcContourSet& cset, const int nvp, rcPolyMe
|
||
|
|
ctx->log(RC_LOG_ERROR, "rcBuildPolyMesh: Out of memory 'mesh.verts' (%d).", maxVertices);
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
- mesh.polys = (unsigned short*)rcAlloc(sizeof(unsigned short)*maxTris*nvp*2, RC_ALLOC_PERM);
|
||
|
|
+ mesh.polys = (unsigned short*)rcAlloc(sizeof(unsigned short)*maxTris*nvp*2*2, RC_ALLOC_PERM);
|
||
|
|
if (!mesh.polys)
|
||
|
|
{
|
||
|
|
ctx->log(RC_LOG_ERROR, "rcBuildPolyMesh: Out of memory 'mesh.polys' (%d).", maxTris*nvp*2);
|
||
|
|
@@ -1053,7 +1044,7 @@ bool rcBuildPolyMesh(rcContext* ctx, rcContourSet& cset, const int nvp, rcPolyMe
|
||
|
|
vflags[indices[j]] = 1;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
-
|
||
|
|
+
|
||
|
|
// Build initial polygons.
|
||
|
|
int npolys = 0;
|
||
|
|
memset(polys, 0xff, maxVertsPerCont*nvp*sizeof(unsigned short));
|
||
|
|
@@ -1150,7 +1141,6 @@ bool rcBuildPolyMesh(rcContext* ctx, rcContourSet& cset, const int nvp, rcPolyMe
|
||
|
|
}
|
||
|
|
// Remove vertex
|
||
|
|
// Note: mesh.nverts is already decremented inside removeVertex()!
|
||
|
|
- // Fixup vertex flags
|
||
|
|
for (int j = i; j < mesh.nverts; ++j)
|
||
|
|
vflags[j] = vflags[j+1];
|
||
|
|
--i;
|
||
|
|
@@ -1163,37 +1153,6 @@ bool rcBuildPolyMesh(rcContext* ctx, rcContourSet& cset, const int nvp, rcPolyMe
|
||
|
|
ctx->log(RC_LOG_ERROR, "rcBuildPolyMesh: Adjacency failed.");
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
-
|
||
|
|
- // Find portal edges
|
||
|
|
- if (mesh.borderSize > 0)
|
||
|
|
- {
|
||
|
|
- const int w = cset.width;
|
||
|
|
- const int h = cset.height;
|
||
|
|
- for (int i = 0; i < mesh.npolys; ++i)
|
||
|
|
- {
|
||
|
|
- unsigned short* p = &mesh.polys[i*2*nvp];
|
||
|
|
- for (int j = 0; j < nvp; ++j)
|
||
|
|
- {
|
||
|
|
- if (p[j] == RC_MESH_NULL_IDX) break;
|
||
|
|
- // Skip connected edges.
|
||
|
|
- if (p[nvp+j] != RC_MESH_NULL_IDX)
|
||
|
|
- continue;
|
||
|
|
- int nj = j+1;
|
||
|
|
- if (nj >= nvp || p[nj] == RC_MESH_NULL_IDX) nj = 0;
|
||
|
|
- const unsigned short* va = &mesh.verts[p[j]*3];
|
||
|
|
- const unsigned short* vb = &mesh.verts[p[nj]*3];
|
||
|
|
-
|
||
|
|
- if ((int)va[0] == 0 && (int)vb[0] == 0)
|
||
|
|
- p[nvp+j] = 0x8000 | 0;
|
||
|
|
- else if ((int)va[2] == h && (int)vb[2] == h)
|
||
|
|
- p[nvp+j] = 0x8000 | 1;
|
||
|
|
- else if ((int)va[0] == w && (int)vb[0] == w)
|
||
|
|
- p[nvp+j] = 0x8000 | 2;
|
||
|
|
- else if ((int)va[2] == 0 && (int)vb[2] == 0)
|
||
|
|
- p[nvp+j] = 0x8000 | 3;
|
||
|
|
- }
|
||
|
|
- }
|
||
|
|
- }
|
||
|
|
|
||
|
|
// Just allocate the mesh flags array. The user is resposible to fill it.
|
||
|
|
mesh.flags = (unsigned short*)rcAlloc(sizeof(unsigned short)*mesh.npolys, RC_ALLOC_PERM);
|
||
|
|
@@ -1206,11 +1165,11 @@ bool rcBuildPolyMesh(rcContext* ctx, rcContourSet& cset, const int nvp, rcPolyMe
|
||
|
|
|
||
|
|
if (mesh.nverts > 0xffff)
|
||
|
|
{
|
||
|
|
- ctx->log(RC_LOG_ERROR, "rcBuildPolyMesh: The resulting mesh has too many vertices %d (max %d). Data can be corrupted.", mesh.nverts, 0xffff);
|
||
|
|
+ ctx->log(RC_LOG_ERROR, "rcMergePolyMeshes: The resulting mesh has too many vertices %d (max %d). Data can be corrupted.", mesh.nverts, 0xffff);
|
||
|
|
}
|
||
|
|
if (mesh.npolys > 0xffff)
|
||
|
|
{
|
||
|
|
- ctx->log(RC_LOG_ERROR, "rcBuildPolyMesh: The resulting mesh has too many polygons %d (max %d). Data can be corrupted.", mesh.npolys, 0xffff);
|
||
|
|
+ ctx->log(RC_LOG_ERROR, "rcMergePolyMeshes: The resulting mesh has too many polygons %d (max %d). Data can be corrupted.", mesh.npolys, 0xffff);
|
||
|
|
}
|
||
|
|
|
||
|
|
ctx->stopTimer(RC_TIMER_BUILD_POLYMESH);
|
||
|
|
@@ -1218,7 +1177,6 @@ bool rcBuildPolyMesh(rcContext* ctx, rcContourSet& cset, const int nvp, rcPolyMe
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
-/// @see rcAllocPolyMesh, rcPolyMesh
|
||
|
|
bool rcMergePolyMeshes(rcContext* ctx, rcPolyMesh** meshes, const int nmeshes, rcPolyMesh& mesh)
|
||
|
|
{
|
||
|
|
rcAssert(ctx);
|
||
|
|
@@ -1310,7 +1268,7 @@ bool rcMergePolyMeshes(rcContext* ctx, rcPolyMesh** meshes, const int nmeshes, r
|
||
|
|
ctx->log(RC_LOG_ERROR, "rcMergePolyMeshes: Out of memory 'vremap' (%d).", maxVertsPerMesh);
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
- memset(vremap, 0, sizeof(unsigned short)*maxVertsPerMesh);
|
||
|
|
+ memset(nextVert, 0, sizeof(int)*maxVerts);
|
||
|
|
|
||
|
|
for (int i = 0; i < nmeshes; ++i)
|
||
|
|
{
|
||
|
|
@@ -1362,67 +1320,3 @@ bool rcMergePolyMeshes(rcContext* ctx, rcPolyMesh** meshes, const int nmeshes, r
|
||
|
|
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
-
|
||
|
|
-bool rcCopyPolyMesh(rcContext* ctx, const rcPolyMesh& src, rcPolyMesh& dst)
|
||
|
|
-{
|
||
|
|
- rcAssert(ctx);
|
||
|
|
-
|
||
|
|
- // Destination must be empty.
|
||
|
|
- rcAssert(dst.verts == 0);
|
||
|
|
- rcAssert(dst.polys == 0);
|
||
|
|
- rcAssert(dst.regs == 0);
|
||
|
|
- rcAssert(dst.areas == 0);
|
||
|
|
- rcAssert(dst.flags == 0);
|
||
|
|
-
|
||
|
|
- dst.nverts = src.nverts;
|
||
|
|
- dst.npolys = src.npolys;
|
||
|
|
- dst.maxpolys = src.npolys;
|
||
|
|
- dst.nvp = src.nvp;
|
||
|
|
- rcVcopy(dst.bmin, src.bmin);
|
||
|
|
- rcVcopy(dst.bmax, src.bmax);
|
||
|
|
- dst.cs = src.cs;
|
||
|
|
- dst.ch = src.ch;
|
||
|
|
- dst.borderSize = src.borderSize;
|
||
|
|
-
|
||
|
|
- dst.verts = (unsigned short*)rcAlloc(sizeof(unsigned short)*src.nverts*3, RC_ALLOC_PERM);
|
||
|
|
- if (!dst.verts)
|
||
|
|
- {
|
||
|
|
- ctx->log(RC_LOG_ERROR, "rcCopyPolyMesh: Out of memory 'dst.verts' (%d).", src.nverts*3);
|
||
|
|
- return false;
|
||
|
|
- }
|
||
|
|
- memcpy(dst.verts, src.verts, sizeof(unsigned short)*src.nverts*3);
|
||
|
|
-
|
||
|
|
- dst.polys = (unsigned short*)rcAlloc(sizeof(unsigned short)*src.npolys*2*src.nvp, RC_ALLOC_PERM);
|
||
|
|
- if (!dst.polys)
|
||
|
|
- {
|
||
|
|
- ctx->log(RC_LOG_ERROR, "rcCopyPolyMesh: Out of memory 'dst.polys' (%d).", src.npolys*2*src.nvp);
|
||
|
|
- return false;
|
||
|
|
- }
|
||
|
|
- memcpy(dst.polys, src.polys, sizeof(unsigned short)*src.npolys*2*src.nvp);
|
||
|
|
-
|
||
|
|
- dst.regs = (unsigned short*)rcAlloc(sizeof(unsigned short)*src.npolys, RC_ALLOC_PERM);
|
||
|
|
- if (!dst.regs)
|
||
|
|
- {
|
||
|
|
- ctx->log(RC_LOG_ERROR, "rcCopyPolyMesh: Out of memory 'dst.regs' (%d).", src.npolys);
|
||
|
|
- return false;
|
||
|
|
- }
|
||
|
|
- memcpy(dst.regs, src.regs, sizeof(unsigned short)*src.npolys);
|
||
|
|
-
|
||
|
|
- dst.areas = (unsigned char*)rcAlloc(sizeof(unsigned char)*src.npolys, RC_ALLOC_PERM);
|
||
|
|
- if (!dst.areas)
|
||
|
|
- {
|
||
|
|
- ctx->log(RC_LOG_ERROR, "rcCopyPolyMesh: Out of memory 'dst.areas' (%d).", src.npolys);
|
||
|
|
- return false;
|
||
|
|
- }
|
||
|
|
- memcpy(dst.areas, src.areas, sizeof(unsigned char)*src.npolys);
|
||
|
|
-
|
||
|
|
- dst.flags = (unsigned short*)rcAlloc(sizeof(unsigned short)*src.npolys, RC_ALLOC_PERM);
|
||
|
|
- if (!dst.flags)
|
||
|
|
- {
|
||
|
|
- ctx->log(RC_LOG_ERROR, "rcCopyPolyMesh: Out of memory 'dst.flags' (%d).", src.npolys);
|
||
|
|
- return false;
|
||
|
|
- }
|
||
|
|
- memcpy(dst.flags, src.flags, sizeof(unsigned char)*src.npolys);
|
||
|
|
-
|
||
|
|
- return true;
|
||
|
|
-}
|
||
|
|
diff --git a/dep/recastnavigation/Recast/RecastMeshDetail.cpp b/dep/recastnavigation/Recast/RecastMeshDetail.cpp
|
||
|
|
index f49d674..ffb4b58 100644
|
||
|
|
--- a/dep/recastnavigation/Recast/RecastMeshDetail.cpp
|
||
|
|
+++ b/dep/recastnavigation/Recast/RecastMeshDetail.cpp
|
||
|
|
@@ -267,11 +267,11 @@ static int addEdge(rcContext* ctx, int* edges, int& nedges, const int maxEdges,
|
||
|
|
int e = findEdge(edges, nedges, s, t);
|
||
|
|
if (e == UNDEF)
|
||
|
|
{
|
||
|
|
- int* edge = &edges[nedges*4];
|
||
|
|
- edge[0] = s;
|
||
|
|
- edge[1] = t;
|
||
|
|
- edge[2] = l;
|
||
|
|
- edge[3] = r;
|
||
|
|
+ int* e = &edges[nedges*4];
|
||
|
|
+ e[0] = s;
|
||
|
|
+ e[1] = t;
|
||
|
|
+ e[2] = l;
|
||
|
|
+ e[3] = r;
|
||
|
|
return nedges++;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
@@ -554,7 +554,7 @@ static bool buildPolyDetail(rcContext* ctx, const float* in, const int nin,
|
||
|
|
float dx = vi[0] - vj[0];
|
||
|
|
float dy = vi[1] - vj[1];
|
||
|
|
float dz = vi[2] - vj[2];
|
||
|
|
- float d = rcSqrt(dx*dx + dz*dz);
|
||
|
|
+ float d = sqrtf(dx*dx + dz*dz);
|
||
|
|
int nn = 1 + (int)floorf(d/sampleDist);
|
||
|
|
if (nn >= MAX_VERTS_PER_EDGE) nn = MAX_VERTS_PER_EDGE-1;
|
||
|
|
if (nverts+nn >= MAX_VERTS)
|
||
|
|
@@ -583,10 +583,10 @@ static bool buildPolyDetail(rcContext* ctx, const float* in, const int nin,
|
||
|
|
int maxi = -1;
|
||
|
|
for (int m = a+1; m < b; ++m)
|
||
|
|
{
|
||
|
|
- float dev = distancePtSeg(&edge[m*3],va,vb);
|
||
|
|
- if (dev > maxd)
|
||
|
|
+ float d = distancePtSeg(&edge[m*3],va,vb);
|
||
|
|
+ if (d > maxd)
|
||
|
|
{
|
||
|
|
- maxd = dev;
|
||
|
|
+ maxd = d;
|
||
|
|
maxi = m;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
@@ -743,15 +743,12 @@ static bool buildPolyDetail(rcContext* ctx, const float* in, const int nin,
|
||
|
|
|
||
|
|
static void getHeightData(const rcCompactHeightfield& chf,
|
||
|
|
const unsigned short* poly, const int npoly,
|
||
|
|
- const unsigned short* verts, const int bs,
|
||
|
|
+ const unsigned short* verts,
|
||
|
|
rcHeightPatch& hp, rcIntArray& stack)
|
||
|
|
{
|
||
|
|
// Floodfill the heightfield to get 2D height data,
|
||
|
|
// starting at vertex locations as seeds.
|
||
|
|
|
||
|
|
- // Note: Reads to the compact heightfield are offset by border size (bs)
|
||
|
|
- // since border size offset is already removed from the polymesh vertices.
|
||
|
|
-
|
||
|
|
memset(hp.data, 0, sizeof(unsigned short)*hp.width*hp.height);
|
||
|
|
|
||
|
|
stack.resize(0);
|
||
|
|
@@ -775,7 +772,7 @@ static void getHeightData(const rcCompactHeightfield& chf,
|
||
|
|
az < hp.ymin || az >= hp.ymin+hp.height)
|
||
|
|
continue;
|
||
|
|
|
||
|
|
- const rcCompactCell& c = chf.cells[(ax+bs)+(az+bs)*chf.width];
|
||
|
|
+ const rcCompactCell& c = chf.cells[ax+az*chf.width];
|
||
|
|
for (int i = (int)c.index, ni = (int)(c.index+c.count); i < ni; ++i)
|
||
|
|
{
|
||
|
|
const rcCompactSpan& s = chf.spans[i];
|
||
|
|
@@ -847,7 +844,7 @@ static void getHeightData(const rcCompactHeightfield& chf,
|
||
|
|
if (hp.data[ax-hp.xmin+(ay-hp.ymin)*hp.width] != 0)
|
||
|
|
continue;
|
||
|
|
|
||
|
|
- const int ai = (int)chf.cells[(ax+bs)+(ay+bs)*chf.width].index + rcGetCon(cs, dir);
|
||
|
|
+ const int ai = (int)chf.cells[ax+ay*chf.width].index + rcGetCon(cs, dir);
|
||
|
|
|
||
|
|
int idx = ax-hp.xmin+(ay-hp.ymin)*hp.width;
|
||
|
|
hp.data[idx] = 1;
|
||
|
|
@@ -903,7 +900,7 @@ static void getHeightData(const rcCompactHeightfield& chf,
|
||
|
|
if (hp.data[ax-hp.xmin+(ay-hp.ymin)*hp.width] != RC_UNSET_HEIGHT)
|
||
|
|
continue;
|
||
|
|
|
||
|
|
- const int ai = (int)chf.cells[(ax+bs)+(ay+bs)*chf.width].index + rcGetCon(cs, dir);
|
||
|
|
+ const int ai = (int)chf.cells[ax+ay*chf.width].index + rcGetCon(cs, dir);
|
||
|
|
|
||
|
|
const rcCompactSpan& as = chf.spans[ai];
|
||
|
|
int idx = ax-hp.xmin+(ay-hp.ymin)*hp.width;
|
||
|
|
@@ -941,11 +938,8 @@ static unsigned char getTriFlags(const float* va, const float* vb, const float*
|
||
|
|
return flags;
|
||
|
|
}
|
||
|
|
|
||
|
|
-/// @par
|
||
|
|
-///
|
||
|
|
-/// See the #rcConfig documentation for more information on the configuration parameters.
|
||
|
|
-///
|
||
|
|
-/// @see rcAllocPolyMeshDetail, rcPolyMesh, rcCompactHeightfield, rcPolyMeshDetail, rcConfig
|
||
|
|
+
|
||
|
|
+
|
||
|
|
bool rcBuildPolyMeshDetail(rcContext* ctx, const rcPolyMesh& mesh, const rcCompactHeightfield& chf,
|
||
|
|
const float sampleDist, const float sampleMaxError,
|
||
|
|
rcPolyMeshDetail& dmesh)
|
||
|
|
@@ -961,7 +955,6 @@ bool rcBuildPolyMeshDetail(rcContext* ctx, const rcPolyMesh& mesh, const rcCompa
|
||
|
|
const float cs = mesh.cs;
|
||
|
|
const float ch = mesh.ch;
|
||
|
|
const float* orig = mesh.bmin;
|
||
|
|
- const int borderSize = mesh.borderSize;
|
||
|
|
|
||
|
|
rcIntArray edges(64);
|
||
|
|
rcIntArray tris(512);
|
||
|
|
@@ -1072,7 +1065,7 @@ bool rcBuildPolyMeshDetail(rcContext* ctx, const rcPolyMesh& mesh, const rcCompa
|
||
|
|
hp.ymin = bounds[i*4+2];
|
||
|
|
hp.width = bounds[i*4+1]-bounds[i*4+0];
|
||
|
|
hp.height = bounds[i*4+3]-bounds[i*4+2];
|
||
|
|
- getHeightData(chf, p, npoly, mesh.verts, borderSize, hp, stack);
|
||
|
|
+ getHeightData(chf, p, npoly, mesh.verts, hp, stack);
|
||
|
|
|
||
|
|
// Build detail mesh.
|
||
|
|
int nverts = 0;
|
||
|
|
@@ -1164,7 +1157,6 @@ bool rcBuildPolyMeshDetail(rcContext* ctx, const rcPolyMesh& mesh, const rcCompa
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
-/// @see rcAllocPolyMeshDetail, rcPolyMeshDetail
|
||
|
|
bool rcMergePolyMeshDetails(rcContext* ctx, rcPolyMeshDetail** meshes, const int nmeshes, rcPolyMeshDetail& mesh)
|
||
|
|
{
|
||
|
|
rcAssert(ctx);
|
||
|
|
diff --git a/dep/recastnavigation/Recast/RecastRasterization.cpp b/dep/recastnavigation/Recast/RecastRasterization.cpp
|
||
|
|
index d2bb7c9..71adfb6 100644
|
||
|
|
--- a/dep/recastnavigation/Recast/RecastRasterization.cpp
|
||
|
|
+++ b/dep/recastnavigation/Recast/RecastRasterization.cpp
|
||
|
|
@@ -154,13 +154,6 @@ static void addSpan(rcHeightfield& hf, const int x, const int y,
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
-/// @par
|
||
|
|
-///
|
||
|
|
-/// The span addition can be set to favor flags. If the span is merged to
|
||
|
|
-/// another span and the new @p smax is within @p flagMergeThr units
|
||
|
|
-/// from the existing span, the span flags are merged.
|
||
|
|
-///
|
||
|
|
-/// @see rcHeightfield, rcSpan.
|
||
|
|
void rcAddSpan(rcContext* /*ctx*/, rcHeightfield& hf, const int x, const int y,
|
||
|
|
const unsigned short smin, const unsigned short smax,
|
||
|
|
const unsigned char area, const int flagMergeThr)
|
||
|
|
@@ -283,11 +276,6 @@ static void rasterizeTri(const float* v0, const float* v1, const float* v2,
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
-/// @par
|
||
|
|
-///
|
||
|
|
-/// No spans will be added if the triangle does not overlap the heightfield grid.
|
||
|
|
-///
|
||
|
|
-/// @see rcHeightfield
|
||
|
|
void rcRasterizeTriangle(rcContext* ctx, const float* v0, const float* v1, const float* v2,
|
||
|
|
const unsigned char area, rcHeightfield& solid,
|
||
|
|
const int flagMergeThr)
|
||
|
|
@@ -303,11 +291,6 @@ void rcRasterizeTriangle(rcContext* ctx, const float* v0, const float* v1, const
|
||
|
|
ctx->stopTimer(RC_TIMER_RASTERIZE_TRIANGLES);
|
||
|
|
}
|
||
|
|
|
||
|
|
-/// @par
|
||
|
|
-///
|
||
|
|
-/// Spans will only be added for triangles that overlap the heightfield grid.
|
||
|
|
-///
|
||
|
|
-/// @see rcHeightfield
|
||
|
|
void rcRasterizeTriangles(rcContext* ctx, const float* verts, const int /*nv*/,
|
||
|
|
const int* tris, const unsigned char* areas, const int nt,
|
||
|
|
rcHeightfield& solid, const int flagMergeThr)
|
||
|
|
@@ -331,11 +314,6 @@ void rcRasterizeTriangles(rcContext* ctx, const float* verts, const int /*nv*/,
|
||
|
|
ctx->stopTimer(RC_TIMER_RASTERIZE_TRIANGLES);
|
||
|
|
}
|
||
|
|
|
||
|
|
-/// @par
|
||
|
|
-///
|
||
|
|
-/// Spans will only be added for triangles that overlap the heightfield grid.
|
||
|
|
-///
|
||
|
|
-/// @see rcHeightfield
|
||
|
|
void rcRasterizeTriangles(rcContext* ctx, const float* verts, const int /*nv*/,
|
||
|
|
const unsigned short* tris, const unsigned char* areas, const int nt,
|
||
|
|
rcHeightfield& solid, const int flagMergeThr)
|
||
|
|
@@ -359,11 +337,6 @@ void rcRasterizeTriangles(rcContext* ctx, const float* verts, const int /*nv*/,
|
||
|
|
ctx->stopTimer(RC_TIMER_RASTERIZE_TRIANGLES);
|
||
|
|
}
|
||
|
|
|
||
|
|
-/// @par
|
||
|
|
-///
|
||
|
|
-/// Spans will only be added for triangles that overlap the heightfield grid.
|
||
|
|
-///
|
||
|
|
-/// @see rcHeightfield
|
||
|
|
void rcRasterizeTriangles(rcContext* ctx, const float* verts, const unsigned char* areas, const int nt,
|
||
|
|
rcHeightfield& solid, const int flagMergeThr)
|
||
|
|
{
|
||
|
|
diff --git a/dep/recastnavigation/Recast/RecastRegion.cpp b/dep/recastnavigation/Recast/RecastRegion.cpp
|
||
|
|
index 76e631c..6ad9fa5 100644
|
||
|
|
--- a/dep/recastnavigation/Recast/RecastRegion.cpp
|
||
|
|
+++ b/dep/recastnavigation/Recast/RecastRegion.cpp
|
||
|
|
@@ -283,8 +283,6 @@ static bool floodRegion(int x, int y, int i,
|
||
|
|
if (chf.areas[ai] != area)
|
||
|
|
continue;
|
||
|
|
unsigned short nr = srcReg[ai];
|
||
|
|
- if (nr & RC_BORDER_REG) // Do not take borders into account.
|
||
|
|
- continue;
|
||
|
|
if (nr != 0 && nr != r)
|
||
|
|
ar = nr;
|
||
|
|
|
||
|
|
@@ -298,9 +296,9 @@ static bool floodRegion(int x, int y, int i,
|
||
|
|
const int ai2 = (int)chf.cells[ax2+ay2*w].index + rcGetCon(as, dir2);
|
||
|
|
if (chf.areas[ai2] != area)
|
||
|
|
continue;
|
||
|
|
- unsigned short nr2 = srcReg[ai2];
|
||
|
|
- if (nr2 != 0 && nr2 != r)
|
||
|
|
- ar = nr2;
|
||
|
|
+ unsigned short nr = srcReg[ai2];
|
||
|
|
+ if (nr != 0 && nr != r)
|
||
|
|
+ ar = nr;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
@@ -321,13 +319,16 @@ static bool floodRegion(int x, int y, int i,
|
||
|
|
const int ai = (int)chf.cells[ax+ay*w].index + rcGetCon(cs, dir);
|
||
|
|
if (chf.areas[ai] != area)
|
||
|
|
continue;
|
||
|
|
- if (chf.dist[ai] >= lev && srcReg[ai] == 0)
|
||
|
|
+ if (chf.dist[ai] >= lev)
|
||
|
|
{
|
||
|
|
- srcReg[ai] = r;
|
||
|
|
- srcDist[ai] = 0;
|
||
|
|
- stack.push(ax);
|
||
|
|
- stack.push(ay);
|
||
|
|
- stack.push(ai);
|
||
|
|
+ if (srcReg[ai] == 0)
|
||
|
|
+ {
|
||
|
|
+ srcReg[ai] = r;
|
||
|
|
+ srcDist[ai] = 0;
|
||
|
|
+ stack.push(ax);
|
||
|
|
+ stack.push(ay);
|
||
|
|
+ stack.push(ai);
|
||
|
|
+ }
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
@@ -678,17 +679,17 @@ static void walkContour(int x, int y, int i, int dir,
|
||
|
|
// Remove adjacent duplicates.
|
||
|
|
if (cont.size() > 1)
|
||
|
|
{
|
||
|
|
- for (int j = 0; j < cont.size(); )
|
||
|
|
+ for (int i = 0; i < cont.size(); )
|
||
|
|
{
|
||
|
|
- int nj = (j+1) % cont.size();
|
||
|
|
- if (cont[j] == cont[nj])
|
||
|
|
+ int ni = (i+1) % cont.size();
|
||
|
|
+ if (cont[i] == cont[ni])
|
||
|
|
{
|
||
|
|
- for (int k = j; k < cont.size()-1; ++k)
|
||
|
|
- cont[k] = cont[k+1];
|
||
|
|
+ for (int j = i; j < cont.size()-1; ++j)
|
||
|
|
+ cont[j] = cont[j+1];
|
||
|
|
cont.pop();
|
||
|
|
}
|
||
|
|
else
|
||
|
|
- ++j;
|
||
|
|
+ ++i;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
@@ -806,14 +807,14 @@ static bool filterSmallRegions(rcContext* ctx, int minRegionArea, int mergeRegio
|
||
|
|
connectsToBorder = true;
|
||
|
|
continue;
|
||
|
|
}
|
||
|
|
- rcRegion& neireg = regions[creg.connections[j]];
|
||
|
|
- if (neireg.visited)
|
||
|
|
+ rcRegion& nreg = regions[creg.connections[j]];
|
||
|
|
+ if (nreg.visited)
|
||
|
|
continue;
|
||
|
|
- if (neireg.id == 0 || (neireg.id & RC_BORDER_REG))
|
||
|
|
+ if (nreg.id == 0 || (nreg.id & RC_BORDER_REG))
|
||
|
|
continue;
|
||
|
|
// Visit
|
||
|
|
- stack.push(neireg.id);
|
||
|
|
- neireg.visited = true;
|
||
|
|
+ stack.push(nreg.id);
|
||
|
|
+ nreg.visited = true;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
@@ -936,16 +937,7 @@ static bool filterSmallRegions(rcContext* ctx, int minRegionArea, int mergeRegio
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
-/// @par
|
||
|
|
-///
|
||
|
|
-/// This is usually the second to the last step in creating a fully built
|
||
|
|
-/// compact heightfield. This step is required before regions are built
|
||
|
|
-/// using #rcBuildRegions or #rcBuildRegionsMonotone.
|
||
|
|
-///
|
||
|
|
-/// After this step, the distance data is available via the rcCompactHeightfield::maxDistance
|
||
|
|
-/// and rcCompactHeightfield::dist fields.
|
||
|
|
-///
|
||
|
|
-/// @see rcCompactHeightfield, rcBuildRegions, rcBuildRegionsMonotone
|
||
|
|
+
|
||
|
|
bool rcBuildDistanceField(rcContext* ctx, rcCompactHeightfield& chf)
|
||
|
|
{
|
||
|
|
rcAssert(ctx);
|
||
|
|
@@ -1028,25 +1020,6 @@ struct rcSweepSpan
|
||
|
|
unsigned short nei; // neighbour id
|
||
|
|
};
|
||
|
|
|
||
|
|
-/// @par
|
||
|
|
-///
|
||
|
|
-/// Non-null regions will consist of connected, non-overlapping walkable spans that form a single contour.
|
||
|
|
-/// Contours will form simple polygons.
|
||
|
|
-///
|
||
|
|
-/// If multiple regions form an area that is smaller than @p minRegionArea, then all spans will be
|
||
|
|
-/// re-assigned to the zero (null) region.
|
||
|
|
-///
|
||
|
|
-/// Partitioning can result in smaller than necessary regions. @p mergeRegionArea helps
|
||
|
|
-/// reduce unecessarily small regions.
|
||
|
|
-///
|
||
|
|
-/// See the #rcConfig documentation for more information on the configuration parameters.
|
||
|
|
-///
|
||
|
|
-/// The region data will be available via the rcCompactHeightfield::maxRegions
|
||
|
|
-/// and rcCompactSpan::reg fields.
|
||
|
|
-///
|
||
|
|
-/// @warning The distance field must be created using #rcBuildDistanceField before attempting to build regions.
|
||
|
|
-///
|
||
|
|
-/// @see rcCompactHeightfield, rcCompactSpan, rcBuildDistanceField, rcBuildRegionsMonotone, rcConfig
|
||
|
|
bool rcBuildRegionsMonotone(rcContext* ctx, rcCompactHeightfield& chf,
|
||
|
|
const int borderSize, const int minRegionArea, const int mergeRegionArea)
|
||
|
|
{
|
||
|
|
@@ -1086,8 +1059,6 @@ bool rcBuildRegionsMonotone(rcContext* ctx, rcCompactHeightfield& chf,
|
||
|
|
paintRectRegion(w-bw, w, 0, h, id|RC_BORDER_REG, chf, srcReg); id++;
|
||
|
|
paintRectRegion(0, w, 0, bh, id|RC_BORDER_REG, chf, srcReg); id++;
|
||
|
|
paintRectRegion(0, w, h-bh, h, id|RC_BORDER_REG, chf, srcReg); id++;
|
||
|
|
-
|
||
|
|
- chf.borderSize = borderSize;
|
||
|
|
}
|
||
|
|
|
||
|
|
rcIntArray prev(256);
|
||
|
|
@@ -1199,25 +1170,6 @@ bool rcBuildRegionsMonotone(rcContext* ctx, rcCompactHeightfield& chf,
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
-/// @par
|
||
|
|
-///
|
||
|
|
-/// Non-null regions will consist of connected, non-overlapping walkable spans that form a single contour.
|
||
|
|
-/// Contours will form simple polygons.
|
||
|
|
-///
|
||
|
|
-/// If multiple regions form an area that is smaller than @p minRegionArea, then all spans will be
|
||
|
|
-/// re-assigned to the zero (null) region.
|
||
|
|
-///
|
||
|
|
-/// Watershed partitioning can result in smaller than necessary regions, especially in diagonal corridors.
|
||
|
|
-/// @p mergeRegionArea helps reduce unecessarily small regions.
|
||
|
|
-///
|
||
|
|
-/// See the #rcConfig documentation for more information on the configuration parameters.
|
||
|
|
-///
|
||
|
|
-/// The region data will be available via the rcCompactHeightfield::maxRegions
|
||
|
|
-/// and rcCompactSpan::reg fields.
|
||
|
|
-///
|
||
|
|
-/// @warning The distance field must be created using #rcBuildDistanceField before attempting to build regions.
|
||
|
|
-///
|
||
|
|
-/// @see rcCompactHeightfield, rcCompactSpan, rcBuildDistanceField, rcBuildRegionsMonotone, rcConfig
|
||
|
|
bool rcBuildRegions(rcContext* ctx, rcCompactHeightfield& chf,
|
||
|
|
const int borderSize, const int minRegionArea, const int mergeRegionArea)
|
||
|
|
{
|
||
|
|
@@ -1257,19 +1209,11 @@ bool rcBuildRegions(rcContext* ctx, rcCompactHeightfield& chf,
|
||
|
|
// const int expandIters = 4 + walkableRadius * 2;
|
||
|
|
const int expandIters = 8;
|
||
|
|
|
||
|
|
- if (borderSize > 0)
|
||
|
|
- {
|
||
|
|
- // Make sure border will not overflow.
|
||
|
|
- const int bw = rcMin(w, borderSize);
|
||
|
|
- const int bh = rcMin(h, borderSize);
|
||
|
|
- // Paint regions
|
||
|
|
- paintRectRegion(0, bw, 0, h, regionId|RC_BORDER_REG, chf, srcReg); regionId++;
|
||
|
|
- paintRectRegion(w-bw, w, 0, h, regionId|RC_BORDER_REG, chf, srcReg); regionId++;
|
||
|
|
- paintRectRegion(0, w, 0, bh, regionId|RC_BORDER_REG, chf, srcReg); regionId++;
|
||
|
|
- paintRectRegion(0, w, h-bh, h, regionId|RC_BORDER_REG, chf, srcReg); regionId++;
|
||
|
|
-
|
||
|
|
- chf.borderSize = borderSize;
|
||
|
|
- }
|
||
|
|
+ // Mark border regions.
|
||
|
|
+ paintRectRegion(0, borderSize, 0, h, regionId|RC_BORDER_REG, chf, srcReg); regionId++;
|
||
|
|
+ paintRectRegion(w-borderSize, w, 0, h, regionId|RC_BORDER_REG, chf, srcReg); regionId++;
|
||
|
|
+ paintRectRegion(0, w, 0, borderSize, regionId|RC_BORDER_REG, chf, srcReg); regionId++;
|
||
|
|
+ paintRectRegion(0, w, h-borderSize, h, regionId|RC_BORDER_REG, chf, srcReg); regionId++;
|
||
|
|
|
||
|
|
while (level > 0)
|
||
|
|
{
|
||
|
|
@@ -1298,6 +1242,7 @@ bool rcBuildRegions(rcContext* ctx, rcCompactHeightfield& chf,
|
||
|
|
{
|
||
|
|
if (chf.dist[i] < level || srcReg[i] != 0 || chf.areas[i] == RC_NULL_AREA)
|
||
|
|
continue;
|
||
|
|
+
|
||
|
|
if (floodRegion(x, y, i, level, regionId, chf, srcReg, srcDist, stack))
|
||
|
|
regionId++;
|
||
|
|
}
|
||
|
|
@@ -1305,6 +1250,7 @@ bool rcBuildRegions(rcContext* ctx, rcCompactHeightfield& chf,
|
||
|
|
}
|
||
|
|
|
||
|
|
ctx->stopTimer(RC_TIMER_BUILD_REGIONS_FLOOD);
|
||
|
|
+
|
||
|
|
}
|
||
|
|
|
||
|
|
// Expand current regions until no empty connected cells found.
|
||
|
|
diff --git a/src/server/collision/Management/MMapManager.cpp b/src/server/collision/Management/MMapManager.cpp
|
||
|
|
index 65c13c0..a3f89f4 100644
|
||
|
|
--- a/src/server/collision/Management/MMapManager.cpp
|
||
|
|
+++ b/src/server/collision/Management/MMapManager.cpp
|
||
|
|
@@ -63,7 +63,7 @@ namespace MMAP
|
||
|
|
|
||
|
|
dtNavMesh* mesh = dtAllocNavMesh();
|
||
|
|
ASSERT(mesh);
|
||
|
|
- if (dtStatusFailed(mesh->init(¶ms)))
|
||
|
|
+ if (DT_SUCCESS != mesh->init(¶ms))
|
||
|
|
{
|
||
|
|
dtFreeNavMesh(mesh);
|
||
|
|
TC_LOG_ERROR(LOG_FILTER_MAPS, "MMAP:loadMapData: Failed to initialize dtNavMesh for mmap %03u from file %s", mapId, fileName);
|
||
|
|
@@ -152,7 +152,7 @@ namespace MMAP
|
||
|
|
dtTileRef tileRef = 0;
|
||
|
|
|
||
|
|
// memory allocated for data is now managed by detour, and will be deallocated when the tile is removed
|
||
|
|
- if (dtStatusSucceed(mmap->navMesh->addTile(data, fileHeader.size, DT_TILE_FREE_DATA, 0, &tileRef)))
|
||
|
|
+ if (DT_SUCCESS == mmap->navMesh->addTile(data, fileHeader.size, DT_TILE_FREE_DATA, 0, &tileRef))
|
||
|
|
{
|
||
|
|
mmap->mmapLoadedTiles.insert(std::pair<uint32, dtTileRef>(packedGridPos, tileRef));
|
||
|
|
++loadedTiles;
|
||
|
|
@@ -193,7 +193,7 @@ namespace MMAP
|
||
|
|
dtTileRef tileRef = mmap->mmapLoadedTiles[packedGridPos];
|
||
|
|
|
||
|
|
// unload, and mark as non loaded
|
||
|
|
- if (dtStatusFailed(mmap->navMesh->removeTile(tileRef, NULL, NULL)))
|
||
|
|
+ if (DT_SUCCESS != mmap->navMesh->removeTile(tileRef, NULL, NULL))
|
||
|
|
{
|
||
|
|
// this is technically a memory leak
|
||
|
|
// if the grid is later reloaded, dtNavMesh::addTile will return error but no extra memory is used
|
||
|
|
@@ -227,7 +227,7 @@ namespace MMAP
|
||
|
|
{
|
||
|
|
uint32 x = (i->first >> 16);
|
||
|
|
uint32 y = (i->first & 0x0000FFFF);
|
||
|
|
- if (dtStatusFailed(mmap->navMesh->removeTile(i->second, NULL, NULL)))
|
||
|
|
+ if (DT_SUCCESS != mmap->navMesh->removeTile(i->second, NULL, NULL))
|
||
|
|
TC_LOG_ERROR(LOG_FILTER_MAPS, "MMAP:unloadMap: Could not unload %03u%02i%02i.mmtile from navmesh", mapId, x, y);
|
||
|
|
else
|
||
|
|
{
|
||
|
|
@@ -288,7 +288,7 @@ namespace MMAP
|
||
|
|
// allocate mesh query
|
||
|
|
dtNavMeshQuery* query = dtAllocNavMeshQuery();
|
||
|
|
ASSERT(query);
|
||
|
|
- if (dtStatusFailed(query->init(mmap->navMesh, 1024)))
|
||
|
|
+ if (DT_SUCCESS != query->init(mmap->navMesh, 1024))
|
||
|
|
{
|
||
|
|
dtFreeNavMeshQuery(query);
|
||
|
|
TC_LOG_ERROR(LOG_FILTER_MAPS, "MMAP:GetNavMeshQuery: Failed to initialize dtNavMeshQuery for mapId %03u instanceId %u", mapId, instanceId);
|
||
|
|
diff --git a/src/server/game/Grids/GridDefines.h b/src/server/game/Grids/GridDefines.h
|
||
|
|
index 9250c78..ad48e4f 100644
|
||
|
|
--- a/src/server/game/Grids/GridDefines.h
|
||
|
|
+++ b/src/server/game/Grids/GridDefines.h
|
||
|
|
@@ -35,7 +35,7 @@ class Player;
|
||
|
|
|
||
|
|
#define MAX_NUMBER_OF_GRIDS 64
|
||
|
|
|
||
|
|
-#define SIZE_OF_GRIDS 533.3333f
|
||
|
|
+#define SIZE_OF_GRIDS 533.33333f
|
||
|
|
#define CENTER_GRID_ID (MAX_NUMBER_OF_GRIDS/2)
|
||
|
|
|
||
|
|
#define CENTER_GRID_OFFSET (SIZE_OF_GRIDS/2)
|
||
|
|
diff --git a/src/server/game/Miscellaneous/SharedDefines.h b/src/server/game/Miscellaneous/SharedDefines.h
|
||
|
|
index 02f5965..e4a2536 100644
|
||
|
|
--- a/src/server/game/Miscellaneous/SharedDefines.h
|
||
|
|
+++ b/src/server/game/Miscellaneous/SharedDefines.h
|
||
|
|
@@ -3542,7 +3542,7 @@ enum PartyResult
|
||
|
|
};
|
||
|
|
|
||
|
|
const uint32 MMAP_MAGIC = 0x4d4d4150; // 'MMAP'
|
||
|
|
-#define MMAP_VERSION 4
|
||
|
|
+#define MMAP_VERSION 3
|
||
|
|
|
||
|
|
struct MmapTileHeader
|
||
|
|
{
|
||
|
|
diff --git a/src/server/game/Movement/PathGenerator.cpp b/src/server/game/Movement/PathGenerator.cpp
|
||
|
|
index c902eb8..182582a 100644
|
||
|
|
--- a/src/server/game/Movement/PathGenerator.cpp
|
||
|
|
+++ b/src/server/game/Movement/PathGenerator.cpp
|
||
|
|
@@ -97,7 +97,7 @@ dtPolyRef PathGenerator::GetPathPolyByPosition(dtPolyRef const* polyPath, uint32
|
||
|
|
for (uint32 i = 0; i < polyPathSize; ++i)
|
||
|
|
{
|
||
|
|
float closestPoint[VERTEX_SIZE];
|
||
|
|
- if (dtStatusFailed(_navMeshQuery->closestPointOnPoly(polyPath[i], point, closestPoint)))
|
||
|
|
+ if (DT_SUCCESS != _navMeshQuery->closestPointOnPoly(polyPath[i], point, closestPoint))
|
||
|
|
continue;
|
||
|
|
|
||
|
|
float d = dtVdist2DSqr(point, closestPoint);
|
||
|
|
@@ -132,7 +132,8 @@ dtPolyRef PathGenerator::GetPolyByLocation(float const* point, float* distance)
|
||
|
|
// first try with low search box
|
||
|
|
float extents[VERTEX_SIZE] = {3.0f, 5.0f, 3.0f}; // bounds of poly search area
|
||
|
|
float closestPoint[VERTEX_SIZE] = {0.0f, 0.0f, 0.0f};
|
||
|
|
- if (dtStatusSucceed(_navMeshQuery->findNearestPoly(point, extents, &_filter, &polyRef, closestPoint)) && polyRef != INVALID_POLYREF)
|
||
|
|
+ dtStatus result = _navMeshQuery->findNearestPoly(point, extents, &_filter, &polyRef, closestPoint);
|
||
|
|
+ if (DT_SUCCESS == result && polyRef != INVALID_POLYREF)
|
||
|
|
{
|
||
|
|
*distance = dtVdist(closestPoint, point);
|
||
|
|
return polyRef;
|
||
|
|
@@ -140,10 +141,9 @@ dtPolyRef PathGenerator::GetPolyByLocation(float const* point, float* distance)
|
||
|
|
|
||
|
|
// still nothing ..
|
||
|
|
// try with bigger search box
|
||
|
|
- // Note that the extent should not overlap more than 128 polygons in the navmesh (see dtNavMeshQuery::findNearestPoly)
|
||
|
|
- extents[1] = 50.0f;
|
||
|
|
-
|
||
|
|
- if (dtStatusSucceed(_navMeshQuery->findNearestPoly(point, extents, &_filter, &polyRef, closestPoint)) && polyRef != INVALID_POLYREF)
|
||
|
|
+ extents[1] = 200.0f;
|
||
|
|
+ result = _navMeshQuery->findNearestPoly(point, extents, &_filter, &polyRef, closestPoint);
|
||
|
|
+ if (DT_SUCCESS == result && polyRef != INVALID_POLYREF)
|
||
|
|
{
|
||
|
|
*distance = dtVdist(closestPoint, point);
|
||
|
|
return polyRef;
|
||
|
|
@@ -228,7 +228,7 @@ void PathGenerator::BuildPolyPath(G3D::Vector3 const& startPos, G3D::Vector3 con
|
||
|
|
{
|
||
|
|
float closestPoint[VERTEX_SIZE];
|
||
|
|
// we may want to use closestPointOnPolyBoundary instead
|
||
|
|
- if (dtStatusSucceed(_navMeshQuery->closestPointOnPoly(endPoly, endPoint, closestPoint)))
|
||
|
|
+ if (DT_SUCCESS == _navMeshQuery->closestPointOnPoly(endPoly, endPoint, closestPoint))
|
||
|
|
{
|
||
|
|
dtVcopy(endPoint, closestPoint);
|
||
|
|
SetActualEndPosition(G3D::Vector3(endPoint[2], endPoint[0], endPoint[1]));
|
||
|
|
@@ -319,13 +319,13 @@ void PathGenerator::BuildPolyPath(G3D::Vector3 const& startPos, G3D::Vector3 con
|
||
|
|
|
||
|
|
// we need any point on our suffix start poly to generate poly-path, so we need last poly in prefix data
|
||
|
|
float suffixEndPoint[VERTEX_SIZE];
|
||
|
|
- if (dtStatusFailed(_navMeshQuery->closestPointOnPoly(suffixStartPoly, endPoint, suffixEndPoint)))
|
||
|
|
+ if (DT_SUCCESS != _navMeshQuery->closestPointOnPoly(suffixStartPoly, endPoint, suffixEndPoint))
|
||
|
|
{
|
||
|
|
// we can hit offmesh connection as last poly - closestPointOnPoly() don't like that
|
||
|
|
// try to recover by using prev polyref
|
||
|
|
--prefixPolyLength;
|
||
|
|
suffixStartPoly = _pathPolyRefs[prefixPolyLength-1];
|
||
|
|
- if (dtStatusFailed(_navMeshQuery->closestPointOnPoly(suffixStartPoly, endPoint, suffixEndPoint)))
|
||
|
|
+ if (DT_SUCCESS != _navMeshQuery->closestPointOnPoly(suffixStartPoly, endPoint, suffixEndPoint))
|
||
|
|
{
|
||
|
|
// suffixStartPoly is still invalid, error state
|
||
|
|
BuildShortcut();
|
||
|
|
@@ -346,7 +346,7 @@ void PathGenerator::BuildPolyPath(G3D::Vector3 const& startPos, G3D::Vector3 con
|
||
|
|
(int*)&suffixPolyLength,
|
||
|
|
MAX_PATH_LENGTH-prefixPolyLength); // max number of polygons in output path
|
||
|
|
|
||
|
|
- if (!suffixPolyLength || dtStatusFailed(dtResult))
|
||
|
|
+ if (!suffixPolyLength || dtResult != DT_SUCCESS)
|
||
|
|
{
|
||
|
|
// this is probably an error state, but we'll leave it
|
||
|
|
// and hopefully recover on the next Update
|
||
|
|
@@ -380,7 +380,7 @@ void PathGenerator::BuildPolyPath(G3D::Vector3 const& startPos, G3D::Vector3 con
|
||
|
|
(int*)&_polyLength,
|
||
|
|
MAX_PATH_LENGTH); // max number of polygons in output path
|
||
|
|
|
||
|
|
- if (!_polyLength || dtStatusFailed(dtResult))
|
||
|
|
+ if (!_polyLength || dtResult != DT_SUCCESS)
|
||
|
|
{
|
||
|
|
// only happens if we passed bad data to findPath(), or navmesh is messed up
|
||
|
|
TC_LOG_ERROR(LOG_FILTER_MAPS, "%u's Path Build failed: 0 length path", _sourceUnit->GetGUIDLow());
|
||
|
|
@@ -430,7 +430,7 @@ void PathGenerator::BuildPointPath(const float *startPoint, const float *endPoin
|
||
|
|
_pointPathLimit); // maximum number of points
|
||
|
|
}
|
||
|
|
|
||
|
|
- if (pointCount < 2 || dtStatusFailed(dtResult))
|
||
|
|
+ if (pointCount < 2 || dtResult != DT_SUCCESS)
|
||
|
|
{
|
||
|
|
// only happens if pass bad data to findStraightPath or navmesh is broken
|
||
|
|
// single point paths can be generated here
|
||
|
|
@@ -579,7 +579,7 @@ bool PathGenerator::HaveTile(const G3D::Vector3& p) const
|
||
|
|
if (tx < 0 || ty < 0)
|
||
|
|
return false;
|
||
|
|
|
||
|
|
- return (_navMesh->getTileAt(tx, ty, 0) != NULL);
|
||
|
|
+ return (_navMesh->getTileAt(tx, ty) != NULL);
|
||
|
|
}
|
||
|
|
|
||
|
|
uint32 PathGenerator::FixupCorridor(dtPolyRef* path, uint32 npath, uint32 maxPath, dtPolyRef const* visited, uint32 nvisited)
|
||
|
|
@@ -639,7 +639,7 @@ bool PathGenerator::GetSteerTarget(float const* startPos, float const* endPos,
|
||
|
|
uint32 nsteerPath = 0;
|
||
|
|
dtStatus dtResult = _navMeshQuery->findStraightPath(startPos, endPos, path, pathSize,
|
||
|
|
steerPath, steerPathFlags, steerPathPolys, (int*)&nsteerPath, MAX_STEER_POINTS);
|
||
|
|
- if (!nsteerPath || dtStatusFailed(dtResult))
|
||
|
|
+ if (!nsteerPath || DT_SUCCESS != dtResult)
|
||
|
|
return false;
|
||
|
|
|
||
|
|
// Find vertex far enough to steer to.
|
||
|
|
@@ -676,10 +676,10 @@ dtStatus PathGenerator::FindSmoothPath(float const* startPos, float const* endPo
|
||
|
|
uint32 npolys = polyPathSize;
|
||
|
|
|
||
|
|
float iterPos[VERTEX_SIZE], targetPos[VERTEX_SIZE];
|
||
|
|
- if (dtStatusFailed(_navMeshQuery->closestPointOnPolyBoundary(polys[0], startPos, iterPos)))
|
||
|
|
+ if (DT_SUCCESS != _navMeshQuery->closestPointOnPolyBoundary(polys[0], startPos, iterPos))
|
||
|
|
return DT_FAILURE;
|
||
|
|
|
||
|
|
- if (dtStatusFailed(_navMeshQuery->closestPointOnPolyBoundary(polys[npolys-1], endPos, targetPos)))
|
||
|
|
+ if (DT_SUCCESS != _navMeshQuery->closestPointOnPolyBoundary(polys[npolys-1], endPos, targetPos))
|
||
|
|
return DT_FAILURE;
|
||
|
|
|
||
|
|
dtVcopy(&smoothPath[nsmoothPath*VERTEX_SIZE], iterPos);
|
||
|
|
@@ -758,7 +758,7 @@ dtStatus PathGenerator::FindSmoothPath(float const* startPos, float const* endPo
|
||
|
|
|
||
|
|
// Handle the connection.
|
||
|
|
float startPos[VERTEX_SIZE], endPos[VERTEX_SIZE];
|
||
|
|
- if (dtStatusSucceed(_navMesh->getOffMeshConnectionPolyEndPoints(prevRef, polyRef, startPos, endPos)))
|
||
|
|
+ if (DT_SUCCESS == _navMesh->getOffMeshConnectionPolyEndPoints(prevRef, polyRef, startPos, endPos))
|
||
|
|
{
|
||
|
|
if (nsmoothPath < maxSmoothPathSize)
|
||
|
|
{
|
||
|
|
diff --git a/src/server/scripts/Commands/cs_mmaps.cpp b/src/server/scripts/Commands/cs_mmaps.cpp
|
||
|
|
index 690988e..1e62a99 100644
|
||
|
|
--- a/src/server/scripts/Commands/cs_mmaps.cpp
|
||
|
|
+++ b/src/server/scripts/Commands/cs_mmaps.cpp
|
||
|
|
@@ -153,11 +153,7 @@ public:
|
||
|
|
// navmesh poly -> navmesh tile location
|
||
|
|
dtQueryFilter filter = dtQueryFilter();
|
||
|
|
dtPolyRef polyRef = INVALID_POLYREF;
|
||
|
|
- if (dtStatusFailed(navmeshquery->findNearestPoly(location, extents, &filter, &polyRef, NULL)))
|
||
|
|
- {
|
||
|
|
- handler->PSendSysMessage("Dt [??,??] (invalid poly, probably no tile loaded)");
|
||
|
|
- return true;
|
||
|
|
- }
|
||
|
|
+ navmeshquery->findNearestPoly(location, extents, &filter, &polyRef, NULL);
|
||
|
|
|
||
|
|
if (polyRef == INVALID_POLYREF)
|
||
|
|
handler->PSendSysMessage("Dt [??, ??] (invalid poly, probably no tile loaded)");
|
||
|
|
@@ -165,16 +161,11 @@ public:
|
||
|
|
{
|
||
|
|
dtMeshTile const* tile;
|
||
|
|
dtPoly const* poly;
|
||
|
|
- if (dtStatusSucceed(navmesh->getTileAndPolyByRef(polyRef, &tile, &poly)))
|
||
|
|
- {
|
||
|
|
- if (tile)
|
||
|
|
- {
|
||
|
|
- handler->PSendSysMessage("Dt [%02i,%02i]", tile->header->x, tile->header->y);
|
||
|
|
- return false;
|
||
|
|
- }
|
||
|
|
- }
|
||
|
|
-
|
||
|
|
- handler->PSendSysMessage("Dt [??,??] (no tile loaded)");
|
||
|
|
+ navmesh->getTileAndPolyByRef(polyRef, &tile, &poly);
|
||
|
|
+ if (tile)
|
||
|
|
+ handler->PSendSysMessage("Dt [%02i, %02i]", tile->header->x, tile->header->y);
|
||
|
|
+ else
|
||
|
|
+ handler->PSendSysMessage("Dt [??, ??] (no tile loaded)");
|
||
|
|
}
|
||
|
|
|
||
|
|
return true;
|
||
|
|
diff --git a/src/tools/mmaps_generator/Info/readme.txt b/src/tools/mmaps_generator/Info/readme.txt
|
||
|
|
index bde8e61..ff3f2f4 100644
|
||
|
|
--- a/src/tools/mmaps_generator/Info/readme.txt
|
||
|
|
+++ b/src/tools/mmaps_generator/Info/readme.txt
|
||
|
|
@@ -8,7 +8,7 @@ Generator command line args
|
||
|
|
"map_id tile_x,tile_y (start_x start_y start_z) (end_x end_y end_z) size //optional comments"
|
||
|
|
Single mesh connection per line.
|
||
|
|
|
||
|
|
---silent [] Make us script friendly. Do not wait for user input
|
||
|
|
+--silent Make us script friendly. Do not wait for user input
|
||
|
|
on error or completion.
|
||
|
|
|
||
|
|
--bigBaseUnit [true|false] Generate tile/map using bigger basic unit.
|
||
|
|
@@ -20,7 +20,7 @@ Generator command line args
|
||
|
|
|
||
|
|
float between 45 and 90 degrees (default 60)
|
||
|
|
|
||
|
|
---skipLiquid [true|false] extract liquid data for maps
|
||
|
|
+--skipLiquid liquid data for maps
|
||
|
|
|
||
|
|
false: include liquid data (default)
|
||
|
|
|
||
|
|
diff --git a/src/tools/mmaps_generator/MapBuilder.cpp b/src/tools/mmaps_generator/MapBuilder.cpp
|
||
|
|
index 9c2dda5..cd85d92 100644
|
||
|
|
--- a/src/tools/mmaps_generator/MapBuilder.cpp
|
||
|
|
+++ b/src/tools/mmaps_generator/MapBuilder.cpp
|
||
|
|
@@ -36,7 +36,7 @@ namespace DisableMgr
|
||
|
|
}
|
||
|
|
|
||
|
|
#define MMAP_MAGIC 0x4d4d4150 // 'MMAP'
|
||
|
|
-#define MMAP_VERSION 4
|
||
|
|
+#define MMAP_VERSION 3
|
||
|
|
|
||
|
|
struct MmapTileHeader
|
||
|
|
{
|
||
|
|
@@ -202,10 +202,7 @@ namespace MMAP
|
||
|
|
minX = INT_MIN;
|
||
|
|
minY = INT_MIN;
|
||
|
|
|
||
|
|
- float bmin[3] = { 0, 0, 0 };
|
||
|
|
- float bmax[3] = { 0, 0, 0 };
|
||
|
|
- float lmin[3] = { 0, 0, 0 };
|
||
|
|
- float lmax[3] = { 0, 0, 0 };
|
||
|
|
+ float bmin[3], bmax[3], lmin[3], lmax[3];
|
||
|
|
MeshData meshData;
|
||
|
|
|
||
|
|
// make sure we process maps which don't have tiles
|
||
|
|
@@ -246,20 +243,11 @@ namespace MMAP
|
||
|
|
printf("Building mesh from file\n");
|
||
|
|
int tileX, tileY, mapId;
|
||
|
|
if (fread(&mapId, sizeof(int), 1, file) != 1)
|
||
|
|
- {
|
||
|
|
- fclose(file);
|
||
|
|
return;
|
||
|
|
- }
|
||
|
|
if (fread(&tileX, sizeof(int), 1, file) != 1)
|
||
|
|
- {
|
||
|
|
- fclose(file);
|
||
|
|
return;
|
||
|
|
- }
|
||
|
|
if (fread(&tileY, sizeof(int), 1, file) != 1)
|
||
|
|
- {
|
||
|
|
- fclose(file);
|
||
|
|
return;
|
||
|
|
- }
|
||
|
|
|
||
|
|
dtNavMesh* navMesh = NULL;
|
||
|
|
buildNavMesh(mapId, navMesh);
|
||
|
|
@@ -272,45 +260,25 @@ namespace MMAP
|
||
|
|
|
||
|
|
uint32 verticesCount, indicesCount;
|
||
|
|
if (fread(&verticesCount, sizeof(uint32), 1, file) != 1)
|
||
|
|
- {
|
||
|
|
- fclose(file);
|
||
|
|
return;
|
||
|
|
- }
|
||
|
|
-
|
||
|
|
if (fread(&indicesCount, sizeof(uint32), 1, file) != 1)
|
||
|
|
- {
|
||
|
|
- fclose(file);
|
||
|
|
return;
|
||
|
|
- }
|
||
|
|
|
||
|
|
float* verts = new float[verticesCount];
|
||
|
|
int* inds = new int[indicesCount];
|
||
|
|
|
||
|
|
if (fread(verts, sizeof(float), verticesCount, file) != verticesCount)
|
||
|
|
- {
|
||
|
|
- fclose(file);
|
||
|
|
- delete[] verts;
|
||
|
|
- delete[] inds;
|
||
|
|
return;
|
||
|
|
- }
|
||
|
|
-
|
||
|
|
if (fread(inds, sizeof(int), indicesCount, file) != indicesCount)
|
||
|
|
- {
|
||
|
|
- fclose(file);
|
||
|
|
- delete[] verts;
|
||
|
|
- delete[] inds;
|
||
|
|
return;
|
||
|
|
- }
|
||
|
|
|
||
|
|
MeshData data;
|
||
|
|
|
||
|
|
for (uint32 i = 0; i < verticesCount; ++i)
|
||
|
|
data.solidVerts.append(verts[i]);
|
||
|
|
- delete[] verts;
|
||
|
|
|
||
|
|
for (uint32 i = 0; i < indicesCount; ++i)
|
||
|
|
data.solidTris.append(inds[i]);
|
||
|
|
- delete[] inds;
|
||
|
|
|
||
|
|
TerrainBuilder::cleanVertices(data.solidVerts, data.solidTris);
|
||
|
|
// get bounds of current tile
|
||
|
|
@@ -364,12 +332,12 @@ namespace MMAP
|
||
|
|
buildNavMesh(mapID, navMesh);
|
||
|
|
if (!navMesh)
|
||
|
|
{
|
||
|
|
- printf("[Map %03i] Failed creating navmesh!\n", mapID);
|
||
|
|
+ printf("[Map %i] Failed creating navmesh!\n", mapID);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
// now start building mmtiles for each tile
|
||
|
|
- printf("[Map %03i] We have %u tiles. \n", mapID, (unsigned int)tiles->size());
|
||
|
|
+ printf("[Map %i] We have %u tiles. \n", mapID, (unsigned int)tiles->size());
|
||
|
|
for (std::set<uint32>::iterator it = tiles->begin(); it != tiles->end(); ++it)
|
||
|
|
{
|
||
|
|
uint32 tileX, tileY;
|
||
|
|
@@ -386,13 +354,13 @@ namespace MMAP
|
||
|
|
dtFreeNavMesh(navMesh);
|
||
|
|
}
|
||
|
|
|
||
|
|
- printf("[Map %03i] Complete!\n", mapID);
|
||
|
|
+ printf("[Map %i] Complete!\n", mapID);
|
||
|
|
}
|
||
|
|
|
||
|
|
/**************************************************************************/
|
||
|
|
void MapBuilder::buildTile(uint32 mapID, uint32 tileX, uint32 tileY, dtNavMesh* navMesh)
|
||
|
|
{
|
||
|
|
- printf("[Map %03i] Building tile [%02u,%02u]\n", mapID, tileX, tileY);
|
||
|
|
+ printf("[Map %i] Building tile [%02u,%02u]\n", mapID, tileX, tileY);
|
||
|
|
|
||
|
|
MeshData meshData;
|
||
|
|
|
||
|
|
@@ -478,10 +446,10 @@ namespace MMAP
|
||
|
|
navMeshParams.maxPolys = maxPolysPerTile;
|
||
|
|
|
||
|
|
navMesh = dtAllocNavMesh();
|
||
|
|
- printf("[Map %03i] Creating navMesh...\n", mapID);
|
||
|
|
+ printf("[Map %i] Creating navMesh...\n", mapID);
|
||
|
|
if (!navMesh->init(&navMeshParams))
|
||
|
|
{
|
||
|
|
- printf("[Map %03i] Failed creating navmesh! \n", mapID);
|
||
|
|
+ printf("[Map %i] Failed creating navmesh! \n", mapID);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
@@ -493,7 +461,7 @@ namespace MMAP
|
||
|
|
{
|
||
|
|
dtFreeNavMesh(navMesh);
|
||
|
|
char message[1024];
|
||
|
|
- sprintf(message, "[Map %03i] Failed to open %s for writing!\n", mapID, fileName);
|
||
|
|
+ sprintf(message, "[Map %i] Failed to open %s for writing!\n", mapID, fileName);
|
||
|
|
perror(message);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
@@ -528,8 +496,8 @@ namespace MMAP
|
||
|
|
|
||
|
|
// these are WORLD UNIT based metrics
|
||
|
|
// this are basic unit dimentions
|
||
|
|
- // value have to divide GRID_SIZE(533.3333f) ( aka: 0.5333, 0.2666, 0.3333, 0.1333, etc )
|
||
|
|
- const static float BASE_UNIT_DIM = m_bigBaseUnit ? 0.5333333f : 0.2666666f;
|
||
|
|
+ // value have to divide GRID_SIZE(533.33333f) ( aka: 0.5333, 0.2666, 0.3333, 0.1333, etc )
|
||
|
|
+ const static float BASE_UNIT_DIM = m_bigBaseUnit ? 0.533333f : 0.266666f;
|
||
|
|
|
||
|
|
// All are in UNIT metrics!
|
||
|
|
const static int VERTEX_PER_MAP = int(GRID_SIZE/BASE_UNIT_DIM + 0.5f);
|
||
|
|
@@ -549,12 +517,12 @@ namespace MMAP
|
||
|
|
config.tileSize = VERTEX_PER_TILE;
|
||
|
|
config.walkableRadius = m_bigBaseUnit ? 1 : 2;
|
||
|
|
config.borderSize = config.walkableRadius + 3;
|
||
|
|
- config.maxEdgeLen = VERTEX_PER_TILE + 1; // anything bigger than tileSize
|
||
|
|
+ config.maxEdgeLen = VERTEX_PER_TILE + 1; //anything bigger than tileSize
|
||
|
|
config.walkableHeight = m_bigBaseUnit ? 3 : 6;
|
||
|
|
config.walkableClimb = m_bigBaseUnit ? 2 : 4; // keep less than walkableHeight
|
||
|
|
config.minRegionArea = rcSqr(60);
|
||
|
|
config.mergeRegionArea = rcSqr(50);
|
||
|
|
- config.maxSimplificationError = 1.8f; // eliminates most jagged edges (tiny polygons)
|
||
|
|
+ config.maxSimplificationError = 2.0f; // eliminates most jagged edges (tinny polygons)
|
||
|
|
config.detailSampleDist = config.cs * 64;
|
||
|
|
config.detailSampleMaxError = config.ch * 2;
|
||
|
|
|
||
|
|
@@ -571,7 +539,19 @@ namespace MMAP
|
||
|
|
|
||
|
|
// merge per tile poly and detail meshes
|
||
|
|
rcPolyMesh** pmmerge = new rcPolyMesh*[TILES_PER_MAP * TILES_PER_MAP];
|
||
|
|
+ if (!pmmerge)
|
||
|
|
+ {
|
||
|
|
+ printf("%s alloc pmmerge FIALED!\n", tileString);
|
||
|
|
+ return;
|
||
|
|
+ }
|
||
|
|
+
|
||
|
|
rcPolyMeshDetail** dmmerge = new rcPolyMeshDetail*[TILES_PER_MAP * TILES_PER_MAP];
|
||
|
|
+ if (!dmmerge)
|
||
|
|
+ {
|
||
|
|
+ printf("%s alloc dmmerge FIALED!\n", tileString);
|
||
|
|
+ return;
|
||
|
|
+ }
|
||
|
|
+
|
||
|
|
int nmerge = 0;
|
||
|
|
// build all tiles
|
||
|
|
for (int y = 0; y < TILES_PER_MAP; ++y)
|
||
|
|
@@ -666,9 +646,12 @@ namespace MMAP
|
||
|
|
rcFreeContourSet(tile.cset);
|
||
|
|
tile.cset = NULL;
|
||
|
|
|
||
|
|
- pmmerge[nmerge] = tile.pmesh;
|
||
|
|
- dmmerge[nmerge] = tile.dmesh;
|
||
|
|
- nmerge++;
|
||
|
|
+ if (tile.pmesh)
|
||
|
|
+ {
|
||
|
|
+ pmmerge[nmerge] = tile.pmesh;
|
||
|
|
+ dmmerge[nmerge] = tile.dmesh;
|
||
|
|
+ nmerge++;
|
||
|
|
+ }
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
@@ -676,9 +659,6 @@ namespace MMAP
|
||
|
|
if (!iv.polyMesh)
|
||
|
|
{
|
||
|
|
printf("%s alloc iv.polyMesh FIALED!\n", tileString);
|
||
|
|
- delete[] pmmerge;
|
||
|
|
- delete[] dmmerge;
|
||
|
|
- delete[] tiles;
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
rcMergePolyMeshes(m_rcContext, pmmerge, nmerge, *iv.polyMesh);
|
||
|
|
@@ -687,9 +667,6 @@ namespace MMAP
|
||
|
|
if (!iv.polyMeshDetail)
|
||
|
|
{
|
||
|
|
printf("%s alloc m_dmesh FIALED!\n", tileString);
|
||
|
|
- delete[] pmmerge;
|
||
|
|
- delete[] dmmerge;
|
||
|
|
- delete[] tiles;
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
rcMergePolyMeshDetails(m_rcContext, dmmerge, nmerge, *iv.polyMeshDetail);
|
||
|
|
@@ -697,8 +674,17 @@ namespace MMAP
|
||
|
|
// free things up
|
||
|
|
delete[] pmmerge;
|
||
|
|
delete[] dmmerge;
|
||
|
|
+
|
||
|
|
delete[] tiles;
|
||
|
|
|
||
|
|
+ // remove padding for extraction
|
||
|
|
+ for (int i = 0; i < iv.polyMesh->nverts; ++i)
|
||
|
|
+ {
|
||
|
|
+ unsigned short* v = &iv.polyMesh->verts[i*3];
|
||
|
|
+ v[0] -= (unsigned short)config.borderSize;
|
||
|
|
+ v[2] -= (unsigned short)config.borderSize;
|
||
|
|
+ }
|
||
|
|
+
|
||
|
|
// set polygons as walkable
|
||
|
|
// TODO: special flags for DYNAMIC polygons, ie surfaces that can be turned on and off
|
||
|
|
for (int i = 0; i < iv.polyMesh->npolys; ++i)
|
||
|
|
@@ -737,8 +723,7 @@ namespace MMAP
|
||
|
|
rcVcopy(params.bmax, bmax);
|
||
|
|
params.cs = config.cs;
|
||
|
|
params.ch = config.ch;
|
||
|
|
- params.tileLayer = 0;
|
||
|
|
- params.buildBvTree = true;
|
||
|
|
+ params.tileSize = VERTEX_PER_MAP;
|
||
|
|
|
||
|
|
// will hold final navmesh
|
||
|
|
unsigned char* navData = NULL;
|
||
|
|
@@ -807,7 +792,7 @@ namespace MMAP
|
||
|
|
if (!file)
|
||
|
|
{
|
||
|
|
char message[1024];
|
||
|
|
- sprintf(message, "[Map %03i] Failed to open %s for writing!\n", mapID, fileName);
|
||
|
|
+ sprintf(message, "[Map %i] Failed to open %s for writing!\n", mapID, fileName);
|
||
|
|
perror(message);
|
||
|
|
navMesh->removeTile(tileRef, NULL, NULL);
|
||
|
|
continue;
|
||
|
|
@@ -869,50 +854,50 @@ namespace MMAP
|
||
|
|
{
|
||
|
|
if (m_skipContinents)
|
||
|
|
switch (mapID)
|
||
|
|
- {
|
||
|
|
- case 0:
|
||
|
|
- case 1:
|
||
|
|
- case 530:
|
||
|
|
- case 571:
|
||
|
|
- return true;
|
||
|
|
- default:
|
||
|
|
- break;
|
||
|
|
- }
|
||
|
|
+ {
|
||
|
|
+ case 0:
|
||
|
|
+ case 1:
|
||
|
|
+ case 530:
|
||
|
|
+ case 571:
|
||
|
|
+ return true;
|
||
|
|
+ default:
|
||
|
|
+ break;
|
||
|
|
+ }
|
||
|
|
|
||
|
|
if (m_skipJunkMaps)
|
||
|
|
switch (mapID)
|
||
|
|
- {
|
||
|
|
- case 13: // test.wdt
|
||
|
|
- case 25: // ScottTest.wdt
|
||
|
|
- case 29: // Test.wdt
|
||
|
|
- case 42: // Colin.wdt
|
||
|
|
- case 169: // EmeraldDream.wdt (unused, and very large)
|
||
|
|
- case 451: // development.wdt
|
||
|
|
- case 573: // ExteriorTest.wdt
|
||
|
|
- case 597: // CraigTest.wdt
|
||
|
|
- case 605: // development_nonweighted.wdt
|
||
|
|
- case 606: // QA_DVD.wdt
|
||
|
|
+ {
|
||
|
|
+ case 13: // test.wdt
|
||
|
|
+ case 25: // ScottTest.wdt
|
||
|
|
+ case 29: // Test.wdt
|
||
|
|
+ case 42: // Colin.wdt
|
||
|
|
+ case 169: // EmeraldDream.wdt (unused, and very large)
|
||
|
|
+ case 451: // development.wdt
|
||
|
|
+ case 573: // ExteriorTest.wdt
|
||
|
|
+ case 597: // CraigTest.wdt
|
||
|
|
+ case 605: // development_nonweighted.wdt
|
||
|
|
+ case 606: // QA_DVD.wdt
|
||
|
|
+ return true;
|
||
|
|
+ default:
|
||
|
|
+ if (isTransportMap(mapID))
|
||
|
|
return true;
|
||
|
|
- default:
|
||
|
|
- if (isTransportMap(mapID))
|
||
|
|
- return true;
|
||
|
|
- break;
|
||
|
|
- }
|
||
|
|
+ break;
|
||
|
|
+ }
|
||
|
|
|
||
|
|
if (m_skipBattlegrounds)
|
||
|
|
switch (mapID)
|
||
|
|
- {
|
||
|
|
- case 30: // AV
|
||
|
|
- case 37: // ?
|
||
|
|
- case 489: // WSG
|
||
|
|
- case 529: // AB
|
||
|
|
- case 566: // EotS
|
||
|
|
- case 607: // SotA
|
||
|
|
- case 628: // IoC
|
||
|
|
- return true;
|
||
|
|
- default:
|
||
|
|
- break;
|
||
|
|
- }
|
||
|
|
+ {
|
||
|
|
+ case 30: // AV
|
||
|
|
+ case 37: // ?
|
||
|
|
+ case 489: // WSG
|
||
|
|
+ case 529: // AB
|
||
|
|
+ case 566: // EotS
|
||
|
|
+ case 607: // SotA
|
||
|
|
+ case 628: // IoC
|
||
|
|
+ return true;
|
||
|
|
+ default:
|
||
|
|
+ break;
|
||
|
|
+ }
|
||
|
|
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
@@ -923,37 +908,37 @@ namespace MMAP
|
||
|
|
switch (mapID)
|
||
|
|
{
|
||
|
|
// transport maps
|
||
|
|
- case 582:
|
||
|
|
- case 584:
|
||
|
|
- case 586:
|
||
|
|
- case 587:
|
||
|
|
- case 588:
|
||
|
|
- case 589:
|
||
|
|
- case 590:
|
||
|
|
- case 591:
|
||
|
|
- case 592:
|
||
|
|
- case 593:
|
||
|
|
- case 594:
|
||
|
|
- case 596:
|
||
|
|
- case 610:
|
||
|
|
- case 612:
|
||
|
|
- case 613:
|
||
|
|
- case 614:
|
||
|
|
- case 620:
|
||
|
|
- case 621:
|
||
|
|
- case 622:
|
||
|
|
- case 623:
|
||
|
|
- case 641:
|
||
|
|
- case 642:
|
||
|
|
- case 647:
|
||
|
|
- case 672:
|
||
|
|
- case 673:
|
||
|
|
- case 712:
|
||
|
|
- case 713:
|
||
|
|
- case 718:
|
||
|
|
- return true;
|
||
|
|
- default:
|
||
|
|
- return false;
|
||
|
|
+ case 582:
|
||
|
|
+ case 584:
|
||
|
|
+ case 586:
|
||
|
|
+ case 587:
|
||
|
|
+ case 588:
|
||
|
|
+ case 589:
|
||
|
|
+ case 590:
|
||
|
|
+ case 591:
|
||
|
|
+ case 592:
|
||
|
|
+ case 593:
|
||
|
|
+ case 594:
|
||
|
|
+ case 596:
|
||
|
|
+ case 610:
|
||
|
|
+ case 612:
|
||
|
|
+ case 613:
|
||
|
|
+ case 614:
|
||
|
|
+ case 620:
|
||
|
|
+ case 621:
|
||
|
|
+ case 622:
|
||
|
|
+ case 623:
|
||
|
|
+ case 641:
|
||
|
|
+ case 642:
|
||
|
|
+ case 647:
|
||
|
|
+ case 672:
|
||
|
|
+ case 673:
|
||
|
|
+ case 712:
|
||
|
|
+ case 713:
|
||
|
|
+ case 718:
|
||
|
|
+ return true;
|
||
|
|
+ default:
|
||
|
|
+ return false;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
diff --git a/src/tools/mmaps_generator/MapBuilder.h b/src/tools/mmaps_generator/MapBuilder.h
|
||
|
|
index 6ab0b31..3ffaea0 100644
|
||
|
|
--- a/src/tools/mmaps_generator/MapBuilder.h
|
||
|
|
+++ b/src/tools/mmaps_generator/MapBuilder.h
|
||
|
|
@@ -61,7 +61,7 @@ namespace MMAP
|
||
|
|
class MapBuilder
|
||
|
|
{
|
||
|
|
public:
|
||
|
|
- MapBuilder(float maxWalkableAngle = 55.f,
|
||
|
|
+ MapBuilder(float maxWalkableAngle = 60.f,
|
||
|
|
bool skipLiquid = false,
|
||
|
|
bool skipContinents = false,
|
||
|
|
bool skipJunkMaps = true,
|
||
|
|
diff --git a/src/tools/mmaps_generator/PathCommon.h b/src/tools/mmaps_generator/PathCommon.h
|
||
|
|
index 94a11e0..3e06ff5 100644
|
||
|
|
--- a/src/tools/mmaps_generator/PathCommon.h
|
||
|
|
+++ b/src/tools/mmaps_generator/PathCommon.h
|
||
|
|
@@ -114,6 +114,7 @@ namespace MMAP
|
||
|
|
const char *p = dirpath.c_str();
|
||
|
|
DIR * dirp = opendir(p);
|
||
|
|
struct dirent * dp;
|
||
|
|
+ dirp = opendir(p);
|
||
|
|
|
||
|
|
while (dirp)
|
||
|
|
{
|
||
|
|
diff --git a/src/tools/mmaps_generator/PathGenerator.cpp b/src/tools/mmaps_generator/PathGenerator.cpp
|
||
|
|
index 882ec7f..47d35b5 100644
|
||
|
|
--- a/src/tools/mmaps_generator/PathGenerator.cpp
|
||
|
|
+++ b/src/tools/mmaps_generator/PathGenerator.cpp
|
||
|
|
@@ -235,14 +235,14 @@ bool handleArgs(int argc, char** argv,
|
||
|
|
int finish(const char* message, int returnValue)
|
||
|
|
{
|
||
|
|
printf("%s", message);
|
||
|
|
- getchar(); // Wait for user input
|
||
|
|
+ getchar();
|
||
|
|
return returnValue;
|
||
|
|
}
|
||
|
|
|
||
|
|
int main(int argc, char** argv)
|
||
|
|
{
|
||
|
|
int threads = 3, mapnum = -1;
|
||
|
|
- float maxAngle = 55.0f;
|
||
|
|
+ float maxAngle = 60.0f;
|
||
|
|
int tileX = -1, tileY = -1;
|
||
|
|
bool skipLiquid = false,
|
||
|
|
skipContinents = false,
|
||
|
|
diff --git a/src/tools/mmaps_generator/TerrainBuilder.cpp b/src/tools/mmaps_generator/TerrainBuilder.cpp
|
||
|
|
index 5c76161..3a87da3 100644
|
||
|
|
--- a/src/tools/mmaps_generator/TerrainBuilder.cpp
|
||
|
|
+++ b/src/tools/mmaps_generator/TerrainBuilder.cpp
|
||
|
|
@@ -260,8 +260,7 @@ namespace MMAP
|
||
|
|
meshData.solidVerts.append(coord[1]);
|
||
|
|
}
|
||
|
|
|
||
|
|
- int indices[] = { 0, 0, 0 };
|
||
|
|
- int loopStart = 0, loopEnd = 0, loopInc = 0;
|
||
|
|
+ int indices[3], loopStart = 0, loopEnd = 0, loopInc = 0;
|
||
|
|
getLoopVars(portion, loopStart, loopEnd, loopInc);
|
||
|
|
for (int i = loopStart; i < loopEnd; i+=loopInc)
|
||
|
|
for (int j = TOP; j <= BOTTOM; j+=1)
|
||
|
|
@@ -341,8 +340,7 @@ namespace MMAP
|
||
|
|
|
||
|
|
delete [] liquid_map;
|
||
|
|
|
||
|
|
- int indices[] = { 0, 0, 0 };
|
||
|
|
- int loopStart = 0, loopEnd = 0, loopInc = 0, triInc = BOTTOM-TOP;
|
||
|
|
+ int indices[3], loopStart = 0, loopEnd = 0, loopInc = 0, triInc = BOTTOM-TOP;
|
||
|
|
getLoopVars(portion, loopStart, loopEnd, loopInc);
|
||
|
|
|
||
|
|
// generate triangles
|
||
|
|
diff --git a/src/tools/mmaps_generator/TerrainBuilder.h b/src/tools/mmaps_generator/TerrainBuilder.h
|
||
|
|
index e9ff2a3..069a5a9 100644
|
||
|
|
--- a/src/tools/mmaps_generator/TerrainBuilder.h
|
||
|
|
+++ b/src/tools/mmaps_generator/TerrainBuilder.h
|
||
|
|
@@ -47,7 +47,7 @@ namespace MMAP
|
||
|
|
static const int V9_SIZE_SQ = V9_SIZE*V9_SIZE;
|
||
|
|
static const int V8_SIZE = 128;
|
||
|
|
static const int V8_SIZE_SQ = V8_SIZE*V8_SIZE;
|
||
|
|
- static const float GRID_SIZE = 533.3333f;
|
||
|
|
+ static const float GRID_SIZE = 533.33333f;
|
||
|
|
static const float GRID_PART_SIZE = GRID_SIZE/V8_SIZE;
|
||
|
|
|
||
|
|
// see contrib/extractor/system.cpp, CONF_use_minHeight
|
||
|
|
--
|
||
|
|
1.8.3.msysgit.0
|
||
|
|
|