OGLplus  (0.59.0) a C++ wrapper for rendering APIs

intersection.hpp
Go to the documentation of this file.
1 #ifndef EAGINE_MATH_INTERSECTION_HPP
9 #define EAGINE_MATH_INTERSECTION_HPP
10 
11 #include "../valid_if/nonnegative.hpp"
12 #include "../valid_if/positive.hpp"
13 #include "functions.hpp"
14 #include "primitives.hpp"
15 #include "vector.hpp"
16 #include <utility>
17 
18 #ifdef __clang__
19 EAGINE_DIAG_PUSH()
20 EAGINE_DIAG_OFF(double-promotion)
21 #endif
22 
23 namespace eagine::math {
24 //------------------------------------------------------------------------------
25 // utils
26 //------------------------------------------------------------------------------
27 template <typename T, typename P, typename L>
28 static inline auto
29 nearest_ray_param(const std::pair<valid_if<T, P, L>, valid_if<T, P, L>>& params)
30  -> valid_if<T, P, L> {
31 
32  const auto& t0 = std::get<0>(params);
33  const auto& t1 = std::get<1>(params);
34 
35  if(t0 >= 0.F) {
36  if(t1 >= 0.F) {
37  if(t0 < t1) {
38  return t0;
39  } else {
40  return t1;
41  }
42  } else {
43  return t0;
44  }
45  } else {
46  if(t1 >= 0.F) {
47  return t1;
48  }
49  }
50  return {};
51 }
52 //------------------------------------------------------------------------------
53 // line-sphere
54 //------------------------------------------------------------------------------
55 template <typename T, bool V>
56 static constexpr auto
57 _line_sphere_intersection_a(vector<T, 3, V> ld, vector<T, 3, V> oc) noexcept
58  -> T {
59  return -T(2) * dot(ld, oc);
60 }
61 //------------------------------------------------------------------------------
62 template <typename T, bool V>
63 static constexpr auto _line_sphere_intersection_d(vector<T, 3, V> ld) noexcept
64  -> valid_if_positive<T> {
65  return T(2) * dot(ld, ld);
66 }
67 //------------------------------------------------------------------------------
68 template <typename T, bool V>
69 static constexpr auto _line_sphere_intersection_b(
70  vector<T, 3, V> ld,
71  vector<T, 3, V> oc,
72  T sr) noexcept -> valid_if_nonnegative<T> {
73  using std::pow;
74  return T(
75  pow(2 * dot(ld, oc), 2) - 4 * dot(ld, ld) * (dot(oc, oc) - pow(sr, 2)));
76 }
77 //------------------------------------------------------------------------------
78 template <typename T>
79 static constexpr auto _line_sphere_intersection_t(
80  T a,
81  valid_if_nonnegative<T> b,
82  valid_if_positive<T> d) noexcept {
83  using std::sqrt;
84  using R = std::pair<optionally_valid<T>, optionally_valid<T>>;
85  return (b && d) ? (extract(b) > T(0))
86  ? R{{(a + sqrt(extract(b))) / extract(d), true},
87  {(a - sqrt(extract(b))) / extract(d), true}}
88  : R{{a / extract(d), true}, {}}
89  : R{};
90 }
91 //------------------------------------------------------------------------------
92 template <typename T, bool V>
93 static constexpr auto _line_sphere_intersection_p(
94  const line<T, V>& ray,
95  const std::pair<optionally_valid<T>, optionally_valid<T>>& ts) {
96  using E = optionally_valid<vector<T, 3, V>>;
97  using R = std::pair<E, E>;
98  return R{
99  std::get<0>(ts) ? E{ray.point_at(extract(std::get<0>(ts))), true} : E{},
100  std::get<1>(ts) ? E{ray.point_at(extract(std::get<1>(ts))), true} : E{},
101  };
102 }
103 //------------------------------------------------------------------------------
104 template <typename T, bool V>
105 auto line_sphere_intersection_params(
106  const line<T, V>& ray,
107  const sphere<T, V>& sph) noexcept
108  -> std::pair<optionally_valid<T>, optionally_valid<T>> {
109  return _line_sphere_intersection_t(
110  _line_sphere_intersection_a(ray.direction(), ray.origin() - sph.center()),
111  _line_sphere_intersection_b(
112  ray.direction(), ray.origin() - sph.center(), sph.radius()),
113  _line_sphere_intersection_d(ray.direction()));
114 }
115 //------------------------------------------------------------------------------
119 template <typename T, bool V>
120 static constexpr auto line_sphere_intersection(
121  const line<T, V>& ray,
122  const sphere<T, V>& sph) noexcept -> std::
123  pair<optionally_valid<vector<T, 3, V>>, optionally_valid<vector<T, 3, V>>> {
124  return _line_sphere_intersection_p(
125  ray, line_sphere_intersection_params(ray, sph));
126 }
127 //------------------------------------------------------------------------------
128 template <typename T, bool V>
129 static constexpr auto _line_sphere_intersection_n_p(
130  const line<T, V>& ray,
131  const std::pair<optionally_valid<T>, optionally_valid<T>>& ts) {
133  using std::abs;
134 
135  return std::get<0>(ts)
136  ? std::get<1>(ts)
137  ? abs(extract(std::get<0>(ts))) < abs(extract(std::get<1>(ts)))
138  ? R{ray.point_at(extract(std::get<0>(ts))), true}
139  : R{ray.point_at(extract(std::get<1>(ts))), true}
140  : R{ray.point_at(extract(std::get<0>(ts))), true}
141  : R{};
142 }
143 //------------------------------------------------------------------------------
147 template <typename T, bool V>
148 static constexpr auto nearest_line_sphere_intersection(
149  const line<T, V>& ray,
150  const sphere<T, V>& sph) noexcept -> optionally_valid<vector<T, 3, V>> {
151  return _line_sphere_intersection_n_p(
152  ray, line_sphere_intersection_params(ray, sph));
153 }
154 //------------------------------------------------------------------------------
155 // line-triangle
156 //------------------------------------------------------------------------------
157 template <typename T, bool V>
158 static inline auto line_triangle_intersection_param(
159  const line<T, V>& ray,
160  const triangle<T, V>& tri) noexcept -> optionally_valid<T> {
161 
162  const vector<T, 3, V> h = cross(ray.direction(), tri.ac());
163  const T a = dot(tri.ab(), h);
164 
165  if(const auto ia = reciprocal(a)) {
166  const T f = extract(ia);
167  const vector<T, 3, V> s = ray.origin() - tri.a();
168  const T u = f * dot(s, h);
169 
170  if((u >= T(0)) && (u <= T(1))) {
171  const vector<T, 3, V> q = cross(s, tri.ab());
172  const T v = f * dot(ray.direction(), q);
173 
174  if((v >= T(0)) && (u + v <= T(1))) {
175  const T t = f * dot(tri.ac(), q);
176  return {t, t >= T(0)};
177  }
178  }
179  }
180  return {};
181 }
182 //------------------------------------------------------------------------------
185 template <typename T, bool V>
186 static inline auto line_triangle_intersection(
187  const line<T, V>& ray,
188  const triangle<T, V>& tri) noexcept -> optionally_valid<vector<T, 3, V>> {
189  if(const auto t = line_triangle_intersection_param(ray, tri)) {
190  return {ray.origin() + ray.direction() * extract(t), true};
191  }
192  return {};
193 }
194 //------------------------------------------------------------------------------
195 } // namespace eagine::math
196 
197 #ifdef __clang__
198 EAGINE_DIAG_POP()
199 #endif
200 
201 #endif // EAGINE_MATH_INTERSECTION_HPP
constexpr auto direction() const noexcept -> vector< T, N, V >
Returns the line direction.
Definition: primitives.hpp:35
Basic template for spheres in N-dimensional space.
Definition: primitives.hpp:122
Basic template for lines in N-dimensional space.
Definition: primitives.hpp:19
static constexpr auto extract(api_result_value< Result, api_result_validity::never > &) noexcept -> Result &
Overload of extract for api_result_value.
Definition: c_api_wrap.hpp:270
Primary template for conditionally valid values.
Definition: decl.hpp:49
Basic template for triangles in N-dimensional space.
Definition: primitives.hpp:57
static constexpr auto reciprocal(T x) noexcept -> optionally_valid< T >
Returns the reciprocal of x if x is not zero.
Definition: functions.hpp:85
static constexpr auto nearest_line_sphere_intersection(const line< T, V > &ray, const sphere< T, V > &sph) noexcept -> optionally_valid< vector< T, 3, V >>
Finds nearest line-sphere intersection point.
Definition: intersection.hpp:148
Basic N-dimensional vector implementation template.
Definition: fwd.hpp:19
constexpr auto point_at(T t) const noexcept -> vector< T, N, V >
Returns a point on the line at the specified parameter t.
Definition: primitives.hpp:40
Math-related code is placed in this namespace.
Definition: eagine.hpp:48
static constexpr auto dot(const vector< T, N, V > &a, const vector< T, N, V > &b) noexcept
Vector dot product.
Definition: vector.hpp:311
static constexpr auto line_sphere_intersection(const line< T, V > &ray, const sphere< T, V > &sph) noexcept -> std::pair< optionally_valid< vector< T, 3, V >>, optionally_valid< vector< T, 3, V >>>
Finds line-sphere intersection points.
Definition: intersection.hpp:120
constexpr auto origin() const noexcept -> vector< T, N, V >
Returns the line origin.
Definition: primitives.hpp:30
static auto cross(const vector< T, 3, V > &a, const vector< T, 3, V > &b) noexcept
3D vector cross product.
Definition: vector.hpp:326
static auto line_triangle_intersection(const line< T, V > &ray, const triangle< T, V > &tri) noexcept -> optionally_valid< vector< T, 3, V >>
Finds line-triangle intersection point.
Definition: intersection.hpp:186

Copyright © 2015-2021 Matúš Chochlík.
<chochlik -at -gmail.com>
Documentation generated on Tue Apr 13 2021 by Doxygen (version 1.8.17).