From 8fce111502297c303d1bdaad486aa1bae179d1da Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Wed, 21 Aug 2024 14:40:33 +0200 Subject: [PATCH] Recast: fix BVTree calculations and rendering (XZY -> XYZ) Should've been converted to the source engine coordinate system as well, but we missed this as then rendering thereof was 'fixed' incorrectly causing incorrect bounding volumes to appear correctly. Fixed the renderer and the calculation; the AI now never gets stuck in-game regardless whether 256 or 512 sized tiles are used. --- src/game/shared/ai_utility_shared.cpp | 17 +-- .../DebugUtils/Source/DetourDebugDraw.cpp | 5 +- .../Detour/Source/DetourNavMeshBuilder.cpp | 101 +++++++++--------- 3 files changed, 64 insertions(+), 59 deletions(-) diff --git a/src/game/shared/ai_utility_shared.cpp b/src/game/shared/ai_utility_shared.cpp index f48f23b4..8c161528 100644 --- a/src/game/shared/ai_utility_shared.cpp +++ b/src/game/shared/ai_utility_shared.cpp @@ -205,9 +205,8 @@ void CAI_Utility::DrawNavMeshBVTree( continue; const float flCellSize = 1.0f / pTile->header->bvQuantFactor; - - const fltx4 xTileAABB = LoadGatherSIMD(pTile->header->bmin[0], pTile->header->bmin[1], pTile->header->bmin[2], 0.0f); - const fltx4 xCellSize = LoadGatherSIMD(flCellSize, flCellSize, flCellSize, 0.0f); + const float* tileBmin = pTile->header->bmin; + const float* tileBmax = pTile->header->bmax; for (int j = 0, nc = pTile->header->bvNodeCount; j < nc; ++j) { @@ -219,11 +218,15 @@ void CAI_Utility::DrawNavMeshBVTree( vTransforms.xmm[1] = LoadGatherSIMD(0.0f, 1.0f, 0.0f, 0.0f); vTransforms.xmm[2] = LoadGatherSIMD(0.0f, 0.0f, 1.0f, 0.0f); - // Formula: tile->header->bm##[axis]+node->bm##[axis]*cs; - const fltx4 xMins = MaddSIMD(LoadGatherSIMD(pNode->bmin[0], pNode->bmin[1], pNode->bmin[2], 0.0f), xCellSize, xTileAABB); - const fltx4 xMaxs = MaddSIMD(LoadGatherSIMD(pNode->bmax[0], pNode->bmax[1], pNode->bmax[2], 0.0f), xCellSize, xTileAABB); + const Vector3D mins(tileBmax[0]-pNode->bmax[0]*flCellSize, + tileBmin[1]+pNode->bmin[1]*flCellSize, + tileBmin[2]+pNode->bmin[2]*flCellSize); - v_RenderBox(vTransforms.mat, *reinterpret_cast(&xMins), *reinterpret_cast(&xMaxs), + const Vector3D maxs(tileBmax[0]-pNode->bmin[0]*flCellSize, + tileBmin[1]+pNode->bmax[1]*flCellSize, + tileBmin[2]+pNode->bmax[2]*flCellSize); + + v_RenderBox(vTransforms.mat, mins, maxs, Color(188, 188, 188, 255), bDepthBuffer); } } diff --git a/src/thirdparty/recast/DebugUtils/Source/DetourDebugDraw.cpp b/src/thirdparty/recast/DebugUtils/Source/DetourDebugDraw.cpp index 6b11d621..88900863 100644 --- a/src/thirdparty/recast/DebugUtils/Source/DetourDebugDraw.cpp +++ b/src/thirdparty/recast/DebugUtils/Source/DetourDebugDraw.cpp @@ -524,10 +524,11 @@ static void drawMeshTileBVTree(duDebugDraw* dd, const dtMeshTile* tile, const fl const dtBVNode* n = &tile->bvTree[i]; if (n->i < 0) // Leaf indices are positive. continue; - duAppendBoxWire(dd, tile->header->bmin[0] + n->bmin[0]*cs, + duAppendBoxWire(dd, + tile->header->bmax[0] - n->bmax[0]*cs, tile->header->bmin[1] + n->bmin[1]*cs, tile->header->bmin[2] + n->bmin[2]*cs, - tile->header->bmin[0] + n->bmax[0]*cs, + tile->header->bmax[0] - n->bmin[0]*cs, tile->header->bmin[1] + n->bmax[1]*cs, tile->header->bmin[2] + n->bmax[2]*cs, duRGBA(255,255,255,128)); diff --git a/src/thirdparty/recast/Detour/Source/DetourNavMeshBuilder.cpp b/src/thirdparty/recast/Detour/Source/DetourNavMeshBuilder.cpp index e8bed244..09a9cdf7 100644 --- a/src/thirdparty/recast/Detour/Source/DetourNavMeshBuilder.cpp +++ b/src/thirdparty/recast/Detour/Source/DetourNavMeshBuilder.cpp @@ -164,6 +164,15 @@ static void subdivide(BVItem* items, int nitems, int imin, int imax, int& curNod } } +static const unsigned short DT_MESH_NULL_IDX = 0xffff; +static int countPolyVerts(const unsigned short* p, const int nvp) // todo(amos): deduplicate +{ + for (int i = 0; i < nvp; ++i) + if (p[i] == DT_MESH_NULL_IDX) + return i; + return nvp; +} + static int createBVTree(dtNavMeshCreateParams* params, dtBVNode* nodes, int /*nnodes*/) { // Build tree @@ -173,59 +182,60 @@ static int createBVTree(dtNavMeshCreateParams* params, dtBVNode* nodes, int /*nn { BVItem& it = items[i]; it.i = i; + + float polyVerts[DT_VERTS_PER_POLYGON*3]; + + const float* targetVert; + int vertCount; + // Calc polygon bounds. Use detail meshes if available. if (params->detailMeshes) { - int vb = (int)params->detailMeshes[i*4+0]; - int ndv = (int)params->detailMeshes[i*4+1]; - float bmin[3]; - float bmax[3]; + const int vb = (int)params->detailMeshes[i*4+0]; + vertCount = (int)params->detailMeshes[i*4+1]; - const float* dv = ¶ms->detailVerts[vb*3]; - rdVcopy(bmin, dv); - rdVcopy(bmax, dv); - - for (int j = 1; j < ndv; j++) - { - rdVmin(bmin, &dv[j * 3]); - rdVmax(bmax, &dv[j * 3]); - } - - // BV-tree uses cs for all dimensions - it.bmin[0] = (unsigned short)rdClamp((int)((bmin[0] - params->bmin[0])*quantFactor), 0, 0xffff); - it.bmin[1] = (unsigned short)rdClamp((int)((bmin[1] - params->bmin[1])*quantFactor), 0, 0xffff); - it.bmin[2] = (unsigned short)rdClamp((int)((bmin[2] - params->bmin[2])*quantFactor), 0, 0xffff); - - it.bmax[0] = (unsigned short)rdClamp((int)((bmax[0] - params->bmin[0])*quantFactor), 0, 0xffff); - it.bmax[1] = (unsigned short)rdClamp((int)((bmax[1] - params->bmin[1])*quantFactor), 0, 0xffff); - it.bmax[2] = (unsigned short)rdClamp((int)((bmax[2] - params->bmin[2])*quantFactor), 0, 0xffff); + targetVert = ¶ms->detailVerts[vb*3]; } else { - const unsigned short* p = ¶ms->polys[i*params->nvp * 2]; - it.bmin[0] = it.bmax[0] = params->verts[p[0] * 3 + 0]; - it.bmin[1] = it.bmax[1] = params->verts[p[0] * 3 + 1]; - it.bmin[2] = it.bmax[2] = params->verts[p[0] * 3 + 2]; + const int nvp = params->nvp; - for (int j = 1; j < params->nvp; ++j) + const unsigned short* p = ¶ms->polys[i*nvp * 2]; + vertCount = countPolyVerts(p, nvp); + + for (int j = 0; j < vertCount; ++j) { - if (p[j] == MESH_NULL_IDX) break; - unsigned short x = params->verts[p[j] * 3 + 0]; - unsigned short y = params->verts[p[j] * 3 + 1]; - unsigned short z = params->verts[p[j] * 3 + 2]; + const unsigned short* polyVert = ¶ms->verts[p[j] * 3]; + float* flPolyVert = &polyVerts[j * 3]; - if (x < it.bmin[0]) it.bmin[0] = x; - if (y < it.bmin[1]) it.bmin[1] = y; - if (z < it.bmin[2]) it.bmin[2] = z; - - if (x > it.bmax[0]) it.bmax[0] = x; - if (y > it.bmax[1]) it.bmax[1] = y; - if (z > it.bmax[2]) it.bmax[2] = z; + flPolyVert[0] = params->bmin[0]+polyVert[0]*params->cs; + flPolyVert[1] = params->bmin[1]+polyVert[1]*params->cs; + flPolyVert[2] = params->bmin[2]+polyVert[2]*params->ch; } - // Remap z - it.bmin[2] = (unsigned short)rdMathFloorf((float)it.bmin[2] * params->ch / params->cs); - it.bmax[2] = (unsigned short)rdMathCeilf((float)it.bmax[2] * params->ch / params->cs); + + targetVert = polyVerts; } + + float bmin[3]; + float bmax[3]; + + rdVcopy(bmin, targetVert); + rdVcopy(bmax, targetVert); + + for (int j = 1; j < vertCount; j++) + { + rdVmin(bmin, &targetVert[j * 3]); + rdVmax(bmax, &targetVert[j * 3]); + } + + // BV-tree uses cs for all dimensions + it.bmin[0] = (unsigned short)rdClamp((int)((params->bmax[0] - bmax[0])*quantFactor), 0, 0xffff); + it.bmin[1] = (unsigned short)rdClamp((int)((bmin[1] - params->bmin[1])*quantFactor), 0, 0xffff); + it.bmin[2] = (unsigned short)rdClamp((int)((bmin[2] - params->bmin[2])*quantFactor), 0, 0xffff); + + it.bmax[0] = (unsigned short)rdClamp((int)((params->bmax[0] - bmin[0])*quantFactor), 0, 0xffff); + it.bmax[1] = (unsigned short)rdClamp((int)((bmax[1] - params->bmin[1])*quantFactor), 0, 0xffff); + it.bmax[2] = (unsigned short)rdClamp((int)((bmax[2] - params->bmin[2])*quantFactor), 0, 0xffff); } int curNode = 0; @@ -561,15 +571,6 @@ bool dtCreateTraverseTableData(const dtTraverseTableCreateParams* params) return true; } -static const unsigned short DT_MESH_NULL_IDX = 0xffff; -static int countPolyVerts(const unsigned short* p, const int nvp) // todo(amos): deduplicate -{ - for (int i = 0; i < nvp; ++i) - if (p[i] == DT_MESH_NULL_IDX) - return i; - return nvp; -} - struct CellItem { float pos[3];