opynsim
Unofficial C++ Documentation
Loading...
Searching...
No Matches
aabb_functions.h
Go to the documentation of this file.
1#pragma once
2
10
11#include <array>
12#include <concepts>
13#include <functional>
14#include <optional>
15#include <ranges>
16
17namespace osc { struct Sphere; }
18
19namespace osc
20{
21 // returns the average centroid of `aabb`
22 constexpr Vector3 centroid_of(const AABB& aabb)
23 {
24 return 0.5f * (aabb.min + aabb.max);
25 }
26
27 // returns the widths of the edges of `aabb`
28 constexpr Vector3 dimensions_of(const AABB& aabb)
29 {
30 return aabb.max - aabb.min;
31 }
32
33 // returns the half-widths of the edges of `aabb`
34 constexpr Vector3 half_widths_of(const AABB& aabb)
35 {
36 return 0.5f * dimensions_of(aabb);
37 }
38
39 // returns the volume of `aabb`
40 constexpr float volume_of(const AABB& aabb)
41 {
42 Vector3 const dims = dimensions_of(aabb);
43 return dims.x() * dims.y() * dims.z();
44 }
45
46 // tests if `aabb` has zero width along all of its edges
47 constexpr bool is_point(const AABB& aabb)
48 {
49 return aabb.min == aabb.max;
50 }
51
52 // tests if `aabb` has zero width along any of its edges
53 constexpr bool has_zero_volume(const AABB& aabb)
54 {
55 return volume_of(aabb) == 0.0f;
56 }
57
58 // returns the eight corner vertices of `aabb`
59 std::array<Vector3, 8> corner_vertices_of(const AABB& aabb);
60
61 // returns an `AABB` computed by transforming `aabb` with `m`
62 AABB transform_aabb(const Matrix4x4& m, const AABB& aabb);
63
64 // returns an `AABB` computed by transforming `aabb` with `t`
65 AABB transform_aabb(const Transform& t, const AABB& aabb);
66
67 // returns an `AABB` that tightly bounds `x`
68 constexpr AABB bounding_aabb_of(const Vector3& x)
69 {
70 return AABB{.min = x, .max = x};
71 }
72
73 // returns an `AABB` that tightly bounds both `x` and `y`
74 constexpr AABB bounding_aabb_of(const AABB& x, const Vector3& y)
75 {
76 return AABB{elementwise_min(x.min, y), elementwise_max(x.max, y)};
77 }
78
79 // returns an `AABB` that tightly bounds both `x` and `y`
80 constexpr AABB bounding_aabb_of(const AABB& x, const AABB& y)
81 {
82 return AABB{elementwise_min(x.min, y.min), elementwise_max(x.max, y.max)};
83 }
84
85 // returns an `AABB` that tightly bounds the union of `x` and `y`, or only `y` if `x` is `std::nullopt`
86 constexpr AABB bounding_aabb_of(const std::optional<AABB>& x, const AABB& y)
87 {
88 return x ? bounding_aabb_of(*x, y) : y;
89 }
90
91 // returns an `AABB` that tightly bounds any non-`std::nullopt` `AABB`s in `x` or `y`
92 //
93 // if both `x` and `y` are `std::nullopt`, returns `std::nullopt`
94 constexpr std::optional<AABB> bounding_aabb_of(std::optional<AABB> x, std::optional<AABB> y)
95 {
96 if (x and y) {
97 return bounding_aabb_of(*x, *y);
98 }
99 else if (x) {
100 return *x;
101 }
102 else if (y) {
103 return *y;
104 }
105 else {
106 return std::nullopt;
107 }
108 }
109
110 namespace detail
111 {
112 // returns an `AABB` that tightly bounds the `Vector3`s projected from `r`
113 template<std::ranges::input_range R, class Proj = std::identity>
114 requires std::convertible_to<typename std::projected<std::ranges::iterator_t<R>, Proj>::value_type, const Vector3&>
115 constexpr AABB bounding_aabb_of_nonempty_range(R&& r, Proj proj = {})
116 {
117 auto it = std::ranges::begin(r);
118 const auto last = std::ranges::end(r);
119
120 AABB rv = bounding_aabb_of(std::invoke(proj, *it));
121 while (++it != last) {
122 rv = bounding_aabb_of(rv, std::invoke(proj, *it));
123 }
124 return rv;
125 }
126 }
127
128 // returns an `AABB` that tightly bounds the `Vector3`s projected from `r`
129 template<std::ranges::input_range R, class Proj = std::identity>
130 requires std::convertible_to<typename std::projected<std::ranges::iterator_t<R>, Proj>::value_type, const Vector3&>
131 constexpr std::optional<AABB> bounding_aabb_of(R&& r, Proj proj = {})
132 {
133 if (std::ranges::begin(r) != std::ranges::end(r)) {
134 return detail::bounding_aabb_of_nonempty_range(std::forward<R>(r), std::move(proj));
135 } else {
136 return std::nullopt;
137 }
138 }
139
140 // returns an `AABB` that tightly bounds the `Vector3`s projected from `r` (specialized for compile-time-non-empty ranges)
141 template<InputRangeWithSizeGreaterThan<0> R, class Proj = std::identity>
142 requires std::convertible_to<typename std::projected<std::ranges::iterator_t<R>, Proj>::value_type, const Vector3&>
143 constexpr AABB bounding_aabb_of(R&& r, Proj proj = {})
144 {
145 return detail::bounding_aabb_of_nonempty_range(std::forward<R>(r), std::move(proj));
146 }
147
148 // returns an `AABB` that tightly bounds the `AABB`s projected from `r`
149 template<std::ranges::input_range Range, class Proj = std::identity>
150 requires std::convertible_to<typename std::projected<std::ranges::iterator_t<Range>, Proj>::value_type, const AABB&>
151 constexpr std::optional<AABB> bounding_aabb_of(Range&& r, Proj proj = {})
152 {
153 auto it = std::ranges::begin(r);
154 auto const last = std::ranges::end(r);
155 if (it == last) {
156 return std::nullopt; // empty range
157 }
158
159 AABB rv = std::invoke(proj, *it);
160 while (++it != last) {
161 rv = bounding_aabb_of(rv, std::invoke(proj, *it));
162 }
163 return rv;
164 }
165
166 // returns an `AABB` that tightly bounds any non-`std::nullopt` `std::optional<AABB>`s projected from `r`
167 //
168 // if no element in `r` projects an `AABB`, returns `std::nullopt`
169 template<std::ranges::input_range Range, class Proj = std::identity>
170 requires
171 std::convertible_to<typename std::projected<std::ranges::iterator_t<Range>, Proj>::value_type, const std::optional<AABB>&>
172 and (not std::convertible_to<typename std::projected<std::ranges::iterator_t<Range>, Proj>::value_type, const AABB&>)
173 constexpr std::optional<AABB> bounding_aabb_of(Range&& r, Proj proj = {})
174 {
175 auto it = std::ranges::begin(r);
176 const auto last = std::ranges::end(r);
177
178 // find first non-nullopt AABB (or the end)
179 std::optional<AABB> rv;
180 while (!rv && it != last) {
181 rv = std::invoke(proj, *it++);
182 }
183 if (not rv) {
184 return rv;
185 }
186
187 // combine with remainder of range
188 for (; it != last; ++it) {
189 rv = bounding_aabb_of(std::invoke(proj, *it), *rv);
190 }
191
192 return rv;
193 }
194
195 // returns an `AABB` that tightly bounds the `Sphere`
197
198 // returns a `Rect` in normalized device coordinate-like (NDC-like) space that loosely
199 // bounds the world-space-located `aabb`
200 //
201 // if the AABB does not lie within the NDC clipping bounds (i.e. between (-1, -1)
202 // and (1, 1)), returns `std::nullopt`
203 std::optional<Rect> loosely_project_into_ndc(
204 const AABB& aabb,
205 const Matrix4x4& view_mat,
206 const Matrix4x4& proj_mat,
207 float znear,
208 float zfar
209 );
210}
constexpr reference x()
Returns (*this)[0]
Definition vector.h:157
constexpr reference z()
Returns (*this)[2]
Definition vector.h:167
constexpr reference y()
Returns (*this)[1]
Definition vector.h:162
constexpr AABB bounding_aabb_of_nonempty_range(R &&r, Proj proj={})
Definition aabb_functions.h:115
Definition custom_decoration_generator.h:5
constexpr bool has_zero_volume(const AABB &aabb)
Definition aabb_functions.h:53
constexpr Vector3 half_widths_of(const AABB &aabb)
Definition aabb_functions.h:34
constexpr Vector3 centroid_of(const AABB &aabb)
Definition aabb_functions.h:22
constexpr Vector3 dimensions_of(const AABB &aabb)
Definition aabb_functions.h:28
constexpr bool is_point(const AABB &aabb)
Definition aabb_functions.h:47
constexpr AABB bounding_aabb_of(const Vector3 &x)
Definition aabb_functions.h:68
AABB transform_aabb(const Matrix4x4 &m, const AABB &aabb)
std::optional< Rect > loosely_project_into_ndc(const AABB &aabb, const Matrix4x4 &view_mat, const Matrix4x4 &proj_mat, float znear, float zfar)
Vector< float, 3 > Vector3
Definition vector.h:644
constexpr Vector< T, N > elementwise_max(const Vector< T, N > &x, const Vector< T, N > &y)
Definition common_functions.h:125
constexpr Vector< T, N > elementwise_min(const Vector< T, N > &x, const Vector< T, N > &y)
Definition common_functions.h:111
and
Definition algorithms.h:158
std::array< Vector3, 8 > corner_vertices_of(const AABB &aabb)
constexpr float volume_of(const AABB &aabb)
Definition aabb_functions.h:40
Definition aabb.h:14
Vector3 min
Definition aabb.h:18
Vector3 max
Definition aabb.h:19
Definition sphere.h:9
Definition transform.h:11