diff --git a/Detour/Include/DetourNavMesh.h b/Detour/Include/DetourNavMesh.h index 9539a19..d87fee8 100644 --- a/Detour/Include/DetourNavMesh.h +++ b/Detour/Include/DetourNavMesh.h @@ -22,16 +22,39 @@ #include "DetourAlloc.h" #include "DetourStatus.h" +// Undefine (or define in a build cofnig) the following line to use 64bit polyref. +// Generally not needed, useful for very large worlds. +// Note: tiles build using 32bit refs are not compatible with 64bit refs! +//#define DT_POLYREF64 1 + +#ifdef DT_POLYREF64 +// TODO: figure out a multiplatform version of uint64_t +// - maybe: https://code.google.com/p/msinttypes/ +// - or: http://www.azillionmonkeys.com/qed/pstdint.h +#include +#endif + // Note: If you want to use 64-bit refs, change the types of both dtPolyRef & dtTileRef. // It is also recommended that you change dtHashRef() to a proper 64-bit hash. /// A handle to a polygon within a navigation mesh tile. /// @ingroup detour +#ifdef DT_POLYREF64 +static const unsigned int DT_SALT_BITS = 16; +static const unsigned int DT_TILE_BITS = 28; +static const unsigned int DT_POLY_BITS = 20; +typedef uint64_t dtPolyRef; +#else typedef unsigned int dtPolyRef; +#endif /// A handle to a tile within a navigation mesh. /// @ingroup detour +#ifdef DT_POLYREF64 +typedef uint64_t dtTileRef; +#else typedef unsigned int dtTileRef; +#endif /// The maximum number of vertices per navigation polygon. /// @ingroup detour @@ -469,7 +492,11 @@ public: /// @param[in] ip The index of the polygon within the tile. inline dtPolyRef encodePolyId(unsigned int salt, unsigned int it, unsigned int ip) const { +#ifdef DT_POLYREF64 + return ((dtPolyRef)salt << (DT_POLY_BITS+DT_TILE_BITS)) | ((dtPolyRef)it << DT_POLY_BITS) | (dtPolyRef)ip; +#else return ((dtPolyRef)salt << (m_polyBits+m_tileBits)) | ((dtPolyRef)it << m_polyBits) | (dtPolyRef)ip; +#endif } /// Decodes a standard polygon reference. @@ -481,12 +508,21 @@ public: /// @see #encodePolyId inline void decodePolyId(dtPolyRef ref, unsigned int& salt, unsigned int& it, unsigned int& ip) const { +#ifdef DT_POLYREF64 + const dtPolyRef saltMask = ((dtPolyRef)1<> (DT_POLY_BITS+DT_TILE_BITS)) & saltMask); + it = (unsigned int)((ref >> DT_POLY_BITS) & tileMask); + ip = (unsigned int)(ref & polyMask); +#else const dtPolyRef saltMask = ((dtPolyRef)1<> (m_polyBits+m_tileBits)) & saltMask); it = (unsigned int)((ref >> m_polyBits) & tileMask); ip = (unsigned int)(ref & polyMask); +#endif } /// Extracts a tile's salt value from the specified polygon reference. @@ -495,8 +531,13 @@ public: /// @see #encodePolyId inline unsigned int decodePolyIdSalt(dtPolyRef ref) const { +#ifdef DT_POLYREF64 + const dtPolyRef saltMask = ((dtPolyRef)1<> (DT_POLY_BITS+DT_TILE_BITS)) & saltMask); +#else const dtPolyRef saltMask = ((dtPolyRef)1<> (m_polyBits+m_tileBits)) & saltMask); +#endif } /// Extracts the tile's index from the specified polygon reference. @@ -505,8 +546,13 @@ public: /// @see #encodePolyId inline unsigned int decodePolyIdTile(dtPolyRef ref) const { +#ifdef DT_POLYREF64 + const dtPolyRef tileMask = ((dtPolyRef)1<> DT_POLY_BITS) & tileMask); +#else const dtPolyRef tileMask = ((dtPolyRef)1<> m_polyBits) & tileMask); +#endif } /// Extracts the polygon's index (within its tile) from the specified polygon reference. @@ -515,8 +561,13 @@ public: /// @see #encodePolyId inline unsigned int decodePolyIdPoly(dtPolyRef ref) const { +#ifdef DT_POLYREF64 + const dtPolyRef polyMask = ((dtPolyRef)1<maxTiles)); m_polyBits = dtIlog2(dtNextPow2((unsigned int)params->maxPolys)); // Only allow 31 salt bits, since the salt mask is calculated using 32bit uint and it will overflow. m_saltBits = dtMin((unsigned int)31, 32 - m_tileBits - m_polyBits); + if (m_saltBits < 10) return DT_FAILURE | DT_INVALID_PARAM; +#endif return DT_SUCCESS; } @@ -1209,7 +1214,11 @@ dtStatus dtNavMesh::removeTile(dtTileRef ref, unsigned char** data, int* dataSiz tile->offMeshCons = 0; // Update salt, salt should never be zero. +#ifdef DT_POLYREF64 + tile->salt = (tile->salt+1) & ((1<salt = (tile->salt+1) & ((1<salt == 0) tile->salt++; diff --git a/Detour/Source/DetourNode.cpp b/Detour/Source/DetourNode.cpp index de7b159..57cb206 100644 --- a/Detour/Source/DetourNode.cpp +++ b/Detour/Source/DetourNode.cpp @@ -22,6 +22,19 @@ #include "DetourCommon.h" #include +#ifdef DT_POLYREF64 +// From Thomas Wang, https://gist.github.com/badboy/6267743 +inline unsigned int dtHashRef(dtPolyRef a) +{ + a = (~a) + (a << 18); // a = (a << 18) - a - 1; + a = a ^ (a >> 31); + a = a * 21; // a = (a + (a << 2)) + (a << 4); + a = a ^ (a >> 11); + a = a + (a << 6); + a = a ^ (a >> 22); + return (unsigned int)a; +} +#else inline unsigned int dtHashRef(dtPolyRef a) { a += ~(a<<15); @@ -32,6 +45,7 @@ inline unsigned int dtHashRef(dtPolyRef a) a ^= (a>>16); return (unsigned int)a; } +#endif ////////////////////////////////////////////////////////////////////////////////////////// dtNodePool::dtNodePool(int maxNodes, int hashSize) :