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.
This commit is contained in:
Kawe Mazidjatari 2024-11-03 15:33:44 +01:00
parent d0a8549dc9
commit 3e7c7cb7da
3 changed files with 9 additions and 36 deletions

View File

@ -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;

View File

@ -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)]

View File

@ -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);
}