Added define to compile Detour with 64bit dtPolyRefs

This commit is contained in:
Mikko Mononen 2013-12-22 18:01:02 +02:00
parent 7308f91d80
commit 6a7f5268ab
3 changed files with 80 additions and 4 deletions

View File

@ -22,16 +22,39 @@
#include "DetourAlloc.h" #include "DetourAlloc.h"
#include "DetourStatus.h" #include "DetourStatus.h"
// Undefine (or define in a build cofnig) the following line to use 64bit polyref.
// Generally not needed, useful for very large worlds.
// Note: tiles build using 32bit refs are not compatible with 64bit refs!
//#define DT_POLYREF64 1
#ifdef DT_POLYREF64
// TODO: figure out a multiplatform version of uint64_t
// - maybe: https://code.google.com/p/msinttypes/
// - or: http://www.azillionmonkeys.com/qed/pstdint.h
#include <stdint.h>
#endif
// Note: If you want to use 64-bit refs, change the types of both dtPolyRef & dtTileRef. // 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. // It is also recommended that you change dtHashRef() to a proper 64-bit hash.
/// A handle to a polygon within a navigation mesh tile. /// A handle to a polygon within a navigation mesh tile.
/// @ingroup detour /// @ingroup detour
#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; typedef unsigned int dtPolyRef;
#endif
/// A handle to a tile within a navigation mesh. /// A handle to a tile within a navigation mesh.
/// @ingroup detour /// @ingroup detour
#ifdef DT_POLYREF64
typedef uint64_t dtTileRef;
#else
typedef unsigned int dtTileRef; typedef unsigned int dtTileRef;
#endif
/// The maximum number of vertices per navigation polygon. /// The maximum number of vertices per navigation polygon.
/// @ingroup detour /// @ingroup detour
@ -469,7 +492,11 @@ public:
/// @param[in] ip The index of the polygon within the tile. /// @param[in] ip The index of the polygon within the tile.
inline dtPolyRef encodePolyId(unsigned int salt, unsigned int it, unsigned int ip) const inline dtPolyRef encodePolyId(unsigned int salt, unsigned int it, unsigned int ip) const
{ {
#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; return ((dtPolyRef)salt << (m_polyBits+m_tileBits)) | ((dtPolyRef)it << m_polyBits) | (dtPolyRef)ip;
#endif
} }
/// Decodes a standard polygon reference. /// Decodes a standard polygon reference.
@ -481,12 +508,21 @@ public:
/// @see #encodePolyId /// @see #encodePolyId
inline void decodePolyId(dtPolyRef ref, unsigned int& salt, unsigned int& it, unsigned int& ip) const inline void decodePolyId(dtPolyRef ref, unsigned int& salt, unsigned int& it, unsigned int& ip) const
{ {
#ifdef DT_POLYREF64
const dtPolyRef saltMask = ((dtPolyRef)1<<DT_SALT_BITS)-1;
const dtPolyRef tileMask = ((dtPolyRef)1<<DT_TILE_BITS)-1;
const dtPolyRef polyMask = ((dtPolyRef)1<<DT_POLY_BITS)-1;
salt = (unsigned int)((ref >> (DT_POLY_BITS+DT_TILE_BITS)) & saltMask);
it = (unsigned int)((ref >> DT_POLY_BITS) & tileMask);
ip = (unsigned int)(ref & polyMask);
#else
const dtPolyRef saltMask = ((dtPolyRef)1<<m_saltBits)-1; const dtPolyRef saltMask = ((dtPolyRef)1<<m_saltBits)-1;
const dtPolyRef tileMask = ((dtPolyRef)1<<m_tileBits)-1; const dtPolyRef tileMask = ((dtPolyRef)1<<m_tileBits)-1;
const dtPolyRef polyMask = ((dtPolyRef)1<<m_polyBits)-1; const dtPolyRef polyMask = ((dtPolyRef)1<<m_polyBits)-1;
salt = (unsigned int)((ref >> (m_polyBits+m_tileBits)) & saltMask); salt = (unsigned int)((ref >> (m_polyBits+m_tileBits)) & saltMask);
it = (unsigned int)((ref >> m_polyBits) & tileMask); it = (unsigned int)((ref >> m_polyBits) & tileMask);
ip = (unsigned int)(ref & polyMask); ip = (unsigned int)(ref & polyMask);
#endif
} }
/// Extracts a tile's salt value from the specified polygon reference. /// Extracts a tile's salt value from the specified polygon reference.
@ -495,8 +531,13 @@ public:
/// @see #encodePolyId /// @see #encodePolyId
inline unsigned int decodePolyIdSalt(dtPolyRef ref) const inline unsigned int decodePolyIdSalt(dtPolyRef ref) const
{ {
#ifdef DT_POLYREF64
const dtPolyRef saltMask = ((dtPolyRef)1<<DT_SALT_BITS)-1;
return (unsigned int)((ref >> (DT_POLY_BITS+DT_TILE_BITS)) & saltMask);
#else
const dtPolyRef saltMask = ((dtPolyRef)1<<m_saltBits)-1; const dtPolyRef saltMask = ((dtPolyRef)1<<m_saltBits)-1;
return (unsigned int)((ref >> (m_polyBits+m_tileBits)) & saltMask); return (unsigned int)((ref >> (m_polyBits+m_tileBits)) & saltMask);
#endif
} }
/// Extracts the tile's index from the specified polygon reference. /// Extracts the tile's index from the specified polygon reference.
@ -505,8 +546,13 @@ public:
/// @see #encodePolyId /// @see #encodePolyId
inline unsigned int decodePolyIdTile(dtPolyRef ref) const inline unsigned int decodePolyIdTile(dtPolyRef ref) const
{ {
#ifdef DT_POLYREF64
const dtPolyRef tileMask = ((dtPolyRef)1<<DT_TILE_BITS)-1;
return (unsigned int)((ref >> DT_POLY_BITS) & tileMask);
#else
const dtPolyRef tileMask = ((dtPolyRef)1<<m_tileBits)-1; const dtPolyRef tileMask = ((dtPolyRef)1<<m_tileBits)-1;
return (unsigned int)((ref >> m_polyBits) & tileMask); return (unsigned int)((ref >> m_polyBits) & tileMask);
#endif
} }
/// Extracts the polygon's index (within its tile) from the specified polygon reference. /// Extracts the polygon's index (within its tile) from the specified polygon reference.
@ -515,8 +561,13 @@ public:
/// @see #encodePolyId /// @see #encodePolyId
inline unsigned int decodePolyIdPoly(dtPolyRef ref) const inline unsigned int decodePolyIdPoly(dtPolyRef ref) const
{ {
#ifdef DT_POLYREF64
const dtPolyRef polyMask = ((dtPolyRef)1<<DT_POLY_BITS)-1;
return (unsigned int)(ref & polyMask);
#else
const dtPolyRef polyMask = ((dtPolyRef)1<<m_polyBits)-1; const dtPolyRef polyMask = ((dtPolyRef)1<<m_polyBits)-1;
return (unsigned int)(ref & polyMask); return (unsigned int)(ref & polyMask);
#endif
} }
/// @} /// @}
@ -576,9 +627,11 @@ private:
dtMeshTile* m_nextFree; ///< Freelist of tiles. dtMeshTile* m_nextFree; ///< Freelist of tiles.
dtMeshTile* m_tiles; ///< List of tiles. dtMeshTile* m_tiles; ///< List of tiles.
#ifndef DT_POLYREF64
unsigned int m_saltBits; ///< Number of salt bits in the tile ID. unsigned int m_saltBits; ///< Number of salt bits in the tile ID.
unsigned int m_tileBits; ///< Number of tile 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_polyBits; ///< Number of poly bits in the tile ID.
#endif
}; };
/// Allocates a navigation mesh object using the Detour allocator. /// Allocates a navigation mesh object using the Detour allocator.

