Move Vectormath main
C++20 game and graphics mathematics
Loading...
Searching...
No Matches
Frustum3.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <algorithm>
4#include <array>
5#include <cassert>
6#include <cmath>
7#include <cstddef>
8#include <cstdint>
9#include <optional>
10#include <type_traits>
11
12#include <mv/math/Mat4.hpp>
15
16namespace mv::math
17{
18 enum class FrustumPlane : std::uint8_t
19 {
20 Left,
21 Right,
22 Bottom,
23 Top,
24 Near,
25 Far
26 };
27
28 enum class FrustumPlaneMask : std::uint8_t
29 {
30 None = 0U,
31 Left = 1U << 0U,
32 Right = 1U << 1U,
33 Bottom = 1U << 2U,
34 Top = 1U << 3U,
35 Near = 1U << 4U,
36 Far = 1U << 5U,
37 All = (1U << 6U) - 1U
38 };
39
42 {
43 return static_cast<FrustumPlaneMask>(static_cast<std::uint8_t>(left) |
44 static_cast<std::uint8_t>(right));
45 }
46
49 {
50 return static_cast<FrustumPlaneMask>(static_cast<std::uint8_t>(left) &
51 static_cast<std::uint8_t>(right));
52 }
53
55 FrustumPlaneMask value) noexcept
56 {
57 return static_cast<FrustumPlaneMask>(
58 static_cast<std::uint8_t>(FrustumPlaneMask::All) &
59 ~static_cast<std::uint8_t>(value));
60 }
61
63 FrustumPlaneMask right) noexcept
64 {
65 left = left | right;
66 return left;
67 }
68
70 FrustumPlaneMask right) noexcept
71 {
72 left = left & right;
73 return left;
74 }
75
77 FrustumPlane plane) noexcept
78 {
79 return static_cast<FrustumPlaneMask>(
80 1U << static_cast<std::uint8_t>(plane));
81 }
82
84 FrustumPlane plane) noexcept
85 {
87 }
88
89 namespace detail
90 {
91 template <typename T>
92 [[nodiscard]] inline std::optional<Plane3<T>> TryPlaneFromCoefficients(
93 T x, T y, T z, T offset) noexcept
94 {
95 const T maximum = std::max({std::abs(x), std::abs(y), std::abs(z)});
96 if (!(maximum > T(0)) || !std::isfinite(maximum) ||
97 !std::isfinite(offset))
98 {
99 return std::nullopt;
100 }
101 const Vec3<T> scaled(x / maximum, y / maximum, z / maximum);
102 const T scaledLength = Length(scaled);
103 const auto normal = Normal3<T>::TryFrom(scaled);
104 if (!normal || !(scaledLength > T(0)) ||
105 !std::isfinite(scaledLength))
106 {
107 return std::nullopt;
108 }
111 }
112 } // namespace detail
113
114 template <typename T>
115 requires std::is_floating_point_v<T>
117 {
118 public:
119 using Component = T;
120
121 [[nodiscard]] static std::optional<Frustum3> TryFromPlanes(
122 const std::array<Plane3<T>, 6>& planes,
124 {
125 constexpr FrustumPlaneMask Required =
129 if ((activePlanes & Required) != Required)
130 {
131 return std::nullopt;
132 }
133 return Frustum3(planes, activePlanes, UncheckedTag{});
134 }
135
136 [[nodiscard]] static std::optional<Frustum3> TryFromViewProjection(
137 const Mat4<T>& viewProjection,
140 {
141 if (!viewProjection.IsFinite())
142 {
143 return std::nullopt;
144 }
145
146 // Gribb and Hartmann, "Fast Extraction of Viewing Frustum Planes
147 // from the World-View-Projection Matrix" (2001), transposed for
148 // Move's row vectors and extended to explicit ZO/NO and reverse-Z
149 // policies. Extracted normals point into the frustum.
150 const Vec4<T> column0 = viewProjection.Column(0U);
151 const Vec4<T> column1 = viewProjection.Column(1U);
152 const Vec4<T> column2 = viewProjection.Column(2U);
153 const Vec4<T> column3 = viewProjection.Column(3U);
154 const auto makePlane = [](const Vec4<T>& coefficients)
155 {
158 coefficients.W());
159 };
160
161 const auto left = makePlane(column3 + column0);
162 const auto right = makePlane(column3 - column0);
163 const auto bottom = makePlane(column3 + column1);
164 const auto top = makePlane(column3 - column1);
166 ? column2
167 : column3 + column2);
168 const auto upperDepth = makePlane(column3 - column2);
170 ? lowerDepth
171 : upperDepth;
173 ? upperDepth
174 : lowerDepth;
175 if (!left || !right || !bottom || !top || !nearPlane)
176 {
177 return std::nullopt;
178 }
179
180 std::array<Plane3<T>, 6> planes{*left, *right, *bottom,
181 *top, *nearPlane, Plane3<T>()};
183 if (farPlane)
184 {
185 planes[static_cast<std::size_t>(FrustumPlane::Far)] = *farPlane;
186 }
187 else
188 {
190 }
191 return Frustum3(planes, active, UncheckedTag{});
192 }
193
194 [[nodiscard]] const Plane3<T>& Plane(FrustumPlane plane) const noexcept
195 {
197 return Planes_[static_cast<std::size_t>(plane)];
198 }
199
200 [[nodiscard]] bool IsActive(FrustumPlane plane) const noexcept
201 {
202 return HasPlane(ActivePlanes_, plane);
203 }
204
206 {
207 return ActivePlanes_;
208 }
209
210 private:
211 struct UncheckedTag
212 {
213 };
214
215 Frustum3(const std::array<Plane3<T>, 6>& planes,
216 FrustumPlaneMask activePlanes,
217 UncheckedTag) noexcept :
218 Planes_(planes), ActivePlanes_(activePlanes)
219 {
220 }
221
222 std::array<Plane3<T>, 6> Planes_{};
224 };
225
228} // namespace mv::math
static std::optional< Frustum3 > TryFromPlanes(const std::array< Plane3< T >, 6 > &planes, FrustumPlaneMask activePlanes=FrustumPlaneMask::All) noexcept
Definition Frustum3.hpp:121
static std::optional< Frustum3 > TryFromViewProjection(const Mat4< T > &viewProjection, ClipDepth clipDepth, DepthDirection depthDirection) noexcept
Definition Frustum3.hpp:136
FrustumPlaneMask ActivePlanes() const noexcept
Definition Frustum3.hpp:205
bool IsActive(FrustumPlane plane) const noexcept
Definition Frustum3.hpp:200
const Plane3< T > & Plane(FrustumPlane plane) const noexcept
Definition Frustum3.hpp:194
static std::optional< Normal3 > TryFrom(const Vec3< T > &value) noexcept
Definition Normal3.hpp:46
static std::optional< Plane3 > TryFromNormalAndOffset(const Normal3< T > &normal, T offset) noexcept
Definition Plane3.hpp:30
std::optional< Plane3< T > > TryPlaneFromCoefficients(T x, T y, T z, T offset) noexcept
Definition Frustum3.hpp:92
constexpr FrustumPlaneMask & operator|=(FrustumPlaneMask &left, FrustumPlaneMask right) noexcept
Definition Frustum3.hpp:62
constexpr FrustumPlaneMask operator|(FrustumPlaneMask left, FrustumPlaneMask right) noexcept
Definition Frustum3.hpp:40
constexpr FrustumPlaneMask operator&(FrustumPlaneMask left, FrustumPlaneMask right) noexcept
Definition Frustum3.hpp:47
constexpr FrustumPlaneMask & operator&=(FrustumPlaneMask &left, FrustumPlaneMask right) noexcept
Definition Frustum3.hpp:69
T Length(const Quat< T > &value) noexcept
Definition Quat.hpp:116
constexpr FrustumPlaneMask PlaneMask(FrustumPlane plane) noexcept
Definition Frustum3.hpp:76
constexpr FrustumPlaneMask operator~(FrustumPlaneMask value) noexcept
Definition Frustum3.hpp:54
constexpr bool HasPlane(FrustumPlaneMask mask, FrustumPlane plane) noexcept
Definition Frustum3.hpp:83