From 05dee8a02773141cbe6cbfb1c0557018210ced05 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Sun, 26 Mar 2023 18:19:46 +0200 Subject: a --- draw/anim.cpp | 1 + draw/anim.hpp | 2 +- draw/floor.cpp | 1 + editor/update.cpp | 3 +- serialize/world-reader.cpp | 1 + shaders/tile.hpp | 1 + src/chunk-collision.cpp | 1 + src/chunk-render.cpp | 87 ------------------------- src/chunk-scenery.cpp | 157 +++++++++++++++++++++++++++++++++++++++++++++ src/chunk-scenery.hpp | 30 +++++++++ src/chunk.cpp | 1 + src/chunk.hpp | 18 +++--- test/json.cpp | 1 + test/serializer.cpp | 1 + test/tile-iter.cpp | 1 + 15 files changed, 209 insertions(+), 97 deletions(-) create mode 100644 src/chunk-scenery.cpp create mode 100644 src/chunk-scenery.hpp diff --git a/draw/anim.cpp b/draw/anim.cpp index 84afbfe3..1c333ca1 100644 --- a/draw/anim.cpp +++ b/draw/anim.cpp @@ -3,6 +3,7 @@ #include "chunk.hpp" #include "shaders/tile.hpp" #include "main/clickable.hpp" +#include "chunk-scenery.hpp" #include #include #include diff --git a/draw/anim.hpp b/draw/anim.hpp index 9f279b38..8df5aebe 100644 --- a/draw/anim.hpp +++ b/draw/anim.hpp @@ -41,7 +41,7 @@ private: }; using quad_data = std::array; - Array _draw_array; + Array _draw_array; GL::Mesh _mesh; GL::Buffer _vertex_buffer{quad_data{}, Magnum::GL::BufferUsage::DynamicDraw}, _index_buffer{make_index_array()}; diff --git a/draw/floor.cpp b/draw/floor.cpp index 6c5e1266..74d4a54d 100644 --- a/draw/floor.cpp +++ b/draw/floor.cpp @@ -3,6 +3,7 @@ #include "tile.hpp" #include "chunk.hpp" #include "tile-atlas.hpp" +#include "compat/assert.hpp" #include namespace floormat { diff --git a/editor/update.cpp b/editor/update.cpp index 4f7b517a..069399c7 100644 --- a/editor/update.cpp +++ b/editor/update.cpp @@ -5,7 +5,8 @@ #include "main/clickable.hpp" #include "floormat/events.hpp" #include "floormat/main.hpp" -#include "character.hpp" +#include "src/character.hpp" +#include "src/tile-iterator.hpp" #include namespace floormat { diff --git a/serialize/world-reader.cpp b/serialize/world-reader.cpp index c5f504c9..f4e5221c 100644 --- a/serialize/world-reader.cpp +++ b/serialize/world-reader.cpp @@ -8,6 +8,7 @@ #include "loader/scenery.hpp" #include "src/tile-atlas.hpp" #include "src/anim-atlas.hpp" +#include "src/chunk-scenery.hpp" #include diff --git a/shaders/tile.hpp b/shaders/tile.hpp index c4080ab8..5c3d7a13 100644 --- a/shaders/tile.hpp +++ b/shaders/tile.hpp @@ -62,6 +62,7 @@ decltype(auto) tile_shader::draw(T&& mesh, Xs&&... xs) template constexpr Math::Vector2 tile_shader::project(const Math::Vector3& pt) { + static_assert(std::is_floating_point_v); const auto x = pt[0], y = pt[1], z = -pt[2]; return { x-y, (x+y+z*2)*T(.59) }; } diff --git a/src/chunk-collision.cpp b/src/chunk-collision.cpp index f0548df6..aceafc3f 100644 --- a/src/chunk-collision.cpp +++ b/src/chunk-collision.cpp @@ -2,6 +2,7 @@ #include "tile-atlas.hpp" #include "entity.hpp" #include "src/RTree-search.hpp" +#include "src/chunk-scenery.hpp" #include #include diff --git a/src/chunk-render.cpp b/src/chunk-render.cpp index be3d64c4..94200239 100644 --- a/src/chunk-render.cpp +++ b/src/chunk-render.cpp @@ -1,8 +1,6 @@ #include "chunk.hpp" #include "tile-atlas.hpp" #include "shaders/tile.hpp" -#include "entity.hpp" -#include "anim-atlas.hpp" #include #include #include @@ -104,93 +102,8 @@ auto chunk::ensure_wall_mesh() noexcept -> wall_mesh_tuple return { wall_mesh, wall_indexes, count }; } -void chunk::ensure_scenery_draw_array(Array& array) -{ - const size_t len_ = _entities.size(); - - if (len_ <= array.size()) - return; - - size_t len; - - if (len_ > 1 << 17) - len = len_; - else - len = std::bit_ceil(len_); - - array = Array{len}; -} - -auto chunk::ensure_scenery_mesh(Array&& array) noexcept -> scenery_mesh_tuple -{ - return ensure_scenery_mesh(static_cast&>(array)); -} -auto chunk::ensure_scenery_mesh(Array& array) noexcept -> scenery_mesh_tuple -{ - constexpr auto entity_ord_lessp = [](const auto& a, const auto& b) { - return a.ord < b.ord; - }; - - fm_assert(_entities_sorted); - - const auto size = _entities.size(); - ensure_scenery_draw_array(array); - for (auto i = 0uz; const auto& e : _entities) - array[i++] = { e.get(), e->ordinal() }; - std::sort(array.begin(), array.begin() + size, entity_ord_lessp); - const auto es = ArrayView{array, size}; - - if (_scenery_modified) - { - _scenery_modified = false; - - const auto count = fm_begin( - size_t ret = 0; - for (const auto& [e, ord] : es) - ret += !e->is_dynamic(); - return ret; - ); - - scenery_indexes.clear(); - scenery_indexes.reserve(count); - scenery_vertexes.clear(); - scenery_vertexes.reserve(count); - - for (const auto& [e, ord] : es) - { - if (e->is_dynamic()) - continue; - - const auto i = scenery_indexes.size(); - scenery_indexes.emplace_back(); - scenery_indexes.back() = tile_atlas::indices(i); - const auto& atlas = e->atlas; - const auto& fr = *e; - const auto pos = e->coord.local(); - const auto coord = Vector3(pos) * TILE_SIZE + Vector3(Vector2(fr.offset), 0); - const auto quad = atlas->frame_quad(coord, fr.r, fr.frame); - const auto& group = atlas->group(fr.r); - const auto texcoords = atlas->texcoords_for_frame(fr.r, fr.frame, !group.mirror_from.isEmpty()); - const float depth = tile_shader::depth_value(pos, tile_shader::scenery_depth_offset); - scenery_vertexes.emplace_back(); - auto& v = scenery_vertexes.back(); - for (auto j = 0uz; j < 4; j++) - v[j] = { quad[j], texcoords[j], depth }; - } - - GL::Mesh mesh{GL::MeshPrimitive::Triangles}; - mesh.addVertexBuffer(GL::Buffer{scenery_vertexes}, 0, tile_shader::Position{}, tile_shader::TextureCoordinates{}, tile_shader::Depth{}) - .setIndexBuffer(GL::Buffer{scenery_indexes}, 0, GL::MeshIndexType::UnsignedShort) - .setCount(int32_t(6 * count)); - scenery_mesh = Utility::move(mesh); - } - - fm_assert(!size || es); - - return { scenery_mesh, es, size }; -} } // namespace floormat diff --git a/src/chunk-scenery.cpp b/src/chunk-scenery.cpp new file mode 100644 index 00000000..b6be04b1 --- /dev/null +++ b/src/chunk-scenery.cpp @@ -0,0 +1,157 @@ +#include "chunk-scenery.hpp" +#include "shaders/tile.hpp" +#include "entity.hpp" +#include "anim-atlas.hpp" +#include "tile-atlas.hpp" +#include +#include +#include + +namespace floormat { + +auto chunk::ensure_scenery_mesh(Array&& array) noexcept -> scenery_mesh_tuple +{ + return ensure_scenery_mesh(static_cast&>(array)); +} + +bool operator<(const chunk::topo_sort_data& a, const chunk::topo_sort_data& b) +{ + +} + +bool chunk::topo_sort_data::intersects(const topo_sort_data& o) const +{ + return min[0] <= o.max[0] && max[0] >= o.min[0] && + min[1] <= o.max[1] && max[1] >= o.min[1]; +} + +auto chunk::make_topo_sort_data(const entity& e) -> topo_sort_data +{ + const auto& a = *e.atlas; + const auto& g = a.group(e.r); + const auto& f = a.frame(e.r, e.frame); + const auto world_pos = TILE_SIZE20 * Vector3(e.coord.local()) + Vector3(g.offset) + Vector3(Vector2(e.offset), 0); + const auto px_start = tile_shader::project(world_pos) - Vector2(f.ground), px_end = px_start + Vector2(f.size); + topo_sort_data data = { + .min = Vector2i(px_start), .max = Vector2i(px_end), + .center = data.min + (data.max - data.min)/2, + .ord = e.ordinal(), + .is_character = false, + }; + if (e.type() == entity_type::scenery && !e.is_dynamic()) + { + const auto bb_min_ = world_pos - Vector3(Vector2(e.bbox_size/2) + Vector2(e.bbox_offset), 0); + const auto bb_max_ = bb_min_ + Vector3(Vector2(e.bbox_size), 0); + Vector2 start, end; + switch (e.r) + { + using enum rotation; + case N: + case S: + start = Vector2(bb_min_[0], bb_min_[1]); + end = Vector2(bb_max_[0], bb_max_[1]); + break; + case W: + case E: + start = Vector2(bb_min_[0], bb_max_[1]); + end = Vector2(bb_max_[0], bb_min_[1]); + break; + default: + break; + } + const auto bb_min = tile_shader::project(Vector3(start, 0)); + const auto bb_max = tile_shader::project(Vector3(end, 0)); + const auto bb_len = std::fabs(bb_max[0] - bb_min[0]); + if (bb_len >= 1) + data.slope = (bb_max[1]-bb_min[1])/bb_len; + } + else if (e.type() == entity_type::character) + data.is_character = true; + return data; +} + +auto chunk::ensure_scenery_mesh(Array& array) noexcept -> scenery_mesh_tuple +{ + constexpr auto entity_ord_lessp = [](const auto& a, const auto& b) { + return a.ord < b.ord; + }; + + fm_assert(_entities_sorted); + + const auto size = _entities.size(); + + ensure_scenery_draw_array(array); + for (auto i = 0uz; const auto& e : _entities) + array[i++] = { e.get(), e->ordinal(), make_topo_sort_data(*e) }; + std::sort(array.begin(), array.begin() + size, entity_ord_lessp); + + const auto es = ArrayView{array, size}; + + if (_scenery_modified) + { + _scenery_modified = false; + + const auto count = fm_begin( + size_t ret = 0; + for (const auto& [e, ord, _data] : es) + ret += !e->is_dynamic(); + return ret; + ); + + scenery_indexes.clear(); + scenery_indexes.reserve(count); + scenery_vertexes.clear(); + scenery_vertexes.reserve(count); + + for (const auto& [e, ord, _data] : es) + { + if (e->is_dynamic()) + continue; + + const auto i = scenery_indexes.size(); + scenery_indexes.emplace_back(); + scenery_indexes.back() = tile_atlas::indices(i); + const auto& atlas = e->atlas; + const auto& fr = *e; + const auto pos = e->coord.local(); + const auto coord = Vector3(pos) * TILE_SIZE + Vector3(Vector2(fr.offset), 0); + const auto quad = atlas->frame_quad(coord, fr.r, fr.frame); + const auto& group = atlas->group(fr.r); + const auto texcoords = atlas->texcoords_for_frame(fr.r, fr.frame, !group.mirror_from.isEmpty()); + const float depth = tile_shader::depth_value(pos, tile_shader::scenery_depth_offset); + scenery_vertexes.emplace_back(); + auto& v = scenery_vertexes.back(); + for (auto j = 0uz; j < 4; j++) + v[j] = { quad[j], texcoords[j], depth }; + } + + GL::Mesh mesh{GL::MeshPrimitive::Triangles}; + mesh.addVertexBuffer(GL::Buffer{scenery_vertexes}, 0, tile_shader::Position{}, tile_shader::TextureCoordinates{}, tile_shader::Depth{}) + .setIndexBuffer(GL::Buffer{scenery_indexes}, 0, GL::MeshIndexType::UnsignedShort) + .setCount(int32_t(6 * count)); + scenery_mesh = Utility::move(mesh); + } + + fm_assert(!size || es); + + return { scenery_mesh, es, size }; +} + +void chunk::ensure_scenery_draw_array(Array& array) +{ + const size_t len_ = _entities.size(); + + if (len_ <= array.size()) + return; + + size_t len; + + if (len_ > 1 << 17) + len = len_; + else + len = std::bit_ceil(len_); + + array = Array{len}; +} + +} // namespace floormat diff --git a/src/chunk-scenery.hpp b/src/chunk-scenery.hpp new file mode 100644 index 00000000..0e24f6ff --- /dev/null +++ b/src/chunk-scenery.hpp @@ -0,0 +1,30 @@ +#pragma once +#include "chunk.hpp" +#include +#include + +namespace floormat { + +struct chunk::topo_sort_data +{ + Vector2i min, max, center; + float slope = 0, ord; + bool visited : 1 = false; + bool is_character : 1; + + bool intersects(const topo_sort_data& other) const; + friend bool operator<(const topo_sort_data& a, const topo_sort_data& b); +}; +struct chunk::draw_entity +{ + entity* e; + float ord; + topo_sort_data data; +}; +struct chunk::scenery_mesh_tuple { + GL::Mesh& mesh; + ArrayView array; + size_t size; +}; + +} // namespace floormat diff --git a/src/chunk.cpp b/src/chunk.cpp index 21ebe800..5450a02e 100644 --- a/src/chunk.cpp +++ b/src/chunk.cpp @@ -1,6 +1,7 @@ #include "chunk.hpp" #include "src/tile-atlas.hpp" #include "anim-atlas.hpp" +#include "tile-iterator.hpp" #include #include diff --git a/src/chunk.hpp b/src/chunk.hpp index 2fecb6fe..c53bc3e8 100644 --- a/src/chunk.hpp +++ b/src/chunk.hpp @@ -1,19 +1,23 @@ #pragma once #include "object-id.hpp" +#include "tile-defs.hpp" #include "tile.hpp" -#include "tile-iterator.hpp" +#include "local-coords.hpp" #include "src/RTree.h" -#include #include #include #include #include +namespace Corrade::Containers { template class Array; } + namespace floormat { struct anim_atlas; struct entity; struct entity_proto; +class tile_iterator; +class tile_const_iterator; enum class collision : unsigned char { view, shoot, move, @@ -78,12 +82,9 @@ struct chunk final const ArrayView ids; const size_t size; }; - struct draw_entity { entity* e; float ord; }; - struct scenery_mesh_tuple final { - GL::Mesh& mesh; - ArrayView array; - size_t size; - }; + struct topo_sort_data; + struct draw_entity; + struct scenery_mesh_tuple; struct vertex { Vector3 position; @@ -138,6 +139,7 @@ private: _entities_sorted : 1 = true; void ensure_scenery_draw_array(Array& array); + static topo_sort_data make_topo_sort_data(const entity& e); struct bbox final // NOLINT(cppcoreguidelines-pro-type-member-init) { diff --git a/test/json.cpp b/test/json.cpp index 8cc6ed96..d9498e49 100644 --- a/test/json.cpp +++ b/test/json.cpp @@ -9,6 +9,7 @@ #include "chunk.hpp" #include "world.hpp" #include "loader/loader.hpp" +#include "tile-iterator.hpp" #include #include diff --git a/test/serializer.cpp b/test/serializer.cpp index 0e10b899..8107ad68 100644 --- a/test/serializer.cpp +++ b/test/serializer.cpp @@ -5,6 +5,7 @@ #include "src/character.hpp" #include "src/tile-atlas.hpp" #include "src/anim-atlas.hpp" +#include "src/tile-iterator.hpp" #include namespace floormat { diff --git a/test/tile-iter.cpp b/test/tile-iter.cpp index 1b6e2fcc..85ad8797 100644 --- a/test/tile-iter.cpp +++ b/test/tile-iter.cpp @@ -1,6 +1,7 @@ #include "app.hpp" #include "chunk.hpp" #include "world.hpp" +#include "tile-iterator.hpp" namespace floormat { static inline bool always_false() -- cgit v1.2.3