diff options
Diffstat (limited to 'src/Math')
| -rw-r--r-- | src/Math/AABB.cpp | 17 | ||||
| -rw-r--r-- | src/Math/AABB.hpp | 32 | ||||
| -rw-r--r-- | src/Math/Ray.hpp | 33 |
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; +}; |
