mirror of
https://github.com/Mauler125/r5sdk.git
synced 2025-02-09 19:15:03 +01:00
Recast: do not connect adjacent polygons with traverse links
Connecting adjacent polygons with traverse links will cause pathfinding to run into itself infinitely if either of the 2 poly's first link references the polygon from which the traverse link originates from. The behavior in-game is that the AI become stuck in the area with error code FAIL_NO_ROUTE_BLOCKED. Implemented the method 'dtNavMesh::arePolysAdjacent' to make sure we never connect adjacent polygons on our own or neighboring tile with a traverse link.
This commit is contained in:
parent
e7240e5551
commit
582ecec038
@ -820,7 +820,22 @@ public:
|
||||
/// @param[out] poly The polygon.
|
||||
void getTileAndPolyByRefUnsafe(const dtPolyRef ref, const dtMeshTile** tile, const dtPoly** poly) const;
|
||||
|
||||
/// Returns whether goal poly is reachable from start poly
|
||||
/// Returns whether both polygons are adjacent by a shared edge.
|
||||
/// @param[in] baseRef The reference to the first poly.
|
||||
/// @param[in] landRef The reference to the second poly.
|
||||
/// @return True if both polygons are adjacent by a shared edge.
|
||||
bool arePolysAdjacent(const dtPolyRef baseRef, const dtPolyRef landRef) const;
|
||||
|
||||
/// Returns whether both polygons are adjacent by a shared edge.
|
||||
/// @param[in] basePoly The first poly.
|
||||
/// @param[in] baseTile The first tile.
|
||||
/// @param[in] landPoly The second poly.
|
||||
/// @param[in] landTile The second tile.
|
||||
/// @return True if both polygons are adjacent by a shared edge.
|
||||
bool arePolysAdjacent(const dtPoly* const basePoly, const dtMeshTile* baseTile,
|
||||
const dtPoly* const landPoly, const dtMeshTile* landTile) const;
|
||||
|
||||
/// Returns whether goal poly is reachable from start poly.
|
||||
/// @param[in] fromRef The reference to the start poly.
|
||||
/// @param[in] goalRef The reference to the goal poly.
|
||||
/// @param[in] checkDisjointGroupsOnly Whether to only check disjoint poly groups.
|
||||
|
@ -889,6 +889,12 @@ dtStatus dtNavMesh::connectTraverseLinks(const dtTileRef tileRef, const dtTraver
|
||||
if (landPoly->getType() == DT_POLYTYPE_OFFMESH_CONNECTION)
|
||||
continue;
|
||||
|
||||
// If both polygons are sharing an edge, we should not establish the link as
|
||||
// it will cause pathfinding to fail in this area when both polygons have
|
||||
// their first link set to another; the path will never exit these polygons.
|
||||
if (arePolysAdjacent(basePoly, baseTile, landPoly, landTile))
|
||||
continue;
|
||||
|
||||
dtPolyDetail* const landDetail = &landTile->detailMeshes[o];
|
||||
|
||||
for (int p = 0; (p < landPoly->vertCount) && !moveToNextTile; ++p)
|
||||
@ -1673,8 +1679,66 @@ void dtNavMesh::getTileAndPolyByRefUnsafe(const dtPolyRef ref, const dtMeshTile*
|
||||
*poly = &m_tiles[it].polys[ip];
|
||||
}
|
||||
|
||||
bool dtNavMesh::arePolysAdjacent(const dtPolyRef fromRef, const dtPolyRef goalRef) const
|
||||
{
|
||||
const dtMeshTile* fromTile = nullptr;
|
||||
const dtMeshTile* goalTile = nullptr;
|
||||
const dtPoly* fromPoly = nullptr;
|
||||
const dtPoly* goalPoly = nullptr;
|
||||
|
||||
getTileAndPolyByRefUnsafe(fromRef, &fromTile, &fromPoly);
|
||||
getTileAndPolyByRefUnsafe(goalRef, &goalTile, &goalPoly);
|
||||
|
||||
return arePolysAdjacent(fromPoly, fromTile, goalPoly, goalTile);
|
||||
}
|
||||
|
||||
bool dtNavMesh::arePolysAdjacent(const dtPoly* const basePoly, const dtMeshTile* baseTile,
|
||||
const dtPoly* const landPoly, const dtMeshTile* landTile) const
|
||||
{
|
||||
if (baseTile == landTile)
|
||||
{
|
||||
for (int i = 0; i < landPoly->vertCount; ++i)
|
||||
{
|
||||
const unsigned short nei = landPoly->neis[i];
|
||||
|
||||
if (!nei)
|
||||
continue;
|
||||
|
||||
if (nei & DT_EXT_LINK)
|
||||
continue;
|
||||
|
||||
const int idx = (nei-1);
|
||||
|
||||
if (&baseTile->polys[idx] == basePoly)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else // Check external linkage.
|
||||
{
|
||||
unsigned int linkIndex = landPoly->firstLink;
|
||||
while (linkIndex != DT_NULL_LINK)
|
||||
{
|
||||
const dtLink* const link = &landTile->links[linkIndex];
|
||||
|
||||
if (link->side != 0xff && link->traverseType == DT_NULL_TRAVERSE_TYPE)
|
||||
{
|
||||
const dtMeshTile* neiTile;
|
||||
const dtPoly* neiPoly;
|
||||
getTileAndPolyByRefUnsafe(link->ref, &neiTile, &neiPoly);
|
||||
|
||||
if (neiPoly == basePoly)
|
||||
return true;
|
||||
}
|
||||
|
||||
linkIndex = link->next;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool dtNavMesh::isGoalPolyReachable(const dtPolyRef fromRef, const dtPolyRef goalRef,
|
||||
const bool checkDisjointGroupsOnly, const int traverseTableIndex) const
|
||||
const bool checkDisjointGroupsOnly, const int traverseTableIndex) const
|
||||
{
|
||||
// Same poly is always reachable.
|
||||
if (fromRef == goalRef)
|
||||
|
Loading…
x
Reference in New Issue
Block a user