mirror of
https://github.com/Mauler125/r5sdk.git
synced 2025-02-09 19:15:03 +01:00
Recast: initial working implementation of traverse link generation algorithm
Traversing now works in-game, but there's still work needed to polish the algorithm and creating a proper lookup for jump types as currently only 1 jump type is supported.
This commit is contained in:
parent
c12690b33c
commit
acaf4cf32b
@ -353,6 +353,12 @@ void Editor::handleUpdate(const float dt)
|
|||||||
updateToolStates(dt);
|
updateToolStates(dt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Editor::buildTraverseLinks()
|
||||||
|
{
|
||||||
|
if (!m_navMesh) return;
|
||||||
|
dtCreateTraverseLinks(m_navMesh);
|
||||||
|
}
|
||||||
|
|
||||||
void Editor::buildStaticPathingData()
|
void Editor::buildStaticPathingData()
|
||||||
{
|
{
|
||||||
if (!m_navMesh) return;
|
if (!m_navMesh) return;
|
||||||
|
@ -145,6 +145,7 @@ public:
|
|||||||
else
|
else
|
||||||
m_editor->buildTile(m_hitPos);
|
m_editor->buildTile(m_hitPos);
|
||||||
|
|
||||||
|
m_editor->buildTraverseLinks();
|
||||||
m_editor->buildStaticPathingData();
|
m_editor->buildStaticPathingData();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -597,6 +598,7 @@ void Editor_TileMesh::buildAllTiles()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
buildTraverseLinks();
|
||||||
buildStaticPathingData();
|
buildStaticPathingData();
|
||||||
|
|
||||||
// Start the build process.
|
// Start the build process.
|
||||||
|
@ -239,6 +239,7 @@ public:
|
|||||||
void resetCommonSettings();
|
void resetCommonSettings();
|
||||||
void handleCommonSettings();
|
void handleCommonSettings();
|
||||||
|
|
||||||
|
void buildTraverseLinks();
|
||||||
void buildStaticPathingData();
|
void buildStaticPathingData();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -415,6 +415,10 @@ struct dtMeshHeader
|
|||||||
/// @ingroup detour
|
/// @ingroup detour
|
||||||
struct dtMeshTile
|
struct dtMeshTile
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
|
unsigned int allocLink();
|
||||||
|
void freeLink(unsigned int link);
|
||||||
|
|
||||||
unsigned int salt; ///Counter describing modifications to the tile.
|
unsigned int salt; ///Counter describing modifications to the tile.
|
||||||
|
|
||||||
unsigned int linksFreeList; ///Index to the next free link.
|
unsigned int linksFreeList; ///Index to the next free link.
|
||||||
|
@ -182,6 +182,12 @@ private:
|
|||||||
/// @return True if the disjoint set data was successfully created.
|
/// @return True if the disjoint set data was successfully created.
|
||||||
bool dtCreateDisjointPolyGroups(dtNavMesh* nav, dtDisjointSet& disjoint);
|
bool dtCreateDisjointPolyGroups(dtNavMesh* nav, dtDisjointSet& disjoint);
|
||||||
|
|
||||||
|
/// Builds navigation mesh traverse links from the provided navmesh.
|
||||||
|
/// @ingroup detour
|
||||||
|
/// @param[in] nav The navigation mesh to use.
|
||||||
|
/// @return True if the traverse links were successfully created.
|
||||||
|
bool dtCreateTraverseLinks(dtNavMesh* nav);
|
||||||
|
|
||||||
/// Builds navigation mesh static traversal table from the provided navmesh.
|
/// Builds navigation mesh static traversal table from the provided navmesh.
|
||||||
/// @ingroup detour
|
/// @ingroup detour
|
||||||
/// @param[in] nav The navigation mesh to use.
|
/// @param[in] nav The navigation mesh to use.
|
||||||
|
@ -115,19 +115,19 @@ inline int computeTileHash(int x, int y, const int mask)
|
|||||||
return (int)(n & mask);
|
return (int)(n & mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline unsigned int allocLink(dtMeshTile* tile)
|
unsigned int dtMeshTile::allocLink()
|
||||||
{
|
{
|
||||||
if (tile->linksFreeList == DT_NULL_LINK)
|
if (linksFreeList == DT_NULL_LINK)
|
||||||
return DT_NULL_LINK;
|
return DT_NULL_LINK;
|
||||||
unsigned int link = tile->linksFreeList;
|
unsigned int link = linksFreeList;
|
||||||
tile->linksFreeList = tile->links[link].next;
|
linksFreeList = links[link].next;
|
||||||
return link;
|
return link;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void freeLink(dtMeshTile* tile, unsigned int link)
|
void dtMeshTile::freeLink(unsigned int link)
|
||||||
{
|
{
|
||||||
tile->links[link].next = tile->linksFreeList;
|
links[link].next = linksFreeList;
|
||||||
tile->linksFreeList = link;
|
linksFreeList = link;
|
||||||
}
|
}
|
||||||
|
|
||||||
int dtCalcTraversalTableCellIndex(const int numPolyGroups,
|
int dtCalcTraversalTableCellIndex(const int numPolyGroups,
|
||||||
@ -409,7 +409,7 @@ void dtNavMesh::unconnectLinks(dtMeshTile* tile, dtMeshTile* target)
|
|||||||
poly->firstLink = nj;
|
poly->firstLink = nj;
|
||||||
else
|
else
|
||||||
tile->links[pj].next = nj;
|
tile->links[pj].next = nj;
|
||||||
freeLink(tile, j);
|
tile->freeLink(j);
|
||||||
j = nj;
|
j = nj;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -453,7 +453,7 @@ void dtNavMesh::connectExtLinks(dtMeshTile* tile, dtMeshTile* target, int side)
|
|||||||
int nnei = findConnectingPolys(va,vb, target, rdOppositeTile(dir), nei,neia,4);
|
int nnei = findConnectingPolys(va,vb, target, rdOppositeTile(dir), nei,neia,4);
|
||||||
for (int k = 0; k < nnei; ++k)
|
for (int k = 0; k < nnei; ++k)
|
||||||
{
|
{
|
||||||
unsigned int idx = allocLink(tile);
|
unsigned int idx = tile->allocLink();
|
||||||
if (idx != DT_NULL_LINK)
|
if (idx != DT_NULL_LINK)
|
||||||
{
|
{
|
||||||
dtLink* link = &tile->links[idx];
|
dtLink* link = &tile->links[idx];
|
||||||
@ -528,7 +528,7 @@ void dtNavMesh::connectExtOffMeshLinks(dtMeshTile* tile, dtMeshTile* target, int
|
|||||||
rdVcopy(v, nearestPt);
|
rdVcopy(v, nearestPt);
|
||||||
|
|
||||||
// Link off-mesh connection to target poly.
|
// Link off-mesh connection to target poly.
|
||||||
unsigned int idx = allocLink(target);
|
unsigned int idx = target->allocLink();
|
||||||
dtLink* link = nullptr;
|
dtLink* link = nullptr;
|
||||||
if (idx != DT_NULL_LINK)
|
if (idx != DT_NULL_LINK)
|
||||||
{
|
{
|
||||||
@ -550,7 +550,7 @@ void dtNavMesh::connectExtOffMeshLinks(dtMeshTile* tile, dtMeshTile* target, int
|
|||||||
dtLink* tlink = nullptr;
|
dtLink* tlink = nullptr;
|
||||||
if (targetCon->flags & DT_OFFMESH_CON_BIDIR)
|
if (targetCon->flags & DT_OFFMESH_CON_BIDIR)
|
||||||
{
|
{
|
||||||
tidx = allocLink(tile);
|
tidx = tile->allocLink();
|
||||||
if (tidx != DT_NULL_LINK)
|
if (tidx != DT_NULL_LINK)
|
||||||
{
|
{
|
||||||
const unsigned short landPolyIdx = (unsigned short)decodePolyIdPoly(ref);
|
const unsigned short landPolyIdx = (unsigned short)decodePolyIdPoly(ref);
|
||||||
@ -611,7 +611,7 @@ void dtNavMesh::connectIntLinks(dtMeshTile* tile)
|
|||||||
// Skip hard and non-internal edges.
|
// Skip hard and non-internal edges.
|
||||||
if (poly->neis[j] == 0 || (poly->neis[j] & DT_EXT_LINK)) continue;
|
if (poly->neis[j] == 0 || (poly->neis[j] & DT_EXT_LINK)) continue;
|
||||||
|
|
||||||
unsigned int idx = allocLink(tile);
|
unsigned int idx = tile->allocLink();
|
||||||
if (idx != DT_NULL_LINK)
|
if (idx != DT_NULL_LINK)
|
||||||
{
|
{
|
||||||
dtLink* link = &tile->links[idx];
|
dtLink* link = &tile->links[idx];
|
||||||
@ -657,7 +657,7 @@ void dtNavMesh::baseOffMeshLinks(dtMeshTile* tile)
|
|||||||
rdVcopy(v, nearestPt);
|
rdVcopy(v, nearestPt);
|
||||||
|
|
||||||
// Link off-mesh connection to target poly.
|
// Link off-mesh connection to target poly.
|
||||||
unsigned int idx = allocLink(tile);
|
unsigned int idx = tile->allocLink();
|
||||||
if (idx != DT_NULL_LINK)
|
if (idx != DT_NULL_LINK)
|
||||||
{
|
{
|
||||||
dtLink* link = &tile->links[idx];
|
dtLink* link = &tile->links[idx];
|
||||||
@ -674,7 +674,7 @@ void dtNavMesh::baseOffMeshLinks(dtMeshTile* tile)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Start end-point is always connect back to off-mesh connection.
|
// Start end-point is always connect back to off-mesh connection.
|
||||||
unsigned int tidx = allocLink(tile);
|
unsigned int tidx = tile->allocLink();
|
||||||
if (tidx != DT_NULL_LINK)
|
if (tidx != DT_NULL_LINK)
|
||||||
{
|
{
|
||||||
const unsigned short landPolyIdx = (unsigned short)decodePolyIdPoly(ref);
|
const unsigned short landPolyIdx = (unsigned short)decodePolyIdPoly(ref);
|
||||||
|
@ -461,6 +461,103 @@ bool dtCreateDisjointPolyGroups(dtNavMesh* nav, dtDisjointSet& disjoint)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: create lookup table and look for distance + slope to determine the
|
||||||
|
// correct jumpType.
|
||||||
|
// TODO: make sure we don't generate duplicate pairs of jump types between
|
||||||
|
// 2 polygons.
|
||||||
|
static void connectTileTraverseLinks(dtNavMesh* const nav, dtMeshTile* const tile)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < tile->header->polyCount; ++i)
|
||||||
|
{
|
||||||
|
dtPoly* const startPoly = &tile->polys[i];
|
||||||
|
|
||||||
|
for (int j = 0; j < startPoly->vertCount; ++j)
|
||||||
|
{
|
||||||
|
// Hard edges only!
|
||||||
|
if (startPoly->neis[j] != 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Polygon 1 edge
|
||||||
|
const float* const startPolySpos = &tile->verts[startPoly->verts[j] * 3];
|
||||||
|
const float* const startPolyEpos = &tile->verts[startPoly->verts[(j + 1) % startPoly->vertCount] * 3];
|
||||||
|
|
||||||
|
for (int k = 0; k < tile->header->polyCount; ++k)
|
||||||
|
{
|
||||||
|
if (i == k) continue; // Skip self
|
||||||
|
|
||||||
|
dtPoly* const endPoly = &tile->polys[k];
|
||||||
|
|
||||||
|
for (int m = 0; m < endPoly->vertCount; ++m)
|
||||||
|
{
|
||||||
|
// Hard edges only!
|
||||||
|
if (endPoly->neis[m] != 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Polygon 2 edge
|
||||||
|
const float* const endPolySpos = &tile->verts[endPoly->verts[m] * 3];
|
||||||
|
const float* const endPolyEpos = &tile->verts[endPoly->verts[(m + 1) % endPoly->vertCount] * 3];
|
||||||
|
|
||||||
|
// TODO: calculate edge midpoint first !!!
|
||||||
|
const unsigned char dist1 = dtCalcLinkDistance(startPolySpos, endPolyEpos);
|
||||||
|
const unsigned char dist2 = dtCalcLinkDistance(startPolyEpos, endPolySpos);
|
||||||
|
|
||||||
|
// TODO: needs lookup table for distance !!!
|
||||||
|
if ((dist1 >= 10 && dist1 <= 30) && (dist2 >= 10 && dist2 <= 30))
|
||||||
|
{
|
||||||
|
const unsigned int idx = tile->allocLink();
|
||||||
|
|
||||||
|
if (idx == DT_NULL_LINK) // TODO: should move on to next tile.
|
||||||
|
continue;
|
||||||
|
|
||||||
|
dtLink* const forwardLink = &tile->links[idx];
|
||||||
|
|
||||||
|
forwardLink->ref = nav->getPolyRefBase(tile) | (unsigned int)k;
|
||||||
|
forwardLink->edge = (unsigned char)j;
|
||||||
|
forwardLink->side = 0xFF;
|
||||||
|
forwardLink->next = startPoly->firstLink;
|
||||||
|
startPoly->firstLink = idx;
|
||||||
|
forwardLink->traverseType = 1;
|
||||||
|
forwardLink->traverseDist = dist1;
|
||||||
|
|
||||||
|
const unsigned int tidx = tile->allocLink();
|
||||||
|
|
||||||
|
if (tidx == DT_NULL_LINK) // TODO: should move on to next tile.
|
||||||
|
continue;
|
||||||
|
|
||||||
|
dtLink* const reverseLink = &tile->links[tidx];
|
||||||
|
|
||||||
|
reverseLink->ref = nav->getPolyRefBase(tile) | (unsigned int)i;
|
||||||
|
reverseLink->edge = (unsigned char)m;
|
||||||
|
reverseLink->side = 0xFF;
|
||||||
|
reverseLink->next = endPoly->firstLink;
|
||||||
|
endPoly->firstLink = tidx;
|
||||||
|
reverseLink->traverseType = 1;
|
||||||
|
reverseLink->traverseDist = dist2;
|
||||||
|
|
||||||
|
forwardLink->reverseLink = (unsigned short)tidx;
|
||||||
|
reverseLink->reverseLink = (unsigned short)idx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool dtCreateTraverseLinks(dtNavMesh* nav)
|
||||||
|
{
|
||||||
|
rdAssert(nav);
|
||||||
|
|
||||||
|
for (int i = 0; i < nav->getMaxTiles(); i++)
|
||||||
|
{
|
||||||
|
dtMeshTile* tile = nav->getTile(i);
|
||||||
|
if (!tile->header) continue;
|
||||||
|
|
||||||
|
connectTileTraverseLinks(nav, tile);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// todo(amos): remove param 'tableCount' and make struct 'dtTraversalTableCreateParams'
|
// todo(amos): remove param 'tableCount' and make struct 'dtTraversalTableCreateParams'
|
||||||
bool dtCreateTraversalTableData(dtNavMesh* nav, const dtDisjointSet& disjoint, const int tableCount)
|
bool dtCreateTraversalTableData(dtNavMesh* nav, const dtDisjointSet& disjoint, const int tableCount)
|
||||||
{
|
{
|
||||||
@ -876,18 +973,6 @@ bool dtCreateNavMeshData(dtNavMeshCreateParams* params, unsigned char** outData,
|
|||||||
n++;
|
n++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if DT_NAVMESH_SET_VERSION >= 8
|
|
||||||
// Polygon cells.
|
|
||||||
for (int i = 0; i < (int)cellItems.size(); i++)
|
|
||||||
{
|
|
||||||
const CellItem& cellItem = cellItems[i];
|
|
||||||
dtCell& cell = navCells[i];
|
|
||||||
|
|
||||||
rdVcopy(cell.pos, cellItem.pos);
|
|
||||||
cell.polyIndex = cellItem.polyIndex;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Store polygons
|
// Store polygons
|
||||||
// Mesh polys
|
// Mesh polys
|
||||||
@ -1040,9 +1125,21 @@ bool dtCreateNavMeshData(dtNavMeshCreateParams* params, unsigned char** outData,
|
|||||||
n++;
|
n++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if DT_NAVMESH_SET_VERSION >= 8
|
||||||
|
// Polygon cells.
|
||||||
|
for (int i = 0; i < (int)cellItems.size(); i++)
|
||||||
|
{
|
||||||
|
const CellItem& cellItem = cellItems[i];
|
||||||
|
dtCell& cell = navCells[i];
|
||||||
|
|
||||||
|
rdVcopy(cell.pos, cellItem.pos);
|
||||||
|
cell.polyIndex = cellItem.polyIndex;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
rdFree(offMeshConClass);
|
rdFree(offMeshConClass);
|
||||||
|
|
||||||
*outData = data;
|
*outData = data;
|
||||||
*outDataSize = dataSize;
|
*outDataSize = dataSize;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user