summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Goodliffe <dan@randomdan.homeip.net>2025-03-07 00:43:25 +0000
committerDan Goodliffe <dan@randomdan.homeip.net>2025-03-11 01:13:59 +0000
commitd0aceb54752078200bc75a96888ffaf7483678cb (patch)
treeb28332738e1446771c42c8ddd37261bdf380b14b
parentPosition is moved to Frustum (diff)
downloadilt-d0aceb54752078200bc75a96888ffaf7483678cb.tar.bz2
ilt-d0aceb54752078200bc75a96888ffaf7483678cb.tar.xz
ilt-d0aceb54752078200bc75a96888ffaf7483678cb.zip
Add function to test if an AABB is visible in a frustum
-rw-r--r--gfx/aabb.cpp6
-rw-r--r--gfx/aabb.h2
-rw-r--r--gfx/frustum.cpp26
-rw-r--r--gfx/frustum.h4
4 files changed, 38 insertions, 0 deletions
diff --git a/gfx/aabb.cpp b/gfx/aabb.cpp
index 862dacb..0a04ef4 100644
--- a/gfx/aabb.cpp
+++ b/gfx/aabb.cpp
@@ -22,3 +22,9 @@ AxisAlignedBoundingBox::operator+=(const GlobalPosition3D & point)
max = glm::max(max, point);
return *this;
}
+
+AxisAlignedBoundingBox
+AxisAlignedBoundingBox::operator-(const GlobalPosition3D & viewPoint) const
+{
+ return {min - viewPoint, max - viewPoint};
+}
diff --git a/gfx/aabb.h b/gfx/aabb.h
index 568e91a..db3a215 100644
--- a/gfx/aabb.h
+++ b/gfx/aabb.h
@@ -11,6 +11,8 @@ public:
AxisAlignedBoundingBox & operator+=(const GlobalPosition3D & point);
+ AxisAlignedBoundingBox operator-(const GlobalPosition3D & viewPoint) const;
+
[[nodiscard]] static AxisAlignedBoundingBox fromPoints(std::span<const GlobalPosition3D> points);
GlobalPosition3D min, max;
diff --git a/gfx/frustum.cpp b/gfx/frustum.cpp
index a9dbdf0..8031d85 100644
--- a/gfx/frustum.cpp
+++ b/gfx/frustum.cpp
@@ -1,4 +1,5 @@
#include "frustum.h"
+#include "aabb.h"
#include <algorithm>
#include <collections.h>
#include <glm/ext/matrix_transform.hpp>
@@ -18,6 +19,31 @@ Frustum::updateView(const glm::mat4 & newView)
updateCache();
}
+bool
+Frustum::contains(const AxisAlignedBoundingBox & aabb) const
+{
+ static constexpr auto EXTENT_CORNER_IDXS = [] {
+ using Extent = GlobalPosition3D AxisAlignedBoundingBox::*;
+ constexpr auto EXTENTS = std::array {&AxisAlignedBoundingBox::min, &AxisAlignedBoundingBox::max};
+ std::array<glm::vec<3, Extent>, 2ZU * 2ZU * 2ZU> out {};
+ std::ranges::copy(std::views::cartesian_product(EXTENTS, EXTENTS, EXTENTS)
+ | std::views::transform(
+ std::make_from_tuple<glm::vec<3, Extent>, std::tuple<Extent, Extent, Extent>>),
+ out.begin());
+ return out;
+ }();
+
+ const std::array<RelativePosition4D, 8> corners
+ = EXTENT_CORNER_IDXS * [relativeAabb = aabb - position](auto idxs) -> glm::vec4 {
+ return {(relativeAabb.*(idxs.x)).x, (relativeAabb.*(idxs.y)).y, (relativeAabb.*(idxs.z)).z, 1.F};
+ };
+ return std::ranges::none_of(planes, [&corners](const auto & frustumPlane) {
+ return (std::ranges::all_of(corners, [&frustumPlane](const auto & corner) {
+ return glm::dot(frustumPlane, corner) < 0.F;
+ }));
+ });
+}
+
void
Frustum::updateCache()
{
diff --git a/gfx/frustum.h b/gfx/frustum.h
index 46f4108..5ee7d2c 100644
--- a/gfx/frustum.h
+++ b/gfx/frustum.h
@@ -4,6 +4,8 @@
#include <array>
#include <glm/mat4x4.hpp>
+class AxisAlignedBoundingBox;
+
class Frustum {
public:
Frustum(const GlobalPosition3D & pos, const glm::mat4 & view, const glm::mat4 & projection);
@@ -28,6 +30,8 @@ public:
void updateView(const glm::mat4 & view);
+ [[nodiscard]] bool contains(const AxisAlignedBoundingBox &) const;
+
protected:
static constexpr size_t FACES = 6;
void updateCache();