Move Vectormath main
C++20 game and graphics mathematics
Loading...
Searching...
No Matches
FrustumQueries.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <array>
4#include <cmath>
5#include <cstddef>
6#include <type_traits>
7
12
13namespace mv::math
14{
15 enum class Containment : std::uint8_t
16 {
17 Outside,
19 Inside
20 };
21
27
28 template <typename T>
29 requires std::is_floating_point_v<T>
31 {
32 public:
34 Frustum_(frustum)
35 {
36 for (std::size_t index = 0U; index < 6U; ++index)
37 {
38 const FrustumPlane plane = static_cast<FrustumPlane>(index);
39 if (!frustum.IsActive(plane))
40 {
41 continue;
42 }
43 const Vec3<T> normal = frustum.Plane(plane).Normal().Vector();
44 AbsoluteNormals_[index] =
45 Vec3<T>(std::abs(normal.X()), std::abs(normal.Y()),
46 std::abs(normal.Z()));
47 }
48 }
49
51 {
52 return Frustum_;
53 }
54
56 FrustumPlane plane) const noexcept
57 {
58 return AbsoluteNormals_[static_cast<std::size_t>(plane)];
59 }
60
61 private:
62 Frustum3<T> Frustum_;
63 std::array<Vec3<T>, 6> AbsoluteNormals_{};
64 };
65
68
69 namespace detail
70 {
71 template <typename T, typename RadiusForPlane>
72 [[nodiscard]] inline CullingResult ClassifyAgainstFrustum(
73 const Frustum3<T>& frustum,
74 const Point3<T>& center,
78 {
81 requestedPlanes & frustum.ActivePlanes();
82 for (std::size_t index = 0U; index < 6U; ++index)
83 {
84 const FrustumPlane plane = static_cast<FrustumPlane>(index);
85 if (!HasPlane(active, plane))
86 {
87 continue;
88 }
90 const T distance = frustum.Plane(plane).SignedDistance(center);
91 if (distance < -radius - tolerance)
92 {
94 }
95 if (distance <= radius + tolerance)
96 {
98 }
99 }
103 remaining};
104 }
105 } // namespace detail
106
107 template <typename T>
110 const Point3<T>& point,
112 T tolerance = T(0)) noexcept
113 {
114 return detail::ClassifyAgainstFrustum(prepared.Frustum(), point, active,
115 std::abs(tolerance),
116 [](FrustumPlane) noexcept
117 {
118 return T(0);
119 });
120 }
121
122 template <typename T>
125 const Sphere3<T>& sphere,
127 T tolerance = T(0)) noexcept
128 {
129 return detail::ClassifyAgainstFrustum(
130 prepared.Frustum(), sphere.Center(), active, std::abs(tolerance),
131 [&sphere](FrustumPlane) noexcept
132 {
133 return sphere.Radius();
134 });
135 }
136
137 template <typename T>
140 const Aabb3<T>& box,
142 T tolerance = T(0)) noexcept
143 {
144 const auto center = box.TryCenter();
145 const auto halfExtents = box.TryHalfExtents();
146 if (!center || !halfExtents)
147 {
149 }
150 return detail::ClassifyAgainstFrustum(
151 prepared.Frustum(), *center, active, std::abs(tolerance),
153 {
154 return Dot(prepared.AbsoluteNormal(plane), *halfExtents);
155 });
156 }
157
158 template <typename T>
161 const Obb3<T>& box,
163 T tolerance = T(0)) noexcept
164 {
165 const std::array<Vec3<T>, 3> axes = {
166 box.AxisX().Vector(), box.AxisY().Vector(), box.AxisZ().Vector()};
167 return detail::ClassifyAgainstFrustum(
168 prepared.Frustum(), box.Center(), active, std::abs(tolerance),
169 [&prepared, &box, &axes](FrustumPlane plane) noexcept
170 {
171 const Vec3<T> normal =
172 prepared.Frustum().Plane(plane).Normal().Vector();
173 return box.HalfExtents().X() * std::abs(Dot(normal, axes[0])) +
174 box.HalfExtents().Y() * std::abs(Dot(normal, axes[1])) +
175 box.HalfExtents().Z() * std::abs(Dot(normal, axes[2]));
176 });
177 }
178
179 template <typename T, typename Bounds>
188} // namespace mv::math
const Frustum3< T > & Frustum() const noexcept
PreparedFrustum3(const Frustum3< T > &frustum) noexcept
const Vec3< T > & AbsoluteNormal(FrustumPlane plane) const noexcept
CullingResult Classify(const PreparedFrustum3< T > &prepared, const Point3< T > &point, FrustumPlaneMask active=FrustumPlaneMask::All, T tolerance=T(0)) noexcept
constexpr FrustumPlaneMask PlaneMask(FrustumPlane plane) noexcept
Definition Frustum3.hpp:76
constexpr bool HasPlane(FrustumPlaneMask mask, FrustumPlane plane) noexcept
Definition Frustum3.hpp:83
FrustumPlaneMask RemainingPlanes