mirror of
https://github.com/Mauler125/r5sdk.git
synced 2025-02-09 19:15:03 +01:00
Recast: fix bugs causing mesh links to leak when removing and readding tiles
Rework the way traverse links are tracked and how the traverse table gets recreated when a tile gets removed/added. We would rebuild the entire traverse network and thus leak links since we also cleared the map that tracks the connections.
This commit is contained in:
parent
794f619d84
commit
d81f6a24aa
@ -783,6 +783,8 @@ void Editor::connectTileTraverseLinks(dtMeshTile* const baseTile, const bool lin
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
const dtMeshHeader* baseHeader = baseTile->header;
|
const dtMeshHeader* baseHeader = baseTile->header;
|
||||||
|
const dtPolyRef basePolyRefBase = m_navMesh->getPolyRefBase(baseTile);
|
||||||
|
|
||||||
bool firstBaseTileLinkUsed = false;
|
bool firstBaseTileLinkUsed = false;
|
||||||
|
|
||||||
for (int i = 0; i < baseHeader->polyCount; ++i)
|
for (int i = 0; i < baseHeader->polyCount; ++i)
|
||||||
@ -847,6 +849,8 @@ void Editor::connectTileTraverseLinks(dtMeshTile* const baseTile, const bool lin
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
const dtMeshHeader* landHeader = landTile->header;
|
const dtMeshHeader* landHeader = landTile->header;
|
||||||
|
const dtPolyRef landPolyRefBase = m_navMesh->getPolyRefBase(landTile);
|
||||||
|
|
||||||
bool firstLandTileLinkUsed = false;
|
bool firstLandTileLinkUsed = false;
|
||||||
|
|
||||||
for (int l = 0; l < landHeader->polyCount; ++l)
|
for (int l = 0; l < landHeader->polyCount; ++l)
|
||||||
@ -942,7 +946,10 @@ void Editor::connectTileTraverseLinks(dtMeshTile* const baseTile, const bool lin
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
const TraverseLinkPolyPair linkedPolyPair(basePoly, landPoly);
|
const dtPolyRef basePolyRef = basePolyRefBase | i;
|
||||||
|
const dtPolyRef landPolyRef = landPolyRefBase | l;
|
||||||
|
|
||||||
|
const TraverseLinkPolyPair linkedPolyPair(basePolyRef, landPolyRef);
|
||||||
auto linkedIt = m_traverseLinkPolyMap.find(linkedPolyPair);
|
auto linkedIt = m_traverseLinkPolyMap.find(linkedPolyPair);
|
||||||
|
|
||||||
bool traverseLinkFound = false;
|
bool traverseLinkFound = false;
|
||||||
@ -992,7 +999,7 @@ void Editor::connectTileTraverseLinks(dtMeshTile* const baseTile, const bool lin
|
|||||||
|
|
||||||
dtLink* const forwardLink = &baseTile->links[forwardIdx];
|
dtLink* const forwardLink = &baseTile->links[forwardIdx];
|
||||||
|
|
||||||
forwardLink->ref = m_navMesh->getPolyRefBase(landTile) | (dtPolyRef)l;
|
forwardLink->ref = landPolyRef;
|
||||||
forwardLink->edge = (unsigned char)j;
|
forwardLink->edge = (unsigned char)j;
|
||||||
forwardLink->side = landSide;
|
forwardLink->side = landSide;
|
||||||
forwardLink->bmin = 0;
|
forwardLink->bmin = 0;
|
||||||
@ -1005,7 +1012,7 @@ void Editor::connectTileTraverseLinks(dtMeshTile* const baseTile, const bool lin
|
|||||||
|
|
||||||
dtLink* const reverseLink = &landTile->links[reverseIdx];
|
dtLink* const reverseLink = &landTile->links[reverseIdx];
|
||||||
|
|
||||||
reverseLink->ref = m_navMesh->getPolyRefBase(baseTile) | (dtPolyRef)i;
|
reverseLink->ref = basePolyRef;
|
||||||
reverseLink->edge = (unsigned char)m;
|
reverseLink->edge = (unsigned char)m;
|
||||||
reverseLink->side = baseSide;
|
reverseLink->side = baseSide;
|
||||||
reverseLink->bmin = 0;
|
reverseLink->bmin = 0;
|
||||||
@ -1030,6 +1037,8 @@ void Editor::connectTileTraverseLinks(dtMeshTile* const baseTile, const bool lin
|
|||||||
bool Editor::createTraverseLinks()
|
bool Editor::createTraverseLinks()
|
||||||
{
|
{
|
||||||
rdAssert(m_navMesh);
|
rdAssert(m_navMesh);
|
||||||
|
m_traverseLinkPolyMap.clear();
|
||||||
|
|
||||||
const int maxTiles = m_navMesh->getMaxTiles();
|
const int maxTiles = m_navMesh->getMaxTiles();
|
||||||
|
|
||||||
// First pass to connect edges between external tiles together.
|
// First pass to connect edges between external tiles together.
|
||||||
@ -1052,7 +1061,6 @@ bool Editor::createTraverseLinks()
|
|||||||
connectTileTraverseLinks(baseTile, false);
|
connectTileTraverseLinks(baseTile, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_traverseLinkPolyMap.clear();
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -243,8 +243,6 @@ public:
|
|||||||
m_editor->removeTile(m_hitPos);
|
m_editor->removeTile(m_hitPos);
|
||||||
else
|
else
|
||||||
m_editor->buildTile(m_hitPos);
|
m_editor->buildTile(m_hitPos);
|
||||||
|
|
||||||
m_editor->buildStaticPathingData();
|
|
||||||
}
|
}
|
||||||
else if (m_cursorMode == TT_CURSOR_MODE_DEBUG)
|
else if (m_cursorMode == TT_CURSOR_MODE_DEBUG)
|
||||||
{
|
{
|
||||||
@ -727,6 +725,18 @@ void Editor_TileMesh::buildTile(const float* pos)
|
|||||||
m_navMesh->connectExtOffMeshLinks(targetRef);
|
m_navMesh->connectExtOffMeshLinks(targetRef);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dtMeshTile* tile = (dtMeshTile*)m_navMesh->getTileByRef(tileRef);
|
||||||
|
|
||||||
|
// Reconnect the traverse links.
|
||||||
|
connectTileTraverseLinks(tile, true);
|
||||||
|
connectTileTraverseLinks(tile, false);
|
||||||
|
|
||||||
|
dtTraverseTableCreateParams params;
|
||||||
|
createTraverseTableParams(¶ms);
|
||||||
|
|
||||||
|
dtCreateDisjointPolyGroups(¶ms);
|
||||||
|
updateStaticPathingData(¶ms);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -768,7 +778,34 @@ void Editor_TileMesh::removeTile(const float* pos)
|
|||||||
getTileExtents(tx, ty, m_lastBuiltTileBmin, m_lastBuiltTileBmax);
|
getTileExtents(tx, ty, m_lastBuiltTileBmin, m_lastBuiltTileBmax);
|
||||||
|
|
||||||
m_tileCol = duRGBA(255,0,0,180);
|
m_tileCol = duRGBA(255,0,0,180);
|
||||||
m_navMesh->removeTile(m_navMesh->getTileRefAt(tx,ty,0),0,0);
|
const dtTileRef tileRef = m_navMesh->getTileRefAt(tx,ty, 0);
|
||||||
|
|
||||||
|
if (dtStatusSucceed(m_navMesh->removeTile(tileRef, 0, 0)))
|
||||||
|
{
|
||||||
|
// Update traverse link map so the next time we rebuild this
|
||||||
|
// tile, the polygon pairs will be marked as available.
|
||||||
|
const unsigned int tileId = m_navMesh->decodePolyIdTile(tileRef);
|
||||||
|
|
||||||
|
for (auto it = m_traverseLinkPolyMap.cbegin(); it != m_traverseLinkPolyMap.cend();)
|
||||||
|
{
|
||||||
|
const TraverseLinkPolyPair& pair = it->first;
|
||||||
|
|
||||||
|
if (m_navMesh->decodePolyIdTile(pair.poly1) == tileId ||
|
||||||
|
m_navMesh->decodePolyIdTile(pair.poly2) == tileId)
|
||||||
|
{
|
||||||
|
it = m_traverseLinkPolyMap.erase(it);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
|
||||||
|
dtTraverseTableCreateParams params;
|
||||||
|
createTraverseTableParams(¶ms);
|
||||||
|
|
||||||
|
dtCreateDisjointPolyGroups(¶ms);
|
||||||
|
updateStaticPathingData(¶ms);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Editor_TileMesh::buildAllTiles()
|
void Editor_TileMesh::buildAllTiles()
|
||||||
@ -837,6 +874,8 @@ void Editor_TileMesh::removeAllTiles()
|
|||||||
for (int y = 0; y < th; ++y)
|
for (int y = 0; y < th; ++y)
|
||||||
for (int x = 0; x < tw; ++x)
|
for (int x = 0; x < tw; ++x)
|
||||||
m_navMesh->removeTile(m_navMesh->getTileRefAt(x,y,0),0,0);
|
m_navMesh->removeTile(m_navMesh->getTileRefAt(x,y,0),0,0);
|
||||||
|
|
||||||
|
m_traverseLinkPolyMap.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Editor_TileMesh::buildAllHulls()
|
void Editor_TileMesh::buildAllHulls()
|
||||||
|
@ -194,7 +194,7 @@ enum EditorPolyFlags
|
|||||||
|
|
||||||
struct TraverseLinkPolyPair
|
struct TraverseLinkPolyPair
|
||||||
{
|
{
|
||||||
TraverseLinkPolyPair(const dtPoly* p1, const dtPoly* p2)
|
TraverseLinkPolyPair(dtPolyRef p1, dtPolyRef p2)
|
||||||
{
|
{
|
||||||
if (p1 > p2)
|
if (p1 > p2)
|
||||||
rdSwap(p1, p2);
|
rdSwap(p1, p2);
|
||||||
@ -213,8 +213,8 @@ struct TraverseLinkPolyPair
|
|||||||
return poly2 < other.poly2;
|
return poly2 < other.poly2;
|
||||||
}
|
}
|
||||||
|
|
||||||
const dtPoly* poly1;
|
dtPolyRef poly1;
|
||||||
const dtPoly* poly2;
|
dtPolyRef poly2;
|
||||||
};
|
};
|
||||||
|
|
||||||
class EditorDebugDraw : public DebugDrawGL
|
class EditorDebugDraw : public DebugDrawGL
|
||||||
|
@ -316,6 +316,15 @@ bool dtCreateDisjointPolyGroups(const dtTraverseTableCreateParams* params)
|
|||||||
while (plink != DT_NULL_LINK)
|
while (plink != DT_NULL_LINK)
|
||||||
{
|
{
|
||||||
const dtLink l = tile->links[plink];
|
const dtLink l = tile->links[plink];
|
||||||
|
|
||||||
|
// Polygons linked with traverse links are not necessarily on
|
||||||
|
// the same group, these should be skipped.
|
||||||
|
if (l.traverseType != DT_NULL_TRAVERSE_TYPE)
|
||||||
|
{
|
||||||
|
plink = l.next;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
const dtMeshTile* t;
|
const dtMeshTile* t;
|
||||||
const dtPoly* p;
|
const dtPoly* p;
|
||||||
nav->getTileAndPolyByRefUnsafe(l.ref, &t, &p);
|
nav->getTileAndPolyByRefUnsafe(l.ref, &t, &p);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user