summaryrefslogtreecommitdiffhomepage
path: root/src/chunk-walls.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/chunk-walls.cpp')
-rw-r--r--src/chunk-walls.cpp533
1 files changed, 334 insertions, 199 deletions
diff --git a/src/chunk-walls.cpp b/src/chunk-walls.cpp
index fb4b6560..39faf0bd 100644
--- a/src/chunk-walls.cpp
+++ b/src/chunk-walls.cpp
@@ -2,11 +2,15 @@
#include "tile-bbox.hpp"
#include "quads.hpp"
#include "wall-atlas.hpp"
+#include "tile-bbox.hpp"
+#include "compat/unroll.hpp"
+#include "RTree-search.hpp"
#include "shaders/shader.hpp"
-#include <Corrade/Containers/ArrayViewStl.h>
-#include <Corrade/Containers/Pair.h>
-#include <Corrade/Containers/Optional.h>
+#include <cr/ArrayViewStl.h>
+#include <cr/GrowableArray.h>
+#include <cr/Optional.h>
#include <utility>
+#include <concepts>
#include <algorithm>
#include <ranges>
@@ -30,116 +34,232 @@ wall_atlas* chunk::wall_atlas_at(size_t i) const noexcept
namespace {
+using Wall::Group;
using Wall::Group_;
using Wall::Direction_;
+using Wall::Frame;
+
+template<typename T> using Vec2_ = VectorTypeFor<2, T>;
+template<typename T> using Vec3_ = VectorTypeFor<3, T>;
+
+template<typename F, size_t N>
+struct minmax_v
+{
+ VectorTypeFor<N, F> min, max;
+};
-constexpr Quads::quad get_quad(Direction_ D, Group_ G, float depth)
+struct quad_table_entry
{
- CORRADE_ASSUME(D < Direction_::COUNT);
- CORRADE_ASSUME(G < Group_::COUNT);
- constexpr Vector2 half_tile = TILE_SIZE2*.5f;
- constexpr float X = half_tile.x(), Y = half_tile.y(), Z = TILE_SIZE.z();
- const bool is_west = D == Wall::Direction_::W;
+ bool x : 1, y : 1, z : 1, dmx :1 = false, dmy : 1 = false, _fuzz : 3 = false;
+};
+static_assert(sizeof(quad_table_entry) == sizeof(uint8_t));
+template<bool IsWest>
+constexpr std::array<quad_table_entry, 4> make_quad_table_entry(Group_ G)
+{
fm_assert(G < Group_::COUNT);
+
+ constexpr bool x0 = false, x1 = true,
+ y0 = false, y1 = true,
+ z0 = false, z1 = true;
+ constexpr bool t = true, f = false;
+
switch (G)
{
using enum Group_;
case COUNT: std::unreachable();
case wall:
- if (!is_west)
+ if (!IsWest)
return {{
- { X, -Y, 0 },
- { X, -Y, Z },
- {-X, -Y, 0 },
- {-X, -Y, Z },
+ { x1, y0, z0 },
+ { x1, y0, z1 },
+ { x0, y0, z0 },
+ { x0, y0, z1 },
}};
else
return {{
- {-X, -Y, 0 },
- {-X, -Y, Z },
- {-X, Y, 0 },
- {-X, Y, Z },
+ { x0, y0, z0 },
+ { x0, y0, z1 },
+ { x0, y1, z0 },
+ { x0, y1, z1 },
}};
case side:
- if (!is_west)
+ if (!IsWest)
return {{
- { X, -Y - depth, 0 },
- { X, -Y - depth, Z },
- { X, -Y, 0 },
- { X, -Y, Z },
+ { x1, y0, z0, f, t },
+ { x1, y0, z1, f, t },
+ { x1, y0, z0 },
+ { x1, y0, z1 },
}};
else
return {{
- { -X, Y, 0 },
- { -X, Y, Z },
- { -X - depth, Y, 0 },
- { -X - depth, Y, Z },
+ { x0, y1, z0 },
+ { x0, y1, z1 },
+ { x0, y1, z0, t, f },
+ { x0, y1, z1, t, f },
}};
case top:
- if (!is_west)
+ if (!IsWest)
return {{
- { -X, -Y - depth, Z },
- { X, -Y - depth, Z },
- { -X, -Y, Z },
- { X, -Y, Z },
+ { x0, y0, z1, f, t },
+ { x1, y0, z1, f, t },
+ { x0, y0, z1 },
+ { x1, y0, z1 },
}};
else
return {{
- { -X, -Y, Z },
- { -X, Y, Z },
- { -X - depth, -Y, Z },
- { -X - depth, Y, Z },
+ { x0, y0, z1 },
+ { x0, y1, z1 },
+ { x0, y0, z1, t, f },
+ { x0, y1, z1, t, f },
}};
case corner:
- if (!is_west)
+ if (!IsWest)
return {{
- {-X, -Y, 0 },
- {-X, -Y, Z },
- {-X - depth, -Y, 0 },
- {-X - depth, -Y, Z },
+ { x0, y0, z0 },
+ { x0, y0, z1 },
+ { x0, y0, z0, t, f },
+ { x0, y0, z1, t, f },
}};
else
return {{
- {-X, -Y - depth, 0 },
- {-X, -Y - depth, Z },
- {-X, -Y, 0 },
- {-X, -Y, Z },
+ { x0, y0, z0, f, t },
+ { x0, y0, z1, f, t },
+ { x0, y0, z0 },
+ { x0, y0, z1 },
}};
}
std::unreachable();
}
-Array<Quads::indexes> make_indexes_()
+template<Group_ G, bool IsWest, typename F = float>
+constexpr auto get_quadʹ(minmax_v<F, 3> bounds, F d)
{
- auto array = Array<Quads::indexes>{NoInit, chunk::max_wall_quad_count };
- for (auto i = 0uz; i < chunk::max_wall_quad_count; i++)
- array[i] = Quads::quad_indexes(i);
+ F x[2] { bounds.min.x(), bounds.max.x() },
+ y[2] { bounds.min.y(), bounds.max.y() },
+ z[2] { bounds.min.z(), bounds.max.z() },
+ dmx[2] { 0, d },
+ dmy[2] { 0, d };
+
+ std::array<Vec3_<F>, 4> array = {};
+
+ unroll<static_array_size<decltype(array)>>([&]<typename Index>(Index) {
+ constexpr size_t i = Index::value;
+ constexpr auto table = make_quad_table_entry<IsWest>(G);
+ constexpr auto e = table[i];
+ array.data()[i] = { x[e.x] - dmx[e.dmx], y[e.y] - dmy[e.dmy], z[e.z], };
+ });
+
return array;
}
-ArrayView<const Quads::indexes> make_indexes(size_t max)
+template<Group_ G, bool IsWest, typename F = float>
+constexpr CORRADE_ALWAYS_INLINE auto get_quad(F d)
+{
+ constexpr auto half_tile = Vec2_<F>(TILE_SIZE2*.5f);
+ constexpr auto X = half_tile.x(), Y = half_tile.y(), Z = F(TILE_SIZE.z());
+
+ return get_quadʹ<G, IsWest, F>({ { -X, -Y, 0, }, { X, Y, Z, }, }, d);
+}
+
+template<bool IsWest>
+CutResult<Int>::rect get_wall_rect(local_coords tile)
{
- static const auto indexes = make_indexes_();
- fm_assert(max <= chunk::max_wall_quad_count);
- return indexes.prefix(max);
+ constexpr auto nʹ = wall_north<Int>(0, 0), wʹ = wall_west<Int>(0, 0);
+ constexpr auto t0 = !IsWest ? nʹ.first() : wʹ.first(),
+ t1 = !IsWest ? nʹ.second() : wʹ.second();
+ const auto offset = Vector2i{tile} * iTILE_SIZE2;
+ const auto min = offset + t0, max = offset + t1;
+ return { min, max };
}
-constexpr float depth_offset_for_group(Group_ G, bool is_west)
+template<bool IsWest, std::invocable<Vector2, Vector2> F>
+void cut_holes_in_wall(chunk& c, local_coords tile, Vector2i min, Vector2i max, F&& fun)
{
- CORRADE_ASSUME(G < Group_::COUNT);
- float p = is_west ? tile_shader::wall_west_offset : 0;
+ CutResult<float>::rect hole;
+
+ //constexpr auto eps = Vector2{.125f};
+ if (c.find_hole_in_bbox(hole, Vector2(min) /*- eps*/, Vector2(max) /*+ eps*/))
+ {
+ fun(min, max);
+ }
+ else
+ {
+ fm_assert(Vector2(Vector2i(hole.min)) == hole.min);
+ fm_assert(Vector2(Vector2i(hole.max)) == hole.max);
+ auto res = CutResult<Int>::cut(min, max, Vector2i(hole.min), Vector2i(hole.max));
+ if (!res.found())
+ {
+ fun(min, max);
+ }
+ else
+ {
+ for (auto i = 0u; i < res.size; i++)
+ {
+ const auto [min, max] = res.array[i];
+ cut_holes_in_wall<IsWest>(c, tile, min, max, fun);
+ }
+ }
+ }
+}
+
+struct quad_tuple
+{
+ Vector2ui tex_pos, tex_size;
+ Vector2i min, max;
+};
+
+template<bool IsWest>
+quad_tuple get_wall_quad_stuff(const CutResult<Int>::rect& geom, const CutResult<Int>::rect& orig,
+ Vector2ui orig_tex_pos, Vector2ui orig_tex_size)
+{
+ return {};
+}
+
+ArrayView<const Quads::indexes> make_indexes(uint32_t count)
+{
+ static auto arrayʹ = [] {
+ auto array = Array<Quads::indexes>{};
+ arrayReserve(array, 64);
+ return array;
+ }();
+ auto& array = 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);
+}
+
+Array<std::array<chunk::vertex, 4>>& make_vertexes()
+{
+ static auto array = [] {
+ Array<std::array<chunk::vertex, 4>> array;
+ arrayReserve(array, 32);
+ return array;
+ }();
+ return array;
+}
+
+template<Group_ G, bool IsWest>
+constexpr float depth_offset_for_group()
+{
+ static_assert(G < Group_::COUNT);
+ float p = IsWest ? tile_shader::wall_west_offset : 0;
switch (G)
{
default:
return tile_shader::wall_depth_offset + p;
- case Wall::Group_::corner:
- case Wall::Group_::side:
+ case Group_::corner:
+ case Group_::side:
return tile_shader::wall_side_offset + p;
}
}
-Wall::Frame variant_from_frame(ArrayView<const Wall::Frame> frames, global_coords coord, variant_t variant, bool is_west)
+Frame variant_from_frame(ArrayView<const Frame> frames, global_coords coord, variant_t variant, bool is_west)
{
auto sz = (unsigned)frames.size();
if (variant == (variant_t)-1)
@@ -148,168 +268,183 @@ Wall::Frame variant_from_frame(ArrayView<const Wall::Frame> frames, global_coord
return frames[variant];
}
-} // namespace
+constexpr std::array<chunk::vertex, 4>& 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];
+};
-GL::Mesh chunk::make_wall_mesh()
+template<Group_ G, bool IsWest>
+void do_wall_part(const Group& group, wall_atlas& A, chunk& c, chunk::wall_stuff& W,
+ Array<std::array<chunk::vertex, 4>>& vertexes,
+ global_coords coord, uint32_t& N, uint32_t tile)
{
- fm_debug_assert(_walls);
- uint32_t N = 0;
+ if (!group.is_defined)
+ return;
- static auto vertexes = Array<std::array<vertex, 4>>{NoInit, max_wall_quad_count };
+ const uint32_t k = tile*2 + IsWest;
+ constexpr auto D = IsWest ? Direction_::W : Direction_::N;
+ const auto variant_2 = W.variants[k];
+ const auto pos = local_coords{tile};
+ const auto center = Vector3(pos) * TILE_SIZE;
+ const auto& dir = A.calc_direction(D);
+ const auto Depth = A.info().depth;
- for (uint32_t k = 0; k < 2*TILE_COUNT; k++)
+ if constexpr(G == Group_::side) [[unlikely]]
{
- const bool is_west = k & 1;
- const auto D = is_west ? Wall::Direction_::W : Wall::Direction_::N;
- const auto& atlas = _walls->atlases[k];
- if (!atlas)
- continue;
- const auto variant_2 = _walls->variants[k];
- const auto pos = local_coords{k / 2u};
- const auto center = Vector3(pos) * TILE_SIZE;
- const auto& dir = atlas->calc_direction(D);
- const auto coord = global_coords{_coord, pos};
- const auto Depth = atlas->info().depth;
-
- for (auto [s, member, G] : Wall::Direction::groups_for_draw)
- {
- CORRADE_ASSUME(G < Group_::COUNT);
-
- bool side_ok = G == Wall::Group_::side;
+ bool corner_ok = false, pillar_ok = false;
- if (!(dir.*member).is_defined)
- continue;
-
- if (G == Wall::Group_::side) [[unlikely]]
+ if constexpr(!IsWest)
+ {
+ if (auto t = c.at_offset(pos, {-1, 0}); !(t && t->wall_north_atlas()))
{
- bool corner_ok = false, pillar_ok = false;
-
- if (!is_west)
- {
- if (auto t = at_offset_(pos, {-1, 0}); !(t && t->wall_north_atlas()))
- {
- if (_walls->atlases[k+1]) // west on same tile
- pillar_ok = true;
- if (auto t = at_offset_(pos, {0, -1}); t && t->wall_west_atlas())
- corner_ok = true;
- }
- if (side_ok)
- if (auto t = at_offset_(pos, {1, -1}); t && t->wall_west_atlas())
- side_ok = false;
- if (side_ok)
- if (auto t = at_offset_(pos, {1, -1}); t && t->wall_west_atlas())
- side_ok = false;
- }
- else
- {
- if (auto t = at_offset_(pos, {0, -1}); !(t && t->wall_west_atlas()))
- if (auto t = at_offset_(pos, {-1, 0}); t && t->wall_north_atlas())
- corner_ok = true;
- if (side_ok)
- if (auto t = at_offset_(pos, {-1, 1}); t && t->wall_north_atlas())
- side_ok = false;
- }
-
- if (pillar_ok) [[unlikely]]
- {
- if (dir.top.is_defined)
- {
- const auto frames = atlas->frames(dir.top);
- const auto frame = variant_from_frame(frames, coord, variant_2, is_west);
- constexpr Vector2 half_tile = TILE_SIZE2*.5f;
- constexpr float X = half_tile.x(), Y = half_tile.y(), Z = TILE_SIZE.z();
- Quads::quad quad = {{
- { -X - Depth, -Y - Depth, Z },
- { -X, -Y - Depth, Z },
- { -X - Depth, -Y, Z },
- { -X, -Y, Z }
- }};
- fm_assert(frame.size.x() == Depth);
- 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}, atlas->image_size());
- const auto i = N++;
- fm_assert(i < vertexes.size());
- _walls->mesh_indexes[i] = (uint16_t)k;
- const auto depth_offset = depth_offset_for_group(Group_::top, is_west);
- const auto depth = tile_shader::depth_value(pos, depth_offset);
- auto& v = vertexes[i];
- for (auto& v : quad)
- v += center;
- for (uint8_t j = 0; j < 4; j++)
- v[j] = { quad[j], texcoords[j], depth };
- }
- }
- if (corner_ok) [[unlikely]]
- {
- if (dir.corner.is_defined)
- {
- const auto frames = atlas->frames(dir.corner);
- const auto depth_offset = depth_offset_for_group(Group_::corner, is_west);
- const auto pos_x = !is_west ? (float)pos.x : (float)pos.x - 1;
- const auto depth = tile_shader::depth_value(pos_x, pos.y, depth_offset);
- const auto& frame = variant_from_frame(frames, coord, variant_2, is_west);
- const auto texcoords = Quads::texcoords_at(frame.offset, frame.size, atlas->image_size());
- const auto i = N++;
- fm_assert(i < vertexes.size());
- _walls->mesh_indexes[i] = (uint16_t)k;
- auto& v = vertexes[i];
- auto quad = get_quad(D, Group_::corner, (float)Depth);
- for (auto& v : quad)
- v += center;
- for (uint8_t j = 0; j < 4; j++)
- v[j] = { quad[j], texcoords[j], depth };
- }
- else if (dir.wall.is_defined) [[likely]]
- {
- const auto frames = atlas->frames(dir.wall);
- const auto depth_offset = depth_offset_for_group(Group_::corner, is_west);
- const auto depth = tile_shader::depth_value(!is_west ? (float)pos.x : (float)pos.x - 1, depth_offset);
- const auto frame = variant_from_frame(frames, coord, variant_2, is_west);
- 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()}, atlas->image_size());
- const auto i = N++;
- fm_assert(i < vertexes.size());
- _walls->mesh_indexes[i] = (uint16_t)k;
- auto& v = vertexes[i];
- auto quad = get_quad(D, Group_::corner, (float)Depth);
- for (auto& v : quad)
- v += center;
- for (uint8_t j = 0; j < 4; j++)
- v[j] = { quad[j], texcoords[j], depth };
- }
- }
+ if (W.atlases[k + 1]) // west on same tile
+ pillar_ok = true;
+ if (auto t = c.at_offset(pos, {0, -1}); t && t->wall_west_atlas())
+ corner_ok = true;
}
+ }
+ else
+ {
+ if (auto t = c.at_offset(pos, {0, -1}); !(t && t->wall_west_atlas()))
+ if (auto t = c.at_offset(pos, {-1, 0}); t && t->wall_north_atlas())
+ corner_ok = true;
+ }
- if (G != Wall::Group_::side || side_ok) [[likely]]
+ if (pillar_ok) [[unlikely]]
+ {
+ if (dir.top.is_defined)
{
- const auto& group = dir.*member;
- const auto frames = atlas->frames(group);
-
- const auto i = N++;
- fm_assert(i < vertexes.size());
- _walls->mesh_indexes[i] = (uint16_t)k;
- const auto frame = variant_from_frame(frames, coord, variant_2, is_west);
- const auto texcoords = Quads::texcoords_at(frame.offset, frame.size, atlas->image_size());
- const auto depth_offset = depth_offset_for_group(G, is_west);
+ const auto frames = A.frames(dir.top);
+ const auto frame = variant_from_frame(frames, coord, variant_2, IsWest);
+ constexpr Vector2 half_tile = TILE_SIZE2 * .5f;
+ constexpr float X = half_tile.x(), Y = half_tile.y(), Z = TILE_SIZE.z();
+ const auto Depthʹ = (float)(int)Depth;
+ Quads::quad quad = {{
+ {-X - Depthʹ, -Y - Depthʹ, Z},
+ {-X, -Y - Depthʹ, Z},
+ {-X - Depthʹ, -Y, Z},
+ {-X, -Y, Z},
+ }};
+ fm_assert(frame.size.x() == Depth);
+ 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 depth_offset = depth_offset_for_group<Group_::top, IsWest>();
const auto depth = tile_shader::depth_value(pos, depth_offset);
- auto quad = get_quad(D, G, (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 };
+ v[j] = {quad[j], texcoords[j], depth};
}
}
+ if (corner_ok) [[unlikely]]
+ {
+ if (dir.corner.is_defined)
+ {
+ const auto frames = A.frames(dir.corner);
+ const auto depth_offset = depth_offset_for_group<Group_::corner, IsWest>();
+ const auto pos_x = !IsWest ? (float)pos.x : (float)pos.x - 1;
+ 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());
+ auto quad = get_quad<Group_::corner, IsWest>((float)Depth);
+ for (auto& v : quad)
+ v += center;
+ 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};
+ }
+ else if (dir.wall.is_defined) [[likely]]
+ {
+ const auto frames = A.frames(dir.wall);
+ const auto depth_offset = depth_offset_for_group<Group_::corner, IsWest>();
+ const auto depth = tile_shader::depth_value(!IsWest ? (float)pos.x : (float)pos.x - 1, (float)pos.y, depth_offset);
+ const auto frame = variant_from_frame(frames, coord, variant_2, IsWest);
+ 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());
+ auto quad = get_quad<Group_::corner, IsWest>((float)Depth);
+ for (auto& v : quad)
+ v += center;
+ 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};
+ }
+ }
+ }
+
+ {
+ const auto frames = A.frames(group);
+ 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<G, IsWest>();
+ const auto depth = tile_shader::depth_value(pos, depth_offset);
+ auto quad = get_quad<G, IsWest>((float)Depth);
+ for (auto& v : quad)
+ v += center;
+ 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};
+ }
+}
+
+} // namespace
+
+GL::Mesh chunk::make_wall_mesh()
+{
+ fm_debug_assert(_walls);
+
+ uint32_t N = 0;
+#ifdef __CLION_IDE__
+ extern const uint32_t _foo; N = _foo;
+#endif
+
+ 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}};
+
+ static_assert(Wall::Group_COUNT == /* 5 */ 4);
+ static_assert((int)Direction_::COUNT == 2);
+
+ if (auto* A_nʹ = W.atlases[k*2 + 0].get())
+ {
+ auto& A_n = *A_nʹ;
+ const auto& dir = A_n.calc_direction(Direction_::N);
+ do_wall_part<Group_::wall, false>(dir.wall, A_n, *this, W, vertexes, coord, N, k);
+ do_wall_part<Group_::side, false>(dir.side, A_n, *this, W, vertexes, coord, N, k);
+ do_wall_part<Group_::top, false>(dir.top, A_n, *this, W, vertexes, coord, N, k);
+ }
+ if (auto* A_wʹ = W.atlases[k*2 + 1].get())
+ {
+ auto& A_w = *A_wʹ;
+ const auto& dir = A_w.calc_direction(Direction_::W);
+ do_wall_part<Group_::wall, true>(dir.wall, A_w, *this, W, vertexes, coord, N, k);
+ do_wall_part<Group_::side, true>(dir.side, A_w, *this, W, vertexes, coord, N, k);
+ do_wall_part<Group_::top, true>(dir.top, A_w, *this, W, vertexes, coord, N, k);
+ }
}
+ if (N == 0)
+ return GL::Mesh{NoCreate};
+
ranges::sort(ranges::zip_view(vertexes.prefix(N),
- ArrayView<uint_fast16_t>{_walls->mesh_indexes.data(), N}),
+ ArrayView{_walls->mesh_indexes.data(), N}),
[&A = _walls->atlases](const auto& a, const auto& b) {
const auto& [av, ai] = a;
const auto& [bv, bi] = b;
- return A[ai] < A[bi];
+ return A[ai].get() < A[bi].get();
});
auto vertex_view = std::as_const(vertexes).prefix(N);