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.
This commit is contained in:
Kawe Mazidjatari 2024-07-12 21:38:50 +02:00
parent 61705cb85e
commit 2f9776d495
3 changed files with 32 additions and 3 deletions

View File

@ -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
{

View File

@ -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];

View File

@ -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.