summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--draw/anim.cpp25
-rw-r--r--draw/anim.hpp36
-rw-r--r--draw/wall.cpp3
-rw-r--r--draw/wall.hpp5
-rw-r--r--src/anim-atlas.cpp26
-rw-r--r--src/anim-atlas.hpp7
-rw-r--r--src/chunk.hpp3
-rw-r--r--src/scenery.cpp14
-rw-r--r--src/scenery.hpp25
-rw-r--r--src/tile.cpp18
-rw-r--r--src/tile.hpp9
11 files changed, 152 insertions, 19 deletions
diff --git a/draw/anim.cpp b/draw/anim.cpp
new file mode 100644
index 00000000..0b69e4dd
--- /dev/null
+++ b/draw/anim.cpp
@@ -0,0 +1,25 @@
+#include "anim.hpp"
+#include "anim-atlas.hpp"
+#include "shaders/tile.hpp"
+
+namespace floormat {
+
+anim_mesh::anim_mesh() = default;
+
+std::array<UnsignedShort, 6> anim_mesh::make_index_array()
+{
+ using u16 = std::uint16_t;
+ return {{
+ (u16)0, (u16)1, (u16)2,
+ (u16)2, (u16)1, (u16)3,
+ }};
+}
+
+void anim_mesh::draw(local_coords xy, const anim_atlas& atlas, const anim_frame& frame)
+{
+ const auto center_ = Vector3(xy.x, xy.y, 0.f) * TILE_SIZE;
+ const auto pos = atlas.frame_quad(center_, frame);
+ _positions_buffer.setSubData(0, pos);
+}
+
+} // namespace floormat
diff --git a/draw/anim.hpp b/draw/anim.hpp
new file mode 100644
index 00000000..60a4e839
--- /dev/null
+++ b/draw/anim.hpp
@@ -0,0 +1,36 @@
+#pragma once
+
+#include "local-coords.hpp"
+#include <array>
+#include <Corrade/Containers/ArrayViewStl.h>
+#include <Magnum/Magnum.h>
+#include <Magnum/Math/Vector2.h>
+#include <Magnum/Math/Vector3.h>
+#include <Magnum/GL/Mesh.h>
+#include <Magnum/GL/Buffer.h>
+
+namespace floormat::Serialize { struct anim_atlas; struct anim_frame; }
+
+namespace floormat {
+
+struct anim_atlas;
+using anim_frame = Serialize::anim_frame;
+
+struct anim_mesh final
+{
+ anim_mesh();
+ void draw(local_coords pos, const anim_atlas& atlas, const anim_frame& frame);
+
+private:
+ struct vertex_data final { Vector2 texcoords; };
+ using quad_data = std::array<vertex_data, 4>;
+
+ static std::array<UnsignedShort, 6> make_index_array();
+
+
+ GL::Mesh _mesh;
+ GL::Buffer _vertex_buffer{quad_data{}, Magnum::GL::BufferUsage::DynamicDraw},
+ _index_buffer{make_index_array()}, _positions_buffer{quad_data{}};
+};
+
+} // namespace floormat
diff --git a/draw/wall.cpp b/draw/wall.cpp
index 18462e2c..42d62e49 100644
--- a/draw/wall.cpp
+++ b/draw/wall.cpp
@@ -3,6 +3,7 @@
#include "shaders/tile.hpp"
#include "chunk.hpp"
#include "tile-image.hpp"
+#include "anim-atlas.hpp"
#include <Magnum/GL/Texture.h>
#include <Magnum/GL/MeshView.h>
@@ -63,6 +64,8 @@ void wall_mesh::draw(tile_shader& shader, chunk& c)
tex->bind(0);
last_texture = tex;
shader.draw(mesh);
+ if (auto a = c[i].scenery())
+ _anim_mesh.draw(local_coords{i}, *a.atlas, a.atlas->frame(a.frame.r, a.frame.frame));
}
}
diff --git a/draw/wall.hpp b/draw/wall.hpp
index ad1eafad..81c6b60e 100644
--- a/draw/wall.hpp
+++ b/draw/wall.hpp
@@ -1,6 +1,7 @@
#pragma once
#include "tile-defs.hpp"
+#include "anim.hpp"
#include <array>
#include <Corrade/Containers/ArrayViewStl.h>
#include <Magnum/Math/Vector2.h>
@@ -31,13 +32,15 @@ private:
using vertex_array = std::array<quad, COUNT>;
using texture_array = std::array<GL::Texture2D*, COUNT>;
+ anim_mesh _anim_mesh;
+
static void maybe_add_tile(vertex_array& data, texture_array& textures, tile_ref x, std::size_t pos);
static void add_wall(vertex_array& data, texture_array& textures, const tile_image_ref& img, std::size_t pos);
GL::Mesh _mesh;
GL::Buffer _vertex_buffer{vertex_array{}, Magnum::GL::BufferUsage::DynamicDraw},
_index_buffer{make_index_array()},
- _positions_buffer{make_position_array()};
+ _positions_buffer{make_position_array()};
static std::array<std::array<UnsignedShort, 6>, COUNT> make_index_array();
static std::array<std::array<Vector3, 4>, COUNT> make_position_array();
};
diff --git a/src/anim-atlas.cpp b/src/anim-atlas.cpp
index a4344946..6fb4a3c0 100644
--- a/src/anim-atlas.cpp
+++ b/src/anim-atlas.cpp
@@ -1,5 +1,6 @@
#include "anim-atlas.hpp"
#include "compat/assert.hpp"
+#include "shaders/tile.hpp"
#include <Corrade/Containers/StringStlView.h>
#include <Magnum/Math/Color.h>
#include <Magnum/GL/TextureFormat.h>
@@ -66,12 +67,12 @@ auto anim_atlas::frame(rotation r, std::size_t frame) const noexcept -> const an
return g.frames[frame];
}
-auto anim_atlas::frame_texcoords(rotation r, std::size_t idx) const noexcept -> texcoords
+auto anim_atlas::texcoords_for_frame(rotation r, std::size_t i) const noexcept -> texcoords
{
- return frame_texcoords(frame(r, idx));
+ return texcoords_for_frame(frame(r, i));
}
-auto anim_atlas::frame_texcoords(const anim_frame& frame) const noexcept -> texcoords
+auto anim_atlas::texcoords_for_frame(const anim_frame& frame) const noexcept -> texcoords
{
const Vector2 p0(frame.offset), p1(frame.offset + frame.size);
const auto x0 = p0.x()+.5f, x1 = p1.x()-1, y0 = p0.y()+.5f, y1 = p1.y()-1;
@@ -84,6 +85,25 @@ auto anim_atlas::frame_texcoords(const anim_frame& frame) const noexcept -> texc
}};
}
+auto anim_atlas::frame_quad(const Vector3& center, rotation r, std::size_t i) const noexcept -> quad
+{
+ return frame_quad(center, frame(r, i));
+}
+auto anim_atlas::frame_quad(const Vector3& center, const anim_frame& frame) noexcept -> quad
+{
+ const auto size = Vector2d(frame.size) - Vector2d(frame.ground);
+ const auto bottom_right = Vector2(tile_shader::unproject({ size[0]*.5, 0 })),
+ top_right = Vector2(tile_shader::unproject({ size[0]*.5, -size[1] })),
+ bottom_left = Vector2(tile_shader::unproject({ -size[0]*.5, 0 })),
+ top_left = Vector2(tile_shader::unproject({ -size[0]*.5, -size[1] }));
+ const auto cx = center[0], cy = center[1], cz = center[2];
+ return {{
+ { cx + bottom_right[0], cy + bottom_right[1], cz },
+ { cx + top_right[0], cy + top_right[1], cz },
+ { cx + bottom_left[0], cy + bottom_left[1], cz },
+ { cx + top_left[0], cy + top_left[1], cz },
+ }};
+}
} // namespace floormat
diff --git a/src/anim-atlas.hpp b/src/anim-atlas.hpp
index a7553c5c..16e4825d 100644
--- a/src/anim-atlas.hpp
+++ b/src/anim-atlas.hpp
@@ -16,6 +16,7 @@ struct anim_atlas final
using anim_group = Serialize::anim_group;
using anim_frame = Serialize::anim_frame;
using texcoords = std::array<Vector2, 4>;
+ using quad = std::array<Vector3, 4>;
anim_atlas() noexcept;
anim_atlas(StringView name, const ImageView2D& tex, anim_info info) noexcept;
@@ -30,8 +31,10 @@ struct anim_atlas final
const anim_group& group(rotation r) const noexcept;
const anim_frame& frame(rotation r, std::size_t frame) const noexcept;
- texcoords frame_texcoords(rotation r, std::size_t frame) const noexcept;
- texcoords frame_texcoords(const anim_frame& frame) const noexcept;
+ texcoords texcoords_for_frame(rotation r, std::size_t frame) const noexcept;
+ texcoords texcoords_for_frame(const anim_frame& frame) const noexcept;
+ quad frame_quad(const Vector3& center, rotation r, std::size_t frame) const noexcept;
+ static quad frame_quad(const Vector3& center, const anim_frame& frame) noexcept;
fm_DECLARE_DELETED_COPY_ASSIGNMENT(anim_atlas);
diff --git a/src/chunk.hpp b/src/chunk.hpp
index 7967484c..14795de0 100644
--- a/src/chunk.hpp
+++ b/src/chunk.hpp
@@ -40,7 +40,8 @@ struct chunk final
private:
std::array<std::shared_ptr<tile_atlas>, TILE_COUNT> _ground_atlases, _wall_north_atlases, _wall_west_atlases;
- std::array<std::shared_ptr<anim_atlas>, TILE_COUNT> _scenery;
+ std::array<std::shared_ptr<anim_atlas>, TILE_COUNT> _scenery_atlases;
+ std::array<scenery, TILE_COUNT> _scenery_variants = {};
std::array<variant_t, TILE_COUNT> _ground_variants = {}, _wall_north_variants = {}, _wall_west_variants = {};
std::bitset<TILE_COUNT*2> _passability = {};
mutable bool _maybe_empty = true;
diff --git a/src/scenery.cpp b/src/scenery.cpp
index fde0cb56..620fb51e 100644
--- a/src/scenery.cpp
+++ b/src/scenery.cpp
@@ -2,6 +2,20 @@
namespace floormat {
+scenery_proto::operator bool() const noexcept { return atlas != nullptr; }
+scenery_ref::scenery_ref(std::shared_ptr<anim_atlas>& atlas, scenery& frame) noexcept : atlas{atlas}, frame{frame} {}
+scenery_ref::scenery_ref(const scenery_ref&) noexcept = default;
+scenery_ref::scenery_ref(scenery_ref&&) noexcept = default;
+
+scenery_ref& scenery_ref::operator=(const scenery_proto& proto) noexcept
+{
+ atlas = proto.atlas;
+ frame = proto.frame;
+ return *this;
+}
+
+scenery_ref::operator scenery_proto() const noexcept { return { atlas, frame }; }
+scenery_ref::operator bool() const noexcept { return atlas != nullptr; };
} // namespace floormat
diff --git a/src/scenery.hpp b/src/scenery.hpp
index 04c54c22..a59d6990 100644
--- a/src/scenery.hpp
+++ b/src/scenery.hpp
@@ -4,6 +4,8 @@
namespace floormat {
+struct anim_atlas;
+
enum class rotation : std::uint16_t {
N, NE, E, SE, S, SW, W, NW,
COUNT,
@@ -17,15 +19,26 @@ struct scenery final
frame_t frame : 12 = NO_FRAME;
rotation r : 4 = rotation::N;
-
- constexpr operator bool() const noexcept;
};
static_assert(sizeof(scenery) == sizeof(std::uint16_t));
-constexpr scenery::operator bool() const noexcept
-{
- return frame == NO_FRAME;
-}
+struct scenery_proto final {
+ std::shared_ptr<anim_atlas> atlas;
+ scenery frame;
+ operator bool() const noexcept;
+};
+
+struct scenery_ref final {
+ std::shared_ptr<anim_atlas>& atlas;
+ scenery& frame;
+
+ scenery_ref(std::shared_ptr<anim_atlas>& atlas, scenery& frame) noexcept;
+ scenery_ref(const scenery_ref&) noexcept;
+ scenery_ref(scenery_ref&&) noexcept;
+ scenery_ref& operator=(const scenery_proto& proto) noexcept;
+ operator scenery_proto() const noexcept;
+ operator bool() const noexcept;
+};
} // namespace floormat
diff --git a/src/tile.cpp b/src/tile.cpp
index 920ee2e5..6f329702 100644
--- a/src/tile.cpp
+++ b/src/tile.cpp
@@ -32,30 +32,36 @@ pass_mode_ref::operator pass_mode() const noexcept
bool operator==(const tile_proto& a, const tile_proto& b) noexcept {
return a.ground_image() == b.ground_image() &&
a.wall_north_image() == b.wall_north_image() &&
- a.wall_west_image() == b.wall_west_image();
+ a.wall_west_image() == b.wall_west_image() &&
+ a.scenery_image() == b.scenery_image();
};
tile_image_proto tile_proto::ground_image() const noexcept { return { ground_atlas, ground_variant }; }
tile_image_proto tile_proto::wall_north_image() const noexcept { return { wall_north_atlas, wall_north_variant }; }
tile_image_proto tile_proto::wall_west_image() const noexcept { return { wall_west_atlas, wall_west_variant }; }
+scenery_proto tile_proto::scenery_image() const noexcept { return { scenery_atlas, scenery_frame }; }
tile_ref::tile_ref(struct chunk& c, std::uint8_t i) noexcept : _chunk{&c}, i{i} {}
-std::shared_ptr<tile_atlas> tile_ref::ground_atlas() noexcept { return _chunk->_ground_atlases[i]; }
-std::shared_ptr<tile_atlas> tile_ref::wall_north_atlas() noexcept { return _chunk->_wall_north_atlases[i]; }
-std::shared_ptr<tile_atlas> tile_ref::wall_west_atlas() noexcept { return _chunk->_wall_west_atlases[i]; }
+std::shared_ptr<tile_atlas> tile_ref::ground_atlas() noexcept { return _chunk->_ground_atlases[i]; }
+std::shared_ptr<tile_atlas> tile_ref::wall_north_atlas() noexcept { return _chunk->_wall_north_atlases[i]; }
+std::shared_ptr<tile_atlas> tile_ref::wall_west_atlas() noexcept { return _chunk->_wall_west_atlases[i]; }
+std::shared_ptr<anim_atlas> tile_ref::scenery_atlas() noexcept { return _chunk->_scenery_atlases[i]; }
std::shared_ptr<const tile_atlas> tile_ref::ground_atlas() const noexcept { return _chunk->_ground_atlases[i]; }
std::shared_ptr<const tile_atlas> tile_ref::wall_north_atlas() const noexcept { return _chunk->_wall_north_atlases[i]; }
std::shared_ptr<const tile_atlas> tile_ref::wall_west_atlas() const noexcept { return _chunk->_wall_west_atlases[i]; }
+std::shared_ptr<const anim_atlas> tile_ref::scenery_atlas() const noexcept { return _chunk->_scenery_atlases[i]; }
tile_image_ref tile_ref::ground() noexcept { return {_chunk->_ground_atlases[i], _chunk->_ground_variants[i] }; }
tile_image_ref tile_ref::wall_north() noexcept { return {_chunk->_wall_north_atlases[i], _chunk->_wall_north_variants[i] }; }
tile_image_ref tile_ref::wall_west() noexcept { return {_chunk->_wall_west_atlases[i], _chunk->_wall_west_variants[i] }; }
+scenery_ref tile_ref::scenery() noexcept { return {_chunk->_scenery_atlases[i], _chunk->_scenery_variants[i] }; }
tile_image_proto tile_ref::ground() const noexcept { return { _chunk->_ground_atlases[i], _chunk->_ground_variants[i] }; }
tile_image_proto tile_ref::wall_north() const noexcept { return { _chunk->_wall_north_atlases[i], _chunk->_wall_north_variants[i] }; }
tile_image_proto tile_ref::wall_west() const noexcept { return { _chunk->_wall_west_atlases[i], _chunk->_wall_west_variants[i] }; }
+scenery_proto tile_ref::scenery() const noexcept { return {_chunk->_scenery_atlases[i], _chunk->_scenery_variants[i] }; }
pass_mode_ref tile_ref::pass_mode() noexcept { return { *_chunk, i }; }
pass_mode tile_ref::pass_mode() const noexcept { return pass_mode_ref { *const_cast<struct chunk*>(_chunk), i }; }
@@ -63,8 +69,8 @@ pass_mode tile_ref::pass_mode() const noexcept { return pass_mode_ref { *const_c
tile_ref::operator tile_proto() const noexcept
{
return {
- _chunk->_ground_atlases[i], _chunk->_wall_north_atlases[i], _chunk->_wall_west_atlases[i],
- _chunk->_ground_variants[i], _chunk->_wall_north_variants[i], _chunk->_wall_west_variants[i],
+ _chunk->_ground_atlases[i], _chunk->_wall_north_atlases[i], _chunk->_wall_west_atlases[i], _chunk->_scenery_atlases[i],
+ _chunk->_ground_variants[i], _chunk->_wall_north_variants[i], _chunk->_wall_west_variants[i], _chunk->_scenery_variants[i],
pass_mode(),
};
}
diff --git a/src/tile.hpp b/src/tile.hpp
index b7bacc8d..6fad4b30 100644
--- a/src/tile.hpp
+++ b/src/tile.hpp
@@ -1,10 +1,12 @@
#pragma once
#include "compat/defs.hpp"
#include "tile-image.hpp"
+#include "scenery.hpp"
namespace floormat {
struct chunk;
+struct anim_atlas;
// zero is the default, see bitset in chunk.hpp
enum pass_mode : std::uint8_t { pass_shoot_through, pass_ok, pass_blocked, };
@@ -24,12 +26,15 @@ private:
struct tile_proto final
{
std::shared_ptr<tile_atlas> ground_atlas, wall_north_atlas, wall_west_atlas;
+ std::shared_ptr<anim_atlas> scenery_atlas;
variant_t ground_variant = 0, wall_north_variant = 0, wall_west_variant = 0;
+ scenery scenery_frame;
enum pass_mode pass_mode = pass_mode::pass_shoot_through;
tile_image_proto ground_image() const noexcept;
tile_image_proto wall_north_image() const noexcept;
tile_image_proto wall_west_image() const noexcept;
+ scenery_proto scenery_image() const noexcept;
friend bool operator==(const tile_proto& a, const tile_proto& b) noexcept;
};
@@ -41,18 +46,22 @@ struct tile_ref final
tile_image_ref ground() noexcept;
tile_image_ref wall_north() noexcept;
tile_image_ref wall_west() noexcept;
+ scenery_ref scenery() noexcept;
tile_image_proto ground() const noexcept;
tile_image_proto wall_north() const noexcept;
tile_image_proto wall_west() const noexcept;
+ scenery_proto scenery() const noexcept;
std::shared_ptr<tile_atlas> ground_atlas() noexcept;
std::shared_ptr<tile_atlas> wall_north_atlas() noexcept;
std::shared_ptr<tile_atlas> wall_west_atlas() noexcept;
+ std::shared_ptr<anim_atlas> scenery_atlas() noexcept;
std::shared_ptr<const tile_atlas> ground_atlas() const noexcept;
std::shared_ptr<const tile_atlas> wall_north_atlas() const noexcept;
std::shared_ptr<const tile_atlas> wall_west_atlas() const noexcept;
+ std::shared_ptr<const anim_atlas> scenery_atlas() const noexcept;
pass_mode_ref pass_mode() noexcept;
enum pass_mode pass_mode() const noexcept;