From 2f9776d495f6a5c7bedccc3566b81d41d28e09f6 Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Fri, 12 Jul 2024 21:38:50 +0200 Subject: [PATCH] Recast: properly set dtPoly::surfaceArea This field has been reverse engineered and set correctly in this commit. The field contains the quantized surface area of the polygon. --- .../recast/Detour/Include/DetourNavMesh.h | 15 +++++++++++++-- .../recast/Detour/Source/DetourNavMesh.cpp | 17 +++++++++++++++++ .../Detour/Source/DetourNavMeshBuilder.cpp | 3 ++- 3 files changed, 32 insertions(+), 3 deletions(-) diff --git a/src/thirdparty/recast/Detour/Include/DetourNavMesh.h b/src/thirdparty/recast/Detour/Include/DetourNavMesh.h index 0f45e65d..f46c5317 100644 --- a/src/thirdparty/recast/Detour/Include/DetourNavMesh.h +++ b/src/thirdparty/recast/Detour/Include/DetourNavMesh.h @@ -82,6 +82,9 @@ static const int DT_MIN_POLY_GROUP_COUNT = 3; /// The maximum number of traversal tables per navmesh that will be used for static pathing. static const int DT_MAX_TRAVERSAL_TABLES = 5; +/// The cached poly surface area quantization factor. +static const float DT_POLY_AREA_QUANT_FACTOR = 50.f; + /// @{ /// @name Tile Serialization Constants /// These constants are used to detect whether a navigation tile's data @@ -205,11 +208,13 @@ struct dtPoly /// The poly group id determining to which island it belongs, and to which it connects. unsigned short groupId; - // These 3 are most likely related, it needs to be reversed still. + /// The poly surface area. (Quantized by #DT_POLY_AREA_QUANT_FACTOR). + unsigned short surfaceArea; + + // These 2 are most likely related, it needs to be reversed still. // No use case has been found in the executable yet, its possible these are // used internally in the editor. Dynamic reverse engineering required to // confirm this. - unsigned short unk0; unsigned short unk1; unsigned short unk2; @@ -229,6 +234,12 @@ struct dtPoly inline unsigned char getType() const { return areaAndtype >> 6; } }; +/// Calculates the surface area of the polygon. +/// @param[in] poly The polygon. +/// @param[in] verts The polygon vertices. +/// @return The total surface are of the polygon. +float dtCalcPolySurfaceArea(const dtPoly* poly, const float* verts); + /// Defines the location of detail sub-mesh data within a dtMeshTile. struct dtPolyDetail { diff --git a/src/thirdparty/recast/Detour/Source/DetourNavMesh.cpp b/src/thirdparty/recast/Detour/Source/DetourNavMesh.cpp index cbac26dc..962c760c 100644 --- a/src/thirdparty/recast/Detour/Source/DetourNavMesh.cpp +++ b/src/thirdparty/recast/Detour/Source/DetourNavMesh.cpp @@ -1695,6 +1695,23 @@ dtStatus dtNavMesh::getPolyArea(dtPolyRef ref, unsigned char* resultArea) const return DT_SUCCESS; } +float dtCalcPolyArea(const dtPoly* poly, const float* verts) +{ + float polyArea = 0.0f; + + // Only run if we have more than 2 verts since poly's with 2 verts + // (off-mesh connections) don't have any surface area. + for (int j = 2; j < poly->vertCount; ++j) + { + const float* va = &verts[poly->verts[0]*3]; + const float* vb = &verts[poly->verts[j]*3]; + const float* vc = &verts[poly->verts[j-1]*3]; + polyArea += dtTriArea2D(va,vb,vc); + } + + return polyArea; +} + float dtCalcOffMeshRefYaw(const float* spos, const float* epos) { float dx = epos[0]-spos[0]; diff --git a/src/thirdparty/recast/Detour/Source/DetourNavMeshBuilder.cpp b/src/thirdparty/recast/Detour/Source/DetourNavMeshBuilder.cpp index cfe8389d..ca91197c 100644 --- a/src/thirdparty/recast/Detour/Source/DetourNavMeshBuilder.cpp +++ b/src/thirdparty/recast/Detour/Source/DetourNavMeshBuilder.cpp @@ -303,7 +303,6 @@ bool dtCreateDisjointPolyGroups(dtNavMesh* nav, dtDisjointSet& disjoint) // NOTE: these fields are unknown and need to be reversed. // It is possible these are used internally only. - poly.unk0 = (unsigned short)-1; poly.unk1 = (unsigned short)-1; poly.unk2 = (unsigned short)-1; } @@ -815,6 +814,8 @@ bool dtCreateNavMeshData(dtNavMeshCreateParams* params, unsigned char** outData, p->vertCount++; } dtVscale(p->center, p->center, 1 / (float)(p->vertCount)); + p->surfaceArea = (unsigned short)dtMathRoundf(dtCalcPolySurfaceArea(p,navVerts) / DT_POLY_AREA_QUANT_FACTOR); + src += nvp*2; } // Off-mesh connection vertices.