Recast: major optimization on Editor::connectTileTraverseLinks

Check if we have enough space for num new links before starting the complex calculations. This optimization saved 10+ seconds on the firing range and had no effect on the output results; the navmesh still hashed to the same value as the one build before this patch.
This commit is contained in:
Kawe Mazidjatari 2024-08-16 01:21:49 +02:00
parent 965647ae40
commit ec1f72bf04
3 changed files with 58 additions and 15 deletions

View File

@ -651,6 +651,12 @@ static bool traverseLinkInLOS(const InputGeom* geom, const float* lowPos, const
// 2 polygons.
void Editor::connectTileTraverseLinks(dtMeshTile* const baseTile, const bool linkToNeighbor)
{
// If we link to the same tile, we need at least 2 links.
if (!baseTile->linkCountAvailable(linkToNeighbor ? 1 : 2))
return;
bool firstBaseTileLinkUsed = false;
for (int i = 0; i < baseTile->header->polyCount; ++i)
{
dtPoly* const basePoly = &baseTile->polys[i];
@ -689,9 +695,20 @@ void Editor::connectTileTraverseLinks(dtMeshTile* const baseTile, const bool lin
for (int k = 0; k < nneis; ++k)
{
dtMeshTile* landTile = neis[k];
const bool external = baseTile != landTile;
const bool sameTile = baseTile == landTile;
if (!external && i == k) continue; // Skip self
// Don't connect to same tile edges yet, leave that for the second pass.
if (linkToNeighbor && sameTile)
continue;
// Skip same polygon.
if (sameTile && i == k)
continue;
if (!landTile->linkCountAvailable(1))
continue;
bool firstLandTileLinkUsed = false;
for (int m = 0; m < landTile->header->polyCount; ++m)
{
@ -705,6 +722,19 @@ void Editor::connectTileTraverseLinks(dtMeshTile* const baseTile, const bool lin
if (landPoly->neis[n] != 0)
continue;
// We need at least 2 links available, figure out if
// we link to the same tile or another one.
if (linkToNeighbor)
{
if (firstLandTileLinkUsed && !landTile->linkCountAvailable(1))
continue;
else if (firstBaseTileLinkUsed && !baseTile->linkCountAvailable(1))
return;
}
else if (firstBaseTileLinkUsed && !baseTile->linkCountAvailable(2))
return;
// Polygon 2 edge
const float* const landPolySpos = &landTile->verts[landPoly->verts[n] * 3];
const float* const landPolyEpos = &landTile->verts[landPoly->verts[(n + 1) % landPoly->vertCount] * 3];
@ -766,22 +796,14 @@ void Editor::connectTileTraverseLinks(dtMeshTile* const baseTile, const bool lin
if (!traverseLinkInLOS(m_geom, lowerEdgeMid, higherEdgeMid, lowerEdgeDir, higherEdgeDir, offsetAmount))
continue;
// Need at least 2 links
// todo(amos): perhaps optimize this so we check this before raycasting
// etc.. must also check if the tile isn't external because if so, we need
// space for 2 links in the same tile.
const unsigned int forwardIdx = baseTile->allocLink();
if (forwardIdx == DT_NULL_LINK)
return; // Move on to next base tile.
const unsigned int reverseIdx = landTile->allocLink();
if (reverseIdx == DT_NULL_LINK)
{
baseTile->freeLink(forwardIdx);
break; // Move on to next neighbor tile.
}
// Allocated 2 new links, need to check for enough space on subsequent runs.
// This optimization saves a lot of time generating navmeshes for larger or
// more complicated geometry.
firstBaseTileLinkUsed = true;
firstLandTileLinkUsed = true;
dtLink* const forwardLink = &baseTile->links[forwardIdx];

View File

@ -423,6 +423,8 @@ public:
unsigned int allocLink();
void freeLink(unsigned int link);
bool linkCountAvailable(const int count) const;
unsigned int salt; ///Counter describing modifications to the tile.
unsigned int linksFreeList; ///Index to the next free link.

View File

@ -130,6 +130,25 @@ void dtMeshTile::freeLink(unsigned int link)
linksFreeList = link;
}
bool dtMeshTile::linkCountAvailable(const int count) const
{
rdAssert(count > 0);
unsigned int link = linksFreeList;
if (link == DT_NULL_LINK)
return false;
for (int i = 1; i < count; i++)
{
link = links[link].next;
if (link == DT_NULL_LINK)
return false;
}
return true;
}
int dtCalcTraverseTableCellIndex(const int numPolyGroups,
const unsigned short polyGroup1, const unsigned short polyGroup2)
{