summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorStanislaw Halik <sthalik@misaki.pl>2024-01-09 02:59:27 +0100
committerStanislaw Halik <sthalik@misaki.pl>2024-01-09 02:59:45 +0100
commite72eb0b1d3149288d2a5291722c3ba68bb567a84 (patch)
tree5fb4c8dfb97f8f57d946b770b228ff97ac04d5cf
parent76559b1d8c7b0f6a29c729d9c82e4c1e15d988f0 (diff)
a
-rw-r--r--editor/wall-editor.cpp6
-rw-r--r--src/chunk-walls.cpp131
-rw-r--r--src/chunk.hpp2
-rw-r--r--src/wall-atlas.cpp1
-rw-r--r--src/wall-atlas.hpp11
-rw-r--r--src/wall-defs.hpp2
-rw-r--r--test/json/wall-atlas-02_groups.json10
-rw-r--r--test/wall-atlas.cpp4
-rw-r--r--walls/concrete1.json16
-rw-r--r--walls/concrete1.pngbin71441 -> 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
index 137f3295..e0e9c4f4 100644
--- a/walls/concrete1.png
+++ b/walls/concrete1.png
Binary files differ