diff options
author | Stanislaw Halik <sthalik@misaki.pl> | 2023-10-11 17:53:25 +0200 |
---|---|---|
committer | Stanislaw Halik <sthalik@misaki.pl> | 2023-10-11 17:57:13 +0200 |
commit | 5d1954365b9c1010372dfc020afb7ff7450b4e14 (patch) | |
tree | 9809411ea0468da74df62eb6c31849c1df020ea4 | |
parent | ca4544f04cc67c296e58170e76203bc11519d988 (diff) |
a
-rw-r--r-- | bench/01-dijkstra.cpp | 23 | ||||
-rw-r--r-- | compat/int-hash.cpp | 35 | ||||
-rw-r--r-- | compat/int-hash.hpp | 4 | ||||
-rw-r--r-- | src/object.cpp | 2 | ||||
-rw-r--r-- | src/path-search-dijkstra.cpp | 40 | ||||
-rw-r--r-- | src/path-search.hpp | 3 | ||||
-rw-r--r-- | src/point.cpp | 4 | ||||
-rw-r--r-- | src/point.hpp | 79 |
8 files changed, 99 insertions, 91 deletions
diff --git a/bench/01-dijkstra.cpp b/bench/01-dijkstra.cpp index b358f1f9..1f1069ab 100644 --- a/bench/01-dijkstra.cpp +++ b/bench/01-dijkstra.cpp @@ -22,29 +22,32 @@ void Dijkstra(benchmark::State& state) constexpr auto wt = local_coords{wtx, wty}; constexpr auto wpos = global_coords{wch, wt}; - auto& ch = w[chunk_coords_{0,0,0}]; - auto& ch2 = w[wch]; + auto& ch = w[wch]; auto metal2 = tile_image_proto{loader.tile_atlas("metal2", {2, 2}, pass_mode::blocked), 0}; for (int16_t j = wcy - 1; j <= wcy + 1; j++) for (int16_t i = wcx - 1; i <= wcx + 1; i++) { auto &c = w[chunk_coords_{i, j, 0}]; - for (int k : { 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, }) + for (int k : { 3, 4, 5, 6, 11, 12, 13, 14, 15, }) { c[{ k, k }].wall_north() = metal2; c[{ k, k }].wall_west() = metal2; } } - ch2[{ wtx, wty }].wall_west() = metal2; - ch2[{ wtx, wty }].wall_north() = metal2; - ch2[{ wtx+1, wty }].wall_west() = metal2; - ch2[{ wtx, wty -1}].wall_north() = metal2; + ch[{ wtx, wty }].wall_west() = metal2; + ch[{ wtx, wty }].wall_north() = metal2; + ch[{ wtx+1, wty }].wall_west() = metal2; + ch[{ wtx, wty -1}].wall_north() = metal2; - fm_assert(ch.is_passability_modified()); - ch.ensure_passability(); - ch2.ensure_passability(); + for (int16_t j = wcy - 1; j <= wcy + 1; j++) + for (int16_t i = wcx - 1; i <= wcx + 1; i++) + { + auto& c = w[chunk_coords_{i, j, 0}]; + c.mark_passability_modified(); + c.ensure_passability(); + } auto run = [&] { A.Dijkstra(w, diff --git a/compat/int-hash.cpp b/compat/int-hash.cpp index 79b5dfad..f9ae19c1 100644 --- a/compat/int-hash.cpp +++ b/compat/int-hash.cpp @@ -35,41 +35,22 @@ fm_UNROLL_8 } // namespace -#define fnvhash_64_ROUND() do { hash *= 0x01000193u; hash ^= (uint8_t)*str++; } while(false) - -uint64_t fnvhash_64(const void* str_, size_t size) +uint64_t fnvhash_32(const void* buf, size_t size) { - const auto *str = (const char*)str_; + const auto *str = (const char*)buf, *const end = str + size; uint32_t hash = 0x811c9dc5u; - size_t full = size / 8; - for (size_t i = 0; i < full; i++) - { - fnvhash_64_ROUND(); - fnvhash_64_ROUND(); - fnvhash_64_ROUND(); - fnvhash_64_ROUND(); - fnvhash_64_ROUND(); - fnvhash_64_ROUND(); - fnvhash_64_ROUND(); - fnvhash_64_ROUND(); - } - switch (size & 7u) +fm_UNROLL_8 + for (; str != end; ++str) { - case 7: fnvhash_64_ROUND(); [[fallthrough]]; - case 6: fnvhash_64_ROUND(); [[fallthrough]]; - case 5: fnvhash_64_ROUND(); [[fallthrough]]; - case 4: fnvhash_64_ROUND(); [[fallthrough]]; - case 3: fnvhash_64_ROUND(); [[fallthrough]]; - case 2: fnvhash_64_ROUND(); [[fallthrough]]; - case 1: fnvhash_64_ROUND(); [[fallthrough]]; - case 0: break; + hash *= 0x01000193u; + hash ^= (uint8_t)*str; } return hash; } -uint64_t fnvhash_32(const void* str_, size_t size) +uint64_t fnvhash_64(const void* buf, size_t size) { - const auto *str = (const char*)str_, *end = str + size; + const auto *str = (const char*)buf, *const end = str + size; uint64_t hash = 0xcbf29ce484222325u; fm_UNROLL_4 for (; str != end; ++str) diff --git a/compat/int-hash.hpp b/compat/int-hash.hpp index 6a6cbcd4..86fc6a45 100644 --- a/compat/int-hash.hpp +++ b/compat/int-hash.hpp @@ -5,7 +5,7 @@ namespace floormat { size_t int_hash(uint32_t x) noexcept; size_t int_hash(uint64_t x) noexcept; -uint64_t fnvhash_64(const void* str, size_t size); -uint64_t fnvhash_32(const void* str, size_t size); +uint64_t fnvhash_64(const void* buf, size_t size); +uint64_t fnvhash_32(const void* buf, size_t size); } // namespace floormat diff --git a/src/object.cpp b/src/object.cpp index 0605fcf3..b2efb6a1 100644 --- a/src/object.cpp +++ b/src/object.cpp @@ -149,7 +149,7 @@ point object::normalize_coords(global_coords coord, Vector2b cur, Vector2i new_o point object::normalize_coords(const point& pt, Vector2i delta) { - return object::normalize_coords(pt.coord, pt.offset, delta); + return object::normalize_coords(pt.coord(), pt.offset, delta); } template<bool neighbor = true> diff --git a/src/path-search-dijkstra.cpp b/src/path-search-dijkstra.cpp index a40d79ad..7a4f9789 100644 --- a/src/path-search-dijkstra.cpp +++ b/src/path-search-dijkstra.cpp @@ -80,7 +80,7 @@ struct heap_comparator uint32_t distance(point a, point b) { Vector2i dist; - dist += Math::abs(a.coord - b.coord)*iTILE_SIZE2; + dist += Math::abs(a.coord() - b.coord())*iTILE_SIZE2; dist += Vector2i(a.offset - b.offset); return (uint32_t)Math::sqrt(dist.dot()); } @@ -201,7 +201,7 @@ path_search_result astar::Dijkstra(world& w, point from_, point to_, object_id o auto& path = result.path(); path.clear(); indexes[from_] = 0; - nodes.push_back({.dist = 0, .coord = from, .offset = from_offset }); + nodes.push_back({.dist = 0, .pt = from_ }); add_to_heap(0); if (!from_offset.isZero()) @@ -219,7 +219,7 @@ path_search_result astar::Dijkstra(world& w, point from_, point to_, object_id o path_search::is_passable(w, from.chunk3(), bb, own_id, p)) { indexes[{from, offset}] = idx; - nodes.push_back({.dist = from_offset_len, .prev = 0, .coord = from, .offset = offset}); + nodes.push_back({.dist = from_offset_len, .prev = 0, .pt = {from, offset}}); add_to_heap(idx++); } } @@ -232,44 +232,40 @@ path_search_result astar::Dijkstra(world& w, point from_, point to_, object_id o while (!Q.empty()) { const auto id = pop_from_heap(); - point n_pt; - global_coords n_coord; - Vector2b n_offset; - uint32_t n_dist; + point cur_pt; + uint32_t cur_dist; { auto& n = nodes[id]; - n_coord = n.coord; - n_offset = n.offset; - n_pt = {n_coord, n_offset}; - n_dist = n.dist; + cur_pt = n.pt; + cur_dist = n.dist; #if FM_ASTAR_NO_EDGE_CACHE - (void)n_pt; + (void)cur_pt; #endif } - if (auto d = distance({n_coord, n_offset}, {to, to_offset}); d < closest) + if (auto d = distance(cur_pt, to_); d < closest) { closest = d; - closest_pos = {n_coord, n_offset}; - closest_path_len = n_dist; + closest_pos = cur_pt; + closest_path_len = cur_dist; } #ifndef FM_NO_DEBUG if (debug >= 2) [[unlikely]] DBG_nospace << "node" << " px:" << closest << " path:" << closest_path_len - << " pos:" << Vector3i(closest_pos.coord) + << " pos:" << Vector3i(closest_pos.coord()) << ";" << closest_pos.offset; #endif - const auto bb0 = bbox_from_pos(Vector2(n_coord.local()), n_offset, own_size); + const auto bb0 = bbox_from_pos(Vector2(cur_pt.local()), cur_pt.offset, own_size); for (auto [vec, len] : directions) { - auto [new_coord, new_offset] = object::normalize_coords(n_coord, n_offset, vec); - const auto dist = n_dist + len; + auto [new_coord, new_offset] = object::normalize_coords(cur_pt, vec); + const auto dist = cur_dist + len; if (dist >= max_dist) continue; - const auto new_pt = point{.coord = new_coord, .offset = new_offset}; + const auto new_pt = point{new_coord, new_offset}; const size_t new_pt_hash = hash_point(new_pt); auto new_idx = (uint32_t)-1; @@ -316,7 +312,7 @@ path_search_result astar::Dijkstra(world& w, point from_, point to_, object_id o indexes.insert({new_pt, new_idx}, new_pt_hash); auto new_node = visited { .dist = dist, .prev = id, - .coord = new_coord, .offset = new_offset, + .pt = {new_coord, new_offset}, }; nodes.push_back(new_node); } @@ -338,7 +334,7 @@ path_search_result astar::Dijkstra(world& w, point from_, point to_, object_id o if (debug >= 1) DBG_nospace << "dijkstra: closest px:" << closest << " path:" << closest_path_len - << " pos:" << Vector3i(closest_pos.coord) + << " pos:" << Vector3i(closest_pos.coord()) << ";" << closest_pos.offset << " nodes:" << nodes.size() #if !FM_ASTAR_NO_EDGE_CACHE diff --git a/src/path-search.hpp b/src/path-search.hpp index 464596a6..e3fad6e6 100644 --- a/src/path-search.hpp +++ b/src/path-search.hpp @@ -56,8 +56,7 @@ struct astar { uint32_t dist = (uint32_t)-1; uint32_t prev = (uint32_t)-1; - global_coords coord; - Vector2b offset; + point pt; }; using pred = path_search::pred; diff --git a/src/point.cpp b/src/point.cpp index f21e2d40..67a79475 100644 --- a/src/point.cpp +++ b/src/point.cpp @@ -7,8 +7,8 @@ Debug& operator<<(Debug& dbg, const point& pt) const auto flags = dbg.flags(); dbg.setFlags(flags | Debug::Flag::NoSpace); - auto c = Vector3i(pt.coord.chunk3()); - auto t = Vector2i(pt.coord.local()); + auto c = Vector3i(pt.chunk3()); + auto t = Vector2i(pt.local()); auto o = pt.offset; dbg << "point{"; diff --git a/src/point.hpp b/src/point.hpp index 0d9db1df..fd23f72d 100644 --- a/src/point.hpp +++ b/src/point.hpp @@ -1,45 +1,74 @@ #pragma once #include "global-coords.hpp" -#include <Corrade/Utility/Move.h> +#include "compat/defs.hpp" #include <compare> +#include <type_traits> +#include <Corrade/Utility/StlForwardTuple.h> + +namespace floormat { struct point; } + +template<> struct std::tuple_size<floormat::point> : std::integral_constant<floormat::size_t, 2> {}; + +template<floormat::size_t N> struct std::tuple_element<N, floormat::point>; + +template<> struct std::tuple_element<0, floormat::point> { using type = floormat::global_coords; }; +template<> struct std::tuple_element<1, floormat::point> { using type = Magnum::Vector2b; }; namespace floormat { -// todo pack this within 8 bytes struct point { - global_coords coord; + int16_t cx = 0, cy = 0; + int8_t cz = 0; + local_coords tile; Vector2b offset; - constexpr bool operator==(const point&) const = default; - friend constexpr std::strong_ordering operator<=>(const point& a, const point& b) noexcept; + constexpr point(); + constexpr point(global_coords coord, Vector2b offset); + constexpr point(chunk_coords_ coord, local_coords tile, Vector2b offset); + fm_DECLARE_DEFAULT_COPY_ASSIGNMENT(point); + + constexpr bool operator==(const point&) const noexcept = default; + friend constexpr std::strong_ordering operator<=>(const point& a, const point& b); + constexpr global_coords coord() const; + constexpr chunk_coords chunk() const; + constexpr chunk_coords_ chunk3() const; + constexpr local_coords local() const; friend Debug& operator<<(Debug& dbg, const point& pt); }; -constexpr std::strong_ordering operator<=>(const point& p1, const point& p2) noexcept +constexpr std::strong_ordering operator<=>(const point& p1, const point& p2) { - auto c1 = Vector3i(p1.coord), c2 = Vector3i(p2.coord); - - if (auto val = c1.z() <=> c2.z(); val != std::strong_ordering::equal) - return val; - if (auto val = c1.y() <=> c2.y(); val != std::strong_ordering::equal) - return val; - if (auto val = c1.x() <=> c2.x(); val != std::strong_ordering::equal) - return val; - if (auto val = p1.offset.y() <=> p2.offset.y(); val != std::strong_ordering::equal) - return val; - if (auto val = p1.offset.x() <=> p2.offset.x(); val != std::strong_ordering::equal) - return val; - + if (auto val = p1.cz <=> p2.cz; val != std::strong_ordering::equal) return val; + if (auto val = p1.cy <=> p2.cy; val != std::strong_ordering::equal) return val; + if (auto val = p1.cx <=> p2.cx; val != std::strong_ordering::equal) return val; + if (auto val = p1.tile.y <=> p2.tile.y; val != std::strong_ordering::equal) return val; + if (auto val = p1.tile.x <=> p2.tile.x; val != std::strong_ordering::equal) return val; + if (auto val = p1.offset.y() <=> p2.offset.y(); val != std::strong_ordering::equal) return val; + if (auto val = p1.offset.x() <=> p2.offset.x(); val != std::strong_ordering::equal) return val; return std::strong_ordering::equal; } -struct packed_point -{ - uint64_t cx : 12, cy : 12, cz : 4, - tx : 8, ty : 8, - ox : 4, oy : 4; -}; +constexpr point::point() = default; +constexpr point::point(global_coords coord, Vector2b offset) : point{coord.chunk3(), coord.local(), offset} { } + +constexpr point::point(chunk_coords_ coord, local_coords tile, Vector2b offset) : + cx{coord.x}, cy{coord.y}, cz{coord.z}, tile{tile}, offset{offset} +{} + +constexpr global_coords point::coord() const { return {{cx, cy}, tile, cz}; } +constexpr chunk_coords_ point::chunk3() const { return {cx, cy, cz}; } +constexpr chunk_coords point::chunk() const { return {cx, cy}; } +constexpr local_coords point::local() const { return tile; } + +template<size_t N> std::tuple_element_t<N, point> constexpr get(point pt) { + static_assert(N < 2); + if constexpr(N == 0) + return global_coords{{pt.cx, pt.cy}, pt.tile, pt.cz}; + if constexpr(N == 1) + return pt.offset; + return {}; +} } // namespace floormat |