BoundingBox3-Impl.h
Go to the documentation of this file.
1 /*************************************************************************
2 > File Name: BoundingBox3-Impl.h
3 > Project Name: CubbyFlow
4 > Author: Dongmin Kim
5 > Purpose: 3-D axis-aligned bounding box class.
6 > Created Time: 2017/04/01
7 > Copyright (c) 2018, Dongmin Kim
8 *************************************************************************/
9 #ifndef CUBBYFLOW_BOUNDING_BOX3_IMPL_H
10 #define CUBBYFLOW_BOUNDING_BOX3_IMPL_H
11 
12 namespace CubbyFlow
13 {
14  template <typename T>
16  {
17  Reset();
18  }
19 
20  template <typename T>
22  {
23  lowerCorner.x = std::min(point1.x, point2.x);
24  lowerCorner.y = std::min(point1.y, point2.y);
25  lowerCorner.z = std::min(point1.z, point2.z);
26  upperCorner.x = std::max(point1.x, point2.x);
27  upperCorner.y = std::max(point1.y, point2.y);
28  upperCorner.z = std::max(point1.z, point2.z);
29  }
30 
31  template <typename T>
33  lowerCorner(other.lowerCorner), upperCorner(other.upperCorner)
34  {
35  // Do nothing
36  }
37 
38  template <typename T>
40  {
41  return upperCorner.x - lowerCorner.x;
42  }
43 
44  template <typename T>
46  {
47  return upperCorner.y - lowerCorner.y;
48  }
49 
50  template <typename T>
52  {
53  return upperCorner.z - lowerCorner.z;
54  }
55 
56  template <typename T>
58  {
59  return upperCorner[axis] - lowerCorner[axis];
60  }
61 
62  template <typename T>
63  bool BoundingBox<T, 3>::Overlaps(const BoundingBox& other) const
64  {
65  if (upperCorner.x < other.lowerCorner.x || lowerCorner.x > other.upperCorner.x)
66  {
67  return false;
68  }
69 
70  if (upperCorner.y < other.lowerCorner.y || lowerCorner.y > other.upperCorner.y)
71  {
72  return false;
73  }
74 
75  if (upperCorner.z < other.lowerCorner.z || lowerCorner.z > other.upperCorner.z)
76  {
77  return false;
78  }
79 
80  return true;
81  }
82 
83  template <typename T>
84  bool BoundingBox<T, 3>::Contains(const Vector3<T>& point) const
85  {
86  if (upperCorner.x < point.x || lowerCorner.x > point.x)
87  {
88  return false;
89  }
90 
91  if (upperCorner.y < point.y || lowerCorner.y > point.y)
92  {
93  return false;
94  }
95 
96  if (upperCorner.z < point.z || lowerCorner.z > point.z)
97  {
98  return false;
99  }
100 
101  return true;
102  }
103 
104  template <typename T>
105  bool BoundingBox<T, 3>::Intersects(const Ray3<T>& ray) const
106  {
107  T min = 0;
108  T max = std::numeric_limits<T>::max();
109  const Vector3<T>& rayInvDir = ray.direction.RDiv(1);
110 
111  for (size_t i = 0; i < 3; ++i)
112  {
113  T near = (lowerCorner[i] - ray.origin[i]) * rayInvDir[i];
114  T far = (upperCorner[i] - ray.origin[i]) * rayInvDir[i];
115 
116  if (near > far)
117  {
118  std::swap(near, far);
119  }
120 
121  min = std::max(near, min);
122  max = std::min(far, max);
123 
124  if (min > max)
125  {
126  return false;
127  }
128  }
129 
130  return true;
131  }
132 
133  template <typename T>
135  {
136  BoundingBoxRayIntersection3<T> intersection;
137 
138  T min = 0;
139  T max = std::numeric_limits<T>::max();
140  const Vector3<T>& rayInvDir = ray.direction.RDiv(1);
141 
142  for (size_t i = 0; i < 3; ++i)
143  {
144  T near = (lowerCorner[i] - ray.origin[i]) * rayInvDir[i];
145  T far = (upperCorner[i] - ray.origin[i]) * rayInvDir[i];
146 
147  if (near > far)
148  {
149  std::swap(near, far);
150  }
151 
152  min = std::max(near, min);
153  max = std::min(far, max);
154 
155  if (min > max)
156  {
157  intersection.isIntersecting = false;
158  return intersection;
159  }
160  }
161 
162  intersection.isIntersecting = true;
163 
164  if (Contains(ray.origin))
165  {
166  intersection.near = max;
167  intersection.far = std::numeric_limits<T>::max();
168  }
169  else
170  {
171  intersection.near = min;
172  intersection.far = max;
173  }
174 
175  return intersection;
176  }
177 
178  template <typename T>
180  {
181  return (upperCorner + lowerCorner) / static_cast<T>(2);
182  }
183 
184  template <typename T>
186  {
187  return (upperCorner - lowerCorner).Length();
188  }
189 
190  template <typename T>
192  {
193  return (upperCorner - lowerCorner).LengthSquared();
194  }
195 
196  template <typename T>
198  {
199  lowerCorner.x = std::numeric_limits<T>::max();
200  lowerCorner.y = std::numeric_limits<T>::max();
201  lowerCorner.z = std::numeric_limits<T>::max();
202  upperCorner.x = -std::numeric_limits<T>::max();
203  upperCorner.y = -std::numeric_limits<T>::max();
204  upperCorner.z = -std::numeric_limits<T>::max();
205  }
206 
207  template <typename T>
209  {
210  lowerCorner.x = std::min(lowerCorner.x, point.x);
211  lowerCorner.y = std::min(lowerCorner.y, point.y);
212  lowerCorner.z = std::min(lowerCorner.z, point.z);
213  upperCorner.x = std::max(upperCorner.x, point.x);
214  upperCorner.y = std::max(upperCorner.y, point.y);
215  upperCorner.z = std::max(upperCorner.z, point.z);
216  }
217 
218  template <typename T>
220  {
221  lowerCorner.x = std::min(lowerCorner.x, other.lowerCorner.x);
222  lowerCorner.y = std::min(lowerCorner.y, other.lowerCorner.y);
223  lowerCorner.z = std::min(lowerCorner.z, other.lowerCorner.z);
224  upperCorner.x = std::max(upperCorner.x, other.upperCorner.x);
225  upperCorner.y = std::max(upperCorner.y, other.upperCorner.y);
226  upperCorner.z = std::max(upperCorner.z, other.upperCorner.z);
227  }
228 
229  template <typename T>
231  {
232  lowerCorner -= delta;
233  upperCorner += delta;
234  }
235 
236  template <typename T>
238  {
239  static const T h = static_cast<T>(1) / 2;
240  static const Vector3<T> offset[8] =
241  {
242  { -h, -h, -h }, { +h, -h, -h }, { -h, +h, -h }, { +h, +h, -h },
243  { -h, -h, +h },{ +h, -h, +h }, { -h, +h, +h }, { +h, +h, +h }
244  };
245 
246  return Vector3<T>(GetWidth(), GetHeight(), GetDepth()) * offset[idx] + MidPoint();
247  }
248 
249  template <typename T>
251  {
253  }
254 
255  template <typename T>
257  {
258  return (lowerCorner.x >= upperCorner.x || lowerCorner.y >= upperCorner.y || lowerCorner.z >= upperCorner.z);
259  }
260 }
261 
262 #endif
3-D vector class.
Definition: Vector3.h:26
VectorType upperCorner
Upper corner of the bounding box.
Definition: BoundingBox.h:34
bool Contains(const VectorType &point) const
Returns true if the input point is inside of this box.
Definition: BoundingBox-Impl.h:54
T near
Distance to the first intersection point.
Definition: BoundingBox3.h:32
T z
Z (or the third) component of the vector.
Definition: Vector3.h:38
Vector3< T > direction
The direction of the ray.
Definition: Ray3.h:32
bool isIntersecting
True if the box and ray intersects.
Definition: BoundingBox3.h:29
VectorType MidPoint() const
Returns the mid-point of this box.
Definition: BoundingBox-Impl.h:68
BoundingBox()
Default constructor.
Definition: BoundingBox-Impl.h:17
Generic N-D axis-aligned bounding box class.
Definition: BoundingBox.h:23
void Reset()
Resets this box to initial state (min=infinite, max=-infinite).
Definition: BoundingBox-Impl.h:107
Vector3< T > origin
The origin of the ray.
Definition: Ray3.h:26
T far
Distance to the second (and the last) intersection point.
Definition: BoundingBox3.h:35
T x
X (or the first) component of the vector.
Definition: Vector3.h:29
Definition: pybind11Utils.h:24
T Clamp(T val, T low, T high)
Returns the clamped value.
Definition: MathUtils-Impl.h:123
VectorType lowerCorner
Lower corner of the bounding box.
Definition: BoundingBox.h:31
T DiagonalLength() const
Returns diagonal length of this box.
Definition: BoundingBox-Impl.h:81
void Merge(const VectorType &point)
Merges this and other point.
Definition: BoundingBox-Impl.h:117
3-D box-ray intersection result.
Definition: BoundingBox3.h:26
bool Overlaps(const BoundingBox &other) const
Returns true of this box and other box overlaps.
Definition: BoundingBox-Impl.h:40
void Expand(T delta)
Definition: BoundingBox-Impl.h:137
T DiagonalLengthSquared() const
Returns squared diagonal length of this box.
Definition: BoundingBox-Impl.h:94
Class for 3-D ray.
Definition: Ray3.h:23
T y
Y (or the second) component of the vector.
Definition: Vector3.h:35