View File

@ -193,11 +193,13 @@ dtNavMesh::dtNavMesh() :
m_tileLutMask(0), m_tileLutMask(0),
m_posLookup(0), m_posLookup(0),
m_nextFree(0), m_nextFree(0),
m_tiles(0), m_tiles(0)
m_saltBits(0),
m_tileBits(0),
m_polyBits(0)
{ {
#ifndef DT_POLYREF64
m_saltBits = 0;
m_tileBits = 0;
m_polyBits = 0;
#endif
memset(&m_params, 0, sizeof(dtNavMeshParams)); memset(&m_params, 0, sizeof(dtNavMeshParams));
m_orig[0] = 0; m_orig[0] = 0;
m_orig[1] = 0; m_orig[1] = 0;
@ -249,12 +251,15 @@ dtStatus dtNavMesh::init(const dtNavMeshParams* params)
} }
// Init ID generator values. // Init ID generator values.
#ifndef DT_POLYREF64
m_tileBits = dtIlog2(dtNextPow2((unsigned int)params->maxTiles)); m_tileBits = dtIlog2(dtNextPow2((unsigned int)params->maxTiles));
m_polyBits = dtIlog2(dtNextPow2((unsigned int)params->maxPolys)); 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. // 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); m_saltBits = dtMin((unsigned int)31, 32 - m_tileBits - m_polyBits);
if (m_saltBits < 10) if (m_saltBits < 10)
return DT_FAILURE | DT_INVALID_PARAM; return DT_FAILURE | DT_INVALID_PARAM;
#endif
return DT_SUCCESS; return DT_SUCCESS;
} }
@ -1209,7 +1214,11 @@ dtStatus dtNavMesh::removeTile(dtTileRef ref, unsigned char** data, int* dataSiz
tile->offMeshCons = 0; tile->offMeshCons = 0;
// Update salt, salt should never be zero. // Update salt, salt should never be zero.
#ifdef DT_POLYREF64
tile->salt = (tile->salt+1) & ((1<<DT_SALT_BITS)-1);
#else
tile->salt = (tile->salt+1) & ((1<<m_saltBits)-1); tile->salt = (tile->salt+1) & ((1<<m_saltBits)-1);
#endif
if (tile->salt == 0) if (tile->salt == 0)
tile->salt++; tile->salt++;

View File

@ -22,6 +22,19 @@
#include "DetourCommon.h" #include "DetourCommon.h"
#include <string.h> #include <string.h>
#ifdef DT_POLYREF64
// From Thomas Wang, https://gist.github.com/badboy/6267743
inline unsigned int dtHashRef(dtPolyRef a)
{
a = (~a) + (a << 18); // a = (a << 18) - a - 1;
a = a ^ (a >> 31);
a = a * 21; // a = (a + (a << 2)) + (a << 4);
a = a ^ (a >> 11);
a = a + (a << 6);
a = a ^ (a >> 22);
return (unsigned int)a;
}
#else
inline unsigned int dtHashRef(dtPolyRef a) inline unsigned int dtHashRef(dtPolyRef a)
{ {
a += ~(a<<15); a += ~(a<<15);
@ -32,6 +45,7 @@ inline unsigned int dtHashRef(dtPolyRef a)
a ^= (a>>16); a ^= (a>>16);
return (unsigned int)a; return (unsigned int)a;
} }
#endif
////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////
dtNodePool::dtNodePool(int maxNodes, int hashSize) : dtNodePool::dtNodePool(int maxNodes, int hashSize) :