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. // 2 polygons.
void Editor::connectTileTraverseLinks(dtMeshTile* const baseTile, const bool linkToNeighbor) 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) for (int i = 0; i < baseTile->header->polyCount; ++i)
{ {
dtPoly* const basePoly = &baseTile->polys[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) for (int k = 0; k < nneis; ++k)
{ {
dtMeshTile* landTile = neis[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) 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) if (landPoly->neis[n] != 0)
continue; 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 // Polygon 2 edge
const float* const landPolySpos = &landTile->verts[landPoly->verts[n] * 3]; const float* const landPolySpos = &landTile->verts[landPoly->verts[n] * 3];
const float* const landPolyEpos = &landTile->verts[landPoly->verts[(n + 1) % landPoly->vertCount] * 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)) if (!traverseLinkInLOS(m_geom, lowerEdgeMid, higherEdgeMid, lowerEdgeDir, higherEdgeDir, offsetAmount))
continue; 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(); const unsigned int forwardIdx = baseTile->allocLink();
if (forwardIdx == DT_NULL_LINK)
return; // Move on to next base tile.
const unsigned int reverseIdx = landTile->allocLink(); const unsigned int reverseIdx = landTile->allocLink();
if (reverseIdx == DT_NULL_LINK) // 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
baseTile->freeLink(forwardIdx); // more complicated geometry.
break; // Move on to next neighbor tile. firstBaseTileLinkUsed = true;
} firstLandTileLinkUsed = true;
dtLink* const forwardLink = &baseTile->links[forwardIdx]; dtLink* const forwardLink = &baseTile->links[forwardIdx];

View File

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

View File

@ -130,6 +130,25 @@ void dtMeshTile::freeLink(unsigned int link)
linksFreeList = 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, int dtCalcTraverseTableCellIndex(const int numPolyGroups,
const unsigned short polyGroup1, const unsigned short polyGroup2) const unsigned short polyGroup1, const unsigned short polyGroup2)
{ {