summaryrefslogtreecommitdiffhomepage
path: root/src/chunk.cpp
diff options
context:
space:
mode:
authorStanislaw Halik <sthalik@misaki.pl>2022-12-05 21:32:57 +0100
committerStanislaw Halik <sthalik@misaki.pl>2022-12-06 01:35:11 +0100
commit0a6612286bfa8c2503c757da2b39da37aa05deaf (patch)
tree3606dbe2ee59026f0fcdba7377034dfcab13da0d /src/chunk.cpp
parent2679d49a53a3f9825ce855f6ed25b3b045ec5aa1 (diff)
src/chunk: plug in lqt for collision detection
Diffstat (limited to 'src/chunk.cpp')
-rw-r--r--src/chunk.cpp183
1 files changed, 72 insertions, 111 deletions
diff --git a/src/chunk.cpp b/src/chunk.cpp
index 55afe1b9..e66b193a 100644
--- a/src/chunk.cpp
+++ b/src/chunk.cpp
@@ -1,9 +1,6 @@
#include "chunk.hpp"
-#include "tile-atlas.hpp"
-#include "shaders/tile.hpp"
-#include <algorithm>
-#include <Corrade/Containers/ArrayViewStl.h>
-#include <Magnum/GL/Buffer.h>
+#include "compat/LooseQuadtree-impl.h"
+#include "src/tile-atlas.hpp"
namespace floormat {
@@ -27,133 +24,97 @@ bool chunk::empty(bool force) const noexcept
tile_atlas* chunk::ground_atlas_at(std::size_t i) const noexcept { return _ground_atlases[i].get(); }
tile_atlas* chunk::wall_atlas_at(std::size_t i) const noexcept { return _wall_atlases[i].get(); }
-static auto make_index_array(std::size_t offset)
-{
- std::array<std::array<UnsignedShort, 6>, TILE_COUNT> array; // NOLINT(cppcoreguidelines-pro-type-member-init)
- for (std::size_t i = 0; i < TILE_COUNT; i++)
- array[i] = tile_atlas::indices(i + offset);
- return array;
-}
+tile_ref chunk::operator[](std::size_t idx) noexcept { return { *this, std::uint8_t(idx) }; }
+tile_proto chunk::operator[](std::size_t idx) const noexcept { return tile_proto(tile_ref { *const_cast<chunk*>(this), std::uint8_t(idx) }); }
+tile_ref chunk::operator[](local_coords xy) noexcept { return operator[](xy.to_index()); }
+tile_proto chunk::operator[](local_coords xy) const noexcept { return operator[](xy.to_index()); }
+
+auto chunk::begin() noexcept -> iterator { return iterator { *this, 0 }; }
+auto chunk::end() noexcept -> iterator { return iterator { *this, TILE_COUNT }; }
+auto chunk::cbegin() const noexcept -> const_iterator { return const_iterator { *this, 0 }; }
+auto chunk::cend() const noexcept -> const_iterator { return const_iterator { *this, TILE_COUNT }; }
+auto chunk::begin() const noexcept -> const_iterator { return cbegin(); }
+auto chunk::end() const noexcept -> const_iterator { return cend(); }
-struct vertex {
- Vector3 position;
- Vector2 texcoords;
- float depth = -1;
-};
+void chunk::mark_ground_modified() noexcept { _ground_modified = true; _pass_modified = true; }
+void chunk::mark_walls_modified() noexcept { _walls_modified = true; _pass_modified = true; }
+void chunk::mark_scenery_modified() noexcept { _scenery_modified = true; _pass_modified = true; }
-auto chunk::ensure_ground_mesh() noexcept -> ground_mesh_tuple
+void chunk::mark_modified() noexcept
{
- if (!_ground_modified)
- return { ground_mesh, ground_indexes };
- _ground_modified = false;
+ mark_ground_modified();
+ mark_walls_modified();
+ mark_scenery_modified();
+}
- for (std::size_t i = 0; i < TILE_COUNT; i++)
- ground_indexes[i] = std::uint8_t(i);
- std::sort(ground_indexes.begin(), ground_indexes.end(), [this](std::uint8_t a, std::uint8_t b) {
- return _ground_atlases[a].get() < _ground_atlases[b].get();
- });
+static constexpr auto tile_size2us = Vector2us(iTILE_SIZE2);
- std::array<std::array<vertex, 4>, TILE_COUNT> vertexes;
- for (std::size_t k = 0; k < TILE_COUNT; k++)
- {
- const std::uint8_t i = ground_indexes[k];
- if (auto atlas = _ground_atlases[i]; !atlas)
- vertexes[k] = {};
- else
- {
- const local_coords pos{i};
- const auto quad = atlas->floor_quad(Vector3(pos.x, pos.y, 0) * TILE_SIZE, TILE_SIZE2);
- const auto texcoords = atlas->texcoords_for_id(_ground_variants[i]);
- const float depth = tile_shader::depth_value(pos);
- auto& v = vertexes[k];
- for (std::size_t j = 0; j < 4; j++)
- v[j] = { quad[j], texcoords[j], depth };
- }
- }
- const auto indexes = make_index_array(0);
-
- GL::Mesh mesh{GL::MeshPrimitive::Triangles};
- mesh.addVertexBuffer(GL::Buffer{vertexes}, 0, tile_shader::Position{}, tile_shader::TextureCoordinates{}, tile_shader::Depth{})
- .setIndexBuffer(GL::Buffer{indexes}, 0, GL::MeshIndexType::UnsignedShort)
- .setCount(6 * TILE_COUNT);
- ground_mesh = Utility::move(mesh);
- return { ground_mesh, ground_indexes };
+static constexpr Vector2s tile_start(std::size_t k)
+{
+ const auto i = std::uint8_t(k);
+ const local_coords coord{i};
+ constexpr auto tile_size2s = Vector2s(tile_size2us), half = tile_size2s/2;
+ return tile_size2s * Vector2s(coord.x, coord.y) - half;
}
-auto chunk::ensure_wall_mesh() noexcept -> wall_mesh_tuple
+auto chunk::ensure_passability() noexcept -> lqt&
{
- if (!_walls_modified)
- return { wall_mesh, wall_indexes };
- _walls_modified = false;
+ auto& qt = *_static_lqt;
+
+ if (!_pass_modified)
+ return qt;
+ _pass_modified = false;
- for (std::size_t i = 0; i < TILE_COUNT*2; i++)
- wall_indexes[i] = std::uint16_t(i);
+ qt.Clear();
+ _lqt_bboxes.clear();
+ _lqt_bboxes.reserve(32);
- std::sort(wall_indexes.begin(), wall_indexes.end(), [this](std::uint16_t a, std::uint16_t b) {
- return _wall_atlases[a] < _wall_atlases[b];
- });
+ constexpr auto whole_tile = [](std::size_t k, pass_mode p) constexpr -> bbox {
+ auto start = tile_start(k);
+ return { start[0], start[1], tile_size2us[0], tile_size2us[1], p };
+ };
- std::array<std::array<vertex, 4>, TILE_COUNT*2> vertexes;
- for (std::size_t k = 0; k < TILE_COUNT*2; k++)
+ constexpr auto wall_north = [](std::size_t k, pass_mode p) constexpr -> bbox {
+ auto start = tile_start(k) - Vector2s(0, 1);
+ return { start[0], start[1], tile_size2us[0], 2, p };
+ };
+
+ constexpr auto wall_west = [](std::size_t k, pass_mode p) constexpr -> bbox {
+ auto start = tile_start(k) - Vector2s(1, 0);
+ return { start[0], start[1], 2, tile_size2us[1], p };
+ };
+
+ for (std::size_t i = 0; i < TILE_COUNT; i++)
{
- const std::uint16_t i = wall_indexes[k];
- if (const auto& atlas = _wall_atlases[i]; !atlas)
- vertexes[k] = {};
- else
- {
- const auto& variant = _wall_variants[i];
- const local_coords pos{i / 2u};
- const auto center = Vector3(pos.x, pos.y, 0) * TILE_SIZE;
- const auto quad = i & 1 ? atlas->wall_quad_W(center, TILE_SIZE) : atlas->wall_quad_N(center, TILE_SIZE);
- const float depth = tile_shader::depth_value(pos);
- const auto texcoords = atlas->texcoords_for_id(variant);
- auto& v = vertexes[k];
- for (std::size_t j = 0; j < 4; j++)
- v[j] = { quad[j], texcoords[j], depth, };
- }
+ const auto tile = const_cast<chunk&>(*this)[i];
+ if (auto s = tile.scenery())
+ if (auto p = s.frame.passability; p != pass_mode::pass)
+ _lqt_bboxes.push_back(whole_tile(i, p));
+ if (auto atlas = tile.ground_atlas())
+ if (auto p = atlas->pass_mode(pass_mode::pass); p != pass_mode::pass)
+ _lqt_bboxes.push_back(whole_tile(i, p));
+ if (auto atlas = tile.wall_north_atlas())
+ if (auto p = atlas->pass_mode(pass_mode::blocked); p != pass_mode::pass)
+ _lqt_bboxes.push_back(wall_north(i, p));
+ if (auto atlas = tile.wall_west_atlas())
+ if (auto p = atlas->pass_mode(pass_mode::blocked); p != pass_mode::pass)
+ _lqt_bboxes.push_back(wall_west(i, p));
}
- using index_t = std::array<std::array<UnsignedShort, 6>, TILE_COUNT>;
- const index_t indexes[2] = { make_index_array(0), make_index_array(TILE_COUNT) };
+ for (auto& bbox : _lqt_bboxes)
+ qt.Insert(&bbox);
- GL::Mesh mesh{GL::MeshPrimitive::Triangles};
- mesh.addVertexBuffer(GL::Buffer{vertexes}, 0, tile_shader::Position{}, tile_shader::TextureCoordinates{}, tile_shader::Depth{})
- .setIndexBuffer(GL::Buffer{indexes}, 0, GL::MeshIndexType::UnsignedShort)
- .setCount(6 * TILE_COUNT);
- wall_mesh = Utility::move(mesh);
- return { wall_mesh, wall_indexes };
+ return qt;
}
-fm_noinline
-chunk::chunk() noexcept // NOLINT(modernize-use-equals-default)
+void chunk::bb_extractor::ExtractBoundingBox(const chunk::bbox* x, BB* bbox)
{
- //fm_debug("chunk ctor");
+ *bbox = { x->left, x->top, std::int16_t(x->width), std::int16_t(x->height) };
}
-tile_ref chunk::operator[](std::size_t idx) noexcept { return { *this, std::uint8_t(idx) }; }
-tile_proto chunk::operator[](std::size_t idx) const noexcept { return tile_proto(tile_ref { *const_cast<chunk*>(this), std::uint8_t(idx) }); }
-tile_ref chunk::operator[](local_coords xy) noexcept { return operator[](xy.to_index()); }
-tile_proto chunk::operator[](local_coords xy) const noexcept { return operator[](xy.to_index()); }
-
-auto chunk::begin() noexcept -> iterator { return iterator { *this, 0 }; }
-auto chunk::end() noexcept -> iterator { return iterator { *this, TILE_COUNT }; }
-auto chunk::cbegin() const noexcept -> const_iterator { return const_iterator { *this, 0 }; }
-auto chunk::cend() const noexcept -> const_iterator { return const_iterator { *this, TILE_COUNT }; }
-auto chunk::begin() const noexcept -> const_iterator { return cbegin(); }
-auto chunk::end() const noexcept -> const_iterator { return cend(); }
-
+chunk::chunk() noexcept : _static_lqt { std::make_unique<lqt>() } {}
+chunk::~chunk() noexcept = default;
chunk::chunk(chunk&&) noexcept = default;
chunk& chunk::operator=(chunk&&) noexcept = default;
-void chunk::mark_ground_modified() noexcept { _ground_modified = true; }
-void chunk::mark_walls_modified() noexcept { _walls_modified = true; }
-void chunk::mark_scenery_modified() noexcept { _scenery_modified = true; }
-
-void chunk::mark_modified() noexcept
-{
- mark_ground_modified();
- mark_walls_modified();
- mark_scenery_modified();
-}
-
} // namespace floormat