diff options
author | Stanislaw Halik <sthalik@misaki.pl> | 2024-05-26 18:11:06 +0200 |
---|---|---|
committer | Stanislaw Halik <sthalik@misaki.pl> | 2024-05-26 18:11:06 +0200 |
commit | e679da407d43b581afaf0539acea1143c022b245 (patch) | |
tree | a3798c7021559cc5fc66caa0350ec74edee4a015 /src | |
parent | 3e1349ce28eae928c8ecfd2ec9bfdde5147ad6a8 (diff) |
w
Diffstat (limited to 'src')
-rw-r--r-- | src/hole-cut.cpp | 189 | ||||
-rw-r--r-- | src/hole.cpp | 196 | ||||
-rw-r--r-- | src/hole.hpp | 34 |
3 files changed, 248 insertions, 171 deletions
diff --git a/src/hole-cut.cpp b/src/hole-cut.cpp new file mode 100644 index 00000000..f87a6c2f --- /dev/null +++ b/src/hole-cut.cpp @@ -0,0 +1,189 @@ +#include "hole.hpp" +#include "compat/array-size.hpp" +#include "compat/iota.hpp" +#include "compat/map.hpp" +//#include <mg/Functions.h> + +#ifdef __GNUG__ +#pragma GCC diagnostic ignored "-Wswitch-default" +//#pragma GCC diagnostic ignored "-Wmissing-field-initializers" +#endif + +namespace floormat { +namespace { + +using bbox = cut_rectangle_result::bbox; +using rect = cut_rectangle_result::rect; + +enum shift : uint8_t { __ = 0, x0 = 1 << 0, x1 = 1 << 1, y0 = 1 << 2, y1 = 1 << 3, }; +enum class location : uint8_t { R0, R1, H0, H1, }; + +struct coords +{ + location x0 : 2; + location x1 : 2; + location y0 : 2; + location y1 : 2; +}; + +struct element +{ + uint8_t size; + std::array<coords, 8> array; +}; + +constexpr element make_element(uint8_t s) +{ + // ReSharper disable CppIdenticalOperandsInBinaryExpression + // NOLINTBEGIN(*-simplify) + switch (s) + { + using enum location; + case x0|x1|y0|y1: return element{1, {{ // 9.1 + {R0, R1, R0, R1}, + }}}; + case __|__|__|__: return element{8, {{ // 14.1 + {R0, H0, R0, H0}, + {H0, H1, R0, H0}, + {H1, R1, R0, H0}, + {R0, H0, H0, H1}, + {H1, R1, H0, H1}, + {R0, H0, H1, R1}, + {H0, H1, H0, R1}, + {H1, R1, H1, R1}, + }}}; + + case x0|x1|__|__: return element{2, {{ // 13.1 + {R0, R1, R0, H0}, + {R0, R1, H1, R1}, + }}}; + case __|__|y0|y1: return element{2, {{ // 13.2 + {R0, H0, H1, R1}, + {H1, R1, R0, R1}, + }}}; + + case x0|x1|y0|__: return element{1, {{ // 12.1 + {R0, R1, H1, R1}, + }}}; + case x0|x1|__|y1: return element{1, {{ // 12.2 + {R0, R1, R0, H0}, + }}}; + case x0|__|y0|y1: return element{1, {{ // 12.3 + {H1, R1, R0, R1}, + }}}; + case __|x1|y0|y1: return element{1, {{ // 12.4 + {R0, H0, R0, R1}, + }}}; + + case x0|__|__|__: return element{3, {{ // 10.1 + {R0, R1, R0, H0}, + {H1, R1, H0, H1}, + {R0, R1, H1, R1}, + }}}; + case __|x1|__|__: return element{3, {{ // 10.2 + {R0, R1, R0, H0}, + {R0, H0, H0, H1}, + {R0, R1, H1, R1}, + }}}; + case __|__|y0|__: return element{3, {{ // 10.3 + {R0, H0, R0, R1}, + {H0, H1, H0, R1}, + {H1, R1, R0, R1}, + }}}; + case __|__|__|y1: return element{3, {{ // 10.4 + {R0, H0, R0, R1}, + {H0, H1, R0, H0}, + {H1, R1, R0, R1}, + }}}; + + case x0|__|y0|__: return element{2, {{ // 11.1 + {H1, R1, R0, H1}, + {R0, R1, H1, R1}, + }}}; + case __|x1|y0|__: return element{2, {{ // 11.2 + {R0, H0, R0, H1}, + {R0, R1, H1, R1}, + }}}; + case x0|__|__|y1: return element{2, {{ // 11.3 + {R0, R1, R0, H0}, + {H1, R1, H0, R1}, + }}}; + case __|x1|__|y1: return element{2, {{ // 11.4 + {R0, R1, R0, H0}, + {R0, H0, H0, H1}, + }}}; + } + // NOLINTEND(*-simplify) + // ReSharper restore CppIdenticalOperandsInBinaryExpression + std::unreachable(); +} + +constexpr auto elements = map(make_element, iota_array<uint8_t, 16>); + +constexpr auto get_value_from_coord(Vector2i r0, Vector2i r1, Vector2i h0, Vector2i h1, coords c) +{ + const auto xs = std::array{ r0.x(), r1.x(), h0.x(), h1.x(), }; + const auto ys = std::array{ r0.y(), r1.y(), h0.y(), h1.y(), }; + const auto x0 = xs[(uint8_t)c.x0]; + const auto x1 = xs[(uint8_t)c.x1]; + const auto y0 = ys[(uint8_t)c.y0]; + const auto y1 = ys[(uint8_t)c.y1]; + return rect{ Vector2i{x0, y0}, Vector2i{x1, y1} }; +} + +[[nodiscard]] +constexpr bool +check_empty(Vector2i r0, Vector2i r1, Vector2i h0, Vector2i h1, Vector2ub input_bb, Vector2ub hole_bb) +{ + bool iempty = Vector2ui{input_bb}.product() == 0; + bool hempty = Vector2ui{hole_bb}.product() == 0; + bool empty_before_x = h1.x() <= r0.x(); + bool empty_after_x = h0.x() >= r1.x(); + bool empty_before_y = h1.y() <= r0.y(); + bool empty_after_y = h0.y() >= r1.y(); + + return iempty | hempty | empty_before_x | empty_after_x | empty_before_y | empty_after_y; +} + +constexpr cut_rectangle_result cut_rectangleʹ(bbox input, bbox hole) +{ + auto ihalf = Vector2i{input.bbox_size/2}; + auto r0 = input.position - ihalf; + auto r1 = input.position + Vector2i{input.bbox_size} - ihalf; + + auto hhalf = Vector2i{hole.bbox_size/2}; + auto h0 = hole.position - hhalf; + auto h1 = hole.position + Vector2i{hole.bbox_size} - hhalf; + + if (check_empty(r0, r1, h0, h1, input.bbox_size, hole.bbox_size)) + return {0, {}}; + + const bool sx = h0.x() <= r0.x(); + const bool ex = h1.x() >= r1.x(); + const bool sy = h0.y() <= r0.y(); + const bool ey = h1.y() >= r1.y(); + + auto val = uint8_t(sx << 0 | ex << 1 | sy << 2 | ey << 3); + CORRADE_ASSUME(val < 16); + const auto elt = elements[val]; + cut_rectangle_result res = { + .size = elt.size, + .array = {}, + }; + + const auto sz = elt.size; + CORRADE_ASSUME(sz <= 8); + + for (auto i = 0u; i < sz; i++) + res.array[i] = get_value_from_coord(r0, r1, h0, h1, elt.array[i]); + + return res; +} + +} // namespace + +cut_rectangle_result cut_rectangle(bbox input, bbox hole) +{ + return cut_rectangleʹ(input, hole); +} +} // namespace floormat diff --git a/src/hole.cpp b/src/hole.cpp index 396d6d44..783fa5ee 100644 --- a/src/hole.cpp +++ b/src/hole.cpp @@ -1,190 +1,54 @@ #include "hole.hpp" -#include "compat/array-size.hpp" -#include "compat/iota.hpp" -#include "compat/map.hpp" -//#include <mg/Functions.h> - -#ifdef __GNUG__ -#pragma GCC diagnostic ignored "-Wswitch-default" -//#pragma GCC diagnostic ignored "-Wmissing-field-initializers" -#endif +#include "chunk.hpp" +#include "tile-constants.hpp" +#include "shaders/shader.hpp" namespace floormat { namespace { -using bbox = cut_rectangle_result::bbox; -using rect = cut_rectangle_result::rect; - -enum shift : uint8_t { __ = 0, x0 = 1 << 0, x1 = 1 << 1, y0 = 1 << 2, y1 = 1 << 3, }; -enum class location : uint8_t { R0, R1, H0, H1, }; - -struct coords -{ - location x0 : 2; - location x1 : 2; - location y0 : 2; - location y1 : 2; -}; +} // namespace -struct element +hole::hole(object_id id, floormat::chunk& c, const hole_proto& proto): + object{id, c, proto} { - uint8_t size; - std::array<coords, 8> array; -}; +} -constexpr element make_element(uint8_t s) +hole::~hole() noexcept { - // ReSharper disable CppIdenticalOperandsInBinaryExpression - // NOLINTBEGIN(*-simplify) - switch (s) - { - using enum location; - case x0|x1|y0|y1: return element{1, {{ // 9.1 - {R0, R1, R0, R1}, - }}}; - case __|__|__|__: return element{8, {{ // 14.1 - {R0, H0, R0, H0}, - {H0, H1, R0, H0}, - {H1, R1, R0, H0}, - {R0, H0, H0, H1}, - {H1, R1, H0, H1}, - {R0, H0, H1, R1}, - {H0, H1, H0, R1}, - {H1, R1, H1, R1}, - }}}; - - case x0|x1|__|__: return element{2, {{ // 13.1 - {R0, R1, R0, H0}, - {R0, R1, H1, R1}, - }}}; - case __|__|y0|y1: return element{2, {{ // 13.2 - {R0, H0, H1, R1}, - {H1, R1, R0, R1}, - }}}; - - case x0|x1|y0|__: return element{1, {{ // 12.1 - {R0, R1, H1, R1}, - }}}; - case x0|x1|__|y1: return element{1, {{ // 12.2 - {R0, R1, R0, H0}, - }}}; - case x0|__|y0|y1: return element{1, {{ // 12.3 - {H1, R1, R0, R1}, - }}}; - case __|x1|y0|y1: return element{1, {{ // 12.4 - {R0, H0, R0, R1}, - }}}; - - case x0|__|__|__: return element{3, {{ // 10.1 - {R0, R1, R0, H0}, - {H1, R1, H0, H1}, - {R0, R1, H1, R1}, - }}}; - case __|x1|__|__: return element{3, {{ // 10.2 - {R0, R1, R0, H0}, - {R0, H0, H0, H1}, - {R0, R1, H1, R1}, - }}}; - case __|__|y0|__: return element{3, {{ // 10.3 - {R0, H0, R0, R1}, - {H0, H1, H0, R1}, - {H1, R1, R0, R1}, - }}}; - case __|__|__|y1: return element{3, {{ // 10.4 - {R0, H0, R0, R1}, - {H0, H1, R0, H0}, - {H1, R1, R0, R1}, - }}}; - - case x0|__|y0|__: return element{2, {{ // 11.1 - {H1, R1, R0, H1}, - {R0, R1, H1, R1}, - }}}; - case __|x1|y0|__: return element{2, {{ // 11.2 - {R0, H0, R0, H1}, - {R0, R1, H1, R1}, - }}}; - case x0|__|__|y1: return element{2, {{ // 11.3 - {R0, R1, R0, H0}, - {H1, R1, H0, R1}, - }}}; - case __|x1|__|y1: return element{2, {{ // 11.4 - {R0, R1, R0, H0}, - {R0, H0, H0, H1}, - }}}; - } - // NOLINTEND(*-simplify) - // ReSharper restore CppIdenticalOperandsInBinaryExpression - std::unreachable(); + c->mark_ground_modified(); + c->mark_walls_modified(); + c->mark_passability_modified(); } -constexpr auto elements = map(make_element, iota_array<uint8_t, 16>); - -constexpr auto get_value_from_coord(Vector2i r0, Vector2i r1, Vector2i h0, Vector2i h1, coords c) +void hole::update(const std::shared_ptr<object>& ptr, size_t& i, const Ns& dt) { - const auto xs = std::array{ r0.x(), r1.x(), h0.x(), h1.x(), }; - const auto ys = std::array{ r0.y(), r1.y(), h0.y(), h1.y(), }; - const auto x0 = xs[(uint8_t)c.x0]; - const auto x1 = xs[(uint8_t)c.x1]; - const auto y0 = ys[(uint8_t)c.y0]; - const auto y1 = ys[(uint8_t)c.y1]; - return rect{ Vector2i{x0, y0}, Vector2i{x1, y1} }; } -[[nodiscard]] -constexpr bool -check_empty(Vector2i r0, Vector2i r1, Vector2i h0, Vector2i h1, Vector2ub input_bb, Vector2ub hole_bb) +hole::operator hole_proto() const { - bool iempty = Vector2ui{input_bb}.product() == 0; - bool hempty = Vector2ui{hole_bb}.product() == 0; - bool empty_before_x = h1.x() <= r0.x(); - bool empty_after_x = h0.x() >= r1.x(); - bool empty_before_y = h1.y() <= r0.y(); - bool empty_after_y = h0.y() >= r1.y(); - - return iempty | hempty | empty_before_x | empty_after_x | empty_before_y | empty_after_y; + hole_proto ret; + static_cast<object_proto&>(ret) = object_proto(*this); + ret.max_distance = max_distance; + ret.color = color; + ret.falloff = falloff; + ret.enabled = enabled; + return ret; } -constexpr cut_rectangle_result cut_rectangleʹ(bbox input, bbox hole) +float hole::depth_offset() const { - auto ihalf = Vector2i{input.bbox_size/2}; - auto r0 = input.position - ihalf; - auto r1 = input.position + Vector2i{input.bbox_size} - ihalf; - - auto hhalf = Vector2i{hole.bbox_size/2}; - auto h0 = hole.position - hhalf; - auto h1 = hole.position + Vector2i{hole.bbox_size} - hhalf; - - if (check_empty(r0, r1, h0, h1, input.bbox_size, hole.bbox_size)) - return {0, {}}; - - const bool sx = h0.x() <= r0.x(); - const bool ex = h1.x() >= r1.x(); - const bool sy = h0.y() <= r0.y(); - const bool ey = h1.y() >= r1.y(); - - auto val = uint8_t(sx << 0 | ex << 1 | sy << 2 | ey << 3); - CORRADE_ASSUME(val < 16); - const auto elt = elements[val]; - cut_rectangle_result res = { - .size = elt.size, - .array = {}, - }; - - const auto sz = elt.size; - CORRADE_ASSUME(sz <= 8); - - for (auto i = 0u; i < sz; i++) - res.array[i] = get_value_from_coord(r0, r1, h0, h1, elt.array[i]); - - return res; + constexpr auto ret = 4 / tile_shader::depth_tile_size; + return ret; } -} // namespace - -cut_rectangle_result cut_rectangle(bbox input, bbox hole) +Vector2 hole::ordinal_offset(Vector2b) const { - return cut_rectangleʹ(input, hole); + constexpr auto ret = Vector2(TILE_COUNT, TILE_COUNT) * TILE_SIZE2; + return ret; } +object_type hole::type() const noexcept { return object_type::hole; } +bool hole::is_virtual() const { return true; } +bool hole::is_dynamic() const { return false; } + } // namespace floormat diff --git a/src/hole.hpp b/src/hole.hpp index b7499ced..64e53149 100644 --- a/src/hole.hpp +++ b/src/hole.hpp @@ -6,16 +6,40 @@ namespace floormat { struct hole_proto final : object_proto { - bool affects_render : 1 = true; - bool affects_physics : 1 = false; + ~hole_proto() noexcept override; + hole_proto(); + hole_proto(const hole_proto&); + hole_proto& operator=(const hole_proto&); + hole_proto(hole_proto&&) noexcept; + hole_proto& operator=(hole_proto&&) noexcept; + bool operator==(const hole_proto&) const; + + uint8_t height = 0; + bool on_render : 1 = true; + bool on_physics : 1 = true; + bool is_wall : 1 = false; }; -struct hole : object +struct hole final : object { - bool affects_render : 1 = true; - bool affects_physics : 1 = false; + uint8_t _height = 0; + const bool on_render : 1 = true; + const bool on_physics : 1 = true; + const bool is_wall : 1 = false; hole(object_id id, class chunk& c, const hole_proto& proto); + ~hole() noexcept override; + + Vector2 ordinal_offset(Vector2b offset) const override; + float depth_offset() const override; + object_type type() const noexcept override; + void update(const std::shared_ptr<object>& ptr, size_t& i, const Ns& dt) override; + bool is_dynamic() const override; + bool is_virtual() const override; + + explicit operator hole_proto() const; + + friend class world; }; struct cut_rectangle_result |