From f70cbc0dade14cf07cad774ffc8f5c903b1a5ea8 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Wed, 12 Mar 2025 02:59:12 +0000 Subject: Split Terrain::generateMeshes into smaller functions Also removes incorrect optimisation that a tile's AABB could be assumed from tile base position; in fact some faces cross the boundaries and the AABB needs to account for this. --- game/terrain.cpp | 54 +++++++++++++++++++++++++++++++++++++----------------- game/terrain.h | 9 ++++++++- 2 files changed, 45 insertions(+), 18 deletions(-) (limited to 'game') diff --git a/game/terrain.cpp b/game/terrain.cpp index d3c1d1a..f10aac6 100644 --- a/game/terrain.cpp +++ b/game/terrain.cpp @@ -30,19 +30,26 @@ Terrain::SurfaceKey::operator<(const SurfaceKey & other) const < std::tie(other.surface, other.basePosition.x, other.basePosition.y); } -void -Terrain::generateMeshes() +inline void +Terrain::copyVerticesToBuffer() const { std::ranges::transform(all_vertices(), glMappedBufferWriter {GL_ARRAY_BUFFER, verticesBuffer, n_vertices()}, [this](const auto & vertex) { return Vertex {point(vertex), normal(vertex)}; }); +} - std::map> surfaceIndices; - const auto getTile = [this](FaceHandle face) { - return point(*fv_begin(face)).xy() / TILE_SIZE; - }; - const auto indexBySurfaceAndTile = std::views::transform([this, &getTile](const auto & faceItr) { +inline GlobalPosition2D +Terrain::getTile(const FaceHandle & face) const +{ + return point(*cfv_begin(face)).xy() / TILE_SIZE; +}; + +Terrain::SurfaceIndices +Terrain::mapSurfaceFacesToIndices() const +{ + SurfaceIndices surfaceIndices; + const auto indexBySurfaceAndTile = std::views::transform([this](const auto & faceItr) { return std::pair {{getSurface(*faceItr), getTile(*faceItr)}, *faceItr}; }); const auto chunkBySurfaceAndTile = std::views::chunk_by([](const auto & face1, const auto & face2) { @@ -61,7 +68,12 @@ Terrain::generateMeshes() std::ranges::transform(fv_range(face), push, &OpenMesh::VertexHandle::idx); } } + return surfaceIndices; +} +void +Terrain::copyIndicesToBuffers(const SurfaceIndices & surfaceIndices) +{ for (const auto & [surfaceKey, indices] : surfaceIndices) { auto meshItr = meshes.find(surfaceKey); if (meshItr == meshes.end()) { @@ -77,17 +89,16 @@ Terrain::generateMeshes() .data(verticesBuffer, GL_ARRAY_BUFFER); } meshItr->second.count = static_cast(indices.size()); - if (!surfaceKey.surface) { - meshItr->second.aabb = {{surfaceKey.basePosition * TILE_SIZE || getExtents().min.z}, - {(surfaceKey.basePosition + 1) * TILE_SIZE || getExtents().max.z}}; - } - else { - meshItr->second.aabb = AxisAlignedBoundingBox::fromPoints( - indices | std::views::transform([this](const auto vertex) -> GlobalPosition3D { - return this->point(VertexHandle {static_cast(vertex)}); - })); - } + meshItr->second.aabb = AxisAlignedBoundingBox::fromPoints( + indices | std::views::transform([this](const auto vertex) { + return this->point(VertexHandle {static_cast(vertex)}); + })); } +} + +void +Terrain::pruneOrphanMeshes(const SurfaceIndices & surfaceIndices) +{ if (meshes.size() > surfaceIndices.size()) { std::erase_if(meshes, [&surfaceIndices](const auto & mesh) { return !surfaceIndices.contains(mesh.first); @@ -95,6 +106,15 @@ Terrain::generateMeshes() } } +void +Terrain::generateMeshes() +{ + copyVerticesToBuffer(); + const auto surfaceIndices = mapSurfaceFacesToIndices(); + copyIndicesToBuffers(surfaceIndices); + pruneOrphanMeshes(surfaceIndices); +} + void Terrain::tick(TickDuration) { diff --git a/game/terrain.h b/game/terrain.h index eaec01d..1a63296 100644 --- a/game/terrain.h +++ b/game/terrain.h @@ -41,9 +41,16 @@ private: struct SurfaceKey { const Surface * surface; GlobalPosition2D basePosition; - bool operator<(const SurfaceKey &) const; + inline bool operator<(const SurfaceKey &) const; }; + using SurfaceIndices = std::map>; + void copyVerticesToBuffer() const; + [[nodiscard]] SurfaceIndices mapSurfaceFacesToIndices() const; + void copyIndicesToBuffers(const SurfaceIndices &); + void pruneOrphanMeshes(const SurfaceIndices &); + [[nodiscard]] inline GlobalPosition2D getTile(const FaceHandle &) const; + glBuffer verticesBuffer; std::map meshes; Texture::Ptr grass = std::make_shared("grass.png"); -- cgit v1.2.3