From c850d52d1b035c9957c058c74ceeb33656eeb22d Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Thu, 21 Jul 2022 02:21:59 +0200 Subject: [PATCH] Add NavMesh poly bounds debug overlay --- r5dev/engine/debugoverlay.cpp | 119 +++++++++++++++--- .../DebugUtils/Source/DetourDebugDraw.cpp | 15 --- .../recast/Detour/Include/DetourCommon.h | 2 + .../recast/Detour/Source/DetourCommon.cpp | 14 +++ r5dev/tier1/IConVar.cpp | 10 +- r5dev/tier1/cvar.cpp | 2 + r5dev/tier1/cvar.h | 2 + 7 files changed, 130 insertions(+), 34 deletions(-) diff --git a/r5dev/engine/debugoverlay.cpp b/r5dev/engine/debugoverlay.cpp index c7bea1af..67b5e5ca 100644 --- a/r5dev/engine/debugoverlay.cpp +++ b/r5dev/engine/debugoverlay.cpp @@ -19,6 +19,7 @@ #include "game/server/ai_utility.h" #include "game/server/ai_network.h" #include "game/server/ai_networkmanager.h" +#include "thirdparty/recast/detour/include/detourcommon.h" #endif // !CLIENT_DLL @@ -382,6 +383,100 @@ static void DrawNavMeshPortals() #endif // !CLIENT_DLL } +static void DrawNavMeshPolyBoundaries() +{ +#ifndef CLIENT_DLL + static const float thr = 0.01f * 0.01f; + Color col{0, 140, 240, 255}; + + //dd->begin(DU_DRAW_LINES, linew); + + const dtNavMesh* mesh = GetNavMeshForHull(navmesh_debug_type->GetInt()); + if (!mesh) + return; + + OverlayBox_t::Transforms vTransforms; + for (int i = navmesh_draw_poly_bounds->GetInt(); i < mesh->getTileCount(); ++i) + { + const dtMeshTile* tile = &mesh->m_tiles[i]; + if (!tile->header) + continue; + + for (int i = 0; i < tile->header->polyCount; ++i) + { + const dtPoly* p = &tile->polys[i]; + + if (p->getType() == DT_POLYTYPE_OFFMESH_CONNECTION) + continue; + + const dtPolyDetail* pd = &tile->detailMeshes[i]; + + for (int j = 0, nj = (int)p->vertCount; j < nj; ++j) + { + Color c = col; + if (navmesh_draw_poly_inner->GetBool()) + { + if (p->neis[j] == 0) + continue; + + if (p->neis[j] & DT_EXT_LINK) + { + bool con = false; + for (unsigned int k = p->firstLink; k != DT_NULL_LINK; k = tile->links[k].next) + { + if (tile->links[k].edge == j) + { + con = true; + break; + } + } + if (con) + c = Color(255, 255, 255, 48); + else + c = Color(0, 0, 0, 48); + } + else + c = Color(0, 48, 64, 32); + } + else + { + if (p->neis[j] != 0) continue; + } + + const float* v0 = &tile->verts[p->verts[j] * 3]; + const float* v1 = &tile->verts[p->verts[(j + 1) % nj] * 3]; + + // Draw detail mesh edges which align with the actual poly edge. + // This is really slow. + for (int k = 0; k < pd->triCount; ++k) + { + const unsigned char* t = &tile->detailTris[(pd->triBase + k) * 4]; + const float* tv[3]; + for (int m = 0; m < 3; ++m) + { + if (t[m] < p->vertCount) + tv[m] = &tile->verts[p->verts[t[m]] * 3]; + else + tv[m] = &tile->detailVerts[(pd->vertBase + (t[m] - p->vertCount)) * 3]; + } + for (int m = 0, n = 2; m < 3; n = m++) + { + if ((dtGetDetailTriEdgeFlags(t[3], n) & DT_DETAIL_EDGE_BOUNDARY) == 0) + continue; + + if (distancePtLine2d(tv[n], v0, v1) < thr && + distancePtLine2d(tv[m], v0, v1) < thr) + { + v_RenderLine(Vector3D(tv[n][0], tv[n][1], tv[n][2]), Vector3D(tv[m][0], tv[m][1], tv[m][2]), c, r_debug_overlay_zbuffer->GetBool()); + } + } + } + } + } + } +#endif // !CLIENT_DLL +} + //------------------------------------------------------------------------------ // Purpose : overlay drawing entrypoint // Input : bDraw - @@ -389,24 +484,18 @@ static void DrawNavMeshPortals() void DrawAllOverlays(bool bDraw) { if (!enable_debug_overlays->GetBool()) - { return; - } - if (ai_script_nodes_draw->GetBool()) - { - DrawAIScriptNodes(); - } - if (navmesh_draw_bvtree->GetInt() > -1) - { - DrawNavMeshBVTree(); - } - if (navmesh_draw_portal->GetInt() > -1) - { - DrawNavMeshPortals(); - } - EnterCriticalSection(&*s_OverlayMutex); + if (ai_script_nodes_draw->GetBool()) + DrawAIScriptNodes(); + if (navmesh_draw_bvtree->GetInt() > -1) + DrawNavMeshBVTree(); + if (navmesh_draw_portal->GetInt() > -1) + DrawNavMeshPortals(); + if (navmesh_draw_poly_bounds->GetInt() > -1) + DrawNavMeshPolyBoundaries(); + OverlayBase_t* pCurrOverlay = *s_pOverlays; // rdi OverlayBase_t* pPrevOverlay = nullptr; // rsi OverlayBase_t* pNextOverlay = nullptr; // rbx diff --git a/r5dev/thirdparty/recast/DebugUtils/Source/DetourDebugDraw.cpp b/r5dev/thirdparty/recast/DebugUtils/Source/DetourDebugDraw.cpp index f6235eef..188f9307 100644 --- a/r5dev/thirdparty/recast/DebugUtils/Source/DetourDebugDraw.cpp +++ b/r5dev/thirdparty/recast/DebugUtils/Source/DetourDebugDraw.cpp @@ -22,21 +22,6 @@ #include "Detour/Include/DetourCommon.h" #include "Detour/Include/DetourNode.h" - -static float distancePtLine2d(const float* pt, const float* p, const float* q) -{ - float pqx = q[0] - p[0]; - float pqz = q[2] - p[2]; - float dx = pt[0] - p[0]; - float dz = pt[2] - p[2]; - float d = pqx*pqx + pqz*pqz; - float t = pqx*dx + pqz*dz; - if (d != 0) t /= d; - dx = p[0] + t*pqx - pt[0]; - dz = p[2] + t*pqz - pt[2]; - return dx*dx + dz*dz; -} - static void drawPolyBoundaries(duDebugDraw* dd, const dtMeshTile* tile, const unsigned int col, const float linew, bool inner) diff --git a/r5dev/thirdparty/recast/Detour/Include/DetourCommon.h b/r5dev/thirdparty/recast/Detour/Include/DetourCommon.h index da8c2b13..428831bf 100644 --- a/r5dev/thirdparty/recast/Detour/Include/DetourCommon.h +++ b/r5dev/thirdparty/recast/Detour/Include/DetourCommon.h @@ -405,6 +405,8 @@ bool dtIntersectSegSeg2D(const float* ap, const float* aq, const float* bp, const float* bq, float& s, float& t); +float distancePtLine2d(const float* pt, const float* p, const float* q); + /// Determines if the specified point is inside the convex polygon on the xz-plane. /// @param[in] pt The point to check. [(x, y, z)] /// @param[in] verts The polygon vertices. [(x, y, z) * @p nverts] diff --git a/r5dev/thirdparty/recast/Detour/Source/DetourCommon.cpp b/r5dev/thirdparty/recast/Detour/Source/DetourCommon.cpp index 0614bd70..c4441723 100644 --- a/r5dev/thirdparty/recast/Detour/Source/DetourCommon.cpp +++ b/r5dev/thirdparty/recast/Detour/Source/DetourCommon.cpp @@ -385,3 +385,17 @@ bool dtIntersectSegSeg2D(const float* ap, const float* aq, return true; } +float distancePtLine2d(const float* pt, const float* p, const float* q) +{ + float pqx = q[0] - p[0]; + float pqz = q[2] - p[2]; + float dx = pt[0] - p[0]; + float dz = pt[2] - p[2]; + float d = pqx * pqx + pqz * pqz; + float t = pqx * dx + pqz * dz; + if (d != 0) t /= d; + dx = p[0] + t * pqx - pt[0]; + dz = p[2] + t * pqz - pt[2]; + return dx * dx + dz * dz; +} + diff --git a/r5dev/tier1/IConVar.cpp b/r5dev/tier1/IConVar.cpp index 297c7e1c..e2eda1f6 100644 --- a/r5dev/tier1/IConVar.cpp +++ b/r5dev/tier1/IConVar.cpp @@ -65,10 +65,12 @@ void ConVar::Init(void) const ai_ainDebugConnect = new ConVar("ai_ainDebugConnect" , "0", FCVAR_DEVELOPMENTONLY, "Debug AIN node connections.", false, 0.f, false, 0.f, nullptr, nullptr); ai_script_nodes_draw_index = new ConVar("ai_script_nodes_draw_index", "0", FCVAR_DEVELOPMENTONLY, "Start index for drawing script nodes.", false, 0.f, false, 0.f, nullptr, nullptr); - navmesh_always_reachable = new ConVar("navmesh_always_reachable" , "0", FCVAR_DEVELOPMENTONLY, "Marks goal poly from agent poly as reachable regardless of table data ( !slower! ).", false, 0.f, false, 0.f, nullptr, nullptr); - navmesh_debug_type = new ConVar("navmesh_debug_type" , "0", FCVAR_DEVELOPMENTONLY, "NavMesh hull index for debug draw.", true, 0.f, true, 4.f, nullptr, "0 = small, 1 = med_short, 2 = medium, 3 = large, 4 = extra large"); - navmesh_draw_bvtree = new ConVar("navmesh_draw_bvtree" , "-1", FCVAR_DEVELOPMENTONLY, "Draws the BVTree of the NavMesh tiles.", false, 0.f, false, 0.f, nullptr, "Index: > 0 && < mesh->m_tileCount"); - navmesh_draw_portal = new ConVar("navmesh_draw_portal" , "-1", FCVAR_DEVELOPMENTONLY, "Draws the portal of the NavMesh tiles.", false, 0.f, false, 0.f, nullptr, "Index: > 0 && < mesh->m_tileCount"); + navmesh_always_reachable = new ConVar("navmesh_always_reachable" , "0" , FCVAR_DEVELOPMENTONLY, "Marks goal poly from agent poly as reachable regardless of table data ( !slower! ).", false, 0.f, false, 0.f, nullptr, nullptr); + navmesh_debug_type = new ConVar("navmesh_debug_type" , "0" , FCVAR_DEVELOPMENTONLY, "NavMesh hull index for debug draw.", true, 0.f, true, 4.f, nullptr, "0 = small, 1 = med_short, 2 = medium, 3 = large, 4 = extra large"); + navmesh_draw_bvtree = new ConVar("navmesh_draw_bvtree" , "-1", FCVAR_DEVELOPMENTONLY, "Draws the BVTree of the NavMesh tiles.", false, 0.f, false, 0.f, nullptr, "Index: > 0 && < mesh->m_tileCount"); + navmesh_draw_portal = new ConVar("navmesh_draw_portal" , "-1", FCVAR_DEVELOPMENTONLY, "Draws the portal of the NavMesh tiles.", false, 0.f, false, 0.f, nullptr, "Index: > 0 && < mesh->m_tileCount"); + navmesh_draw_poly_bounds = new ConVar("navmesh_draw_poly_bounds" , "-1", FCVAR_DEVELOPMENTONLY, "Draws the bounds of the NavMesh polys.", false, 0.f, false, 0.f, nullptr, "Index: > 0 && < mesh->m_tileCount"); + navmesh_draw_poly_inner = new ConVar("navmesh_draw_poly_inner" , "0" , FCVAR_DEVELOPMENTONLY, "Draws the inner bounds of the NavMesh polys (requires navmesh_draw_poly_bounds).", false, 0.f, false, 0.f, nullptr, "Index: > 0 && < mesh->m_tileCount"); sv_showconnecting = new ConVar("sv_showconnecting" , "1", FCVAR_RELEASE, "Logs information about the connecting client to the console.", false, 0.f, false, 0.f, nullptr, nullptr); sv_pylonVisibility = new ConVar("sv_pylonVisibility", "0", FCVAR_RELEASE, "Determines the visiblity to the Pylon master server, 0 = Offline, 1 = Hidden, 2 = Public.", false, 0.f, false, 0.f, nullptr, nullptr); diff --git a/r5dev/tier1/cvar.cpp b/r5dev/tier1/cvar.cpp index a9b754ef..2d1fdaac 100644 --- a/r5dev/tier1/cvar.cpp +++ b/r5dev/tier1/cvar.cpp @@ -51,6 +51,8 @@ ConVar* navmesh_always_reachable = nullptr; ConVar* navmesh_debug_type = nullptr; ConVar* navmesh_draw_bvtree = nullptr; ConVar* navmesh_draw_portal = nullptr; +ConVar* navmesh_draw_poly_bounds = nullptr; +ConVar* navmesh_draw_poly_inner = nullptr; ConVar* sv_showconnecting = nullptr; ConVar* sv_pylonVisibility = nullptr; diff --git a/r5dev/tier1/cvar.h b/r5dev/tier1/cvar.h index 92998f17..3b62b3db 100644 --- a/r5dev/tier1/cvar.h +++ b/r5dev/tier1/cvar.h @@ -50,6 +50,8 @@ extern ConVar* navmesh_always_reachable; extern ConVar* navmesh_debug_type; extern ConVar* navmesh_draw_bvtree; extern ConVar* navmesh_draw_portal; +extern ConVar* navmesh_draw_poly_bounds; +extern ConVar* navmesh_draw_poly_inner; extern ConVar* sv_showconnecting; extern ConVar* sv_pylonVisibility;