From 248a652a1570af0a7b57f3544b09fcc1b61a9898 Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Sun, 13 Oct 2024 14:36:09 +0200 Subject: [PATCH] Recast: add option for collapsing linked polygon groups This is necessary for navmeshes with more than UINT16_MAX polygon islands. Building navmeshes for mp_rr_desertlands_64k_x_64k will hit this limit. --- src/naveditor/Editor.cpp | 4 ++ src/naveditor/include/Editor.h | 1 + .../Detour/Include/DetourNavMeshBuilder.h | 4 ++ .../Detour/Source/DetourNavMeshBuilder.cpp | 64 +++++++++++-------- 4 files changed, 48 insertions(+), 25 deletions(-) diff --git a/src/naveditor/Editor.cpp b/src/naveditor/Editor.cpp index 2e4941a2..60d5fcf9 100644 --- a/src/naveditor/Editor.cpp +++ b/src/naveditor/Editor.cpp @@ -131,6 +131,7 @@ Editor::Editor() : m_filterLedgeSpans(true), m_filterWalkableLowHeightSpans(true), m_traverseRayDynamicOffset(true), + m_collapseLinkedPolyGroups(true), m_buildBvTree(true), m_selectedNavMeshType(NAVMESH_SMALL), m_loadedNavMeshType(NAVMESH_SMALL), @@ -420,6 +421,8 @@ void Editor::handleCommonSettings() if (ImGui::CollapsingHeader("Traverse Table Fine Tuner")) renderTraverseTableFineTuners(); + ImGui::Checkbox("Collapse Linked Poly Groups", &m_collapseLinkedPolyGroups); + if (ImGui::Checkbox("Dynamic Traverse Ray Offset", &m_traverseRayDynamicOffset)) m_traverseLinkDrawParams.dynamicOffset = m_traverseRayDynamicOffset; @@ -827,6 +830,7 @@ void Editor::createTraverseTableParams(dtTraverseTableCreateParams* params) params->tableCount = NavMesh_GetTraverseTableCountForNavMeshType(m_selectedNavMeshType); params->navMeshType = m_selectedNavMeshType; params->canTraverse = animTypeSupportsTraverseLink; + params->collapseGroups = m_collapseLinkedPolyGroups; } void Editor::buildStaticPathingData() diff --git a/src/naveditor/include/Editor.h b/src/naveditor/include/Editor.h index 17e4b8ec..c7a02cc5 100644 --- a/src/naveditor/include/Editor.h +++ b/src/naveditor/include/Editor.h @@ -239,6 +239,7 @@ protected: bool m_filterLedgeSpans; bool m_filterWalkableLowHeightSpans; bool m_traverseRayDynamicOffset; + bool m_collapseLinkedPolyGroups; bool m_buildBvTree; int m_minTileBits; diff --git a/src/thirdparty/recast/Detour/Include/DetourNavMeshBuilder.h b/src/thirdparty/recast/Detour/Include/DetourNavMeshBuilder.h index 81908db6..c20bbbe9 100644 --- a/src/thirdparty/recast/Detour/Include/DetourNavMeshBuilder.h +++ b/src/thirdparty/recast/Detour/Include/DetourNavMeshBuilder.h @@ -207,6 +207,10 @@ struct dtTraverseTableCreateParams ///< The user installed callback which is used to determine if an animType /// can use this traverse link. bool (*canTraverse)(const dtTraverseTableCreateParams* params, const dtLink* link, const int tableIndex); + + ///< Collapses all unique linked poly groups into #DT_FIRST_USABLE_POLY_GROUP. + /// Must be set if there are more than UINT16_MAX polygon islands. + bool collapseGroups; }; /// Builds navigation mesh disjoint poly groups from the provided parameters. diff --git a/src/thirdparty/recast/Detour/Source/DetourNavMeshBuilder.cpp b/src/thirdparty/recast/Detour/Source/DetourNavMeshBuilder.cpp index 4fdd5f53..7ec3c262 100644 --- a/src/thirdparty/recast/Detour/Source/DetourNavMeshBuilder.cpp +++ b/src/thirdparty/recast/Detour/Source/DetourNavMeshBuilder.cpp @@ -298,6 +298,14 @@ bool dtCreateDisjointPolyGroups(const dtTraverseTableCreateParams* params) dtPoly& poly = tile->polys[j]; unsigned int plink = poly.firstLink; + if (params->collapseGroups) + { + if (plink != DT_NULL_LINK) + poly.groupId = DT_FIRST_USABLE_POLY_GROUP; + + continue; + } + // Off-mesh connections need their own ID's, skip the assignment // here since else we will be marking 2 (or more) poly islands // under the same group id. @@ -359,7 +367,10 @@ bool dtCreateDisjointPolyGroups(const dtTraverseTableCreateParams* params) dtPoly& poly = tile->polys[j]; if (poly.groupId != DT_UNLINKED_POLY_GROUP) { - const int id = set.find(poly.groupId); + const int id = params->collapseGroups + ? DT_FIRST_USABLE_POLY_GROUP + : set.find(poly.groupId); + poly.groupId = (unsigned short)id; } } @@ -437,35 +448,38 @@ bool dtUpdateDisjointPolyGroups(const dtTraverseTableCreateParams* params) tile->header->userId = 0; } - // Gather all unique polygroups and map them to a contiguous range. - std::map groupMap; - set.init(DT_FIRST_USABLE_POLY_GROUP); - - for (int i = 0; i < nav->getMaxTiles(); ++i) + if (!params->collapseGroups) { - 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++) + // Gather all unique polygroups and map them to a contiguous range. + std::map groupMap; + set.init(DT_FIRST_USABLE_POLY_GROUP); + + for (int i = 0; i < nav->getMaxTiles(); ++i) { - dtPoly& poly = tile->polys[j]; - unsigned short oldId = poly.groupId; - if (oldId != DT_UNLINKED_POLY_GROUP && groupMap.find(oldId) == groupMap.end()) - groupMap[oldId] = (unsigned short)set.insertNew(); + 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_UNLINKED_POLY_GROUP && groupMap.find(oldId) == groupMap.end()) + groupMap[oldId] = (unsigned short)set.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++) + // Fourth pass to apply the new mapping to all polys. + for (int i = 0; i < nav->getMaxTiles(); ++i) { - dtPoly& poly = tile->polys[j]; - if (poly.groupId != DT_UNLINKED_POLY_GROUP) - poly.groupId = groupMap[poly.groupId]; + 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_UNLINKED_POLY_GROUP) + poly.groupId = groupMap[poly.groupId]; + } } }