13 constexpr bool is_surrounding(glm::ivec2 a, glm::ivec2 b) {
return glm::abs(a.x - b.x) < 2 && glm::abs(a.y - b.y) < 2; }
14 constexpr bool is_neighbor(glm::ivec2 a, glm::ivec2 b) {
return is_surrounding(a, b) && glm::abs(a.y - b.y) != glm::abs(a.x - b.x); }
15 constexpr bool is_diagonal_neighbor(glm::ivec2 a, glm::ivec2 b) {
return is_surrounding(a, b) && glm::abs(a.y - b.y) == glm::abs(a.x - b.x); }
18 concept metric =
false;
20 struct manhattan_metric
22 template <std::
integral T>
23 static constexpr auto distance(glm::tvec2<T> a, glm::tvec2<T> b)
25 const auto d = glm::abs(b - a);
29 template <std::
integral T>
30 static constexpr auto is_valid_neighbor(glm::tvec2<T> a, glm::tvec2<T> b)
32 return is_neighbor(a, b);
35 static constexpr auto is_valid_direction(direction dir)
37 return is_cardinal(dir);
40 using neighbor_metric = manhattan_metric;
42 struct chebyshev_metric
44 template <std::
integral T>
45 static constexpr auto distance(glm::tvec2<T> a, glm::tvec2<T> b)
47 const auto d = glm::abs(b - a);
51 template <std::
integral T>
52 static constexpr bool is_valid_neighbor(glm::tvec2<T> a, glm::tvec2<T> b)
57 static constexpr bool is_valid_direction(direction dir)
62 using surrounding_metric = chebyshev_metric;
64 template <std::
integral T>
65 constexpr auto manhattan_distance(glm::tvec2<T> a, glm::tvec2<T> b)
67 return manhattan_metric::distance(a, b);
70 template <std::
integral T>
71 constexpr auto chebyshev_distance(glm::tvec2<T> a, glm::tvec2<T> b)
73 return chebyshev_metric::distance(a, b);
76 constexpr glm::vec2 tile_pos_to_world_pos(glm::ivec2 tile_pos, glm::vec2 tile_size) {
return glm::vec2(tile_pos) * tile_size; }
77 constexpr glm::vec2 tile_pos_to_world_pos(glm::ivec2 tile_pos,
float tile_size) {
return glm::vec2(tile_pos) * tile_size; }
78 constexpr rec2 world_rect_for_tile(glm::ivec2
pos, glm::vec2 tile_size) {
return rec2::from_size(tile_pos_to_world_pos(
pos, tile_size), tile_size); }
79 constexpr rec2 world_rect_for_tile(glm::ivec2
pos,
float tile_size) {
return rec2::from_size(tile_pos_to_world_pos(
pos, tile_size), { tile_size, tile_size }); }
81 glm::ivec2 world_pos_to_tile_pos(glm::vec2 world_pos, glm::vec2 tile_size) {
return glm::ivec2(glm::floor(world_pos / tile_size)); }
82 glm::ivec2 world_pos_to_tile_pos(glm::vec2 world_pos,
float tile_size) {
return glm::ivec2(glm::floor(world_pos / tile_size)); }
83 irec2 world_rect_to_tile_rect(rec2
const&
world_rect, glm::vec2 tile_size) {
return irec2{ glm::floor(
world_rect.p1 / tile_size), glm::ceil(
world_rect.p2 / tile_size) }; }
84 irec2 world_rect_to_tile_rect(rec2
const&
world_rect,
float tile_size) {
return irec2{ glm::floor(
world_rect.p1 / tile_size), glm::ceil(
world_rect.p2 / tile_size) }; }
86 glm::vec2 snap_world_pos_to_tile_grid(glm::vec2 world_pos, glm::vec2 tile_size) {
87 return glm::floor((world_pos + (tile_size * 0.5f)) / tile_size) * tile_size;
90 template <metric METRIC = chebyshev_metric>
95 constexpr glm::vec2 to_world_pos(glm::ivec2 tile_pos)
const noexcept {
return tile_pos_to_world_pos(tile_pos, tile_size); }
96 constexpr rec2 world_rect_for_tile(glm::ivec2 tile_pos)
const noexcept {
return ghassanpl::geometry::squares::world_rect_for_tile(tile_pos, tile_size); }
97 constexpr glm::ivec2 to_tile_pos(glm::vec2 world_pos)
const noexcept {
return world_pos_to_tile_pos(world_pos, tile_size); }
98 constexpr irec2 to_tile_rect(rec2
const&
world_rect)
const noexcept {
return world_rect_to_tile_rect(
world_rect, tile_size); }
101 using tile_pos = named<glm::ivec2,
"tile_pos", traits::location>;
102 using world_pos = named<glm::vec2,
"world_pos", traits::location>;
104 using tile_rec = named<irec2,
"tile_rec">;
105 using world_rec = named<rec2,
"world_rec">;
constexpr auto bit_count
Equal to the number of bits in the type.
constexpr bool is_surrounding(glm::ivec2 a, glm::ivec2 b)
TODO: Should probably define the terms somewhere (surrounding, neighbor, adjacent,...