diff options
-rw-r--r-- | editor/wall-editor.cpp | 6 | ||||
-rw-r--r-- | src/chunk-walls.cpp | 131 | ||||
-rw-r--r-- | src/chunk.hpp | 2 | ||||
-rw-r--r-- | src/wall-atlas.cpp | 1 | ||||
-rw-r--r-- | src/wall-atlas.hpp | 11 | ||||
-rw-r--r-- | src/wall-defs.hpp | 2 | ||||
-rw-r--r-- | test/json/wall-atlas-02_groups.json | 10 | ||||
-rw-r--r-- | test/wall-atlas.cpp | 4 | ||||
-rw-r--r-- | walls/concrete1.json | 16 | ||||
-rw-r--r-- | walls/concrete1.png | bin | 71441 -> 73754 bytes |
10 files changed, 162 insertions, 21 deletions
diff --git a/editor/wall-editor.cpp b/editor/wall-editor.cpp index 2341f929..b311145a 100644 --- a/editor/wall-editor.cpp +++ b/editor/wall-editor.cpp @@ -80,7 +80,11 @@ void wall_editor::place_tile(world& w, global_coords coords, const std::shared_p case rotation::W: t.wall_west() = { atlas, (variant_t)-1 }; break; default: std::unreachable(); } - c.mark_walls_modified(); + //c.mark_walls_modified(); + for (int y = -1; y <= 1; y++) + for (int x = -1; x <= 1; x++) + if (auto* ch = w.at(coords + Vector2i(x, y))) + ch->mark_walls_modified(); } editor_snap_mode wall_editor::check_snap(int mods) const diff --git a/src/chunk-walls.cpp b/src/chunk-walls.cpp index 82bae536..9e808b41 100644 --- a/src/chunk-walls.cpp +++ b/src/chunk-walls.cpp @@ -4,7 +4,8 @@ #include "wall-atlas.hpp" #include "shaders/shader.hpp" #include <Corrade/Containers/ArrayViewStl.h> -#include <Corrade/Containers/PairStl.h> +#include <Corrade/Containers/Pair.h> +#include <Corrade/Containers/Optional.h> #include <utility> #include <algorithm> #include <ranges> @@ -34,6 +35,30 @@ using Wall::Direction_; // ----------------------- +constexpr Quads::quad get_corner(Direction_ D, Group_ G, float depth) +{ + 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; + + if (!is_west) + return {{ + {-X, -Y, 0 }, + {-X, -Y, Z }, + {-X - depth, -Y, 0 }, + {-X - depth, -Y, Z }, + }}; + else + return {{ + {-X, -Y - depth, 0 }, + {-X, -Y - depth, Z }, + {-X, -Y, 0 }, + {-X, -Y, Z }, + }}; +} + constexpr Quads::quad get_quad(Direction_ D, Group_ G, float depth) { CORRADE_ASSUME(D < Direction_::COUNT); @@ -100,6 +125,8 @@ constexpr Quads::quad get_quad(Direction_ D, Group_ G, float depth) { -X, Y, Z } }}; } + case corner: + return get_corner(D, G, depth); } std::unreachable(); fm_abort("invalid wall_atlas group '%d'", (int)G); @@ -148,7 +175,8 @@ GL::Mesh chunk::make_wall_mesh() for (uint32_t k = 0; k < 2*TILE_COUNT; k++) { - const auto D = k & 1 ? Wall::Direction_::W : Wall::Direction_::N; + 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; @@ -157,23 +185,112 @@ GL::Mesh chunk::make_wall_mesh() const auto center = Vector3(pos) * TILE_SIZE; const auto& dir = atlas->calc_direction(D); const auto vpos = (uint8_t)Vector2ui(global_coords{_coord, pos}.raw()).sum(); + const auto Depth = atlas->info().depth; - for (auto [_, member, G] : Wall::Direction::groups) + for (auto [_, member, G] : Wall::Direction::groups_for_draw) { CORRADE_ASSUME(G < Group_::COUNT); - const auto& group = dir.*member; - if (!group.is_defined) + bool corner_ok = false; + + if (!(dir.*member).is_defined) continue; + + if (!is_west) + { + switch (G) + { + default: + break; + case Wall::Group_::side: + if (auto t2 = at_offset_(pos, {1, 0}); t2 && t2->wall_west_atlas()) + continue; + else if (auto t2 = at_offset_(pos, {1, -1}); t2 && t2->wall_west_atlas()) + continue; + else if (auto t2 = at_offset_(pos, {-1, 0}); t2 && !t2->wall_north_atlas()) + if (auto t2 = at_offset_(pos, {0, -1}); t2 && t2->wall_west_atlas()) + corner_ok = true; + break; + } + } + else + { + switch (G) + { + default: + break; + case Wall::Group_::side: + if (auto t2 = at_offset_(pos, {0, 1}); t2 && t2->wall_north_atlas()) + continue; + else if (auto t2 = at_offset_(pos, {-1, 1}); t2 && t2->wall_north_atlas()) + continue; + else if (auto t2 = at_offset_(pos, {0, -1}); t2 && !t2->wall_west_atlas()) + if (auto t2 = at_offset_(pos, {-1, 0}); t2 && t2->wall_north_atlas()) + corner_ok = true; + break; + } + } + const auto depth_offset = depth_offset_for_group(G); - auto quad = get_quad(D, G, atlas->info().depth); + auto quad = get_quad(D, G, Depth); for (auto& v : quad) v += center; + if (corner_ok) + { + if (dir.corner.is_defined) + { + const auto frames = atlas->frames(dir.corner); + auto variant = (variant_ != (uint8_t)-1 ? variant_ : vpos); + variant += frames.size(); + if (!is_west) + variant -= 1; + else + variant += 1; + variant %= frames.size(); + const auto& frame = frames[variant]; + const auto texcoords = Quads::texcoords_at(frame.offset, frame.size, atlas->image_size()); + const auto i = N++; + _walls->mesh_indexes[i] = (uint16_t)k; + const auto depth = tile_shader::depth_value(pos, depth_offset); + fm_debug_assert(i < vertexes.size()); + auto& v = vertexes[i]; + auto quad = get_quad(D, Group_::corner, 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); + auto variant = (variant_ != (uint8_t)-1 ? variant_ : vpos); + variant += frames.size() - 1; + variant %= frames.size(); + const auto& frame = frames[variant]; + 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++; + _walls->mesh_indexes[i] = (uint16_t)k; + const auto depth = tile_shader::depth_value(pos, depth_offset); + fm_debug_assert(i < vertexes.size()); + auto& v = vertexes[i]; + auto quad = get_corner(D, G, Depth); + for (auto& v : quad) + v += center; + for (uint8_t j = 0; j < 4; j++) + v[j] = { quad[j], texcoords[j], depth }; + } + } + + const auto& group = dir.*member; + const auto frames = atlas->frames(group); + const auto i = N++; fm_debug_assert(i < max_wall_quad_count); _walls->mesh_indexes[i] = (uint16_t)k; - const auto frames = atlas->frames(group); + const auto variant = (variant_ != (uint8_t)-1 ? variant_ : vpos) % frames.size(); const auto& frame = frames[variant]; const auto texcoords = Quads::texcoords_at(frame.offset, frame.size, atlas->image_size()); diff --git a/src/chunk.hpp b/src/chunk.hpp index 89892d90..f2434281 100644 --- a/src/chunk.hpp +++ b/src/chunk.hpp @@ -124,7 +124,7 @@ struct chunk final // for drawing only static constexpr size_t max_wall_quad_count = - TILE_COUNT*Wall::Direction_COUNT*Wall::Group_COUNT; + TILE_COUNT*Wall::Direction_COUNT*(Wall::Group_COUNT+4); private: struct ground_stuff diff --git a/src/wall-atlas.cpp b/src/wall-atlas.cpp index fa6e99a6..9461431c 100644 --- a/src/wall-atlas.cpp +++ b/src/wall-atlas.cpp @@ -93,6 +93,7 @@ Vector2ui wall_atlas::expected_size(unsigned depth, Group_ group) return { size.x(), size.z() }; case top: case side: + case corner: return { depth, size.z() }; default: std::unreachable(); diff --git a/src/wall-atlas.hpp b/src/wall-atlas.hpp index e9421653..9a329a74 100644 --- a/src/wall-atlas.hpp +++ b/src/wall-atlas.hpp @@ -46,21 +46,28 @@ struct Direction using memfn_ptr = Group Direction::*; struct member_tuple { StringView name; memfn_ptr member; Group_ tag; }; - Group wall{}, side{}, top{}; + Group wall{}, side{}, top{}, corner{}; const Group& group(Group_ i) const; const Group& group(size_t i) const; Group& group(Group_ i); Group& group(size_t i); + bool operator==(const Direction&) const noexcept; + static constexpr inline member_tuple groups[] = { { "wall"_s, &Direction::wall, Group_::wall }, { "side"_s, &Direction::side, Group_::side }, { "top"_s, &Direction::top, Group_::top }, + { "corner"_s, &Direction::corner, Group_::corner }, }; static_assert(std::size(groups) == (size_t)Group_::COUNT); - bool operator==(const Direction&) const noexcept; + static constexpr inline member_tuple groups_for_draw[] = { + { "wall"_s, &Direction::wall, Group_::wall }, + { "side"_s, &Direction::side, Group_::side }, + { "top"_s, &Direction::top, Group_::top }, + }; }; struct Info diff --git a/src/wall-defs.hpp b/src/wall-defs.hpp index ea36605b..a19d560b 100644 --- a/src/wall-defs.hpp +++ b/src/wall-defs.hpp @@ -3,7 +3,7 @@ namespace floormat::Wall { -enum class Group_ : uint8_t { wall, side, top, COUNT }; +enum class Group_ : uint8_t { wall, side, top, corner, COUNT }; enum class Direction_ : uint8_t { N, W, COUNT }; diff --git a/test/json/wall-atlas-02_groups.json b/test/json/wall-atlas-02_groups.json index b2d44fc5..d3b25918 100644 --- a/test/json/wall-atlas-02_groups.json +++ b/test/json/wall-atlas-02_groups.json @@ -23,10 +23,6 @@ "offset": 0, "count": 1 }, - "corner-L": { - "offset": 0, - "count": 11 - }, "top": { "from-rotation": "w" } @@ -49,6 +45,10 @@ "offset": 1, "count": 12 }, - "corner-L": { "from-rotation": "n" } + "corner": { + "pixel-size": "42 x 192", + "offset": 2, + "count": 1 + } } } diff --git a/test/wall-atlas.cpp b/test/wall-atlas.cpp index 9258863c..eec4ecee 100644 --- a/test/wall-atlas.cpp +++ b/test/wall-atlas.cpp @@ -65,6 +65,8 @@ void test_read_groups(StringView filename) fm_assert(dir.side.pixel_size == Vector2ui{42, 192} ); fm_assert(dir.side.default_tint == true ); fm_assert(dir.top.default_tint == true ); + fm_assert(dir.corner.index == 2); + fm_assert(dir.corner.count == 1); const auto atlas2 = wall_atlas_def::deserialize(path); fm_assert(atlas2.header == info); @@ -88,8 +90,10 @@ void test_from_rotation(StringView filename) fm_assert(D_n.top.is_defined); fm_assert(D_n.top.from_rotation != null); fm_assert(D_n.top.from_rotation != null); + fm_assert(!D_n.corner.is_defined); fm_assert(D_w.top.from_rotation == null); fm_assert(D_w.top.is_defined); + fm_assert(D_w.corner.is_defined); fm_assert(atlas.direction_array[D_n.top.from_rotation].top.count == 12); } diff --git a/walls/concrete1.json b/walls/concrete1.json index 1f3911ce..91c5069a 100644 --- a/walls/concrete1.json +++ b/walls/concrete1.json @@ -20,30 +20,38 @@ {
"offset": "212 x 0",
"size": "20 x 192"
+ },
+ {
+ "offset": "232 x 0",
+ "size": "20 x 192"
}
],
"n": {
+ "corner": {
+ "count": 1,
+ "mirrored": false,
+ "offset": 5,
+ "pixel-size": "20 x 192"
+ },
"side": {
"count": 1,
- "from-rotation": null,
"mirrored": false,
"offset": 3,
"pixel-size": "20 x 192"
},
"top": {
"count": 1,
- "from-rotation": null,
"mirrored": false,
"offset": 4,
"pixel-size": "192 x 20"
},
"wall": {
"count": 3,
- "from-rotation": null,
"mirrored": false,
"offset": 0,
"pixel-size": "64 x 192"
}
},
- "name": "concrete1"
+ "name": "concrete1",
+ "pass-mode": "blocked"
}
diff --git a/walls/concrete1.png b/walls/concrete1.png Binary files differindex 137f3295..e0e9c4f4 100644 --- a/walls/concrete1.png +++ b/walls/concrete1.png |