Wayverb
overlaps_2d.h
1 #pragma once
2 
3 #include "core/cl/scene_structs.h"
4 #include "core/geo/triangle_vec.h"
5 
6 namespace wayverb {
7 namespace core {
8 namespace geo {
9 namespace detail {
10 constexpr glm::vec2 perp(const glm::vec2& a) { return glm::vec2(-a.y, a.x); }
11 
12 inline glm::vec2 normal_2d(const glm::vec2& a, const glm::vec2& b) {
13  return perp(b - a);
14 }
15 
16 template <typename It, typename Out>
17 void normals_2d(It begin, It end, Out o) {
18  const auto dist = std::distance(begin, end);
19  if (dist == 0) {
20  throw std::runtime_error("Empty range passed to normal-finder.");
21  }
22  if (dist == 1) {
23  throw std::runtime_error("Single point passed to normal-finder.");
24  }
25  *o++ = normal_2d(*(end - 1), *begin++);
26  for (; begin != end; ++begin) {
27  *o++ = normal_2d(*(begin - 1), *begin);
28  }
29 }
30 
31 template <size_t n>
32 std::array<glm::vec2, n> normals_2d(const std::array<glm::vec2, n>& u) {
33  std::array<glm::vec2, n> ret;
34  detail::normals_2d(u.begin(), u.end(), ret.begin());
35  return ret;
36 }
37 
38 struct projection_2d final {
39  float min;
40  float max;
41 };
42 
43 constexpr bool operator<(const projection_2d& a, const projection_2d& b) {
44  return a.min < b.min;
45 }
46 
47 constexpr bool operator==(const projection_2d& a, const projection_2d& b) {
48  return std::tie(a.min, a.max) == std::tie(b.min, b.max);
49 }
50 
51 template <typename It>
52 projection_2d project(It begin, It end, const glm::vec2& axis) {
53  if (begin == end) {
54  throw std::runtime_error("Null shape passed to projection function.");
55  }
56 
57  const auto first = glm::dot(axis, *begin++);
58  projection_2d ret{first, first};
59  for (; begin != end; ++begin) {
60  const auto p = glm::dot(axis, *begin);
61  ret.min = std::min(ret.min, p);
62  ret.max = std::max(ret.max, p);
63  }
64  return ret;
65 }
66 
67 constexpr bool overlaps(const projection_2d& a, const projection_2d& b) {
68  const auto min_max = std::minmax(a, b);
69  return min_max.second.min <= min_max.first.max;
70 }
71 
72 template <typename It, typename Jt>
73 bool overlaps(
74  It i_begin, It i_end, Jt j_begin, Jt j_end, const glm::vec2& axis) {
75  return overlaps(project(i_begin, i_end, axis),
76  project(j_begin, j_end, axis));
77 }
78 
79 template <typename It, typename Jt, typename Kt>
80 bool overlaps(It i_begin,
81  It i_end,
82  Jt j_begin,
83  Jt j_end,
84  Kt axes_begin,
85  Kt axes_end) {
86  return std::all_of(axes_begin, axes_end, [=](const auto& i) {
87  return overlaps(i_begin, i_end, j_begin, j_end, i);
88  });
89 }
90 } // namespace detail
91 
95 template <size_t n, size_t m>
96 bool overlaps_2d(const std::array<glm::vec2, n>& a,
97  const std::array<glm::vec2, m>& b) {
98  const auto a_axes = detail::normals_2d(a);
99  const auto b_axes = detail::normals_2d(b);
100  return detail::overlaps(a.begin(),
101  a.end(),
102  b.begin(),
103  b.end(),
104  a_axes.begin(),
105  a_axes.end()) &&
106  detail::overlaps(a.begin(),
107  a.end(),
108  b.begin(),
109  b.end(),
110  b_axes.begin(),
111  b_axes.end());
112 }
113 
114 } // namespace geo
115 } // namespace core
116 } // namespace wayverb
Definition: traits.cpp:2
Definition: traits.h:46
Definition: capsule_base.h:9
Definition: overlaps_2d.h:38