summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorStanislaw Halik <sthalik@misaki.pl>2023-10-11 17:53:25 +0200
committerStanislaw Halik <sthalik@misaki.pl>2023-10-11 17:57:13 +0200
commit5d1954365b9c1010372dfc020afb7ff7450b4e14 (patch)
tree9809411ea0468da74df62eb6c31849c1df020ea4
parentca4544f04cc67c296e58170e76203bc11519d988 (diff)
a
-rw-r--r--bench/01-dijkstra.cpp23
-rw-r--r--compat/int-hash.cpp35
-rw-r--r--compat/int-hash.hpp4
-rw-r--r--src/object.cpp2
-rw-r--r--src/path-search-dijkstra.cpp40
-rw-r--r--src/path-search.hpp3
-rw-r--r--src/point.cpp4
-rw-r--r--src/point.hpp79
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