#pragma once #include "glm/glm.hpp" #include #include #include #include struct aabb { using vector_type = glm::vec3; using scalar_type = vector_type::value_type; using index_type = vector_type::length_type; static constexpr auto default_min = std::numeric_limits::max(); static constexpr auto default_max =-std::numeric_limits::max(); vector_type min { default_min, default_min, default_min }; vector_type max { default_max, default_max, default_max }; [[nodiscard]] vector_type size() const { return max - min; } [[nodiscard]] vector_type center() const { return min + 0.5f * size(); } [[nodiscard]] vector_type closest_point_inside(const vector_type& point) const { return { std::clamp(point.x, min.x, max.x), std::clamp(point.y, min.y, max.y), std::clamp(point.z, min.z, max.z) }; } aabb& add_aabb(const aabb& other) { for (index_type i{}; i != min.length(); ++i) { min[i] = std::min(min[i], other.min[i]); max[i] = std::max(max[i], other.max[i]); } return *this; } aabb& add_point(const auto& point) { for (index_type i{}; i != min.length(); ++i) { min[i] = std::min(min[i], point[i]); max[i] = std::max(max[i], point[i]); } return *this; } template aabb& add_points(std::span points) { for (const auto& point : points) { add_point(point); } return *this; } aabb& join(const aabb& other) { min = glm::min(min, other.min); max = glm::max(max, other.max); return *this; } [[nodiscard]] aabb transformed(const glm::mat4x4& matrix) const { const auto vertices = std::array{ vector_type{ matrix * glm::vec4{ min.x, min.y, min.z, 1 } }, vector_type{ matrix * glm::vec4{ min.x, min.y, max.z, 1 } }, vector_type{ matrix * glm::vec4{ min.x, max.y, min.z, 1 } }, vector_type{ matrix * glm::vec4{ min.x, max.y, max.z, 1 } }, vector_type{ matrix * glm::vec4{ max.x, min.y, min.z, 1 } }, vector_type{ matrix * glm::vec4{ max.x, min.y, max.z, 1 } }, vector_type{ matrix * glm::vec4{ max.x, max.y, min.z, 1 } }, vector_type{ matrix * glm::vec4{ max.x, max.y, max.z, 1 } } }; return aabb{}.add_points(vertices); } };