#ifndef MATHS_AABB_HPP_ #define MATHS_AABB_HPP_ #include /// @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 ); } }; #endif // MATHS_AABB_HPP_