From 7f01dc47b0fd322d8c2b3f27eb1a94cd450a26a5 Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Mon, 17 Oct 2022 13:28:37 +0200 Subject: a --- src/chunk.cpp | 6 ++++++ src/chunk.hpp | 1 + src/global-coords.cpp | 9 +++++---- src/global-coords.hpp | 26 ++++++++++++++++++++++---- src/world.cpp | 31 +++++++++++++++++++------------ src/world.hpp | 33 +++++++++++---------------------- 6 files changed, 64 insertions(+), 42 deletions(-) (limited to 'src') diff --git a/src/chunk.cpp b/src/chunk.cpp index 95904d81..d8c2d011 100644 --- a/src/chunk.cpp +++ b/src/chunk.cpp @@ -4,9 +4,15 @@ namespace floormat { bool chunk::empty() const { + if (!_maybe_empty) + return false; + for (const tile& x : _tiles) if (x.ground_image || x.wall_north || x.wall_west) + { + _maybe_empty = false; return false; + } return true; } diff --git a/src/chunk.hpp b/src/chunk.hpp index 7ef0bc94..9e41c5fb 100644 --- a/src/chunk.hpp +++ b/src/chunk.hpp @@ -41,6 +41,7 @@ struct chunk final private: std::array _tiles = {}; + mutable bool _maybe_empty = true; }; } // namespace floormat diff --git a/src/global-coords.cpp b/src/global-coords.cpp index 997f1c11..e10e921f 100644 --- a/src/global-coords.cpp +++ b/src/global-coords.cpp @@ -9,9 +9,10 @@ static_assert(std::is_same_v); -static_assert(global_coords{{-1, -1}, {2, 3}} == global_coords{((-1 + (1 << 15)) << 4) + 2, ((-1 + (1 << 15)) << 4) + 3}); -static_assert(global_coords{15, 15}.chunk() == global_coords{}.chunk()); -static_assert(global_coords{15, 16}.chunk() != global_coords{}.chunk()); -static_assert(global_coords{(1 + (1<<15)) << 4 | 3, (2 + (1<<15)) << 4 | 4} == global_coords{{1, 2}, {3, 4}}); +static_assert(TILE_MAX_DIM == (1 << 4)); + +static_assert(global_coords{(int)TILE_MAX_DIM-1, (int)TILE_MAX_DIM-1}.chunk() == global_coords{}.chunk()); +static_assert(global_coords{(int)TILE_MAX_DIM-1, (int)TILE_MAX_DIM}.chunk() != global_coords{}.chunk()); +static_assert(global_coords{(1u + (1<<15)) << 4 | 3, (2u + (1<<15)) << 4 | 4} == global_coords{{1, 2}, {3, 4}}); } // namespace floormat diff --git a/src/global-coords.hpp b/src/global-coords.hpp index e51dc6aa..d3c36c96 100644 --- a/src/global-coords.hpp +++ b/src/global-coords.hpp @@ -1,6 +1,8 @@ #pragma once #include "local-coords.hpp" #include "compat/assert.hpp" +#include +#include namespace floormat { @@ -11,31 +13,47 @@ struct chunk_coords final { }; struct global_coords final { - std::uint32_t x = 0, y = 0; + std::uint32_t x = 1 << 15, y = 1 << 15; constexpr global_coords(chunk_coords c, local_coords xy) : x{ std::uint32_t(c.x + (1 << 15)) << 4 | (xy.x & 0x0f) }, y{ std::uint32_t(c.y + (1 << 15)) << 4 | (xy.y & 0x0f) } {} constexpr global_coords(std::uint32_t x, std::uint32_t y) noexcept : x{x}, y{y} {} + constexpr global_coords(std::int32_t x, std::int32_t y) noexcept : + x{std::uint32_t(x + (1 << 15))}, y{std::uint32_t(y + (1 << 15))} + {} constexpr global_coords() noexcept = default; constexpr local_coords local() const noexcept; constexpr chunk_coords chunk() const noexcept; + constexpr Vector2i to_signed() const noexcept; + constexpr bool operator==(const global_coords& other) const noexcept = default; }; constexpr local_coords global_coords::local() const noexcept { - return { (std::uint8_t)(x % TILE_MAX_DIM), (std::uint8_t)(y % TILE_MAX_DIM) }; + return { + std::uint8_t(x & 0x0f), + std::uint8_t(y & 0x0f), + }; } constexpr chunk_coords global_coords::chunk() const noexcept { return { - (std::int16_t)(std::int32_t(x >> 4) - (1 << 15)), - (std::int16_t)(std::int32_t(y >> 4) - (1 << 15)), + std::int16_t((x - (1 << 15)) >> 4), + std::int16_t((y - (1 << 15)) >> 4), + }; +} + +constexpr Vector2i global_coords::to_signed() const noexcept +{ + return { + std::int32_t(x - (1 << 15)), + std::int32_t(y - (1 << 15)), }; } diff --git a/src/world.cpp b/src/world.cpp index 3057fca8..8337bfba 100644 --- a/src/world.cpp +++ b/src/world.cpp @@ -5,7 +5,7 @@ namespace floormat { struct chunk_pointer_maker final { - operator std::shared_ptr() const { return std::make_shared(); } + inline operator std::shared_ptr() const { return std::make_shared(); } }; world::world() @@ -15,22 +15,26 @@ world::world() std::shared_ptr world::operator[](chunk_coords c) noexcept { + maybe_collect(); + + if (_last_chunk) + { + auto& [ret, pos] = *_last_chunk; + if (pos == c) + return ret; + } + auto [it, inserted] = _chunks.try_emplace(c, chunk_pointer_maker{}); - const auto ret = it->second; - return maybe_collect(), ret; + auto ret = it->second; + _last_chunk = { ret, c }; + return ret; } -std::shared_ptr world::maybe_chunk(chunk_coords c) noexcept -{ - if (const auto it = _chunks.find(c); it != _chunks.cend()) - return it->second; - else - return nullptr; -} -std::shared_ptr world::maybe_chunk(chunk_coords c) const noexcept +std::tuple, tile&> world::operator[](global_coords pt) noexcept { - return const_cast(*this).maybe_chunk(c); + auto c = operator[](pt.chunk()); + return { c, (*c)[pt.local()] }; } bool world::contains(chunk_coords c) const noexcept @@ -41,6 +45,7 @@ bool world::contains(chunk_coords c) const noexcept void world::clear() { _last_collection = 0; + _last_chunk = std::nullopt; _chunks.clear(); _chunks.rehash(initial_capacity); } @@ -61,7 +66,9 @@ void world::collect() else ++it; } + _last_collection = _chunks.size(); + _last_chunk = std::nullopt; } } // namespace floormat diff --git a/src/world.hpp b/src/world.hpp index 1e8469d9..7c256efc 100644 --- a/src/world.hpp +++ b/src/world.hpp @@ -1,24 +1,10 @@ #pragma once #include "compat/int-hash.hpp" #include "global-coords.hpp" +#include "tile.hpp" #include #include - -namespace std { - -template struct hash; - -template<> -struct hash final -{ - constexpr - std::size_t operator()(floormat::chunk_coords c) const noexcept - { - return floormat::int_hash((std::size_t)c.y << 16 | (std::size_t)c.x); - } -}; - -} // namespace std +#include namespace floormat { @@ -28,20 +14,23 @@ struct world final { world(); std::shared_ptr operator[](chunk_coords c) noexcept; - std::shared_ptr maybe_chunk(chunk_coords c) noexcept; - std::shared_ptr maybe_chunk(chunk_coords c) const noexcept; + std::tuple, tile&> operator[](global_coords pt) noexcept; bool contains(chunk_coords c) const noexcept; void clear(); void collect(); private: + void maybe_collect(); + static constexpr std::size_t initial_capacity = 64, collect_every = 32; static constexpr float max_load_factor = .5; - std::size_t _last_collection = 0; + static constexpr auto hasher = [](chunk_coords c) -> std::size_t { + return int_hash((std::size_t)c.y << 16 | (std::size_t)c.x); + }; - void maybe_collect(); - - std::unordered_map> _chunks{initial_capacity}; + std::size_t _last_collection = 0; + mutable std::optional, chunk_coords>> _last_chunk; + std::unordered_map, decltype(hasher)> _chunks{initial_capacity, hasher}; }; } // namespace floormat -- cgit v1.2.3