From b0e86fb89d8ea94601b0244f918df07a3fa82a9e Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Mon, 26 Aug 2024 20:52:50 +0200 Subject: src/chunk: allow arbitrary amount of wall quads for rendering It's required for drawing holes on walls. --- src/chunk-walls.cpp | 72 ++++++++++++++++++++++++++++++++--------------------- src/chunk.hpp | 6 +---- 2 files changed, 44 insertions(+), 34 deletions(-) (limited to 'src') diff --git a/src/chunk-walls.cpp b/src/chunk-walls.cpp index fd59bd24..17aac134 100644 --- a/src/chunk-walls.cpp +++ b/src/chunk-walls.cpp @@ -3,9 +3,10 @@ #include "quads.hpp" #include "wall-atlas.hpp" #include "shaders/shader.hpp" -#include -#include -#include +#include +#include +#include +#include #include #include @@ -115,19 +116,31 @@ constexpr Quads::quad get_quad(float depth) std::unreachable(); } -Array make_indexes_() +ArrayView make_indexes(uint32_t count) { - auto array = Array{NoInit, chunk::max_wall_quad_count }; - for (auto i = 0uz; i < chunk::max_wall_quad_count; i++) - array[i] = Quads::quad_indexes(i); - return array; + static auto array = [] { + auto array = Array{}; + arrayReserve(array, 64); + return array; + }(); + auto i = (uint32_t)array.size(); + if (count > i) [[unlikely]] + { + arrayResize(array, NoInit, count); + for (; i < count; i++) + array.data()[i] = Quads::quad_indexes(i); + } + return array.prefix(count); } -ArrayView make_indexes(size_t max) +Array>& make_vertexes() { - static const auto indexes = make_indexes_(); - fm_assert(max <= chunk::max_wall_quad_count); - return indexes.prefix(max); + static auto array = [] { + Array> array; + arrayReserve(array, 32); + return array; + }(); + return array; } template @@ -154,6 +167,17 @@ Frame variant_from_frame(ArrayView frames, global_coords coord, var return frames[variant]; } +constexpr std::array& alloc_wall_vertexes(uint32_t& N, auto& V, auto& M, uint32_t k) +{ + constexpr uint32_t reserve = 15, mask = ~reserve; + const auto i = N, sz = ++N + reserve & mask; + fm_assert(uint32_t{(UnsignedShort)sz} == sz); + arrayResize(V, NoInit, sz); + arrayResize(M, NoInit, sz); + M[i] = (uint16_t)k; + return V[i]; +}; + template void do_wall_part(const Group& group, wall_atlas& A, chunk& c, chunk::wall_stuff& W, Array>& vertexes, @@ -220,14 +244,11 @@ void do_wall_part(const Group& group, wall_atlas& A, chunk& c, chunk::wall_stuff fm_assert(frame.size.y() >= Depth); auto start = frame.offset + Vector2ui{0, frame.size.y()} - Vector2ui{0, Depth}; const auto texcoords = Quads::texcoords_at(start, Vector2ui{Depth, Depth}, A.image_size()); - const auto i = N++; - fm_assert(i < vertexes.size()); - W.mesh_indexes[i] = (uint16_t)k; const auto depth_offset = depth_offset_for_group(); const auto depth = tile_shader::depth_value(pos, depth_offset); for (auto& v : quad) v += center; - auto& v = vertexes[i]; + auto& v = alloc_wall_vertexes(N, vertexes, W.mesh_indexes, k); for (uint8_t j = 0; j < 4; j++) v[j] = {quad[j], texcoords[j], depth}; } @@ -242,13 +263,10 @@ void do_wall_part(const Group& group, wall_atlas& A, chunk& c, chunk::wall_stuff const auto depth = tile_shader::depth_value(pos_x, pos.y, depth_offset); const auto& frame = variant_from_frame(frames, coord, variant_2, IsWest); const auto texcoords = Quads::texcoords_at(frame.offset, frame.size, A.image_size()); - const auto i = N++; - fm_assert(i < vertexes.size()); - W.mesh_indexes[i] = (uint16_t)k; auto quad = get_quad((float)Depth); for (auto& v : quad) v += center; - auto& v = vertexes[i]; + auto& v = alloc_wall_vertexes(N, vertexes, W.mesh_indexes, k); for (uint8_t j = 0; j < 4; j++) v[j] = {quad[j], texcoords[j], depth}; } @@ -261,13 +279,10 @@ void do_wall_part(const Group& group, wall_atlas& A, chunk& c, chunk::wall_stuff fm_assert(frame.size.x() > Depth); auto start = frame.offset + Vector2ui{frame.size.x(), 0} - Vector2ui{Depth, 0}; const auto texcoords = Quads::texcoords_at(start, {Depth, frame.size.y()}, A.image_size()); - const auto i = N++; - fm_assert(i < vertexes.size()); - W.mesh_indexes[i] = (uint16_t)k; auto quad = get_quad((float)Depth); for (auto& v : quad) v += center; - auto& v = vertexes[i]; + auto& v = alloc_wall_vertexes(N, vertexes, W.mesh_indexes, k); for (uint8_t j = 0; j < 4; j++) v[j] = {quad[j], texcoords[j], depth}; } @@ -277,9 +292,6 @@ void do_wall_part(const Group& group, wall_atlas& A, chunk& c, chunk::wall_stuff if (G == Group_::side || side_ok) { const auto frames = A.frames(group); - const auto i = N++; - fm_assert(i < vertexes.size()); - W.mesh_indexes[i] = (uint16_t)k; const auto frame = variant_from_frame(frames, coord, variant_2, IsWest); const auto texcoords = Quads::texcoords_at(frame.offset, frame.size, A.image_size()); const auto depth_offset = depth_offset_for_group(); @@ -287,7 +299,7 @@ void do_wall_part(const Group& group, wall_atlas& A, chunk& c, chunk::wall_stuff auto quad = get_quad((float)Depth); for (auto& v : quad) v += center; - auto& v = vertexes[i]; + auto& v = alloc_wall_vertexes(N, vertexes, W.mesh_indexes, k); for (uint8_t j = 0; j < 4; j++) v[j] = {quad[j], texcoords[j], depth}; } @@ -300,9 +312,11 @@ GL::Mesh chunk::make_wall_mesh() fm_debug_assert(_walls); uint32_t N = 0; - static auto vertexes = Array>{NoInit, max_wall_quad_count }; + auto& vertexes = make_vertexes(); auto& W = *_walls; + arrayResize(vertexes, 0); + for (uint32_t k = 0; k < TILE_COUNT; k++) { const auto coord = global_coords{_coord, local_coords{k}}; diff --git a/src/chunk.hpp b/src/chunk.hpp index e6379507..335d3440 100644 --- a/src/chunk.hpp +++ b/src/chunk.hpp @@ -107,10 +107,6 @@ public: void remove_object(size_t i); void sort_objects(); - // for drawing only - static constexpr size_t max_wall_quad_count = - TILE_COUNT*Wall::Direction_COUNT*(Wall::Group_COUNT+4); - pass_region make_pass_region(bool debug = false, ArrayView positions = {}); pass_region make_pass_region(const Search::pred& f, bool debug = false, ArrayView positions = {}); @@ -125,7 +121,7 @@ public: { std::array, 2*TILE_COUNT> atlases; std::array variants; - std::array mesh_indexes; + Array mesh_indexes; }; private: -- cgit v1.2.3