summaryrefslogtreecommitdiff
path: root/src/Math
diff options
context:
space:
mode:
Diffstat (limited to 'src/Math')
-rw-r--r--src/Math/AABB.cpp17
-rw-r--r--src/Math/AABB.hpp32
-rw-r--r--src/Math/Ray.hpp33
3 files changed, 82 insertions, 0 deletions
diff --git a/src/Math/AABB.cpp b/src/Math/AABB.cpp
new file mode 100644
index 0000000..aa814a1
--- /dev/null
+++ b/src/Math/AABB.cpp
@@ -0,0 +1,17 @@
+// This file breaks the Ray.hpp <-> AABB.hpp dependency cycle.
+
+#include "AABB.hpp"
+#include "Ray.hpp"
+
+AABB AABB::cast_box(Vector<3> v, AABB against) const {
+ auto ray = Ray{center(), v};
+
+ auto expanded_target = against.sum(*this);
+ auto raycast = ray.cast(expanded_target);
+ if (!raycast.hit) return *this;
+
+ auto result_from = raycast.point - size() / 2.0;
+ auto result_to = result_from + size();
+
+ return {result_from, result_to};
+}
diff --git a/src/Math/AABB.hpp b/src/Math/AABB.hpp
index 11d26a8..19aa81c 100644
--- a/src/Math/AABB.hpp
+++ b/src/Math/AABB.hpp
@@ -8,6 +8,31 @@ struct AABB {
AABB(Vector<3> min, Vector<3> max) : min(min), max(max) {}
explicit AABB(Vector<3> max) : max(max) {}
+ Vector<3> size() const { return max - min; }
+ Vector<3> center() const { return (min + max) / 2; }
+
+ Bool contains(Vector<3> point) const {
+ return point.x() >= min.x() && point.x() <= max.x()
+ && point.y() >= min.y() && point.y() <= max.y()
+ && point.z() >= min.z() && point.z() <= max.z();
+ }
+
+ Bool intersects_on_x(AABB other) const {
+ return min.x() <= other.max.x() && max.x() >= other.min.x();
+ }
+
+ Bool intersects_on_y(AABB other) const {
+ return min.y() <= other.max.y() && max.y() >= other.min.y();
+ }
+
+ Bool intersects_on_z(AABB other) const {
+ return min.z() <= other.max.z() && max.z() >= other.min.z();
+ }
+
+ Bool collides(AABB other) const {
+ return intersects_on_x(other) && intersects_on_y(other) && intersects_on_z(other);
+ }
+
std::array<Vector<3>, 8> corners() const {
return {{
{min.x(), min.y(), min.z()},
@@ -23,5 +48,12 @@ struct AABB {
AABB offset(Vector<3> by) const { return {min + by, max + by}; }
+ AABB sum(AABB with) const {
+ auto new_size = size() + with.size();
+ return {center() - new_size / 2, center() + new_size / 2};
+ }
+
+ AABB cast_box(Vector<3> v, AABB against) const;
+
Vector<3> min, max;
};
diff --git a/src/Math/Ray.hpp b/src/Math/Ray.hpp
new file mode 100644
index 0000000..f83a2b5
--- /dev/null
+++ b/src/Math/Ray.hpp
@@ -0,0 +1,33 @@
+#pragma once
+
+#include "../Common/Lambda.hpp"
+#include "AABB.hpp"
+#include "Vector.hpp"
+
+struct Ray {
+ struct RaycastResult {
+ Bool hit = false;
+ Vec3 point;
+ Vec3 normal;
+ };
+
+ // https://gdbooks.gitbooks.io/3dcollisions/content/Chapter3/raycast_aabb.html
+ RaycastResult cast(AABB box) const {
+ Vec3 t_from = (box.min - origin) / direction;
+ Vec3 t_to = (box.max - origin) / direction;
+
+ Real t_min = t_from.zip(t_to, LAMBDA(std::min, 2)).reduce(LAMBDA(std::max, 2));
+ Real t_max = t_from.zip(t_to, LAMBDA(std::max, 2)).reduce(LAMBDA(std::min, 2));
+
+ if (t_max < 0 || t_min > t_max) return {};
+
+ return {
+ .hit = true,
+ .point = origin + direction * t_min,
+ .normal = t_from.zip(t_to, [](auto a, auto b) { return a < b ? -1.0 : 1.0; })
+ };
+ }
+
+ Vec3 origin;
+ Vec3 direction;
+};