/* * Copyright (C) 2021 Christopher J. Howard * * This file is part of Antkeeper source code. * * Antkeeper source code is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Antkeeper source code is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Antkeeper source code. If not, see . */ #ifndef ANTKEEPER_GEOM_SPHERE_HPP #define ANTKEEPER_GEOM_SPHERE_HPP #include "geom/bounding-volume.hpp" #include "geom/aabb.hpp" #include "math/math.hpp" #include namespace geom { /** * Bounding sphere. */ template struct sphere: public bounding_volume { typedef math::vector vector_type; vector_type center; T radius; sphere(const vector_type& center, T radius); sphere(); virtual bounding_volume_type get_bounding_volume_type() const; virtual bool intersects(const sphere& sphere) const; virtual bool intersects(const aabb& aabb) const; virtual bool contains(const sphere& sphere) const; virtual bool contains(const aabb& aabb) const; virtual bool contains(const vector_type& point) const; }; template sphere::sphere(const vector_type& center, T radius): center(center), radius(radius) {} template sphere::sphere() {} template inline bounding_volume_type sphere::get_bounding_volume_type() const { return bounding_volume_type::sphere; } template bool sphere::intersects(const sphere& sphere) const { vector_type d = center - sphere.center; float r = radius + sphere.radius; return (math::dot(d, d) <= r * r); } template bool sphere::intersects(const aabb& aabb) const { return aabb.intersects(*this); } template bool sphere::contains(const sphere& sphere) const { float containment_radius = radius - sphere.radius; if (containment_radius < T(0)) return false; vector_type d = center - sphere.center; return (math::dot(d, d) <= containment_radius * containment_radius); } template bool sphere::contains(const aabb& aabb) const { T distance = T(0); vector_type a = center - aabb.min_point; vector_type b = center - aabb.max_point; distance += std::max(a.x * a.x, b.x * b.x); distance += std::max(a.y * a.y, b.y * b.y); distance += std::max(a.z * a.z, b.z * b.z); return (distance <= radius * radius); } template bool sphere::contains(const vector_type& point) const { vector_type d = center - point; return (math::dot(d, d) <= radius * radius); } } // namespace geom #endif // ANTKEEPER_GEOM_SPHERE_HPP