/* * 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_CONVEX_HULL_HPP #define ANTKEEPER_GEOM_CONVEX_HULL_HPP #include "bounding-volume.hpp" #include "geom/plane.hpp" #include "geom/sphere.hpp" #include "geom/aabb.hpp" #include #include namespace geom { /** * A plane-bounded convex hull. */ template struct convex_hull: public bounding_volume { /// Vector of planes with descibe the bounds of the convex hull. std::vector> planes; /** * Creates a convex hull. * * @param size Number of planes the convex hull should accommodate. */ convex_hull(std::size_t size); /// Creates a convex hull. convex_hull(); 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 math::vector& point) const; }; template convex_hull::convex_hull(std::size_t size): planes(size, plane()) {} template convex_hull::convex_hull() {} template inline bounding_volume_type convex_hull::get_bounding_volume_type() const { return bounding_volume_type::convex_hull; } template bool convex_hull::intersects(const sphere& sphere) const { for (const plane& plane: planes) if (plane.signed_distance(sphere.center) < -sphere.radius) return false; return true; } template bool convex_hull::intersects(const aabb& aabb) const { math::vector pv; for (const plane& plane: planes) { pv.x = (plane.normal.x > T(0)) ? aabb.max_point.x : aabb.min_point.x; pv.y = (plane.normal.y > T(0)) ? aabb.max_point.y : aabb.min_point.y; pv.z = (plane.normal.z > T(0)) ? aabb.max_point.z : aabb.min_point.z; if (plane.signed_distance(pv) < T(0)) return false; } return true; } template bool convex_hull::contains(const sphere& sphere) const { for (const plane& plane: planes) if (plane.signed_distance(sphere.center) < sphere.radius) return false; return true; } template bool convex_hull::contains(const aabb& aabb) const { math::vector pv; math::vector nv; for (const plane& plane: planes) { pv.x = (plane.normal.x > T(0)) ? aabb.max_point.x : aabb.min_point.x; pv.y = (plane.normal.y > T(0)) ? aabb.max_point.y : aabb.min_point.y; pv.z = (plane.normal.z > T(0)) ? aabb.max_point.z : aabb.min_point.z; nv.x = (plane.normal.x < T(0)) ? aabb.max_point.x : aabb.min_point.x; nv.y = (plane.normal.y < T(0)) ? aabb.max_point.y : aabb.min_point.y; nv.z = (plane.normal.z < T(0)) ? aabb.max_point.z : aabb.min_point.z; if (plane.signed_distance(pv) < T(0) || plane.signed_distance(nv) < T(0)) return false; } return true; } template bool convex_hull::contains(const math::vector& point) const { for (const plane& plane: planes) if (plane.signed_distance(point) < T(0)) return false; return true; } } // namespace geom #endif // ANTKEEPER_GEOM_CONVEX_HULL_HPP