VoxelEngine/src/maths/aabb.hpp

117 lines
3.1 KiB
C++

#ifndef MATHS_AABB_HPP_
#define MATHS_AABB_HPP_
#include <glm/glm.hpp>
/// @brief Axis Aligned Bounding Box
struct AABB {
glm::vec3 a {0.0f};
glm::vec3 b {1.0f, 1.0f, 1.0f};
AABB() = default;
AABB(glm::vec3 size) : a(0.0f), b(size) {
}
AABB(glm::vec3 a, glm::vec3 b) : a(a), b(b) {
}
/// @brief Get AABB point with minimal x,y,z
inline glm::vec3 min() const {
return glm::min(a, b);
}
/// @brief Get AABB point with minimal x,y,z
inline glm::vec3 max() const {
return glm::max(a, b);
}
/// @brief Get AABB dimensions: width, height, depth
inline glm::vec3 size() const {
return glm::vec3(
fabs(b.x - a.x),
fabs(b.y - a.y),
fabs(b.z - a.z)
);
}
inline glm::vec3 center() const {
return (a + b) * 0.5f;
}
/// @brief Multiply AABB size from center
inline void scale(const glm::vec3 mul) {
glm::vec3 center = (a + b) * 0.5f;
a = (a - center) * mul + center;
b = (b - center) * mul + center;
}
/// @brief Multiply AABB size from given origin
inline void scale(const glm::vec3 mul, const glm::vec3 orig) {
glm::vec3 beg = min();
glm::vec3 end = max();
glm::vec3 center = glm::mix(beg, end, orig);
a = (a - center) * mul + center;
b = (b - center) * mul + center;
}
/// @brief Check if given point is inside
inline bool contains(const glm::vec3 pos) const {
const glm::vec3 p = min();
const glm::vec3 s = size();
return !(pos.x < p.x || pos.y < p.y || pos.z < p.z ||
pos.x >= p.x+s.x || pos.y >= p.y+s.y || pos.z >= p.z+s.z);
}
void fix() {
auto beg = min();
auto end = max();
a = beg;
b = end;
}
inline void addPoint(glm::vec3 p) {
a = glm::min(a, p);
b = glm::max(b, p);
}
/// TODO: optimize
void transform(const glm::mat4& matrix) {
auto pa = a;
auto pb = b;
a = matrix * glm::vec4(a, 1.0f);
b = matrix * glm::vec4(b, 1.0f);
fix();
addPoint(matrix * glm::vec4(pb.x, pa.y, pa.z, 1.0f));
addPoint(matrix * glm::vec4(pb.x, pb.y, pa.z, 1.0f));
addPoint(matrix * glm::vec4(pb.x, pb.y, pb.z, 1.0f));
addPoint(matrix * glm::vec4(pa.x, pb.y, pa.z, 1.0f));
addPoint(matrix * glm::vec4(pa.x, pa.y, pb.z, 1.0f));
addPoint(matrix * glm::vec4(pb.x, pa.y, pb.z, 1.0f));
}
inline bool intersect(const AABB& aabb) {
return (
a.x <= aabb.b.x &&
b.x >= aabb.a.x &&
a.y <= aabb.b.y &&
b.y >= aabb.a.y &&
a.z <= aabb.b.z &&
b.z >= aabb.a.z
);
}
inline bool intersect(const AABB& aabb, float margin) {
return (
a.x <= aabb.b.x+margin &&
b.x >= aabb.a.x-margin &&
a.y <= aabb.b.y+margin &&
b.y >= aabb.a.y-margin &&
a.z <= aabb.b.z+margin &&
b.z >= aabb.a.z-margin
);
}
};
#endif // MATHS_AABB_HPP_