Recast: tag unlinked and unusable tiles

Don't add tiles with no links to the position lookup table.
This commit is contained in:
Kawe Mazidjatari 2024-08-31 11:54:09 +02:00
parent 537f149be3
commit 09a052ff18
3 changed files with 23 additions and 7 deletions

View File

@ -159,12 +159,17 @@ static void floodNavmesh(dtNavMesh* nav, NavmeshFlags* flags, dtPolyRef start, u
static void disableUnvisitedPolys(dtNavMesh* nav, NavmeshFlags* flags)
{
for (int i = 0; i < nav->getMaxTiles(); ++i)
for (int i = 0; i < nav->getTileCount(); ++i)
{
const dtMeshTile* tile = ((const dtNavMesh*)nav)->getTile(i);
if (!tile->header) continue;
dtMeshHeader* header = tile->header;
if (!header) continue;
const dtPolyRef base = nav->getPolyRefBase(tile);
for (int j = 0; j < tile->header->polyCount; ++j)
int numUnlinkedPolys = 0;
for (int j = 0; j < header->polyCount; ++j)
{
const dtPolyRef ref = base | (unsigned int)j;
if (!flags->getFlags(ref))
@ -176,8 +181,13 @@ static void disableUnvisitedPolys(dtNavMesh* nav, NavmeshFlags* flags)
targetPoly->groupId = DT_UNLINKED_POLY_GROUP;
targetPoly->firstLink = DT_NULL_LINK;
targetPoly->flags = 0;
numUnlinkedPolys++;
}
}
if (numUnlinkedPolys == header->polyCount)
header->userId = DT_UNLINKED_TILE_USER_ID;
}
}

View File

@ -62,6 +62,12 @@ typedef uint64_t dtTileRef;
typedef unsigned int dtTileRef;
#endif
/// A value that indicates that this tile doesn't contain any polygons with valid links
/// to the rest of the reachable area's of the navigation mesh, this tile will not be
/// added to the position lookup table.
/// @ingroup detour
static const int DT_UNLINKED_TILE_USER_ID = 1;
/// The maximum number of vertices per navigation polygon.
/// @ingroup detour
static const int DT_VERTS_PER_POLYGON = 6;

View File

@ -1045,7 +1045,7 @@ dtStatus dtNavMesh::addTile(unsigned char* data, int dataSize, int flags,
#endif
// Make sure the location is free.
if (!header->userId != 1 && getTileAt(header->x, header->y, header->layer))
if (!header->userId != DT_UNLINKED_TILE_USER_ID && getTileAt(header->x, header->y, header->layer))
return DT_FAILURE | DT_ALREADY_OCCUPIED;
// Allocate a tile.
@ -1094,7 +1094,7 @@ dtStatus dtNavMesh::addTile(unsigned char* data, int dataSize, int flags,
tile->deleteCallback = nullptr;
// Insert tile into the position lut.
if (header->userId != 1)
if (header->userId != DT_UNLINKED_TILE_USER_ID)
{
int h = computeTileHash(header->x, header->y, m_tileLutMask);
tile->next = m_posLookup[h];
@ -1113,7 +1113,7 @@ dtStatus dtNavMesh::addTile(unsigned char* data, int dataSize, int flags,
const int bvtreeSize = rdAlign4(sizeof(dtBVNode)*header->bvNodeCount);
const int offMeshLinksSize = rdAlign4(sizeof(dtOffMeshConnection)*header->offMeshConCount);
#if DT_NAVMESH_SET_VERSION >= 8
const int probesSize = rdAlign4(sizeof(dtCell)*header->maxCellCount);
const int cellsSize = rdAlign4(sizeof(dtCell)*header->maxCellCount);
#endif
unsigned char* d = data + headerSize;
@ -1127,7 +1127,7 @@ dtStatus dtNavMesh::addTile(unsigned char* data, int dataSize, int flags,
tile->bvTree = rdGetThenAdvanceBufferPointer<dtBVNode>(d, bvtreeSize);
tile->offMeshCons = rdGetThenAdvanceBufferPointer<dtOffMeshConnection>(d, offMeshLinksSize);
#if DT_NAVMESH_SET_VERSION >= 8
tile->cells = rdGetThenAdvanceBufferPointer<dtCell>(d, probesSize);
tile->cells = rdGetThenAdvanceBufferPointer<dtCell>(d, cellsSize);
#endif
// If there are no items in the bvtree, reset the tree pointer.