From 794b18c82f374c1bf4343a8dc5a13b673faaaeeb Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Sat, 23 Sep 2023 14:01:53 +0200 Subject: [PATCH] Improve NavMesh render performance --- src/engine/debugoverlay.cpp | 11 +- src/game/shared/ai_utility_shared.cpp | 194 +++++++++++++++++++------- src/game/shared/ai_utility_shared.h | 47 ++++++- src/mathlib/vector.h | 6 + src/mathlib/vplane.h | 7 + 5 files changed, 196 insertions(+), 69 deletions(-) diff --git a/src/engine/debugoverlay.cpp b/src/engine/debugoverlay.cpp index 4bfa3b78..2dec70be 100644 --- a/src/engine/debugoverlay.cpp +++ b/src/engine/debugoverlay.cpp @@ -292,16 +292,7 @@ void DrawAllOverlays(bool bRender) #ifndef CLIENT_DLL if (bOverlayEnabled) { - if (ai_script_nodes_draw->GetInt() > -1) - g_pAIUtility->DrawAIScriptNetwork(*g_pAINetwork); - if (navmesh_draw_bvtree->GetInt() > -1) - g_pAIUtility->DrawNavMeshBVTree(); - if (navmesh_draw_portal->GetInt() > -1) - g_pAIUtility->DrawNavMeshPortals(); - if (navmesh_draw_polys->GetInt() > -1) - g_pAIUtility->DrawNavMeshPolys(); - if (navmesh_draw_poly_bounds->GetInt() > -1) - g_pAIUtility->DrawNavMeshPolyBoundaries(); + g_pAIUtility->RunRenderFrame(); } #endif // !CLIENT_DLL diff --git a/src/game/shared/ai_utility_shared.cpp b/src/game/shared/ai_utility_shared.cpp index 4ca2d373..aded2a3c 100644 --- a/src/game/shared/ai_utility_shared.cpp +++ b/src/game/shared/ai_utility_shared.cpp @@ -38,39 +38,88 @@ static const fltx4 s_xMaxs = LoadAlignedSIMD(s_vMaxs); static const fltx4 s_xSubMask = LoadAlignedSIMD(s_vSubMask); //------------------------------------------------------------------------------ -// Purpose: draw AI script network -// Input : *pAINetwork - +// Purpose: run the NavMesh renderer //------------------------------------------------------------------------------ -void CAI_Utility::DrawAIScriptNetwork(const CAI_Network* pNetwork) const +void CAI_Utility::RunRenderFrame(void) +{ + const int iScriptNodeIndex = ai_script_nodes_draw->GetInt(); + const int iNavMeshBVTreeIndex = navmesh_draw_bvtree->GetInt(); + const int iNavMeshPortalIndex = navmesh_draw_portal->GetInt(); + const int iNavMeshPolyIndex = navmesh_draw_polys->GetInt(); + const int iNavMeshPolyBoundIndex = navmesh_draw_poly_bounds->GetInt(); + + if (iScriptNodeIndex <= -1 && + iNavMeshBVTreeIndex <= -1 && + iNavMeshPortalIndex <= -1 && + iNavMeshPolyIndex <= -1 && + iNavMeshPolyBoundIndex <= -1) + { + // Nothing to render. + return; + } + + const Vector3D& vCamera = MainViewOrigin(); + const QAngle& aCamera = MainViewAngles(); + + const Vector3D vNormal = vCamera - aCamera.GetNormal() * 256.0f; + const VPlane vCullPlane(vNormal, aCamera); + + const float flCameraRange = navmesh_debug_camera_range->GetFloat(); + const int nTileRange = navmesh_debug_tile_range->GetInt(); + const bool bUseDepthBuffer = r_debug_draw_depth_test->GetBool(); + + if (iScriptNodeIndex > -1) + g_pAIUtility->DrawAIScriptNetwork(*g_pAINetwork, vCamera, iScriptNodeIndex, flCameraRange, bUseDepthBuffer); + if (iNavMeshBVTreeIndex > -1) + g_pAIUtility->DrawNavMeshBVTree(nullptr, vCamera, vCullPlane, iNavMeshBVTreeIndex, flCameraRange, nTileRange, bUseDepthBuffer); + if (iNavMeshPortalIndex > -1) + g_pAIUtility->DrawNavMeshPortals(nullptr, vCamera, vCullPlane, iNavMeshPortalIndex, flCameraRange, nTileRange, bUseDepthBuffer); + if (iNavMeshPolyIndex > -1) + g_pAIUtility->DrawNavMeshPolys(nullptr, vCamera, vCullPlane, iNavMeshPolyIndex, flCameraRange, nTileRange, bUseDepthBuffer); + if (iNavMeshPolyBoundIndex > -1) + g_pAIUtility->DrawNavMeshPolyBoundaries(nullptr, vCamera, vCullPlane, iNavMeshPolyBoundIndex, flCameraRange, nTileRange, bUseDepthBuffer); +} + +//------------------------------------------------------------------------------ +// Purpose: draw AI script network +// Input : *pNetwork - +// &vCameraPos - +// iNodeIndex - +// flCameraRange - +// bUseDepthBuffer - +//------------------------------------------------------------------------------ +void CAI_Utility::DrawAIScriptNetwork( + const CAI_Network* pNetwork, + const Vector3D& vCameraPos, + const int iNodeIndex, + const float flCameraRange, + const bool bUseDepthBuffer) const { if (!pNetwork) return; // AI Network not build or loaded. - const bool bUseDepthBuffer = r_debug_draw_depth_test->GetBool(); const bool bDrawNearest = ai_script_nodes_draw_nearest->GetBool(); const int nNodeRange = ai_script_nodes_draw_range->GetInt(); - const float flCameraRange = navmesh_debug_camera_range->GetFloat(); - const Vector3D vCamera = MainViewOrigin(); OverlayBox_t::Transforms vTransforms; std::unordered_set uLinkSet; - for (int i = ai_script_nodes_draw->GetInt(), ns = pNetwork->NumScriptNodes(); i < ns; i++) + for (int i = iNodeIndex, ns = pNetwork->NumScriptNodes(); i < ns; i++) { if (nNodeRange && i > nNodeRange) break; const CAI_ScriptNode* pScriptNode = &pNetwork->m_ScriptNode[i]; - fltx4 xOrigin = LoadUnaligned3SIMD(&pScriptNode->m_vOrigin); - xOrigin = SubSIMD(xOrigin, s_xSubMask); // Subtract 25.f from our scalars to align box with node. + const fltx4 xOrigin = SubSIMD(// Subtract 25.f from our scalars to align box with node. + LoadUnaligned3SIMD(&pScriptNode->m_vOrigin), s_xSubMask); if (flCameraRange > 0.0f) { // Flip the script node Z axis with that of the camera, so that it won't be used for // the final distance computation. This allows for viewing the AI Network from above. - const fltx4 xOriginCamZ = SetComponentSIMD(xOrigin, 2, vCamera.z); + const fltx4 xOriginCamZ = SetComponentSIMD(xOrigin, 2, vCameraPos.z); - if (vCamera.DistTo(*reinterpret_cast(&xOriginCamZ)) > flCameraRange) + if (vCameraPos.DistTo(*reinterpret_cast(&xOriginCamZ)) > flCameraRange) continue; // Do not render if node is not within range set by cvar 'navmesh_debug_camera_range'. } @@ -79,7 +128,7 @@ void CAI_Utility::DrawAIScriptNetwork(const CAI_Network* pNetwork) const { 1.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }, { 0.0f, 0.0f, 1.0f }, - *reinterpret_cast(&xOrigin)); + *reinterpret_cast(&xOrigin)); v_RenderBox(vTransforms.mat, *reinterpret_cast(&s_xMins), *reinterpret_cast(&s_xMaxs), m_BoxColor, bUseDepthBuffer); @@ -104,22 +153,30 @@ void CAI_Utility::DrawAIScriptNetwork(const CAI_Network* pNetwork) const //------------------------------------------------------------------------------ // Purpose: draw NavMesh BVTree -// Input : *pMesh - +// Input : *pMesh - +// &vCameraPos - +// &vCullPlane - +// iBVTreeIndex - +// flCameraRange - +// nTileRange - +// bDepthBuffer - //------------------------------------------------------------------------------ -void CAI_Utility::DrawNavMeshBVTree(dtNavMesh* pMesh) const +void CAI_Utility::DrawNavMeshBVTree( + const dtNavMesh* pMesh, + const Vector3D& vCameraPos, + const VPlane& vCullPlane, + const int iBVTreeIndex, + const float flCameraRange, + const int nTileRange, + const bool bDepthBuffer) const { if (!pMesh) pMesh = GetNavMeshForHull(navmesh_debug_type->GetInt()); if (!pMesh) return; // NavMesh for hull not loaded. - const Vector3D vCamera = MainViewOrigin(); - const bool bDepthBuffer = r_debug_draw_depth_test->GetBool(); - const int nTileRange = navmesh_debug_tile_range->GetInt(); - const float flCameraRange = navmesh_debug_camera_range->GetFloat(); - OverlayBox_t::Transforms vTransforms; - for (int i = navmesh_draw_bvtree->GetInt(), nt = pMesh->getTileCount(); i < nt; ++i) + for (int i = iBVTreeIndex, nt = pMesh->getTileCount(); i < nt; ++i) { if (nTileRange > 0 && i > nTileRange) break; @@ -128,7 +185,7 @@ void CAI_Utility::DrawNavMeshBVTree(dtNavMesh* pMesh) const if (!pTile->header) continue; - if (!IsTileWithinRange(pTile, vCamera, flCameraRange)) + if (!IsTileWithinRange(pTile, vCullPlane, vCameraPos, flCameraRange)) continue; const float flCellSize = 1.0f / pTile->header->bvQuantFactor; @@ -158,21 +215,28 @@ void CAI_Utility::DrawNavMeshBVTree(dtNavMesh* pMesh) const //------------------------------------------------------------------------------ // Purpose: draw NavMesh portals -// Input : *pMesh - +// Input : *pMesh - +// &vCameraPos - +// &vCullPlane - +// iPortalIndex - +// flCameraRange - +// nTileRange - +// bDepthBuffer - //------------------------------------------------------------------------------ -void CAI_Utility::DrawNavMeshPortals(dtNavMesh* pMesh) const +void CAI_Utility::DrawNavMeshPortals(const dtNavMesh* pMesh, + const Vector3D& vCameraPos, + const VPlane& vCullPlane, + const int iPortalIndex, + const float flCameraRange, + const int nTileRange, + const bool bDepthBuffer) const { if (!pMesh) pMesh = GetNavMeshForHull(navmesh_debug_type->GetInt()); if (!pMesh) return; // NavMesh for hull not loaded. - const Vector3D vCamera = MainViewOrigin(); - const bool bDepthBuffer = r_debug_draw_depth_test->GetBool(); - const int nTileRange = navmesh_debug_tile_range->GetInt(); - const float flCameraRange = navmesh_debug_camera_range->GetFloat(); - - for (int i = navmesh_draw_portal->GetInt(), nt = pMesh->getTileCount(); i < nt; ++i) + for (int i = iPortalIndex, nt = pMesh->getTileCount(); i < nt; ++i) { if (nTileRange > 0 && i > nTileRange) break; @@ -181,7 +245,7 @@ void CAI_Utility::DrawNavMeshPortals(dtNavMesh* pMesh) const if (!pTile->header) continue; - if (!IsTileWithinRange(pTile, vCamera, flCameraRange)) + if (!IsTileWithinRange(pTile, vCullPlane, vCameraPos, flCameraRange)) continue; // Draw portals @@ -271,21 +335,28 @@ void CAI_Utility::DrawNavMeshPortals(dtNavMesh* pMesh) const //------------------------------------------------------------------------------ // Purpose: draw NavMesh polys -// Input : *pMesh - +// Input : *pMesh - +// &vCameraPos - +// &vCullPlane - +// iPolyIndex - +// flCameraRange - +// nTileRange - +// bDepthBuffer - //------------------------------------------------------------------------------ -void CAI_Utility::DrawNavMeshPolys(dtNavMesh* pMesh) const +void CAI_Utility::DrawNavMeshPolys(const dtNavMesh* pMesh, + const Vector3D& vCameraPos, + const VPlane& vCullPlane, + const int iPolyIndex, + const float flCameraRange, + const int nTileRange, + const bool bDepthBuffer) const { if (!pMesh) pMesh = GetNavMeshForHull(navmesh_debug_type->GetInt()); if (!pMesh) return; // NavMesh for hull not loaded. - const Vector3D vCamera = MainViewOrigin(); - const bool bDepthBuffer = r_debug_draw_depth_test->GetBool(); - const int nTileRange = navmesh_debug_tile_range->GetInt(); - const float flCameraRange = navmesh_debug_camera_range->GetFloat(); - - for (int i = navmesh_draw_polys->GetInt(); i < pMesh->getTileCount(); ++i) + for (int i = iPolyIndex; i < pMesh->getTileCount(); ++i) { if (nTileRange > 0 && i > nTileRange) break; @@ -294,7 +365,7 @@ void CAI_Utility::DrawNavMeshPolys(dtNavMesh* pMesh) const if (!pTile->header) continue; - if (!IsTileWithinRange(pTile, vCamera, flCameraRange)) + if (!IsTileWithinRange(pTile, vCullPlane, vCameraPos, flCameraRange)) continue; for (int j = 0; j < pTile->header->polyCount; j++) @@ -345,9 +416,21 @@ void CAI_Utility::DrawNavMeshPolys(dtNavMesh* pMesh) const //------------------------------------------------------------------------------ // Purpose : draw NavMesh poly boundaries -// Input : *pMesh - +// Input : *pMesh - +// &vCameraPos - +// &vCullPlane - +// iBoundaryIndex - +// flCameraRange - +// nTileRange - +// bDepthBuffer - //------------------------------------------------------------------------------ -void CAI_Utility::DrawNavMeshPolyBoundaries(dtNavMesh* pMesh) const +void CAI_Utility::DrawNavMeshPolyBoundaries(const dtNavMesh* pMesh, + const Vector3D& vCameraPos, + const VPlane& vCullPlane, + const int iBoundaryIndex, + const float flCameraRange, + const int nTileRange, + const bool bDepthBuffer) const { static const float thr = 0.01f * 0.01f; Color col{ 20, 140, 255, 255 }; @@ -357,13 +440,9 @@ void CAI_Utility::DrawNavMeshPolyBoundaries(dtNavMesh* pMesh) const if (!pMesh) return; // NavMesh for hull not loaded. - const Vector3D vCamera = MainViewOrigin(); - const bool bDepthBuffer = r_debug_draw_depth_test->GetBool(); const bool bDrawInner = navmesh_draw_poly_bounds_inner->GetBool(); - const int nTileRange = navmesh_debug_tile_range->GetInt(); - const float flCameraRange = navmesh_debug_camera_range->GetFloat(); - for (int i = navmesh_draw_poly_bounds->GetInt(), nt = pMesh->getTileCount(); i < nt; ++i) + for (int i = iBoundaryIndex, nt = pMesh->getTileCount(); i < nt; ++i) { if (nTileRange > 0 && i > nTileRange) break; @@ -372,7 +451,7 @@ void CAI_Utility::DrawNavMeshPolyBoundaries(dtNavMesh* pMesh) const if (!pTile->header) continue; - if (!IsTileWithinRange(pTile, vCamera, flCameraRange)) + if (!IsTileWithinRange(pTile, vCullPlane, vCameraPos, flCameraRange)) continue; for (int j = 0; j < pTile->header->polyCount; ++j) @@ -478,16 +557,25 @@ __m128i CAI_Utility::PackNodeLink(int32_t a, int32_t b, int32_t c, int32_t d) co // flCameraRadius - // Output : true if within radius, false otherwise //------------------------------------------------------------------------------ -bool CAI_Utility::IsTileWithinRange(const dtMeshTile* pTile, const Vector3D& vCamera, const float flCameraRadius) const +bool CAI_Utility::IsTileWithinRange(const dtMeshTile* pTile, const VPlane& vPlane, const Vector3D& vCamera, const float flCameraRadius) const { - if (flCameraRadius <= 0.0f) - return false; - const fltx4 xMinBound = LoadGatherSIMD(pTile->header->bmin[0], pTile->header->bmin[1], vCamera.z, 0.0f); const fltx4 xMaxBound = LoadGatherSIMD(pTile->header->bmax[0], pTile->header->bmax[1], vCamera.z, 0.0f); - if (vCamera.DistTo(*reinterpret_cast(&xMinBound)) > flCameraRadius || - vCamera.DistTo(*reinterpret_cast(&xMaxBound)) > flCameraRadius) + const Vector3D* vecMinBound = reinterpret_cast(&xMinBound); + const Vector3D* vecMaxBound = reinterpret_cast(&xMaxBound); + + if (flCameraRadius > 0.0f) + { + // Too far from camera, do not render. + if (vCamera.DistTo(*vecMinBound) > flCameraRadius || + vCamera.DistTo(*vecMinBound) > flCameraRadius) + return false; + } + + // Behind the camera, do not render. + if (vPlane.GetPointSide(*vecMinBound) != SIDE_FRONT || + vPlane.GetPointSide(*vecMaxBound) != SIDE_FRONT) return false; return true; diff --git a/src/game/shared/ai_utility_shared.h b/src/game/shared/ai_utility_shared.h index f381653e..071a534f 100644 --- a/src/game/shared/ai_utility_shared.h +++ b/src/game/shared/ai_utility_shared.h @@ -17,14 +17,49 @@ class CAI_Utility { public: CAI_Utility(void); - void DrawAIScriptNetwork(const CAI_Network* pAINetwork) const; - void DrawNavMeshBVTree(dtNavMesh* mesh = nullptr) const; - void DrawNavMeshPortals(dtNavMesh* mesh = nullptr) const; - void DrawNavMeshPolys(dtNavMesh* mesh = nullptr) const; - void DrawNavMeshPolyBoundaries(dtNavMesh* mesh = nullptr) const; + void RunRenderFrame(void); + + void DrawAIScriptNetwork(const CAI_Network* pNetwork, + const Vector3D& vCameraPos, + const int iNodeIndex, + const float flCameraRange, + const bool bUseDepthBuffer) const; + + void DrawNavMeshBVTree(const dtNavMesh* mesh, + const Vector3D& vCameraPos, + const VPlane& vCullPlane, + const int iBVTreeIndex, + const float flCameraRange, + const int nTileRange, + const bool bUseDepthBuffer) const; + + void DrawNavMeshPortals(const dtNavMesh* mesh, + const Vector3D& vCameraPos, + const VPlane& vCullPlane, + const int iPortalIndex, + const float flCameraRange, + const int nTileRange, + const bool bUseDepthBuffer) const; + + void DrawNavMeshPolys(const dtNavMesh* mesh, + const Vector3D& vCameraPos, + const VPlane& vCullPlane, + const int iPolyIndex, + const float flCameraRange, + const int nTileRange, + const bool bDepthBuffer) const; + + void DrawNavMeshPolyBoundaries(const dtNavMesh* mesh, + const Vector3D& vCameraPos, + const VPlane& vCullPlane, + const int iBoundaryIndex, + const float flCameraRange, + const int nTileRange, + const bool bDepthBuffer) const; + __m128i PackNodeLink(int32_t a, int32_t b, int32_t c = 0, int32_t d = 0) const; int GetNearestNodeToPos(const CAI_Network* pAINetwork, const Vector3D* vec) const; - bool IsTileWithinRange(const dtMeshTile* pTile, const Vector3D& vCamera, const float flCameraRadius) const; + bool IsTileWithinRange(const dtMeshTile* pTile, const VPlane& vPlane, const Vector3D& vCamera, const float flCameraRadius) const; private: Color m_BoxColor; diff --git a/src/mathlib/vector.h b/src/mathlib/vector.h index 2d0e10da..8b5470be 100644 --- a/src/mathlib/vector.h +++ b/src/mathlib/vector.h @@ -2428,6 +2428,7 @@ public: void Normalize(); void NormalizePositive(); + inline Vector3D GetNormal() const; inline struct matrix3x4_t ToMatrix() const; inline Quaternion ToQuaternion() const; @@ -2533,6 +2534,11 @@ inline void QAngle::NormalizePositive() z = AngleNormalizePositive(z); } +inline Vector3D QAngle::GetNormal() const +{ + Vector3D ret(cos(VEC_DEG2RAD(y)), sin(VEC_DEG2RAD(y)), -sin(VEC_DEG2RAD(x))); + return ret; +} #if !defined(__SPU__) inline void QAngle::Random(vec_t minVal, vec_t maxVal) diff --git a/src/mathlib/vplane.h b/src/mathlib/vplane.h index 48f52a0f..a3fefed4 100644 --- a/src/mathlib/vplane.h +++ b/src/mathlib/vplane.h @@ -30,6 +30,7 @@ class VPlane public: VPlane(); VPlane(const Vector3D& vNormal, vec_t dist); + VPlane(const Vector3D& vPoint, const QAngle& ang); void Init(const Vector3D& vNormal, vec_t dist); @@ -86,6 +87,12 @@ inline VPlane::VPlane(const Vector3D& vNormal, vec_t dist) m_Dist = dist; } +inline VPlane::VPlane(const Vector3D& vPoint, const QAngle& ang) +{ + m_Normal = ang.GetNormal(); + m_Dist = vPoint.x * m_Normal.x + vPoint.y * m_Normal.y + vPoint.z * m_Normal.z; +} + inline void VPlane::Init(const Vector3D& vNormal, vec_t dist) { m_Normal = vNormal;