diff options
author | Stanislaw Halik <sthalik@misaki.pl> | 2023-12-09 08:51:08 +0100 |
---|---|---|
committer | Stanislaw Halik <sthalik@misaki.pl> | 2023-12-09 08:51:08 +0100 |
commit | b8b9e24acff21404943252f70ba137c7a8d0be72 (patch) | |
tree | 7586796f7ca6d192490eed1778a388d81efc1d0a | |
parent | 6dcc095ee5a7a26060e6650afa0a754f404584ea (diff) |
w
-rw-r--r-- | serialize/wall-atlas.cpp | 6 | ||||
-rw-r--r-- | src/chunk-walls.cpp | 97 | ||||
-rw-r--r-- | src/chunk.hpp | 11 | ||||
-rw-r--r-- | src/wall-atlas.cpp | 28 | ||||
-rw-r--r-- | src/wall-atlas.hpp | 7 | ||||
-rw-r--r-- | src/wall-defs.hpp | 4 | ||||
-rw-r--r-- | test/wall-atlas.cpp | 4 | ||||
-rw-r--r-- | wall-tileset-tool/main.cpp | 100 |
8 files changed, 142 insertions, 115 deletions
diff --git a/serialize/wall-atlas.cpp b/serialize/wall-atlas.cpp index dfc77bc3..c0e7df03 100644 --- a/serialize/wall-atlas.cpp +++ b/serialize/wall-atlas.cpp @@ -222,8 +222,6 @@ Group read_group_metadata(const json& jgroup) if (jgroup.contains("pixel-size")) val.pixel_size = jgroup["pixel-size"]; - if (jgroup.contains("from-rotation") && !jgroup["from-rotation"].is_null()) - val.from_rotation = (uint8_t)direction_index_from_name(std::string{ jgroup["from-rotation"] }); if (jgroup.contains("mirrored")) val.mirrored = !!jgroup["mirrored"]; @@ -298,10 +296,6 @@ void write_group_metadata(json& jgroup, const Group& val) jgroup["tint-mult"] = val.tint_mult; jgroup["tint-add"] = val.tint_add; } - if (val.from_rotation != group_defaults.from_rotation) - jgroup["from-rotation"] = direction_index_to_name(val.from_rotation); - else - jgroup["from-rotation"] = nullptr; jgroup["mirrored"] = val.mirrored; } diff --git a/src/chunk-walls.cpp b/src/chunk-walls.cpp index 59c20434..f11242ac 100644 --- a/src/chunk-walls.cpp +++ b/src/chunk-walls.cpp @@ -3,7 +3,7 @@ #include "quads.hpp" #include "wall-atlas.hpp" #include "shaders/shader.hpp" -#include <Corrade/Containers/ArrayView.h> +#include <Corrade/Containers/ArrayViewStl.h> #include <Corrade/Containers/PairStl.h> #include <algorithm> @@ -15,6 +15,14 @@ void chunk::ensure_alloc_walls() _walls = Pointer<wall_stuff>{InPlaceInit}; } +wall_atlas* chunk::wall_atlas_at(size_t i) const noexcept +{ + if (!_walls) [[unlikely]] + return {}; + fm_debug_assert(i < TILE_COUNT*2); + return _walls->atlases[i].get(); +} + namespace { constexpr Vector2 half_tile = TILE_SIZE2*.5f; @@ -28,7 +36,7 @@ template<Group_ G, bool IsWest> constexpr std::array<Vector3, 4> make_wall_verte // ----------------------- // corner left -template<> std::array<Vector3, 4> constexpr make_wall_vertex_data<Group_::corner_L, false>(float) +template<> quad constexpr make_wall_vertex_data<Group_::corner_L, false>(float) { constexpr float x_offset = (float)(unsigned)X; return {{ @@ -40,7 +48,7 @@ template<> std::array<Vector3, 4> constexpr make_wall_vertex_data<Group_::corner } // corner right -template<> std::array<Vector3, 4> constexpr make_wall_vertex_data<Group_::corner_R, true>(float) +template<> quad constexpr make_wall_vertex_data<Group_::corner_R, true>(float) { constexpr float y_offset = TILE_SIZE.y() - (float)(unsigned)Y; return {{ @@ -52,7 +60,7 @@ template<> std::array<Vector3, 4> constexpr make_wall_vertex_data<Group_::corner } // wall north -template<> std::array<Vector3, 4> constexpr make_wall_vertex_data<Group_::wall, false>(float) +template<> quad constexpr make_wall_vertex_data<Group_::wall, false>(float) { return {{ { X, -Y, Z }, @@ -63,7 +71,7 @@ template<> std::array<Vector3, 4> constexpr make_wall_vertex_data<Group_::wall, } // wall west -template<> std::array<Vector3, 4> constexpr make_wall_vertex_data<Group_::wall, true>(float) +template<> quad constexpr make_wall_vertex_data<Group_::wall, true>(float) { return {{ {-X, -Y, Z }, @@ -73,20 +81,8 @@ template<> std::array<Vector3, 4> constexpr make_wall_vertex_data<Group_::wall, }}; } -// overlay north -template<> std::array<Vector3, 4> constexpr make_wall_vertex_data<Group_::overlay, false>(float depth) -{ - return make_wall_vertex_data<Wall::Group_::wall, false>(depth); -} - -// overlay west -template<> std::array<Vector3, 4> constexpr make_wall_vertex_data<Group_::overlay, true>(float depth) -{ - return make_wall_vertex_data<Wall::Group_::wall, true>(depth); -} - // side north -template<> std::array<Vector3, 4> constexpr make_wall_vertex_data<Group_::side, false>(float depth) +template<> quad constexpr make_wall_vertex_data<Group_::side, false>(float depth) { auto left = Vector2{X, -Y }, right = Vector2{left.x(), left.y() - depth }; @@ -99,7 +95,7 @@ template<> std::array<Vector3, 4> constexpr make_wall_vertex_data<Group_::side, } // side west -template<> std::array<Vector3, 4> constexpr make_wall_vertex_data<Group_::side, true>(float depth) +template<> quad constexpr make_wall_vertex_data<Group_::side, true>(float depth) { auto right = Vector2{ -X, Y }; auto left = Vector2{ right.x() - depth, right.y() }; @@ -112,7 +108,7 @@ template<> std::array<Vector3, 4> constexpr make_wall_vertex_data<Group_::side, } // top north -template<> std::array<Vector3, 4> constexpr make_wall_vertex_data<Group_::top, false>(float depth) +template<> quad constexpr make_wall_vertex_data<Group_::top, false>(float depth) { auto top_right = Vector2{X, Y - depth }, bottom_right = Vector2{top_right.x(), Y }, @@ -127,7 +123,7 @@ template<> std::array<Vector3, 4> constexpr make_wall_vertex_data<Group_::top, f } // top west -template<> std::array<Vector3, 4> constexpr make_wall_vertex_data<Group_::top, true>(float depth) +template<> quad constexpr make_wall_vertex_data<Group_::top, true>(float depth) { auto top_right = Vector2{-X, -Y }, top_left = Vector2{top_right.x() - depth, top_right.y() }, @@ -144,32 +140,58 @@ template<> std::array<Vector3, 4> constexpr make_wall_vertex_data<Group_::top, t // ----------------------- +Array<Quads::indexes> make_indexes_() +{ + auto array = Array<Quads::indexes>{NoInit, chunk::max_wall_mesh_size}; + for (auto i = 0uz; i < chunk::max_wall_mesh_size; i++) + array[i] = quad_indexes(i); + return array; +} + +ArrayView<const Quads::indexes> make_indexes(size_t max) +{ + static const auto indexes = make_indexes_(); + fm_assert(max < chunk::max_wall_mesh_size); + return indexes.prefix(max); +} + } // namespace -fm_noinline GL::Mesh chunk::make_wall_mesh(size_t count) { fm_debug_assert(_walls); + fm_debug_assert(count > 0); //std::array<std::array<vertex, 4>, TILE_COUNT*2> vertexes; - vertex vertexes[TILE_COUNT*2][4]; + //vertex vertexes[TILE_COUNT*2][4]; + uint32_t i = 0, N = 0; + + static auto vertexes = Array<vertex>{NoInit, max_wall_mesh_size}; + for (auto k = 0uz; k < count; k++) { - const uint16_t i = _walls->indexes[k]; + const uint_fast16_t i = _walls->mesh_indexes[k]; const auto& atlas = _walls->atlases[i]; - const auto& variant = _walls->variants[i]; + fm_assert(atlas != nullptr); + const auto variant = _walls->variants[i]; const local_coords pos{i / 2u}; const auto center = Vector3(pos) * TILE_SIZE; - const auto quad = i & 1 ? wall_quad_W(center, TILE_SIZE) : wall_quad_N(center, TILE_SIZE); + const auto& dir = atlas->calc_direction(i & 1 ? Wall::Direction_::W : Wall::Direction_::N); + // ... + + //const auto quad = i & 1 ? wall_quad_W(center, TILE_SIZE) : wall_quad_N(center, TILE_SIZE); const float depth = tile_shader::depth_value(pos, tile_shader::wall_depth_offset); - const auto texcoords = atlas->texcoords_for_id(variant); + //const auto texcoords = atlas->texcoords_for_id(variant); auto& v = vertexes[k]; for (auto j = 0uz; j < 4; j++) v[j] = { quad[j], texcoords[j], depth, }; } - auto indexes = make_index_array<2>(count); - const auto vertex_view = ArrayView{&vertexes[0], count}; - const auto vert_index_view = ArrayView{indexes.data(), count}; + auto vertex_view = vertexes.prefix(N); + auto index_view = make_indexes(i); + + //auto indexes = make_index_array<2>(count); + //const auto vertex_view = ArrayView{&vertexes[0], count}; + //const auto vert_index_view = ArrayView{indexes.data(), count}; GL::Mesh mesh{GL::MeshPrimitive::Triangles}; mesh.addVertexBuffer(GL::Buffer{vertex_view}, 0, tile_shader::Position{}, tile_shader::TextureCoordinates{}, tile_shader::Depth{}) @@ -184,21 +206,24 @@ auto chunk::ensure_wall_mesh() noexcept -> wall_mesh_tuple return {wall_mesh, {}, 0}; if (!_walls_modified) - return { wall_mesh, _walls->wall_indexes, size_t(wall_mesh.count()/6) }; + return { wall_mesh, _walls->mesh_indexes, size_t(wall_mesh.count()/6) }; _walls_modified = false; size_t count = 0; for (auto i = 0uz; i < TILE_COUNT*2; i++) - if (_walls->_wall_atlases[i]) - _walls->wall_indexes[count++] = uint16_t(i); + if (_walls->atlases[i]) + _walls->mesh_indexes[count++] = uint16_t(i); + + if (count == 0) + return {wall_mesh, {}, 0}; - std::sort(_walls->wall_indexes.data(), _walls->wall_indexes.data() + (ptrdiff_t)count, + std::sort(_walls->mesh_indexes.data(), _walls->mesh_indexes.data() + (ptrdiff_t)count, [this](uint16_t a, uint16_t b) { - return _walls->_wall_atlases[a] < _walls->_wall_atlases[b]; + return _walls->atlases[a] < _walls->atlases[b]; }); wall_mesh = make_wall_mesh(count); - return { wall_mesh, _walls->wall_indexes, count }; + return { wall_mesh, _walls->mesh_indexes, count }; } } // namespace floormat diff --git a/src/chunk.hpp b/src/chunk.hpp index dc80d42e..067b8811 100644 --- a/src/chunk.hpp +++ b/src/chunk.hpp @@ -79,7 +79,7 @@ struct chunk final }; struct wall_mesh_tuple final { GL::Mesh& mesh; - const ArrayView<const uint16_t> ids; + const ArrayView<const uint_fast16_t> ids; const size_t size; }; struct topo_sort_data; @@ -99,6 +99,7 @@ struct chunk final void ensure_alloc_walls(); ground_mesh_tuple ensure_ground_mesh() noexcept; tile_atlas* ground_atlas_at(size_t i) const noexcept; + wall_atlas* wall_atlas_at(size_t i) const noexcept; wall_mesh_tuple ensure_wall_mesh() noexcept; scenery_mesh_tuple ensure_scenery_mesh(scenery_scratch_buffers buffers) noexcept; @@ -116,6 +117,9 @@ struct chunk final void remove_object(size_t i); const std::vector<std::shared_ptr<object>>& objects() const; + // for drawing only + static constexpr size_t max_wall_mesh_size = TILE_COUNT*Wall::Direction_COUNT*Wall::Group_COUNT; + private: struct ground_stuff { @@ -129,10 +133,9 @@ private: { std::array<std::shared_ptr<wall_atlas>, 2*TILE_COUNT> atlases; std::array<variant_t, 2*TILE_COUNT> variants; - std::array<uint_fast16_t, 2*TILE_COUNT> indexes; - size_t count_N = 0, count_W = 0; - bool empty() const { return count_N == 0 && count_W == 0; } + std::array<uint_fast16_t, max_wall_mesh_size> mesh_indexes; + uint32_t mesh_quad_count = 0; }; Pointer<ground_stuff> _ground; diff --git a/src/wall-atlas.cpp b/src/wall-atlas.cpp index b08afbb3..aff48c58 100644 --- a/src/wall-atlas.cpp +++ b/src/wall-atlas.cpp @@ -1,5 +1,6 @@ #include "wall-atlas.hpp" -#include "compat/exception.hpp" +#include "compat/assert.hpp" +//#include "compat/exception.hpp" #include "src/tile-defs.hpp" #include <utility> #include <Corrade/Containers/ArrayViewStl.h> @@ -24,7 +25,6 @@ Vector2ui wall_atlas::expected_size(unsigned depth, Group_ group) switch (group) { using enum Group_; - case overlay: case wall: return { size.x(), size.z() }; case top: @@ -45,7 +45,6 @@ wall_atlas::wall_atlas(wall_atlas_def def, String path, const ImageView2D& img) _info{std::move(def.header)}, _path{std::move(path)}, _direction_map{def.direction_map} { - // todo resolve `from_rotation` here _texture.setLabel(_path) .setWrapping(GL::SamplerWrapping::ClampToEdge) .setMagnificationFilter(GL::SamplerFilter::Nearest) @@ -113,6 +112,28 @@ auto wall_atlas::direction(size_t dir) const -> const Direction* return get_Direction(Direction_(dir)); } +auto wall_atlas::calc_direction(Direction_ dir) const -> const Direction& +{ + if (auto dai = _direction_map[(size_t)dir]) + return _dir_array[dai.val]; + CORRADE_ASSUME(dir < Direction_::COUNT); + switch (dir) + { + case Direction_::N: + if (auto dai = _direction_map[(size_t)Direction_::W]) + return _dir_array[dai.val]; + break; + case Direction_::W: + if (auto dai = _direction_map[(size_t)Direction_::N]) + return _dir_array[dai.val]; + break; + case Direction_::COUNT: + std::unreachable(); + break; + } + fm_abort("wall_atlas: can't find direction '%d'", (int)dir); +} + uint8_t wall_atlas::direction_count() const { return (uint8_t)_dir_array.size(); } auto wall_atlas::raw_frame_array() const -> ArrayView<const Frame> { return _frame_array; } GL::Texture2D& wall_atlas::texture() { fm_debug_assert(_texture.id()); return _texture; } @@ -154,7 +175,6 @@ bool Group::operator==(const Group& other) const noexcept { bool ret = index == other.index && count == other.count && pixel_size == other.pixel_size && - from_rotation == other.from_rotation && mirrored == other.mirrored && default_tint == other.default_tint; if (!ret) diff --git a/src/wall-atlas.hpp b/src/wall-atlas.hpp index c84bac1b..7fb53125 100644 --- a/src/wall-atlas.hpp +++ b/src/wall-atlas.hpp @@ -28,7 +28,6 @@ struct Group Vector2ui pixel_size; Color4 tint_mult{1,1,1,1}; Color3 tint_add{}; - uint8_t from_rotation = (uint8_t)-1; // applies only to images; todo remove it? bool mirrored : 1 = false, default_tint : 1 = true, is_defined : 1 = false; @@ -54,7 +53,6 @@ struct Direction static constexpr inline member_tuple groups[] = { { "wall"_s, &Direction::wall, Group_::wall }, - { "overlay"_s, &Direction::overlay, Group_::overlay }, { "side"_s, &Direction::side, Group_::side }, { "top"_s, &Direction::top, Group_::top }, { "corner-L"_s, &Direction::corner_L, Group_::corner_L, }, @@ -116,7 +114,7 @@ class wall_atlas final Info _info; String _path; GL::Texture2D _texture{NoCreate}; - std::array<DirArrayIndex, 4> _direction_map; + std::array<DirArrayIndex, Wall::Direction_COUNT> _direction_map; Direction* get_Direction(Direction_ num) const; @@ -132,6 +130,7 @@ public: const Group* group(size_t dir, Group_ tag) const; const Group* group(const Direction& dir, Group_ group) const; const Direction* direction(size_t dir) const; + const Direction& calc_direction(Direction_ dir) const; uint8_t direction_count() const; ArrayView<const Frame> frames(const Group& a) const; ArrayView<const Frame> raw_frame_array() const; @@ -153,8 +152,6 @@ public: static constexpr dir_tuple directions[] = { { "n"_s, Direction_::N }, - { "e"_s, Direction_::E }, - { "s"_s, Direction_::S }, { "w"_s, Direction_::W }, }; }; diff --git a/src/wall-defs.hpp b/src/wall-defs.hpp index 05af548c..26f3df4f 100644 --- a/src/wall-defs.hpp +++ b/src/wall-defs.hpp @@ -3,9 +3,9 @@ namespace floormat::Wall { -enum class Group_ : uint8_t { overlay, corner_L, corner_R, wall, side, top, COUNT }; +enum class Group_ : uint8_t { corner_L, corner_R, wall, side, top, COUNT }; -enum class Direction_ : uint8_t { N, E, S, W, COUNT }; +enum class Direction_ : uint8_t { N, W, COUNT }; constexpr inline auto Direction_COUNT = (size_t)Wall::Direction_::COUNT; constexpr inline auto Group_COUNT = (size_t)Wall::Group_::COUNT; diff --git a/test/wall-atlas.cpp b/test/wall-atlas.cpp index 53c8b2de..a130c35f 100644 --- a/test/wall-atlas.cpp +++ b/test/wall-atlas.cpp @@ -65,7 +65,6 @@ void test_read_groups(StringView filename) fm_assert(dir.wall.pixel_size == Vector2ui{} ); fm_assert(dir.overlay.default_tint == false ); fm_assert(dir.wall.mirrored == false ); - fm_assert(dir.wall.from_rotation == (uint8_t)-1 ); fm_assert(dir.side.pixel_size == Vector2ui{42, 192} ); fm_assert(dir.side.default_tint == true ); fm_assert(dir.top.default_tint == true ); @@ -98,9 +97,6 @@ void test_read_groups(StringView filename) fm_assert(dir_index); const auto& dir = atlas.direction_array[dir_index.val]; fm_assert(dir.side.pixel_size != group_defaults.pixel_size); - fm_assert(dir.side.from_rotation == group_defaults.from_rotation); - fm_assert(dir.corner_L.from_rotation != group_defaults.from_rotation); - fm_assert(dir.corner_L.from_rotation == (uint8_t)Direction_::N); return atlas; } diff --git a/wall-tileset-tool/main.cpp b/wall-tileset-tool/main.cpp index a7fc0b6e..128b21d2 100644 --- a/wall-tileset-tool/main.cpp +++ b/wall-tileset-tool/main.cpp @@ -166,73 +166,65 @@ bool do_group(state st, size_t i, size_t j, Group& new_group) new_group.is_defined = true; new_group.pixel_size = Vector2ui(expected_size); - if (old_group.from_rotation == (uint8_t)-1) + for (;;) { - for (;;) + auto filename = asformat("{}/{:04}.png"_cf, path, count+1); + if (!Path::exists(filename)) + break; + count++; + if (Path::isDirectory(filename)) [[unlikely]] { - auto filename = asformat("{}/{:04}.png"_cf, path, count+1); - if (!Path::exists(filename)) - break; - count++; - if (Path::isDirectory(filename)) [[unlikely]] - { - ERR << "fatal: path" << quoted(filename) << "is a directory!"; - return false; - } - - cv::Mat mat = cv::imread(filename, cv::IMREAD_ANYCOLOR), mat2; - if ((Group_)j == Group_::top) - { - cv::rotate(mat, mat2, cv::ROTATE_90_COUNTERCLOCKWISE); - using std::swap; - swap(mat, mat2); - } - - const auto size = Vector2ui{(unsigned)mat.cols, (unsigned)mat.rows}; - - if (size != expected_size) [[unlikely]] - { - ERR << "fatal: wrong image size, expected" - << resolution{expected_size} << colon(',') - << "actual" << resolution{size} - << "-- file" << filename; - return false; - } - - cv::Mat4b buf; - if (mat.channels() == 4) - st.opts.use_alpha = true; - if (!convert_to_bgra32(mat, buf)) [[unlikely]] - { - ERR << "fatal: unknown image pixel format:" - << "channels" << mat.channels() << colon(',') - << "depth" << cv::depthToString(mat.depth()) << colon(',') - << "type" << cv::typeToString(mat.type()) << colon(',') - << "for" << quoted(filename); - return false; - } - - st.frames.push_back({.mat = std::move(buf)}); + ERR << "fatal: path" << quoted(filename) << "is a directory!"; + return false; } - if (count == 0) + cv::Mat mat = cv::imread(filename, cv::IMREAD_ANYCOLOR), mat2; + if ((Group_)j == Group_::top) { - ERR << "fatal: no files found for" << quoted2(dir_name) << "/" << quoted2(group_name); + cv::rotate(mat, mat2, cv::ROTATE_90_COUNTERCLOCKWISE); + using std::swap; + swap(mat, mat2); + } + + const auto size = Vector2ui{(unsigned)mat.cols, (unsigned)mat.rows}; + + if (size != expected_size) [[unlikely]] + { + ERR << "fatal: wrong image size, expected" + << resolution{expected_size} << colon(',') + << "actual" << resolution{size} + << "-- file" << filename; return false; } - DBG << " " << Debug::nospace << count << (count == 1 ? "frame" : "frames"); + cv::Mat4b buf; + if (mat.channels() == 4) + st.opts.use_alpha = true; + if (!convert_to_bgra32(mat, buf)) [[unlikely]] + { + ERR << "fatal: unknown image pixel format:" + << "channels" << mat.channels() << colon(',') + << "depth" << cv::depthToString(mat.depth()) << colon(',') + << "type" << cv::typeToString(mat.type()) << colon(',') + << "for" << quoted(filename); + return false; + } - fm_assert(start + count == st.frames.size()); - new_group.count = count; - new_group.index = start; + st.frames.push_back({.mat = std::move(buf)}); } - else + + if (count == 0) { - new_group.count = 0; - new_group.index = (uint32_t)-1; + ERR << "fatal: no files found for" << quoted2(dir_name) << "/" << quoted2(group_name); + return false; } + DBG << " " << Debug::nospace << count << (count == 1 ? "frame" : "frames"); + + fm_assert(start + count == st.frames.size()); + new_group.count = count; + new_group.index = start; + return true; } |