From 3e7c7cb7dad4d5c519d1c6b10b8800f74a375f0e Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Sun, 3 Nov 2024 15:33:44 +0100 Subject: [PATCH] Recast: fix incorrect base side classification rdClassifyDirection never got intercardinal sides causing it to be unreliable and inaccurate. rdClassifyPointInsideBounds and rdClassifyPointOutsideBounds are tested and confirmed correct during every case, switched use to rdClassifyPointInsideBounds instead and removed rdClassifyDirection for the start side of the neighbor tile lookup. For the links: the base side is always the opposite of the land side. --- .../recast/Detour/Source/DetourNavMesh.cpp | 18 ++++++------- .../recast/Shared/Include/SharedCommon.h | 1 - .../recast/Shared/Source/SharedCommon.cpp | 26 ------------------- 3 files changed, 9 insertions(+), 36 deletions(-) diff --git a/src/thirdparty/recast/Detour/Source/DetourNavMesh.cpp b/src/thirdparty/recast/Detour/Source/DetourNavMesh.cpp index 8bc16e56..0f080184 100644 --- a/src/thirdparty/recast/Detour/Source/DetourNavMesh.cpp +++ b/src/thirdparty/recast/Detour/Source/DetourNavMesh.cpp @@ -870,8 +870,10 @@ dtStatus dtNavMesh::connectTraverseLinks(const dtTileRef tileRef, const dtTraver float baseEdgeNorm[3]; rdCalcEdgeNormal2D(baseEdgeDir, baseEdgeNorm); + float basePolyEdgeMid[3]; + rdVsad(basePolyEdgeMid, baseDetailPolyEdgeSpos, baseDetailPolyEdgeEpos, 0.5f); - const unsigned char baseSide = rdClassifyDirection(baseEdgeDir, baseHeader->bmin, baseHeader->bmax); + const unsigned char startSide = rdClassifyPointInsideBounds(basePolyEdgeMid, baseHeader->bmin, baseHeader->bmax); const int MAX_NEIS = 32; // Max neighbors dtMeshTile* neis[MAX_NEIS]; @@ -882,7 +884,7 @@ dtStatus dtNavMesh::connectTraverseLinks(const dtTileRef tileRef, const dtTraver { // Start with the tile our edge is facing first, as this has the highest // chance for the best connection. - nneis = getNeighbourTilesAt(baseHeader->x, baseHeader->y, baseSide, neis, nneis); + nneis = getNeighbourTilesAt(baseHeader->x, baseHeader->y, startSide, neis, nneis); bool getOpposite = true; // Get the other tiles starting from the opposite of the base side in the @@ -891,11 +893,11 @@ dtStatus dtNavMesh::connectTraverseLinks(const dtTileRef tileRef, const dtTraver // of links on the base tile. for (int n = 1; n < 8; ++n, getOpposite ^= true) { - const int side = getOpposite - ? rdOppositeTile(baseSide+n) - : rdWrapTileSide(baseSide+n); + const unsigned char side = getOpposite + ? rdOppositeTile(startSide+n) + : rdWrapTileSide(startSide+n); - rdAssert(side != baseSide); + rdAssert(side != startSide); const int numSlotsLeft = MAX_NEIS-nneis; if (!numSlotsLeft) @@ -915,9 +917,6 @@ dtStatus dtNavMesh::connectTraverseLinks(const dtTileRef tileRef, const dtTraver neis[0] = baseTile; } - float basePolyEdgeMid[3]; - if (nneis) - rdVsad(basePolyEdgeMid, baseDetailPolyEdgeSpos, baseDetailPolyEdgeEpos, 0.5f); for (int n = nneis - 1; n >= 0; --n) { @@ -1066,6 +1065,7 @@ dtStatus dtNavMesh::connectTraverseLinks(const dtTileRef tileRef, const dtTraver const unsigned char landSide = params.linkToNeighbor ? rdClassifyPointOutsideBounds(landPolyEdgeMid, baseHeader->bmin, baseHeader->bmax) : rdClassifyPointInsideBounds(landPolyEdgeMid, landHeader->bmin, landHeader->bmax); + const unsigned char baseSide = rdOppositeTile(landSide); float newBaseTmin; float newBaseTmax; diff --git a/src/thirdparty/recast/Shared/Include/SharedCommon.h b/src/thirdparty/recast/Shared/Include/SharedCommon.h index 70b01878..0f5316c6 100644 --- a/src/thirdparty/recast/Shared/Include/SharedCommon.h +++ b/src/thirdparty/recast/Shared/Include/SharedCommon.h @@ -542,7 +542,6 @@ float rdCalcLedgeSpanOffsetAmount(const float ledgeSpan, const float slopeAngle, unsigned char rdClassifyPointOutsideBounds(const float* pt, const float* bmin, const float* bmax); unsigned char rdClassifyPointInsideBounds(const float* pt, const float* bmin, const float* bmax); -unsigned char rdClassifyDirection(const float* dir, const float* bmin, const float* bmax); /// Determines if the specified point is inside the axis-aligned bounding box. /// @param[in] pt The point to check. [(x, y, z)] diff --git a/src/thirdparty/recast/Shared/Source/SharedCommon.cpp b/src/thirdparty/recast/Shared/Source/SharedCommon.cpp index 196cd201..f2fed543 100644 --- a/src/thirdparty/recast/Shared/Source/SharedCommon.cpp +++ b/src/thirdparty/recast/Shared/Source/SharedCommon.cpp @@ -713,29 +713,3 @@ unsigned char rdClassifyPointInsideBounds(const float* pt, const float* bmin, co return rdClassifyPointOutsideBounds(newPt, bmin, bmax); } - -unsigned char rdClassifyDirection(const float* dir, const float* bmin, const float* bmax) -{ - const float len = rdMathSqrtf(dir[0]*dir[0] + dir[1]*dir[1]); - float dirNorm[2] = { 0.0f, 0.0f }; - - if (len > RD_EPS) - { - dirNorm[0] = dir[0] / len; - dirNorm[1] = dir[1] / len; - } - - float center[2]; - center[0] = (bmin[0]+bmax[0]) * 0.5f; - center[1] = (bmin[1]+bmax[1]) * 0.5f; - - float boxSize[2]; - boxSize[0] = bmax[0]-bmin[0]; - boxSize[1] = bmax[1]-bmin[1]; - - float newPt[2]; - newPt[0] = center[0]+dirNorm[0] * boxSize[0]; - newPt[1] = center[1]+dirNorm[1] * boxSize[1]; - - return rdClassifyPointOutsideBounds(newPt, bmin, bmax); -}