Recast: move Detour_IsGoalPolyReachable to dtNavMesh

Make the code shared so we can also use it in the Recast editor.
This commit is contained in:
Kawe Mazidjatari 2024-07-07 12:05:35 +02:00
parent c56e1cc801
commit 917b33bb71
4 changed files with 73 additions and 46 deletions

View File

@ -63,41 +63,12 @@ bool Detour_IsGoalPolyReachable(dtNavMesh* const nav, const dtPolyRef fromRef,
if (navmesh_always_reachable.GetBool())
return true;
// Same poly is always reachable.
if (fromRef == goalRef)
return true;
const bool hasAnimType = animType != ANIMTYPE_NONE;
const int traversalTableIndex = hasAnimType
? NavMesh_GetTraversalTableIndexForAnimType(animType)
: NULL;
const dtMeshTile* fromTile = nullptr;
const dtMeshTile* goalTile = nullptr;
const dtPoly* fromPoly = nullptr;
const dtPoly* goalPoly = nullptr;
nav->getTileAndPolyByRefUnsafe(fromRef, &fromTile, &fromPoly);
nav->getTileAndPolyByRefUnsafe(goalRef, &goalTile, &goalPoly);
const unsigned short fromPolyGroupId = fromPoly->groupId;
const unsigned short goalPolyGroupId = goalPoly->groupId;
// If we don't have an anim type, then we shouldn't use the traversal tables
// since these are used for linking separate poly islands together (which
// requires jumping or some form of animation). So instead, check if we are
// on the same poly island.
if (animType == ANIMTYPE_NONE)
return fromPolyGroupId == goalPolyGroupId;
const int* const traversalTable = nav->m_traversalTables[NavMesh_GetTraversalTableIndexForAnimType(animType)];
// Traversal table doesn't exist, attempt the path finding anyways (this is
// a bug in the NavMesh, rebuild it!).
if (!traversalTable)
return true;
const int polyGroupCount = nav->m_params.polyGroupCount;
const int fromPolyBitCell = traversalTable[calcTraversalTableCellIndex(polyGroupCount, fromPolyGroupId, goalPolyGroupId)];
// Check if the bit corresponding to our goal poly is set, if it isn't then
// there are no available traversal links from the current poly to the goal.
return fromPolyBitCell & BitVec_Bit(goalPolyGroupId);
return nav->isGoalPolyReachable(fromRef, goalRef, !hasAnimType, traversalTableIndex);
}
//-----------------------------------------------------------------------------

View File

@ -15,6 +15,11 @@ Members in this module are wrappers around the standard math library
/// The value of PI used by Recast.
static const float DT_PI = 3.14159265f;
/// The total number of bits in an bit cell integer.
static const int DT_BITS_PER_BIT_CELL = 32;
inline int dtBitCellBit(const int bitNum) { return (1 << ((bitNum) & (DT_BITS_PER_BIT_CELL-1))); }
inline float dtMathFabsf(float x) { return fabsf(x); }
inline float dtMathSqrtf(float x) { return sqrtf(x); }
inline float dtMathFloorf(float x) { return floorf(x); }

View File

