summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorStanislaw Halik <sthalik@misaki.pl>2023-12-09 08:51:08 +0100
committerStanislaw Halik <sthalik@misaki.pl>2023-12-09 08:51:08 +0100
commitb8b9e24acff21404943252f70ba137c7a8d0be72 (patch)
tree7586796f7ca6d192490eed1778a388d81efc1d0a
parent6dcc095ee5a7a26060e6650afa0a754f404584ea (diff)
w
-rw-r--r--serialize/wall-atlas.cpp6
-rw-r--r--src/chunk-walls.cpp97
-rw-r--r--src/chunk.hpp11
-rw-r--r--src/wall-atlas.cpp28
-rw-r--r--src/wall-atlas.hpp7
-rw-r--r--src/wall-defs.hpp4
-rw-r--r--test/wall-atlas.cpp4
-rw-r--r--wall-tileset-tool/main.cpp100
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;
}