summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorStanislaw Halik <sthalik@misaki.pl>2023-12-10 09:19:32 +0100
committerStanislaw Halik <sthalik@misaki.pl>2023-12-10 09:19:32 +0100
commit60c80cdca2108d05a0cd0cac8fcfc3658c4e3915 (patch)
treeeb415d0cf95b79919bae5e919d1f19626786524b
parent3464b29a50c1718a298b7e48c5e9c0dd509f1bb1 (diff)
w
-rw-r--r--shaders/shader.hpp7
-rw-r--r--src/chunk-walls.cpp93
-rw-r--r--src/chunk.cpp6
-rw-r--r--src/chunk.hpp8
-rw-r--r--src/wall-atlas.cpp28
-rw-r--r--src/wall-atlas.hpp2
6 files changed, 100 insertions, 44 deletions
diff --git a/shaders/shader.hpp b/shaders/shader.hpp
index c50f4681..d66cccb0 100644
--- a/shaders/shader.hpp
+++ b/shaders/shader.hpp
@@ -40,11 +40,12 @@ struct tile_shader final : private GL::AbstractShaderProgram
template<typename T, typename... Xs> decltype(auto) draw(GL::AbstractTexture& tex, T&& mesh, Xs&&... xs);
static constexpr Vector2s max_screen_tiles = {8, 8};
- static constexpr float character_depth_offset = 1 + 1./64;
- static constexpr float scenery_depth_offset = 1 + 1./64;
+ static constexpr float character_depth_offset = 1 + 2./64;
+ static constexpr float scenery_depth_offset = 1 + 2./64;
static constexpr float ground_depth_offset = 0;
static constexpr float wall_depth_offset = 1;
- static constexpr float z_depth_offset = 1 + 2./64;
+ static constexpr float wall_overlay_depth_offset = 1 + 1./64;
+ static constexpr float z_depth_offset = 1 + 4./64;
static constexpr float depth_tile_size = 1.f/(TILE_MAX_DIM * 2 * max_screen_tiles.product());
static constexpr float foreshortening_factor = 0.578125f;
diff --git a/src/chunk-walls.cpp b/src/chunk-walls.cpp
index 1fe7685f..3d3aa2bb 100644
--- a/src/chunk-walls.cpp
+++ b/src/chunk-walls.cpp
@@ -35,12 +35,13 @@ using namespace floormat::Quads;
using Wall::Group_;
using Wall::Direction_;
-template<Group_ G, bool IsWest> constexpr std::array<Vector3, 4> make_vertex_data(float depth);
+template<Group_ G, bool IsWest> constexpr quad get_quad(float depth);
+constexpr quad get_quad(Direction_ D, Group_ G, float depth);
// -----------------------
// corner left
-template<> quad constexpr make_vertex_data<Group_::corner_L, false>(float)
+template<> quad constexpr get_quad<Group_::corner_L, false>(float)
{
constexpr float x_offset = (float)(unsigned)X;
return {{
@@ -52,7 +53,7 @@ template<> quad constexpr make_vertex_data<Group_::corner_L, false>(float)
}
// corner right
-template<> quad constexpr make_vertex_data<Group_::corner_R, true>(float)
+template<> quad constexpr get_quad<Group_::corner_R, true>(float)
{
constexpr float y_offset = TILE_SIZE.y() - (float)(unsigned)Y;
return {{
@@ -64,7 +65,7 @@ template<> quad constexpr make_vertex_data<Group_::corner_R, true>(float)
}
// wall north
-template<> quad constexpr make_vertex_data<Group_::wall, false>(float)
+template<> quad constexpr get_quad<Group_::wall, false>(float)
{
return {{
{ X, -Y, Z },
@@ -75,7 +76,7 @@ template<> quad constexpr make_vertex_data<Group_::wall, false>(float)
}
// wall west
-template<> quad constexpr make_vertex_data<Group_::wall, true>(float)
+template<> quad constexpr get_quad<Group_::wall, true>(float)
{
return {{
{-X, -Y, Z },
@@ -86,7 +87,7 @@ template<> quad constexpr make_vertex_data<Group_::wall, true>(float)
}
// side north
-template<> quad constexpr make_vertex_data<Group_::side, false>(float depth)
+template<> quad constexpr get_quad<Group_::side, false>(float depth)
{
auto left = Vector2{X, -Y },
right = Vector2{left.x(), left.y() - depth };
@@ -99,7 +100,7 @@ template<> quad constexpr make_vertex_data<Group_::side, false>(float depth)
}
// side west
-template<> quad constexpr make_vertex_data<Group_::side, true>(float depth)
+template<> quad constexpr get_quad<Group_::side, true>(float depth)
{
auto right = Vector2{ -X, Y };
auto left = Vector2{ right.x() - depth, right.y() };
@@ -112,7 +113,7 @@ template<> quad constexpr make_vertex_data<Group_::side, true>(float depth)
}
// top north
-template<> quad constexpr make_vertex_data<Group_::top, false>(float depth)
+template<> quad constexpr get_quad<Group_::top, false>(float depth)
{
auto top_right = Vector2{X, Y - depth },
bottom_right = Vector2{top_right.x(), Y },
@@ -127,7 +128,7 @@ template<> quad constexpr make_vertex_data<Group_::top, false>(float depth)
}
// top west
-template<> quad constexpr make_vertex_data<Group_::top, true>(float depth)
+template<> quad constexpr get_quad<Group_::top, true>(float depth)
{
auto top_right = Vector2{-X, -Y },
top_left = Vector2{top_right.x() - depth, top_right.y() },
@@ -143,7 +144,7 @@ template<> quad constexpr make_vertex_data<Group_::top, true>(float depth)
}
#define FM_WALL_MAKE_CASE(name) \
- case name: return make_vertex_data<name, IsWest>(depth)
+ case name: return get_quad<name, IsWest>(depth)
#define FM_WALL_MAKE_CASES() \
do { \
@@ -159,7 +160,7 @@ template<> quad constexpr make_vertex_data<Group_::top, true>(float depth)
} \
} while (false)
-quad get_vertex_data(Direction_ D, Group_ G, float depth)
+constexpr quad get_quad(Direction_ D, Group_ G, float depth)
{
CORRADE_ASSUME(G < Group_::COUNT);
CORRADE_ASSUME(D < Direction_::COUNT);
@@ -179,13 +180,15 @@ quad get_vertex_data(Direction_ D, Group_ G, float depth)
}
}
}
+#undef FM_WALL_MAKE_CASES
+#undef FM_WALL_MAKE_CASE
// -----------------------
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++)
+ auto array = Array<Quads::indexes>{NoInit, chunk::max_wall_quad_count };
+ for (auto i = 0uz; i < chunk::max_wall_quad_count; i++)
array[i] = quad_indexes(i);
return array;
}
@@ -193,38 +196,67 @@ Array<Quads::indexes> make_indexes_()
ArrayView<const Quads::indexes> make_indexes(size_t max)
{
static const auto indexes = make_indexes_();
- fm_assert(max < chunk::max_wall_mesh_size);
+ fm_assert(max < chunk::max_wall_quad_count);
return indexes.prefix(max);
}
+constexpr auto depth_offset_for_group(Group_ G)
+{
+ CORRADE_ASSUME(G < Group_::COUNT);
+ switch (G)
+ {
+ default:
+ return tile_shader::wall_depth_offset;
+ case Wall::Group_::corner_L:
+ case Wall::Group_::corner_R:
+ return tile_shader::wall_overlay_depth_offset;
+ }
+}
+
} // namespace
-GL::Mesh chunk::make_wall_mesh(size_t count)
+GL::Mesh chunk::make_wall_mesh()
{
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];
- uint32_t i = 0, N = 0;
+ uint32_t N = 0;
- static auto vertexes = Array<vertex>{NoInit, max_wall_mesh_size};
+ static auto vertexes = Array<std::array<vertex, 4>>{NoInit, max_wall_quad_count };
- for (auto k = 0uz; k < count; k++)
+ for (uint32_t k = 0; k < 2*TILE_COUNT; k++)
{
- const auto i = _walls->mesh_indexes[k];
- const auto& atlas = _walls->atlases[i];
+ const auto& atlas = _walls->atlases[k];
fm_assert(atlas != nullptr);
- const auto variant = _walls->variants[i];
- const local_coords pos{i / 2u};
+ const auto variant = _walls->variants[k];
+ const local_coords pos{k / 2u};
const auto center = Vector3(pos) * TILE_SIZE;
- const auto& dir = atlas->calc_direction(i & 1 ? Wall::Direction_::W : Wall::Direction_::N);
- for (auto [_, member, group] : Wall::Direction::groups)
+ const auto D = k & 1 ? Wall::Direction_::W : Wall::Direction_::N;
+ const auto& dir = atlas->calc_direction(D);
+ for (auto [_, member, G] : Wall::Direction::groups)
{
- const auto& G = dir.*member;
- if (!G.is_defined)
+ CORRADE_ASSUME(G < Group_::COUNT);
+ const auto& group = dir.*member;
+ if (!group.is_defined)
continue;
-
+ const auto depth_offset = depth_offset_for_group(G);
+ auto quad = get_quad(D, G, atlas->info().depth);
+ for (auto& v : quad)
+ v += center;
+
+ fm_debug_assert(N + quad.size() <= max_wall_quad_count);
+ const auto i = N++;
+ auto& v = vertexes[i];
+ _walls->mesh_indexes[i] = (uint16_t)k;
+ const auto& frame = atlas->frames(group)[variant];
+ const auto texcoords = Quads::texcoords_at(frame.offset, frame.size, atlas->image_size());
+ const float depth = tile_shader::depth_value(pos, depth_offset);
}
+ }
+
+ for (auto k = 0uz; k < count; k++)
+ {
+
// ...
//const auto quad = i & 1 ? wall_quad_W(center, TILE_SIZE) : wall_quad_N(center, TILE_SIZE);
@@ -235,7 +267,7 @@ GL::Mesh chunk::make_wall_mesh(size_t count)
v[j] = { quad[j], texcoords[j], depth, };
}
- auto vertex_view = vertexes.prefix(N);
+ auto vertex_view = std::as_const(vertexes).prefix(N);
auto index_view = make_indexes(N);
//auto indexes = make_index_array<2>(count);
@@ -246,6 +278,7 @@ GL::Mesh chunk::make_wall_mesh(size_t count)
mesh.addVertexBuffer(GL::Buffer{vertex_view}, 0, tile_shader::Position{}, tile_shader::TextureCoordinates{}, tile_shader::Depth{})
.setIndexBuffer(GL::Buffer{vert_index_view}, 0, GL::MeshIndexType::UnsignedShort)
.setCount(int32_t(6 * count));
+ fm_assert((size_t)mesh.count() == N*6);
return mesh;
}
@@ -258,6 +291,7 @@ auto chunk::ensure_wall_mesh() noexcept -> wall_mesh_tuple
return { wall_mesh, _walls->mesh_indexes, size_t(wall_mesh.count()/6) };
_walls_modified = false;
+#if 0
size_t count = 0;
for (auto i = 0uz; i < TILE_COUNT*2; i++)
if (_walls->atlases[i])
@@ -270,6 +304,7 @@ auto chunk::ensure_wall_mesh() noexcept -> wall_mesh_tuple
[this](uint16_t a, uint16_t b) {
return _walls->atlases[a] < _walls->atlases[b];
});
+#endif
wall_mesh = make_wall_mesh(count);
return { wall_mesh, _walls->mesh_indexes, count };
diff --git a/src/chunk.cpp b/src/chunk.cpp
index ca930777..2222b40a 100644
--- a/src/chunk.cpp
+++ b/src/chunk.cpp
@@ -23,10 +23,12 @@ bool is_log_quiet()
bool chunk::empty(bool force) const noexcept
{
- if (!force && !_maybe_empty)
+ if (!force && !_maybe_empty) [[likely]]
return false;
for (auto i = 0uz; i < TILE_COUNT; i++)
- if (!_objects.empty() || _ground && _ground->_ground_atlases[i] || _walls && _walls->empty())
+ if (!_objects.empty() ||
+ _ground && _ground->_ground_atlases[i] ||
+ _walls && _walls->atlases[i])
return _maybe_empty = false;
if (!_objects.empty())
return false;
diff --git a/src/chunk.hpp b/src/chunk.hpp
index b22ab5e9..d9daf436 100644
--- a/src/chunk.hpp
+++ b/src/chunk.hpp
@@ -118,7 +118,8 @@ struct chunk final
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;
+ static constexpr size_t max_wall_quad_count =
+ TILE_COUNT*Wall::Direction_COUNT*Wall::Group_COUNT;
private:
struct ground_stuff
@@ -133,8 +134,7 @@ private:
{
std::array<std::shared_ptr<wall_atlas>, 2*TILE_COUNT> atlases;
std::array<variant_t, 2*TILE_COUNT> variants;
-
- std::array<uint16_t, max_wall_mesh_size> mesh_indexes;
+ std::array<uint16_t, max_wall_quad_count> mesh_indexes;
};
Pointer<ground_stuff> _ground;
@@ -169,7 +169,7 @@ private:
void _remove_bbox(const bbox& x);
void _add_bbox(const bbox& x);
void _replace_bbox(const bbox& x0, const bbox& x, bool b0, bool b);
- GL::Mesh make_wall_mesh(size_t count);
+ GL::Mesh make_wall_mesh();
template<size_t N> static std::array<std::array<UnsignedShort, 6>, N*TILE_COUNT> make_index_array(size_t max);
};
diff --git a/src/wall-atlas.cpp b/src/wall-atlas.cpp
index 3767949a..8fe19232 100644
--- a/src/wall-atlas.cpp
+++ b/src/wall-atlas.cpp
@@ -9,6 +9,19 @@
namespace floormat {
+namespace {
+
+Vector2ui get_image_size(const ImageView2D& img)
+{
+ const Size<3> size = img.pixels().size();
+ const auto width = size[1], height = size[0];
+ fm_soft_assert(size[2] >= 3 && size[2] <= 4);
+ fm_soft_assert(width > 0 && height > 0);
+ return { (unsigned)width, (unsigned)height };
+}
+
+} // namespace
+
wall_atlas::wall_atlas() noexcept = default;
wall_atlas::~wall_atlas() noexcept = default;
@@ -42,23 +55,25 @@ wall_atlas::wall_atlas(wall_atlas_def def, String path, const ImageView2D& img)
: _dir_array{std::move(def.direction_array)},
_frame_array{std::move(def.frames)},
_info{std::move(def.header)}, _path{std::move(path)},
+ _image_size{get_image_size(img)},
_direction_map{def.direction_map}
{
{
bool found = false;
- for (auto [_, dir] : wall_atlas::directions)
+ for (auto [dir_name, dir] : wall_atlas::directions)
{
const auto* D = direction((size_t)dir);
if (!D)
continue;
- for (auto [_, gmemb, gr] : Direction::groups)
+ for (auto [group_name, gmemb, gr] : Direction::groups)
{
- const auto& G = group(dir, gr);
- if (!G->is_defined)
+ const auto& G = D->*gmemb;
+ if (!G.is_defined)
continue;
found = true;
- if (G->count == 0) [[unlikely]]
- fm_throw("wall_atlas '{}' defined group {}/{} has no frames!"_cf, _path, (int)dir, (int)gr);
+ if (G.count == 0) [[unlikely]]
+ fm_throw("wall_atlas '{}' defined group {}/{} has no frames!"_cf,
+ _path, dir_name, group_name);
}
}
if (!found) [[unlikely]]
@@ -157,6 +172,7 @@ auto wall_atlas::calc_direction(Direction_ dir) const -> const Direction&
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; }
+Vector2ui wall_atlas::image_size() const { return _image_size; }
size_t wall_atlas::enum_to_index(enum rotation r)
{
diff --git a/src/wall-atlas.hpp b/src/wall-atlas.hpp
index 7fb53125..515f60e1 100644
--- a/src/wall-atlas.hpp
+++ b/src/wall-atlas.hpp
@@ -113,6 +113,7 @@ class wall_atlas final
std::vector<Frame> _frame_array;
Info _info;
String _path;
+ Vector2ui _image_size;
GL::Texture2D _texture{NoCreate};
std::array<DirArrayIndex, Wall::Direction_COUNT> _direction_map;
@@ -140,6 +141,7 @@ public:
//StringView path() const { return _path; }
GL::Texture2D& texture();
+ Vector2ui image_size() const;
static size_t enum_to_index(enum rotation x);
static Vector2ui expected_size(unsigned depth, Group_ group);