diff options
author | Dan Goodliffe <dan@randomdan.homeip.net> | 2025-03-12 02:59:12 +0000 |
---|---|---|
committer | Dan Goodliffe <dan@randomdan.homeip.net> | 2025-03-12 02:59:12 +0000 |
commit | f70cbc0dade14cf07cad774ffc8f5c903b1a5ea8 (patch) | |
tree | 6dff7eb8ff1deaa4b11697d7b5a27fac8bff3432 /game/terrain.cpp | |
parent | Perfectly forward range when materializing (diff) | |
download | ilt-f70cbc0dade14cf07cad774ffc8f5c903b1a5ea8.tar.bz2 ilt-f70cbc0dade14cf07cad774ffc8f5c903b1a5ea8.tar.xz ilt-f70cbc0dade14cf07cad774ffc8f5c903b1a5ea8.zip |
Split Terrain::generateMeshes into smaller functionsculling
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.
Diffstat (limited to 'game/terrain.cpp')
-rw-r--r-- | game/terrain.cpp | 54 |
1 files changed, 37 insertions, 17 deletions
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<Vertex> {GL_ARRAY_BUFFER, verticesBuffer, n_vertices()}, [this](const auto & vertex) { return Vertex {point(vertex), normal(vertex)}; }); +} - std::map<SurfaceKey, std::vector<GLuint>> 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<SurfaceKey, FaceHandle> {{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<GLsizei>(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<GlobalDistance>::fromPoints( - indices | std::views::transform([this](const auto vertex) -> GlobalPosition3D { - return this->point(VertexHandle {static_cast<int>(vertex)}); - })); - } + meshItr->second.aabb = AxisAlignedBoundingBox<GlobalDistance>::fromPoints( + indices | std::views::transform([this](const auto vertex) { + return this->point(VertexHandle {static_cast<int>(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); @@ -96,6 +107,15 @@ Terrain::generateMeshes() } void +Terrain::generateMeshes() +{ + copyVerticesToBuffer(); + const auto surfaceIndices = mapSurfaceFacesToIndices(); + copyIndicesToBuffers(surfaceIndices); + pruneOrphanMeshes(surfaceIndices); +} + +void Terrain::tick(TickDuration) { } |