Antkeeper  0.0.1
aabb.hpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2023 Christopher J. Howard
3  *
4  * This file is part of Antkeeper source code.
5  *
6  * Antkeeper source code is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * Antkeeper source code is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 #ifndef ANTKEEPER_GEOM_AABB_HPP
21 #define ANTKEEPER_GEOM_AABB_HPP
22 
24 #include <engine/geom/sphere.hpp>
25 #include <engine/math/vector.hpp>
26 #include <engine/math/matrix.hpp>
28 #include <limits>
29 
30 namespace geom {
31 
35 template <class T>
36 struct aabb: public bounding_volume<T>
37 {
41 
44 
52  static aabb transform(const aabb& a, const transform_type& t);
53 
61  static aabb transform(const aabb& a, const matrix_type& m);
62 
64  aabb();
65 
67  virtual bool intersects(const sphere<T>& sphere) const;
68  virtual bool intersects(const aabb<T>& aabb) const;
69  virtual bool contains(const sphere<T>& sphere) const;
70  virtual bool contains(const aabb<T>& aabb) const;
71  virtual bool contains(const vector_type& point) const;
72 
79  vector_type corner(std::size_t index) const noexcept;
80 };
81 
82 template <class T>
84 {
85  vector_type min_point = {std::numeric_limits<T>::infinity(), std::numeric_limits<T>::infinity(), std::numeric_limits<T>::infinity()};
86  vector_type max_point = {-std::numeric_limits<T>::infinity(), -std::numeric_limits<T>::infinity(), -std::numeric_limits<T>::infinity()};
87 
88  for (std::size_t i = 0; i < 8; ++i)
89  {
90  vector_type transformed_corner = math::mul(t, a.corner(i));
91 
92  for (std::size_t j = 0; j < 3; ++j)
93  {
94  min_point[j] = std::min<T>(min_point[j], transformed_corner[j]);
95  max_point[j] = std::max<T>(max_point[j], transformed_corner[j]);
96  }
97  }
98 
99  return {min_point, max_point};
100 }
101 
102 template <class T>
104 {
105  vector_type min_point = {std::numeric_limits<T>::infinity(), std::numeric_limits<T>::infinity(), std::numeric_limits<T>::infinity()};
106  vector_type max_point = {-std::numeric_limits<T>::infinity(), -std::numeric_limits<T>::infinity(), -std::numeric_limits<T>::infinity()};
107 
108  for (std::size_t i = 0; i < 8; ++i)
109  {
110  vector_type corner = a.corner(i);
111  math::vector<T, 4> transformed_corner = math::mul(m, math::vector<T, 4>{corner.x(), corner.y(), corner.z(), T{1}});
112 
113  for (std::size_t j = 0; j < 3; ++j)
114  {
115  min_point[j] = std::min<T>(min_point[j], transformed_corner[j]);
116  max_point[j] = std::max<T>(max_point[j], transformed_corner[j]);
117  }
118  }
119 
120  return {min_point, max_point};
121 }
122 
123 template <class T>
124 aabb<T>::aabb(const vector_type& min_point, const vector_type& max_point):
125  min_point(min_point),
126  max_point(max_point)
127 {}
128 
129 template <class T>
131 {}
132 
133 template <class T>
135 {
137 }
138 
139 template <class T>
141 {
142  const vector_type radius_vector = {sphere.radius, sphere.radius, sphere.radius};
143  return aabb<T>(min_point - radius_vector, max_point + radius_vector).contains(sphere.center);
144 }
145 
146 template <class T>
147 bool aabb<T>::intersects(const aabb<T>& aabb) const
148 {
149  if (max_point.x() < aabb.min_point.x() || min_point.x() > aabb.max_point.x())
150  return false;
151  if (max_point.y() < aabb.min_point.y() || min_point.y() > aabb.max_point.y())
152  return false;
153  if (max_point.z() < aabb.min_point.z() || min_point.z() > aabb.max_point.z())
154  return false;
155  return true;
156 }
157 
158 template <class T>
160 {
161  if (sphere.center.x() - sphere.radius < min_point.x() || sphere.center.x() + sphere.radius > max_point.x())
162  return false;
163  if (sphere.center.y() - sphere.radius < min_point.y() || sphere.center.y() + sphere.radius > max_point.y())
164  return false;
165  if (sphere.center.z() - sphere.radius < min_point.z() || sphere.center.z() + sphere.radius > max_point.z())
166  return false;
167  return true;
168 }
169 
170 template <class T>
171 bool aabb<T>::contains(const aabb<T>& aabb) const
172 {
173  if (aabb.min_point.x() < min_point.x() || aabb.max_point.x() > max_point.x())
174  return false;
175  if (aabb.min_point.y() < min_point.y() || aabb.max_point.y() > max_point.y())
176  return false;
177  if (aabb.min_point.z() < min_point.z() || aabb.max_point.z() > max_point.z())
178  return false;
179  return true;
180 }
181 
182 template <class T>
183 bool aabb<T>::contains(const vector_type& point) const
184 {
185  if (point.x() < min_point.x() || point.x() > max_point.x())
186  return false;
187  if (point.y() < min_point.y() || point.y() > max_point.y())
188  return false;
189  if (point.z() < min_point.z() || point.z() > max_point.z())
190  return false;
191  return true;
192 }
193 
194 template <class T>
195 typename aabb<T>::vector_type aabb<T>::corner(std::size_t index) const noexcept
196 {
197  return
198  {
199  ((index >> 2) & 1) ? max_point[0] : min_point[0],
200  ((index >> 1) & 1) ? max_point[1] : min_point[1],
201  ((index >> 0) & 1) ? max_point[2] : min_point[2]
202  };
203 }
204 
205 } // namespace geom
206 
207 #endif // ANTKEEPER_GEOM_AABB_HPP
208 
Abstract base class for bounding volumes.
Geometry.
Definition: aabb.hpp:30
bounding_volume_type
Enumerates bounding volume types.
@ aabb
Indicates the bounding volume is an axis-aligned bounding box.
constexpr matrix< T, P, M > mul(const matrix< T, N, M > &a, const matrix< T, P, N > &b) noexcept
Multiplies two matrices.
@ index
General purpose index (uint)
Axis-aligned bounding box.
Definition: aabb.hpp:37
vector_type max_point
Definition: aabb.hpp:43
vector_type corner(std::size_t index) const noexcept
Returns the position of the specified corner.
Definition: aabb.hpp:195
static aabb transform(const aabb &a, const matrix_type &m)
Transforms an AABB.
Definition: aabb.hpp:103
vector_type min_point
Definition: aabb.hpp:42
aabb(const vector_type &min_point, const vector_type &max_point)
Definition: aabb.hpp:124
virtual bool intersects(const sphere< T > &sphere) const
Tests for intersection between this bounding volume and a bounding sphere.
Definition: aabb.hpp:140
static aabb transform(const aabb &a, const transform_type &t)
Transforms an AABB.
Definition: aabb.hpp:83
math::vector< T, 3 > vector_type
Definition: aabb.hpp:38
virtual bounding_volume_type get_bounding_volume_type() const
Returns the enumerated type of this bounding volume.
Definition: aabb.hpp:134
virtual bool contains(const sphere< T > &sphere) const
Tests whether this bounding volume contains a sphere.
Definition: aabb.hpp:159
virtual bool contains(const aabb< T > &aabb) const
Tests whether this bounding volume contains an axis-aligned bounding box.
Definition: aabb.hpp:171
math::matrix< T, 4, 4 > matrix_type
Definition: aabb.hpp:39
math::transform< T > transform_type
Definition: aabb.hpp:40
virtual bool contains(const vector_type &point) const
Tests whether this bounding volume contains a point.
Definition: aabb.hpp:183
virtual bool intersects(const aabb< T > &aabb) const
Tests for intersection between this bounding volume and an axis-aligned bounding box.
Definition: aabb.hpp:147
Bounding sphere.
Definition: sphere.hpp:35
vector_type center
Definition: sphere.hpp:38
n by m column-major matrix.
Definition: math/matrix.hpp:44
Represents 3D TRS transformation.
constexpr element_type & x() noexcept
Returns a reference to the first element.
Definition: vector.hpp:163
constexpr element_type & y() noexcept
Returns a reference to the second element.
Definition: vector.hpp:179
constexpr element_type & z() noexcept
Returns a reference to the third element.
Definition: vector.hpp:195