From 12f39f1c4442ee804a988dfa6f2ab15cd6b4742b Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Thu, 18 Jul 2024 14:22:14 +0200 Subject: [PATCH] Recast: add traverse links debug drawing Originally taken from https://github.com/ASpoonPlaysGames/r2recast, slightly modified to use the new constants added in commit 78a632eec85ca5406adb03617084746b446b0044, and now renders white crosses if reverse links are set. --- src/naveditor/Editor.cpp | 15 +++- src/naveditor/Editor_Common.cpp | 2 +- src/naveditor/include/Editor.h | 3 +- .../DebugUtils/Include/DetourDebugDraw.h | 5 +- .../DebugUtils/Source/DetourDebugDraw.cpp | 74 +++++++++++++++++-- 5 files changed, 89 insertions(+), 10 deletions(-) diff --git a/src/naveditor/Editor.cpp b/src/naveditor/Editor.cpp index ca349007..39e3f799 100644 --- a/src/naveditor/Editor.cpp +++ b/src/naveditor/Editor.cpp @@ -72,7 +72,8 @@ Editor::Editor() : m_loadedNavMeshType(NAVMESH_SMALL), m_navmeshName(NavMesh_GetNameForType(NAVMESH_SMALL)), m_tool(0), - m_ctx(0) + m_ctx(0), + m_traverseLinkDrawTypes(-1) { resetCommonSettings(); m_navQuery = dtAllocNavMeshQuery(); @@ -500,6 +501,18 @@ void Editor::renderDetourDebugMenu() if (ImGui::Checkbox("Transparency", &isEnabled)) toggleNavMeshDrawFlag(DU_DRAWNAVMESH_ALPHA); + + isEnabled = (getNavMeshDrawFlags() & DU_DRAWNAVMESH_TRAVERSE_LINKS); + + if (ImGui::Checkbox("Traverse Links", &isEnabled)) + toggleNavMeshDrawFlag(DU_DRAWNAVMESH_TRAVERSE_LINKS); + + if (isEnabled) + { + ImGui::PushItemWidth(190); + ImGui::SliderInt("Traverse Type", &m_traverseLinkDrawTypes, -1, 31); + ImGui::PopItemWidth(); + } } // NOTE: the climb height should never equal or exceed the agent's height, see https://groups.google.com/g/recastnavigation/c/L5rBamxcOBk/m/5xGLj6YP25kJ diff --git a/src/naveditor/Editor_Common.cpp b/src/naveditor/Editor_Common.cpp index e8e65b27..4e1cf5d7 100644 --- a/src/naveditor/Editor_Common.cpp +++ b/src/naveditor/Editor_Common.cpp @@ -307,7 +307,7 @@ void Editor_StaticTileMeshCommon::renderTileMeshData() { if (m_tileMeshDrawFlags & TM_DRAWFLAGS_NAVMESH) { - duDebugDrawNavMeshWithClosedList(&m_dd, *m_navMesh, *m_navQuery, detourDrawOffset, m_navMeshDrawFlags); + duDebugDrawNavMeshWithClosedList(&m_dd, *m_navMesh, *m_navQuery, detourDrawOffset, m_navMeshDrawFlags, m_traverseLinkDrawTypes); duDebugDrawNavMeshPolysWithFlags(&m_dd, *m_navMesh, EDITOR_POLYFLAGS_DISABLED, detourDrawOffset, detourDrawFlags, duRGBA(0, 0, 0, 128)); } } diff --git a/src/naveditor/include/Editor.h b/src/naveditor/include/Editor.h index d2675bc3..1d664e6e 100644 --- a/src/naveditor/include/Editor.h +++ b/src/naveditor/include/Editor.h @@ -115,7 +115,6 @@ protected: class dtNavMeshQuery* m_navQuery; class dtCrowd* m_crowd; - unsigned int m_navMeshDrawFlags; bool m_filterLowHangingObstacles; bool m_filterLedgeSpans; bool m_filterWalkableLowHeightSpans; @@ -149,6 +148,8 @@ protected: BuildContext* m_ctx; EditorDebugDraw m_dd; + unsigned int m_navMeshDrawFlags; + int m_traverseLinkDrawTypes; float m_recastDrawOffset[3]; float m_detourDrawOffset[3]; diff --git a/src/thirdparty/recast/DebugUtils/Include/DetourDebugDraw.h b/src/thirdparty/recast/DebugUtils/Include/DetourDebugDraw.h index ce96f081..884c13bb 100644 --- a/src/thirdparty/recast/DebugUtils/Include/DetourDebugDraw.h +++ b/src/thirdparty/recast/DebugUtils/Include/DetourDebugDraw.h @@ -38,10 +38,11 @@ enum DrawNavMeshFlags DU_DRAWNAVMESH_POLYGROUPS = 1 << 10, // Render poly group by color. DU_DRAWNAVMESH_DEPTH_MASK = 1 << 11, // Use depth mask. DU_DRAWNAVMESH_ALPHA = 1 << 12, // Use transparency. + DU_DRAWNAVMESH_TRAVERSE_LINKS = 1 << 13, // Render traverse links. }; -void duDebugDrawNavMesh(struct duDebugDraw* dd, const dtNavMesh& mesh, const float* offset, unsigned int flags); -void duDebugDrawNavMeshWithClosedList(struct duDebugDraw* dd, const dtNavMesh& mesh, const dtNavMeshQuery& query, const float* offset, unsigned int flags); +void duDebugDrawNavMesh(struct duDebugDraw* dd, const dtNavMesh& mesh, const float* offset, unsigned int flags, const int linkTypes = -1); +void duDebugDrawNavMeshWithClosedList(struct duDebugDraw* dd, const dtNavMesh& mesh, const dtNavMeshQuery& query, const float* offset, unsigned int flags, const int linkTypes = -1); void duDebugDrawNavMeshNodes(struct duDebugDraw* dd, const dtNavMeshQuery& query, const float* offset); void duDebugDrawNavMeshBVTree(struct duDebugDraw* dd, const dtNavMesh& mesh, const float* offset); void duDebugDrawNavMeshPortals(struct duDebugDraw* dd, const dtNavMesh& mesh, const float* offset); diff --git a/src/thirdparty/recast/DebugUtils/Source/DetourDebugDraw.cpp b/src/thirdparty/recast/DebugUtils/Source/DetourDebugDraw.cpp index 50f1c48b..de962929 100644 --- a/src/thirdparty/recast/DebugUtils/Source/DetourDebugDraw.cpp +++ b/src/thirdparty/recast/DebugUtils/Source/DetourDebugDraw.cpp @@ -133,8 +133,69 @@ static void drawPolyCenters(duDebugDraw* dd, const dtMeshTile* tile, const unsig } } +static void drawTraverseLinks(duDebugDraw* dd, const dtNavMesh& mesh, const dtNavMeshQuery* query, + const dtMeshTile* tile, const float* offset, const int drawLinkType) +{ + for (int i = 0; i < tile->header->polyCount; ++i) + { + const dtPoly* startPoly = &tile->polys[i]; + + if (startPoly->getType() == DT_POLYTYPE_OFFMESH_CONNECTION) // Skip off-mesh links. + continue; + + // Iterate through links in the poly. + for (int j = startPoly->firstLink; j != -1; j = tile->links[j].next) + { + const dtLink* link = &tile->links[j]; + + // Skip "normal" links (non-jumping ones). + if (link->jumpType == DT_NULL_TRAVERSE_TYPE || tile->links[i].ref == 0) + continue; + + // Filter, drawLinkType -1 means draw all + if (drawLinkType != -1 && link->jumpType != drawLinkType) + continue; + + const dtPoly* endPoly; + const dtMeshTile* endTile; + + if (dtStatusFailed(mesh.getTileAndPolyByRef(link->ref, &endTile, &endPoly))) + continue; + + if (endPoly->getType() == DT_POLYTYPE_OFFMESH_CONNECTION) // Skip off-mesh links. + continue; + + float startPos[3]; + float endPos[3]; + + query->getEdgeMidPoint(mesh.getPolyRefBase(tile) | (dtPolyRef)i, link->ref, startPos); + query->getEdgeMidPoint(link->ref, mesh.getPolyRefBase(tile) | (dtPolyRef)i, endPos); + + // Unique color for each type. + const int col = duIntToCol(link->jumpType, 180); + + dd->begin(DU_DRAW_LINES, 2.0f, offset); + + dd->vertex(startPos, col); + dd->vertex(endPos, col); + + const bool hasReverseLink = link->reverseLinkIndex != DT_NULL_TRAVERSE_REVERSE_LINK; + + if (hasReverseLink) + { + // If the reverse link is set, render white crosses to confirm + // the links are set properly. + duAppendCross(dd, startPos[0], startPos[1], startPos[2], 10.f, duRGBA(255,255,255,180)); + duAppendCross(dd, endPos[0], endPos[1], endPos[2], 10.f, duRGBA(255,255,255,180)); + } + + dd->end(); + } + } +} + static void drawMeshTile(duDebugDraw* dd, const dtNavMesh& mesh, const dtNavMeshQuery* query, - const dtMeshTile* tile, const float* offset, unsigned int flags) + const dtMeshTile* tile, const float* offset, unsigned int flags, const int linkTypes) { // If the "Alpha" flag isn't set, force the colour to be opaque instead of semi-transparent. const int tileAlpha = flags & DU_DRAWNAVMESH_ALPHA ? 170 : 255; @@ -192,6 +253,9 @@ static void drawMeshTile(duDebugDraw* dd, const dtNavMesh& mesh, const dtNavMesh if (flags & DU_DRAWNAVMESH_POLYCENTERS) drawPolyCenters(dd, tile, duRGBA(255, 255, 255, 100), 1.0f, offset); + if (flags & DU_DRAWNAVMESH_TRAVERSE_LINKS) + drawTraverseLinks(dd, mesh, query, tile, offset, linkTypes); + if (flags & DU_DRAWNAVMESH_OFFMESHCONS) { dd->begin(DU_DRAW_LINES, 2.0f, offset); @@ -272,7 +336,7 @@ static void drawMeshTile(duDebugDraw* dd, const dtNavMesh& mesh, const dtNavMesh dd->depthMask(true); } -void duDebugDrawNavMesh(duDebugDraw* dd, const dtNavMesh& mesh, const float* offset, unsigned int flags) +void duDebugDrawNavMesh(duDebugDraw* dd, const dtNavMesh& mesh, const float* offset, unsigned int flags, const int linkTypes) { if (!dd) return; @@ -280,11 +344,11 @@ void duDebugDrawNavMesh(duDebugDraw* dd, const dtNavMesh& mesh, const float* off { const dtMeshTile* tile = mesh.getTile(i); if (!tile->header) continue; - drawMeshTile(dd, mesh, 0, tile, offset, flags); + drawMeshTile(dd, mesh, 0, tile, offset, flags, linkTypes); } } -void duDebugDrawNavMeshWithClosedList(struct duDebugDraw* dd, const dtNavMesh& mesh, const dtNavMeshQuery& query, const float* offset, unsigned int flags) +void duDebugDrawNavMeshWithClosedList(struct duDebugDraw* dd, const dtNavMesh& mesh, const dtNavMeshQuery& query, const float* offset, unsigned int flags, const int linkTypes) { if (!dd) return; @@ -294,7 +358,7 @@ void duDebugDrawNavMeshWithClosedList(struct duDebugDraw* dd, const dtNavMesh& m { const dtMeshTile* tile = mesh.getTile(i); if (!tile->header) continue; - drawMeshTile(dd, mesh, q, tile, offset, flags); + drawMeshTile(dd, mesh, q, tile, offset, flags, linkTypes); } if (flags & DU_DRAWNAVMESH_BVTREE)