diff --git a/src/naveditor/Editor.cpp b/src/naveditor/Editor.cpp index ed1c3f3b..82dd0f4d 100644 --- a/src/naveditor/Editor.cpp +++ b/src/naveditor/Editor.cpp @@ -353,6 +353,12 @@ void Editor::handleUpdate(const float dt) updateToolStates(dt); } +void Editor::buildTraverseLinks() +{ + if (!m_navMesh) return; + dtCreateTraverseLinks(m_navMesh); +} + void Editor::buildStaticPathingData() { if (!m_navMesh) return; diff --git a/src/naveditor/Editor_TileMesh.cpp b/src/naveditor/Editor_TileMesh.cpp index de0aeae7..7ecc3c83 100644 --- a/src/naveditor/Editor_TileMesh.cpp +++ b/src/naveditor/Editor_TileMesh.cpp @@ -145,6 +145,7 @@ public: else m_editor->buildTile(m_hitPos); + m_editor->buildTraverseLinks(); m_editor->buildStaticPathingData(); } } @@ -597,6 +598,7 @@ void Editor_TileMesh::buildAllTiles() } } + buildTraverseLinks(); buildStaticPathingData(); // Start the build process. diff --git a/src/naveditor/include/Editor.h b/src/naveditor/include/Editor.h index b3382d43..5b37546c 100644 --- a/src/naveditor/include/Editor.h +++ b/src/naveditor/include/Editor.h @@ -239,6 +239,7 @@ public: void resetCommonSettings(); void handleCommonSettings(); + void buildTraverseLinks(); void buildStaticPathingData(); private: diff --git a/src/thirdparty/recast/Detour/Include/DetourNavMesh.h b/src/thirdparty/recast/Detour/Include/DetourNavMesh.h index 30537110..fce9cdce 100644 --- a/src/thirdparty/recast/Detour/Include/DetourNavMesh.h +++ b/src/thirdparty/recast/Detour/Include/DetourNavMesh.h @@ -415,6 +415,10 @@ struct dtMeshHeader /// @ingroup detour struct dtMeshTile { +public: + unsigned int allocLink(); + void freeLink(unsigned int link); + unsigned int salt; ///Counter describing modifications to the tile. unsigned int linksFreeList; ///Index to the next free link. diff --git a/src/thirdparty/recast/Detour/Include/DetourNavMeshBuilder.h b/src/thirdparty/recast/Detour/Include/DetourNavMeshBuilder.h index a691feb2..6d945cfd 100644 --- a/src/thirdparty/recast/Detour/Include/DetourNavMeshBuilder.h +++ b/src/thirdparty/recast/Detour/Include/DetourNavMeshBuilder.h @@ -182,6 +182,12 @@ private: /// @return True if the disjoint set data was successfully created. 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. /// @ingroup detour /// @param[in] nav The navigation mesh to use. diff --git a/src/thirdparty/recast/Detour/Source/DetourNavMesh.cpp b/src/thirdparty/recast/Detour/Source/DetourNavMesh.cpp index b86cdce1..35084596 100644 --- a/src/thirdparty/recast/Detour/Source/DetourNavMesh.cpp +++ b/src/thirdparty/recast/Detour/Source/DetourNavMesh.cpp @@ -115,19 +115,19 @@ inline int computeTileHash(int x, int y, const int 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; - unsigned int link = tile->linksFreeList; - tile->linksFreeList = tile->links[link].next; + unsigned int link = linksFreeList; + linksFreeList = links[link].next; return link; } -inline void freeLink(dtMeshTile* tile, unsigned int link) +void dtMeshTile::freeLink(unsigned int link) { - tile->links[link].next = tile->linksFreeList; - tile->linksFreeList = link; + links[link].next = linksFreeList; + linksFreeList = link; } int dtCalcTraversalTableCellIndex(const int numPolyGroups, @@ -409,7 +409,7 @@ void dtNavMesh::unconnectLinks(dtMeshTile* tile, dtMeshTile* target) poly->firstLink = nj; else tile->links[pj].next = nj; - freeLink(tile, j); + tile->freeLink(j); j = nj; } 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); for (int k = 0; k < nnei; ++k) { - unsigned int idx = allocLink(tile); + unsigned int idx = tile->allocLink(); if (idx != DT_NULL_LINK) { dtLink* link = &tile->links[idx]; @@ -528,7 +528,7 @@ void dtNavMesh::connectExtOffMeshLinks(dtMeshTile* tile, dtMeshTile* target, int rdVcopy(v, nearestPt); // Link off-mesh connection to target poly. - unsigned int idx = allocLink(target); + unsigned int idx = target->allocLink(); dtLink* link = nullptr; if (idx != DT_NULL_LINK) { @@ -550,7 +550,7 @@ void dtNavMesh::connectExtOffMeshLinks(dtMeshTile* tile, dtMeshTile* target, int dtLink* tlink = nullptr; if (targetCon->flags & DT_OFFMESH_CON_BIDIR) { - tidx = allocLink(tile); + tidx = tile->allocLink(); if (tidx != DT_NULL_LINK) { const unsigned short landPolyIdx = (unsigned short)decodePolyIdPoly(ref); @@ -611,7 +611,7 @@ void dtNavMesh::connectIntLinks(dtMeshTile* tile) // Skip hard and non-internal edges. 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) { dtLink* link = &tile->links[idx]; @@ -657,7 +657,7 @@ void dtNavMesh::baseOffMeshLinks(dtMeshTile* tile) rdVcopy(v, nearestPt); // Link off-mesh connection to target poly. - unsigned int idx = allocLink(tile); + unsigned int idx = tile->allocLink(); if (idx != DT_NULL_LINK) { 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. - unsigned int tidx = allocLink(tile); + unsigned int tidx = tile->allocLink(); if (tidx != DT_NULL_LINK) { const unsigned short landPolyIdx = (unsigned short)decodePolyIdPoly(ref); diff --git a/src/thirdparty/recast/Detour/Source/DetourNavMeshBuilder.cpp b/src/thirdparty/recast/Detour/Source/DetourNavMeshBuilder.cpp index 9c7f4b0d..4d18b8b4 100644 --- a/src/thirdparty/recast/Detour/Source/DetourNavMeshBuilder.cpp +++ b/src/thirdparty/recast/Detour/Source/DetourNavMeshBuilder.cpp @@ -461,6 +461,103 @@ bool dtCreateDisjointPolyGroups(dtNavMesh* nav, dtDisjointSet& disjoint) 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' bool dtCreateTraversalTableData(dtNavMesh* nav, const dtDisjointSet& disjoint, const int tableCount) { @@ -876,18 +973,6 @@ bool dtCreateNavMeshData(dtNavMeshCreateParams* params, unsigned char** outData, 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 // Mesh polys @@ -1040,9 +1125,21 @@ bool dtCreateNavMeshData(dtNavMeshCreateParams* params, unsigned char** outData, 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); - + *outData = data; *outDataSize = dataSize;