From 0a88d801a03cef1aaca0a09c9657f73a8dae755c Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Sun, 11 Aug 2024 12:54:48 +0200 Subject: [PATCH] Recast: separate disjoint set remap code from creation code We need to create the disjoint sets first, then build all traverse links, and finally from there determine all unlinked poly's and remap disjoint sets. Doing this prior to traverse link generation causes polygons that are only linked through traverse links to remain tagged as unlinked. --- src/naveditor/Editor.cpp | 5 + .../Detour/Include/DetourNavMeshBuilder.h | 7 ++ .../Detour/Source/DetourNavMeshBuilder.cpp | 98 +++++++++++-------- 3 files changed, 69 insertions(+), 41 deletions(-) diff --git a/src/naveditor/Editor.cpp b/src/naveditor/Editor.cpp index b49d61a2..2502455e 100644 --- a/src/naveditor/Editor.cpp +++ b/src/naveditor/Editor.cpp @@ -710,6 +710,11 @@ void Editor::buildStaticPathingData() m_ctx->log(RC_LOG_ERROR, "buildStaticPathingData: Failed to build traverse links."); } + if (!dtUpdateDisjointPolyGroups(m_navMesh, data)) + { + m_ctx->log(RC_LOG_ERROR, "buildStaticPathingData: Failed to update disjoint poly groups."); + } + if (!dtCreateTraverseTableData(m_navMesh, data, NavMesh_GetTraverseTableCountForNavMeshType(m_selectedNavMeshType))) { m_ctx->log(RC_LOG_ERROR, "buildStaticPathingData: Failed to build traverse table data."); diff --git a/src/thirdparty/recast/Detour/Include/DetourNavMeshBuilder.h b/src/thirdparty/recast/Detour/Include/DetourNavMeshBuilder.h index 5ab82f37..31b07d8f 100644 --- a/src/thirdparty/recast/Detour/Include/DetourNavMeshBuilder.h +++ b/src/thirdparty/recast/Detour/Include/DetourNavMeshBuilder.h @@ -182,6 +182,13 @@ private: /// @return True if the disjoint set data was successfully created. bool dtCreateDisjointPolyGroups(dtNavMesh* nav, dtDisjointSet& disjoint); +/// Updates navigation mesh disjoint poly groups from the provided navmesh. +/// @ingroup detour +/// @param[in] nav The navigation mesh to use. +/// @param[Out] disjoint The disjoint set data. +/// @return True if the disjoint set data was successfully updated. +bool dtUpdateDisjointPolyGroups(dtNavMesh* nav, dtDisjointSet& disjoint); + /// Builds navigation mesh static traverse table from the provided navmesh. /// @ingroup detour /// @param[in] nav The navigation mesh to use. diff --git a/src/thirdparty/recast/Detour/Source/DetourNavMeshBuilder.cpp b/src/thirdparty/recast/Detour/Source/DetourNavMeshBuilder.cpp index 4b578be2..404237d6 100644 --- a/src/thirdparty/recast/Detour/Source/DetourNavMeshBuilder.cpp +++ b/src/thirdparty/recast/Detour/Source/DetourNavMeshBuilder.cpp @@ -277,7 +277,7 @@ bool dtCreateDisjointPolyGroups(dtNavMesh* nav, dtDisjointSet& disjoint) } } - // First pass to group linked and unlinked poly islands. + // First pass to group poly islands. std::set linkedGroups; for (int i = 0; i < nav->getMaxTiles(); ++i) { @@ -315,14 +315,7 @@ bool dtCreateDisjointPolyGroups(dtNavMesh* nav, dtDisjointSet& disjoint) const bool noLinkedGroups = linkedGroups.empty(); if (noLinkedGroups) - { - // This poly isn't connected to anything, mark it so the game - // won't consider this poly in path generation. - if (poly.firstLink == DT_NULL_LINK) - poly.groupId = DT_STRAY_POLY_GROUP; - else - poly.groupId = (unsigned short)disjoint.insertNew(); - } + poly.groupId = (unsigned short)disjoint.insertNew(); else { const unsigned short rootGroup = *linkedGroups.begin(); @@ -354,38 +347,6 @@ bool dtCreateDisjointPolyGroups(dtNavMesh* nav, dtDisjointSet& disjoint) } } - // Gather all unique polygroups and map them to a contiguous range. - std::map groupMap; - disjoint.init(DT_FIRST_USABLE_POLY_GROUP); - - for (int i = 0; i < nav->getMaxTiles(); ++i) - { - dtMeshTile* tile = nav->getTile(i); - if (!tile || !tile->header || !tile->dataSize) continue; - const int pcount = tile->header->polyCount; - for (int j = 0; j < pcount; j++) - { - dtPoly& poly = tile->polys[j]; - unsigned short oldId = poly.groupId; - if (oldId != DT_STRAY_POLY_GROUP && groupMap.find(oldId) == groupMap.end()) - groupMap[oldId] = (unsigned short)disjoint.insertNew(); - } - } - - // Fourth pass to apply the new mapping to all polys. - for (int i = 0; i < nav->getMaxTiles(); ++i) - { - dtMeshTile* tile = nav->getTile(i); - if (!tile || !tile->header || !tile->dataSize) continue; - const int pcount = tile->header->polyCount; - for (int j = 0; j < pcount; j++) - { - dtPoly& poly = tile->polys[j]; - if (poly.groupId != DT_STRAY_POLY_GROUP) - poly.groupId = groupMap[poly.groupId]; - } - } - // Third pass to handle off-mesh connections. // note(amos): this has to happen after the first and second pass as these // are for grouping directly connected polygons together, else groups linked @@ -433,6 +394,61 @@ bool dtCreateDisjointPolyGroups(dtNavMesh* nav, dtDisjointSet& disjoint) return true; } +bool dtUpdateDisjointPolyGroups(dtNavMesh* nav, dtDisjointSet& disjoint) +{ + // Fourth pass to mark all unlinked poly's. + for (int i = 0; i < nav->getMaxTiles(); ++i) + { + dtMeshTile* tile = nav->getTile(i); + if (!tile || !tile->header || !tile->dataSize) continue; + const int pcount = tile->header->polyCount; + for (int j = 0; j < pcount; j++) + { + dtPoly& poly = tile->polys[j]; + + // This poly isn't connected to anything, mark it so the game + // won't consider this poly in path generation. + if (poly.firstLink == DT_NULL_LINK) + poly.groupId = DT_STRAY_POLY_GROUP; + } + } + + // Gather all unique polygroups and map them to a contiguous range. + std::map groupMap; + disjoint.init(DT_FIRST_USABLE_POLY_GROUP); + + for (int i = 0; i < nav->getMaxTiles(); ++i) + { + dtMeshTile* tile = nav->getTile(i); + if (!tile || !tile->header || !tile->dataSize) continue; + const int pcount = tile->header->polyCount; + for (int j = 0; j < pcount; j++) + { + dtPoly& poly = tile->polys[j]; + unsigned short oldId = poly.groupId; + if (oldId != DT_STRAY_POLY_GROUP && groupMap.find(oldId) == groupMap.end()) + groupMap[oldId] = (unsigned short)disjoint.insertNew(); + } + } + + // Apply the new mapping to all polys. + for (int i = 0; i < nav->getMaxTiles(); ++i) + { + dtMeshTile* tile = nav->getTile(i); + if (!tile || !tile->header || !tile->dataSize) continue; + const int pcount = tile->header->polyCount; + for (int j = 0; j < pcount; j++) + { + dtPoly& poly = tile->polys[j]; + if (poly.groupId != DT_STRAY_POLY_GROUP) + poly.groupId = groupMap[poly.groupId]; + } + } + + nav->setPolyGroupcount(disjoint.getSetCount()); + return true; +} + // todo(amos): remove param 'tableCount' and make struct 'dtTraverseTableCreateParams' bool dtCreateTraverseTableData(dtNavMesh* nav, const dtDisjointSet& disjoint, const int tableCount) {