@ -19,11 +19,8 @@
#ifndef DETOURNAVMESH_H
#define DETOURNAVMESH_H
// Only use types for function prototypes
#ifndef GAMESDK
#include "Shared/Include/SharedAlloc.h"
#include "Detour/Include/DetourStatus.h"
#endif // !GAMESDK
// Undefine (or define in a build config) the following line to use 64bit polyref.
// Generally not needed, useful for very large worlds.
@ -529,6 +526,15 @@ public:
/// @param[out] poly The polygon.
void getTileAndPolyByRefUnsafe(const dtPolyRef ref, const dtMeshTile** tile, const dtPoly** poly) const;
/// Returns whether goal poly is reachable from start poly
/// @param[in] fromRef The reference to the start poly.
/// @param[in] goalRef The reference to the goal poly.
/// @param[in] checkDisjointGroupsOnly Whether to only check disjoint poly groups.
/// @param[in] traversalTableIndex Traversal table to use for checking if islands are linked together.
/// @return True if goal polygon is reachable from start polygon.
bool isGoalPolyReachable(const dtPolyRef fromRef, const dtPolyRef goalRef,
const bool checkDisjointGroupsOnly, const int traversalTableIndex) 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.
@ -777,20 +783,14 @@ public:
/// @param[in] polyGroup2 The poly group ID of the second island.
/// @return The cell index for the static traversal table.
/// @ingroup detour
inline int calcTraversalTableCellIndex(const int numPolyGroups,
const unsigned short polyGroup1, const unsigned short polyGroup2)
{
return polyGroup1*((numPolyGroups+31)/32)+(polyGroup2/32);
}
int calcTraversalTableCellIndex(const int numPolyGroups,
const unsigned short polyGroup1, const unsigned short polyGroup2);
/// Returns the total size needed for the static traversal table.
/// @param[in] numPolyGroups The total number of poly groups.
/// @return the total size needed for the static traversal table.
/// @ingroup detour
inline int calcTraversalTableSize(const int numPolyGroups)
{
return sizeof(int)*(numPolyGroups*((numPolyGroups+31)/32));
}
int calcTraversalTableSize(const int numPolyGroups);
/// Allocates a navigation mesh object using the Detour allocator.
/// @return A navigation mesh that is ready for initialization, or null on failure.

View File

@ -134,6 +134,16 @@ inline void freeLink(dtMeshTile* tile, unsigned int link)
tile->linksFreeList = link;
}
int calcTraversalTableCellIndex(const int numPolyGroups,
const unsigned short polyGroup1, const unsigned short polyGroup2)
{
return polyGroup1*((numPolyGroups+(DT_BITS_PER_BIT_CELL-1))/DT_BITS_PER_BIT_CELL)+(polyGroup2/DT_BITS_PER_BIT_CELL);
}
int calcTraversalTableSize(const int numPolyGroups)
{
return sizeof(int)*(numPolyGroups*((numPolyGroups+(DT_BITS_PER_BIT_CELL-1))/DT_BITS_PER_BIT_CELL));
}
dtNavMesh* rdAllocNavMesh()
{
@ -1275,6 +1285,47 @@ void dtNavMesh::getTileAndPolyByRefUnsafe(const dtPolyRef ref, const dtMeshTile*
*poly = &m_tiles[it].polys[ip];
}
bool dtNavMesh::isGoalPolyReachable(const dtPolyRef fromRef, const dtPolyRef goalRef,
const bool checkDisjointGroupsOnly, const int traversalTableIndex) const
{
// Same poly is always reachable.
if (fromRef == goalRef)
return true;
const dtMeshTile* fromTile = nullptr;
const dtMeshTile* goalTile = nullptr;
const dtPoly* fromPoly = nullptr;
const dtPoly* goalPoly = nullptr;
getTileAndPolyByRefUnsafe(fromRef, &fromTile, &fromPoly);
getTileAndPolyByRefUnsafe(goalRef, &goalTile, &goalPoly);
const unsigned short fromPolyGroupId = fromPoly->groupId;
const unsigned short goalPolyGroupId = goalPoly->groupId;
// If we don't have an anim type, then we shouldn't use the traversal tables
// since these are used for linking isolated poly islands together (which
// requires jumping or some form of animation). So instead, check if we are
// on the same poly island.
if (checkDisjointGroupsOnly)
return fromPolyGroupId == goalPolyGroupId;
rdAssert(traversalTableIndex >= 0 && traversalTableIndex < m_params.traversalTableCount);
const int* const traversalTable = m_traversalTables[traversalTableIndex];
// Traversal table doesn't exist, attempt the path finding anyways (this is
// a bug in the NavMesh, rebuild it!).
if (!traversalTable)
return true;
const int polyGroupCount = m_params.polyGroupCount;
const int fromPolyBitCell = traversalTable[calcTraversalTableCellIndex(polyGroupCount, fromPolyGroupId, goalPolyGroupId)];
// Check if the bit corresponding to our goal poly is set, if it isn't then
// there are no available traversal links from the current poly to the goal.
return fromPolyBitCell & dtBitCellBit(goalPolyGroupId);
}
bool dtNavMesh::isValidPolyRef(dtPolyRef ref) const
{
if (!ref) return false;