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