From 30d459ca7317df713a7b99e7c0b4563ca8afc64a Mon Sep 17 00:00:00 2001 From: Graham Pentheny Date: Mon, 25 Aug 2025 00:44:50 -0400 Subject: [PATCH] Use a vector to store convex volumes rather than fixed-size array --- RecastDemo/Include/InputGeom.h | 27 ++--- RecastDemo/Source/InputGeom.cpp | 115 ++++++++++----------- RecastDemo/Source/Sample_SoloMesh.cpp | 13 ++- RecastDemo/Source/Sample_TempObstacles.cpp | 13 ++- RecastDemo/Source/Sample_TileMesh.cpp | 13 ++- RecastDemo/Source/Tool_ConvexVolume.cpp | 4 +- 6 files changed, 82 insertions(+), 103 deletions(-) diff --git a/RecastDemo/Include/InputGeom.h b/RecastDemo/Include/InputGeom.h index 6d5cafe0..93d93cea 100644 --- a/RecastDemo/Include/InputGeom.h +++ b/RecastDemo/Include/InputGeom.h @@ -28,11 +28,11 @@ struct duDebugDraw; static constexpr int MAX_CONVEXVOL_PTS = 12; struct ConvexVolume { - float verts[MAX_CONVEXVOL_PTS * 3]; - float hmin; - float hmax; - int nverts; - int area; + float verts[MAX_CONVEXVOL_PTS * 3] = {}; + float hmin = 0.0f; + float hmax = 0.0f; + int nverts = 0; + int area = 0; }; struct BuildSettings @@ -75,7 +75,7 @@ struct Mesh { std::vector verts; std::vector tris; - std::vector normals; + std::vector normals; // face normals void reset() { @@ -92,6 +92,9 @@ struct Mesh class InputGeom { + BuildSettings buildSettings; + bool hasBuildSettings = false; + public: std::string filename; Mesh mesh; @@ -100,11 +103,6 @@ public: float meshBoundsMin[3] = {}; float meshBoundsMax[3] = {}; -private: - BuildSettings buildSettings; - bool hasBuildSettings = false; - -public: /// @name Off-Mesh connections. ///@{ static constexpr int MAX_OFFMESH_CONNECTIONS = 256; @@ -117,12 +115,7 @@ public: int offMeshConCount = 0; ///@} - /// @name Convex Volumes. - ///@{ - static const int MAX_VOLUMES = 256; - ConvexVolume convexVolumes[MAX_VOLUMES]; - int convexVolumeCount = 0; - ///@} + std::vector convexVolumes; InputGeom() = default; ~InputGeom(); diff --git a/RecastDemo/Source/InputGeom.cpp b/RecastDemo/Source/InputGeom.cpp index 1354ab93..dc46b8b1 100644 --- a/RecastDemo/Source/InputGeom.cpp +++ b/RecastDemo/Source/InputGeom.cpp @@ -368,7 +368,7 @@ bool InputGeom::loadMesh(rcContext* ctx, const std::string& filepath) filename = filepath; offMeshConCount = 0; - convexVolumeCount = 0; + convexVolumes.clear(); mesh.reset(); mesh.readFromObj(buffer, bufferLen); @@ -407,7 +407,7 @@ bool InputGeom::loadGeomSet(rcContext* ctx, const std::string& filepath) bool InputGeom::loadGeomSet(rcContext* ctx, char* buffer, size_t bufferLen) { offMeshConCount = 0; - convexVolumeCount = 0; + convexVolumes.clear(); char* src = buffer; char* srcEnd = buffer + bufferLen; @@ -467,17 +467,15 @@ bool InputGeom::loadGeomSet(rcContext* ctx, char* buffer, size_t bufferLen) else if (row[0] == 'v') { // Convex volumes - if (convexVolumeCount < MAX_VOLUMES) + ConvexVolume vol; + sscanf(row + 1, "%d %d %f %f", &vol.nverts, &vol.area, &vol.hmin, &vol.hmax); + for (int i = 0; i < vol.nverts; ++i) { - ConvexVolume* vol = &convexVolumes[convexVolumeCount++]; - sscanf(row + 1, "%d %d %f %f", &vol->nverts, &vol->area, &vol->hmin, &vol->hmax); - for (int i = 0; i < vol->nverts; ++i) - { - row[0] = '\0'; - src = parseRow(src, srcEnd, row, sizeof(row) / sizeof(char)); - sscanf(row, "%f %f %f", &vol->verts[i * 3 + 0], &vol->verts[i * 3 + 1], &vol->verts[i * 3 + 2]); - } + row[0] = '\0'; + src = parseRow(src, srcEnd, row, sizeof(row) / sizeof(char)); + sscanf(row, "%f %f %f", &vol.verts[i * 3 + 0], &vol.verts[i * 3 + 1], &vol.verts[i * 3 + 2]); } + convexVolumes.emplace_back(std::move(vol)); } else if (row[0] == 's') { @@ -601,13 +599,12 @@ bool InputGeom::saveGeomSet(const BuildSettings* settings) } // Convex volumes - for (int i = 0; i < convexVolumeCount; ++i) + for (ConvexVolume& vol : convexVolumes) { - ConvexVolume* vol = &convexVolumes[i]; - fprintf(fp, "v %d %d %f %f\n", vol->nverts, vol->area, vol->hmin, vol->hmax); - for (int j = 0; j < vol->nverts; ++j) + fprintf(fp, "v %d %d %f %f\n", vol.nverts, vol.area, vol.hmin, vol.hmax); + for (int j = 0; j < vol.nverts; ++j) { - fprintf(fp, "%f %f %f\n", vol->verts[j * 3 + 0], vol->verts[j * 3 + 1], vol->verts[j * 3 + 2]); + fprintf(fp, "%f %f %f\n", vol.verts[j * 3 + 0], vol.verts[j * 3 + 1], vol.verts[j * 3 + 2]); } } @@ -729,23 +726,18 @@ void InputGeom::drawOffMeshConnections(duDebugDraw* dd, bool highlight) void InputGeom::addConvexVolume(const float* verts, const int nverts, const float minh, const float maxh, unsigned char area) { - if (convexVolumeCount >= MAX_VOLUMES) - { - return; - } - ConvexVolume* vol = &convexVolumes[convexVolumeCount++]; - memset(vol, 0, sizeof(ConvexVolume)); - memcpy(vol->verts, verts, sizeof(float) * 3 * nverts); - vol->hmin = minh; - vol->hmax = maxh; - vol->nverts = nverts; - vol->area = area; + ConvexVolume vol; + memcpy(vol.verts, verts, sizeof(float) * 3 * nverts); + vol.hmin = minh; + vol.hmax = maxh; + vol.nverts = nverts; + vol.area = area; + convexVolumes.emplace_back(std::move(vol)); } void InputGeom::deleteConvexVolume(int i) { - convexVolumeCount--; - convexVolumes[i] = convexVolumes[convexVolumeCount]; + convexVolumes.erase(convexVolumes.begin() + i); } void InputGeom::drawConvexVolumes(struct duDebugDraw* dd, bool /*hilight*/) @@ -753,60 +745,57 @@ void InputGeom::drawConvexVolumes(struct duDebugDraw* dd, bool /*hilight*/) dd->depthMask(false); dd->begin(DU_DRAW_TRIS); - for (int i = 0; i < convexVolumeCount; ++i) + for (const ConvexVolume& vol : convexVolumes) { - const ConvexVolume* vol = &convexVolumes[i]; - unsigned int col = duTransCol(dd->areaToCol(vol->area), 32); - for (int j = 0, k = vol->nverts - 1; j < vol->nverts; k = j++) + unsigned int col = duTransCol(dd->areaToCol(vol.area), 32); + for (int j = 0, k = vol.nverts - 1; j < vol.nverts; k = j++) { - const float* va = &vol->verts[k * 3]; - const float* vb = &vol->verts[j * 3]; + const float* va = &vol.verts[k * 3]; + const float* vb = &vol.verts[j * 3]; - dd->vertex(vol->verts[0], vol->hmax, vol->verts[2], col); - dd->vertex(vb[0], vol->hmax, vb[2], col); - dd->vertex(va[0], vol->hmax, va[2], col); + dd->vertex(vol.verts[0], vol.hmax, vol.verts[2], col); + dd->vertex(vb[0], vol.hmax, vb[2], col); + dd->vertex(va[0], vol.hmax, va[2], col); - dd->vertex(va[0], vol->hmin, va[2], duDarkenCol(col)); - dd->vertex(va[0], vol->hmax, va[2], col); - dd->vertex(vb[0], vol->hmax, vb[2], col); + dd->vertex(va[0], vol.hmin, va[2], duDarkenCol(col)); + dd->vertex(va[0], vol.hmax, va[2], col); + dd->vertex(vb[0], vol.hmax, vb[2], col); - dd->vertex(va[0], vol->hmin, va[2], duDarkenCol(col)); - dd->vertex(vb[0], vol->hmax, vb[2], col); - dd->vertex(vb[0], vol->hmin, vb[2], duDarkenCol(col)); + dd->vertex(va[0], vol.hmin, va[2], duDarkenCol(col)); + dd->vertex(vb[0], vol.hmax, vb[2], col); + dd->vertex(vb[0], vol.hmin, vb[2], duDarkenCol(col)); } } dd->end(); dd->begin(DU_DRAW_LINES, 2.0f); - for (int i = 0; i < convexVolumeCount; ++i) + for (const ConvexVolume& vol : convexVolumes) { - const ConvexVolume* vol = &convexVolumes[i]; - unsigned int col = duTransCol(dd->areaToCol(vol->area), 220); - for (int j = 0, k = vol->nverts - 1; j < vol->nverts; k = j++) + unsigned int col = duTransCol(dd->areaToCol(vol.area), 220); + for (int j = 0, k = vol.nverts - 1; j < vol.nverts; k = j++) { - const float* va = &vol->verts[k * 3]; - const float* vb = &vol->verts[j * 3]; - dd->vertex(va[0], vol->hmin, va[2], duDarkenCol(col)); - dd->vertex(vb[0], vol->hmin, vb[2], duDarkenCol(col)); - dd->vertex(va[0], vol->hmax, va[2], col); - dd->vertex(vb[0], vol->hmax, vb[2], col); - dd->vertex(va[0], vol->hmin, va[2], duDarkenCol(col)); - dd->vertex(va[0], vol->hmax, va[2], col); + const float* va = &vol.verts[k * 3]; + const float* vb = &vol.verts[j * 3]; + dd->vertex(va[0], vol.hmin, va[2], duDarkenCol(col)); + dd->vertex(vb[0], vol.hmin, vb[2], duDarkenCol(col)); + dd->vertex(va[0], vol.hmax, va[2], col); + dd->vertex(vb[0], vol.hmax, vb[2], col); + dd->vertex(va[0], vol.hmin, va[2], duDarkenCol(col)); + dd->vertex(va[0], vol.hmax, va[2], col); } } dd->end(); dd->begin(DU_DRAW_POINTS, 3.0f); - for (int i = 0; i < convexVolumeCount; ++i) + for (const ConvexVolume& vol : convexVolumes) { - const ConvexVolume* vol = &convexVolumes[i]; - unsigned int col = duDarkenCol(duTransCol(dd->areaToCol(vol->area), 220)); - for (int j = 0; j < vol->nverts; ++j) + unsigned int col = duDarkenCol(duTransCol(dd->areaToCol(vol.area), 220)); + for (int j = 0; j < vol.nverts; ++j) { - dd->vertex(vol->verts[j * 3 + 0], vol->verts[j * 3 + 1] + 0.1f, vol->verts[j * 3 + 2], col); - dd->vertex(vol->verts[j * 3 + 0], vol->hmin, vol->verts[j * 3 + 2], col); - dd->vertex(vol->verts[j * 3 + 0], vol->hmax, vol->verts[j * 3 + 2], col); + dd->vertex(vol.verts[j * 3 + 0], vol.verts[j * 3 + 1] + 0.1f, vol.verts[j * 3 + 2], col); + dd->vertex(vol.verts[j * 3 + 0], vol.hmin, vol.verts[j * 3 + 2], col); + dd->vertex(vol.verts[j * 3 + 0], vol.hmax, vol.verts[j * 3 + 2], col); } } dd->end(); diff --git a/RecastDemo/Source/Sample_SoloMesh.cpp b/RecastDemo/Source/Sample_SoloMesh.cpp index c4c60358..10579e9c 100644 --- a/RecastDemo/Source/Sample_SoloMesh.cpp +++ b/RecastDemo/Source/Sample_SoloMesh.cpp @@ -509,16 +509,15 @@ bool Sample_SoloMesh::build() // (Optional) Marks the surface type of voxels in an area defined by a convex volume. // Useful to mark areas of differing cost. - const ConvexVolume* vols = inputGeometry->convexVolumes; - for (int i = 0; i < inputGeometry->convexVolumeCount; ++i) + for (ConvexVolume& vol : inputGeometry->convexVolumes) { rcMarkConvexPolyArea( buildContext, - vols[i].verts, - vols[i].nverts, - vols[i].hmin, - vols[i].hmax, - (unsigned char)vols[i].area, + vol.verts, + vol.nverts, + vol.hmin, + vol.hmax, + (unsigned char)vol.area, *compactHeightfield); } diff --git a/RecastDemo/Source/Sample_TempObstacles.cpp b/RecastDemo/Source/Sample_TempObstacles.cpp index b75851bd..ae8fdf8b 100644 --- a/RecastDemo/Source/Sample_TempObstacles.cpp +++ b/RecastDemo/Source/Sample_TempObstacles.cpp @@ -649,16 +649,15 @@ int Sample_TempObstacles::rasterizeTileLayers( } // (Optional) Mark areas. - const ConvexVolume* vols = inputGeometry->convexVolumes; - for (int i = 0; i < inputGeometry->convexVolumeCount; ++i) + for (ConvexVolume& vol : inputGeometry->convexVolumes) { rcMarkConvexPolyArea( buildContext, - vols[i].verts, - vols[i].nverts, - vols[i].hmin, - vols[i].hmax, - static_cast(vols[i].area), + vol.verts, + vol.nverts, + vol.hmin, + vol.hmax, + static_cast(vol.area), *rasterContext.chf); } diff --git a/RecastDemo/Source/Sample_TileMesh.cpp b/RecastDemo/Source/Sample_TileMesh.cpp index 0e0d661b..074a461a 100644 --- a/RecastDemo/Source/Sample_TileMesh.cpp +++ b/RecastDemo/Source/Sample_TileMesh.cpp @@ -1013,16 +1013,15 @@ unsigned char* Sample_TileMesh::buildTileMesh( } // (Optional) Mark areas. - const ConvexVolume* convexVolumes = inputGeometry->convexVolumes; - for (int i = 0; i < inputGeometry->convexVolumeCount; ++i) + for (ConvexVolume& vol : inputGeometry->convexVolumes) { rcMarkConvexPolyArea( buildContext, - convexVolumes[i].verts, - convexVolumes[i].nverts, - convexVolumes[i].hmin, - convexVolumes[i].hmax, - static_cast(convexVolumes[i].area), + vol.verts, + vol.nverts, + vol.hmin, + vol.hmax, + static_cast(vol.area), *compactHeightfield); } diff --git a/RecastDemo/Source/Tool_ConvexVolume.cpp b/RecastDemo/Source/Tool_ConvexVolume.cpp index 120ea084..b74d6d5c 100644 --- a/RecastDemo/Source/Tool_ConvexVolume.cpp +++ b/RecastDemo/Source/Tool_ConvexVolume.cpp @@ -169,8 +169,8 @@ void ConvexVolumeTool::onClick(const float* /*s*/, const float* p, bool shift) { // Delete int nearestIndex = -1; - const ConvexVolume* vols = geom->convexVolumes; - for (int i = 0; i < geom->convexVolumeCount; ++i) + const std::vector& vols = geom->convexVolumes; + for (int i = 0; i < static_cast(vols.size()); ++i) { if (pointInPoly(vols[i].nverts, vols[i].verts, p) && p[1] >= vols[i].hmin && p[1] <= vols[i].hmax) {