From d5fa52499cfb659b9aa4c7d3c2ca00715635f4cb Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Wed, 18 Sep 2024 17:28:10 +0200 Subject: [PATCH] Recast: combine off-mesh link basing and land connection logic Combine the 2 to avoid an extra loop. Also break out of tile grid loop as soon as a link has been established to save even more processing time. --- src/naveditor/Editor.cpp | 8 +- src/naveditor/Editor_TileMesh.cpp | 7 +- .../recast/Detour/Include/DetourNavMesh.h | 4 +- .../recast/Detour/Source/DetourNavMesh.cpp | 82 ++++++++----------- 4 files changed, 39 insertions(+), 62 deletions(-) diff --git a/src/naveditor/Editor.cpp b/src/naveditor/Editor.cpp index cfe25f2c..ea276156 100644 --- a/src/naveditor/Editor.cpp +++ b/src/naveditor/Editor.cpp @@ -850,12 +850,8 @@ void Editor::connectOffMeshLinks() const dtTileRef targetRef = m_navMesh->getTileRef(target); - // Base off-mesh connections to their starting polygons - // and connect connections inside the tile. - m_navMesh->baseOffMeshLinks(targetRef); - - // Connect off-mesh polygons to outer tiles. - m_navMesh->connectExtOffMeshLinks(targetRef); + // Connect off-mesh polygons to inner and outer tiles. + m_navMesh->connectOffMeshLinks(targetRef); } } diff --git a/src/naveditor/Editor_TileMesh.cpp b/src/naveditor/Editor_TileMesh.cpp index 22766126..8aee3d1b 100644 --- a/src/naveditor/Editor_TileMesh.cpp +++ b/src/naveditor/Editor_TileMesh.cpp @@ -700,10 +700,7 @@ void Editor_TileMesh::buildTile(const float* pos) failure = true; } else if (header->offMeshConCount) - { - m_navMesh->baseOffMeshLinks(tileRef); - m_navMesh->connectExtOffMeshLinks(tileRef); - } + m_navMesh->connectOffMeshLinks(tileRef); if (!failure) { @@ -731,7 +728,7 @@ void Editor_TileMesh::buildTile(const float* pos) getTilePos(&con->pos[3], landTx, landTy); if (landTx == tx && landTy == ty) - m_navMesh->connectExtOffMeshLinks(targetRef); + m_navMesh->connectOffMeshLinks(targetRef); } } diff --git a/src/thirdparty/recast/Detour/Include/DetourNavMesh.h b/src/thirdparty/recast/Detour/Include/DetourNavMesh.h index 273d3d05..906c2766 100644 --- a/src/thirdparty/recast/Detour/Include/DetourNavMesh.h +++ b/src/thirdparty/recast/Detour/Include/DetourNavMesh.h @@ -950,9 +950,7 @@ public: /// Builds external polygon links for a tile. dtStatus connectTraverseLinks(const dtTileRef tileRef, const dtTraverseLinkConnectParams& params); /// Builds external polygon links for a tile. - dtStatus connectExtOffMeshLinks(const dtTileRef tileRef); - /// Builds internal polygons links for a tile. - dtStatus baseOffMeshLinks(const dtTileRef tileRef); + dtStatus connectOffMeshLinks(const dtTileRef tileRef); dtPolyRef clampOffMeshVertToPoly(const dtOffMeshConnection* con, dtMeshTile* conTile, const dtMeshTile* lookupTile, const bool start); diff --git a/src/thirdparty/recast/Detour/Source/DetourNavMesh.cpp b/src/thirdparty/recast/Detour/Source/DetourNavMesh.cpp index d676ebc4..3c3b610c 100644 --- a/src/thirdparty/recast/Detour/Source/DetourNavMesh.cpp +++ b/src/thirdparty/recast/Detour/Source/DetourNavMesh.cpp @@ -577,7 +577,7 @@ static bool connectOffMeshLink(dtMeshTile* tile, dtPoly* fromPoly, const dtPolyR return true; } -dtStatus dtNavMesh::connectExtOffMeshLinks(const dtTileRef tileRef) +dtStatus dtNavMesh::connectOffMeshLinks(const dtTileRef tileRef) { const int tileIndex = (int)decodePolyIdTile((dtPolyRef)tileRef); if (tileIndex >= m_maxTiles) @@ -594,6 +594,28 @@ dtStatus dtNavMesh::connectExtOffMeshLinks(const dtTileRef tileRef) dtOffMeshConnection* con = &tile->offMeshCons[i]; dtPoly* conPoly = &tile->polys[con->poly]; + const dtPolyRef basePolyRef = clampOffMeshVertToPoly(con, tile, tile, true); + + if (!basePolyRef) + continue; + + const unsigned char traverseType = con->getTraverseType(); + const bool invertVertLookup = con->getVertLookupOrder(); + + // Start end-point is always connect back to off-mesh connection. + const unsigned short basePolyIdx = (unsigned short)decodePolyIdPoly(basePolyRef); + dtPoly* basePoly = &tile->polys[basePolyIdx]; + + const dtPolyRef conPolyRef = base | (dtPolyRef)(con->poly); + + if (!connectOffMeshLink(tile, basePoly, conPolyRef, 0xff, 0xff, traverseType, + invertVertLookup ? DT_OFFMESH_CON_TRAVERSE_ON_VERT : DT_OFFMESH_CON_TRAVERSE_ON_POLY)) + return DT_FAILURE | DT_OUT_OF_MEMORY; + + // Link off-mesh connection to target poly. + if (!connectOffMeshLink(tile, conPoly, basePolyRef, 0xff, 0, DT_NULL_TRAVERSE_TYPE, 0)) + return DT_FAILURE | DT_OUT_OF_MEMORY; + // connect to land points. const float halfExtents[3] = { con->rad, con->rad, header->walkableClimb }; float bmin[3], bmax[3]; @@ -608,19 +630,15 @@ dtStatus dtNavMesh::connectExtOffMeshLinks(const dtTileRef tileRef) static const int MAX_NEIS = 32; dtMeshTile* neis[MAX_NEIS]; - const dtPolyRef conPolyRef = base | (dtPolyRef)(con->poly); - const unsigned char side = rdClassifyPointOutsideBounds(&con->pos[3], header->bmin, header->bmax); const unsigned char oppositeSide = (side == 0xff) ? 0xff : (unsigned char)rdOppositeTile(side); - const unsigned char traverseType = con->getTraverseType(); - const bool invertVertLookup = con->getVertLookupOrder(); - #if DT_NAVMESH_SET_VERSION >= 7 // NOTE: need to remove the vert lookup inversion flag from here as the // engine uses this value directly to index into the activity array. con->setTraverseType(traverseType, 0); #endif + bool breakOut = false; for (int y = miny; y <= maxy; ++y) { @@ -653,8 +671,18 @@ dtStatus dtNavMesh::connectExtOffMeshLinks(const dtTileRef tileRef) invertVertLookup ? DT_OFFMESH_CON_TRAVERSE_ON_POLY : DT_OFFMESH_CON_TRAVERSE_ON_VERT)) return DT_FAILURE | DT_OUT_OF_MEMORY; } + + // Off-mesh links have been established, break out entirely. + breakOut = true; + break; } + + if (breakOut) + break; } + + if (breakOut) + break; } } @@ -701,48 +729,6 @@ void dtNavMesh::connectIntLinks(dtMeshTile* tile) } } -dtStatus dtNavMesh::baseOffMeshLinks(const dtTileRef tileRef) -{ - const int tileIndex = (int)decodePolyIdTile((dtPolyRef)tileRef); - if (tileIndex >= m_maxTiles) - return DT_FAILURE | DT_OUT_OF_MEMORY; - - dtMeshTile* tile = &m_tiles[tileIndex]; - const dtMeshHeader* header = tile->header; - - dtPolyRef base = getPolyRefBase(tile); - - for (int i = 0; i < header->offMeshConCount; ++i) - { - // Base off-mesh connection start points. - dtOffMeshConnection* con = &tile->offMeshCons[i]; - dtPoly* conPoly = &tile->polys[con->poly]; - - const dtPolyRef basePolyRef = clampOffMeshVertToPoly(con, tile, tile, true); - - if (!basePolyRef) - continue; - - const unsigned char traverseType = con->getTraverseType(); - const bool invertVertLookup = con->getVertLookupOrder(); - - // Link off-mesh connection to target poly. - if (!connectOffMeshLink(tile, conPoly, basePolyRef, 0xff, 0, DT_NULL_TRAVERSE_TYPE, 0)) - return DT_FAILURE | DT_OUT_OF_MEMORY; - - // Start end-point is always connect back to off-mesh connection. - const unsigned short basePolyIdx = (unsigned short)decodePolyIdPoly(basePolyRef); - dtPoly* basePoly = &tile->polys[basePolyIdx]; - - const dtPolyRef conPolyRef = base | (dtPolyRef)(con->poly); - if (!connectOffMeshLink(tile, basePoly, conPolyRef, 0xff, 0xff, traverseType, - invertVertLookup ? DT_OFFMESH_CON_TRAVERSE_ON_VERT : DT_OFFMESH_CON_TRAVERSE_ON_POLY)) - return DT_FAILURE | DT_OUT_OF_MEMORY; - } - - return DT_SUCCESS; -} - dtStatus dtNavMesh::connectTraverseLinks(const dtTileRef tileRef, const dtTraverseLinkConnectParams& params) { const int tileIndex = (int)decodePolyIdTile((dtPolyRef)tileRef);