Atoms Crowd  7.0.0
ImathFrustumTest.h
1 //
2 // SPDX-License-Identifier: BSD-3-Clause
3 // Copyright Contributors to the OpenEXR Project.
4 //
5 
6 //
7 // A viewing frustum class
8 //
9 // This file contains algorithms applied to or in conjunction with
10 // Frustum visibility testing (Imath::Frustum).
11 //
12 // Methods for frustum-based rejection of primitives are contained here.
13 //
14 
15 #ifndef INCLUDED_ATOMSMATHFRUSTUMTEST_H
16 #define INCLUDED_ATOMSMATHFRUSTUMTEST_H
17 
18 #include <AtomsMath/ImathBox.h>
19 #include <AtomsMath/ImathFrustum.h>
20 #include <AtomsMath/ImathMatrix.h>
21 #include <AtomsMath/ImathNamespace.h>
22 #include <AtomsMath/ImathSphere.h>
23 #include <AtomsMath/ImathVec.h>
24 
25 ATOMSMATH_INTERNAL_NAMESPACE_HEADER_ENTER
26 
82 
83 template <class T> class FrustumTest
84 {
85  public:
88 
90  FrustumTest() noexcept
91  {
92  Frustum<T> frust;
94  cameraMat.makeIdentity();
95  setFrustum (frust, cameraMat);
96  }
97 
99  FrustumTest (const Frustum<T>& frustum, const Matrix44<T>& cameraMat) noexcept
100  {
101  setFrustum (frustum, cameraMat);
102  }
103 
105 
108 
112  void setFrustum (const Frustum<T>& frustum, const Matrix44<T>& cameraMat) noexcept;
113 
115 
118 
121  bool isVisible (const Sphere3<T>& sphere) const noexcept;
122 
125  bool isVisible (const Box<Vec3<T>>& box) const noexcept;
126 
128  bool isVisible (const Vec3<T>& vec) const noexcept;
129 
132  bool completelyContains (const Sphere3<T>& sphere) const noexcept;
133 
136  bool completelyContains (const Box<Vec3<T>>& box) const noexcept;
137 
139  ATOMSMATH_INTERNAL_NAMESPACE::Matrix44<T> cameraMat() const noexcept { return cameraMatrix; }
140 
142  ATOMSMATH_INTERNAL_NAMESPACE::Frustum<T> currentFrustum() const noexcept { return currFrustum; }
143 
145 
146  protected:
147 
148  // To understand why the planes are stored this way, see
149  // the SPECIAL NOTE above.
150 
152 
153  Vec3<T> planeNormX[2]; // The X components from 6 plane equations
154  Vec3<T> planeNormY[2]; // The Y components from 6 plane equations
155  Vec3<T> planeNormZ[2]; // The Z components from 6 plane equations
156 
157  Vec3<T> planeOffsetVec[2]; // The distance offsets from 6 plane equations
158 
159  // The absolute values are stored to assist with bounding box tests.
160  Vec3<T> planeNormAbsX[2]; // The abs(X) components from 6 plane equations
161  Vec3<T> planeNormAbsY[2]; // The abs(X) components from 6 plane equations
162  Vec3<T> planeNormAbsZ[2]; // The abs(X) components from 6 plane equations
163 
164  // These are kept primarily for debugging tools.
165  Frustum<T> currFrustum;
166  Matrix44<T> cameraMatrix;
167 
169 };
170 
171 template <class T>
172 void
173 FrustumTest<T>::setFrustum (const Frustum<T>& frustum, const Matrix44<T>& cameraMat) noexcept
174 {
175  Plane3<T> frustumPlanes[6];
176  frustum.planes (frustumPlanes, cameraMat);
177 
178  // Here's where we effectively transpose the plane equations.
179  // We stuff all six X's into the two planeNormX vectors, etc.
180  for (int i = 0; i < 2; ++i)
181  {
182  int index = i * 3;
183 
184  planeNormX[i] = Vec3<T> (frustumPlanes[index + 0].normal.x,
185  frustumPlanes[index + 1].normal.x,
186  frustumPlanes[index + 2].normal.x);
187  planeNormY[i] = Vec3<T> (frustumPlanes[index + 0].normal.y,
188  frustumPlanes[index + 1].normal.y,
189  frustumPlanes[index + 2].normal.y);
190  planeNormZ[i] = Vec3<T> (frustumPlanes[index + 0].normal.z,
191  frustumPlanes[index + 1].normal.z,
192  frustumPlanes[index + 2].normal.z);
193 
194  planeNormAbsX[i] = Vec3<T> (std::abs (planeNormX[i].x),
195  std::abs (planeNormX[i].y),
196  std::abs (planeNormX[i].z));
197  planeNormAbsY[i] = Vec3<T> (std::abs (planeNormY[i].x),
198  std::abs (planeNormY[i].y),
199  std::abs (planeNormY[i].z));
200  planeNormAbsZ[i] = Vec3<T> (std::abs (planeNormZ[i].x),
201  std::abs (planeNormZ[i].y),
202  std::abs (planeNormZ[i].z));
203 
204  planeOffsetVec[i] = Vec3<T> (frustumPlanes[index + 0].distance,
205  frustumPlanes[index + 1].distance,
206  frustumPlanes[index + 2].distance);
207  }
208  currFrustum = frustum;
209  cameraMatrix = cameraMat;
210 }
211 
212 template <typename T>
213 bool
214 FrustumTest<T>::isVisible (const Sphere3<T>& sphere) const noexcept
215 {
216  Vec3<T> center = sphere.center;
217  Vec3<T> radiusVec = Vec3<T> (sphere.radius, sphere.radius, sphere.radius);
218 
219  // This is a vertical dot-product on three vectors at once.
220  Vec3<T> d0 = planeNormX[0] * center.x + planeNormY[0] * center.y + planeNormZ[0] * center.z -
221  radiusVec - planeOffsetVec[0];
222 
223  if (d0.x >= 0 || d0.y >= 0 || d0.z >= 0)
224  return false;
225 
226  Vec3<T> d1 = planeNormX[1] * center.x + planeNormY[1] * center.y + planeNormZ[1] * center.z -
227  radiusVec - planeOffsetVec[1];
228 
229  if (d1.x >= 0 || d1.y >= 0 || d1.z >= 0)
230  return false;
231 
232  return true;
233 }
234 
235 template <typename T>
236 bool
237 FrustumTest<T>::completelyContains (const Sphere3<T>& sphere) const noexcept
238 {
239  Vec3<T> center = sphere.center;
240  Vec3<T> radiusVec = Vec3<T> (sphere.radius, sphere.radius, sphere.radius);
241 
242  // This is a vertical dot-product on three vectors at once.
243  Vec3<T> d0 = planeNormX[0] * center.x + planeNormY[0] * center.y + planeNormZ[0] * center.z +
244  radiusVec - planeOffsetVec[0];
245 
246  if (d0.x >= 0 || d0.y >= 0 || d0.z >= 0)
247  return false;
248 
249  Vec3<T> d1 = planeNormX[1] * center.x + planeNormY[1] * center.y + planeNormZ[1] * center.z +
250  radiusVec - planeOffsetVec[1];
251 
252  if (d1.x >= 0 || d1.y >= 0 || d1.z >= 0)
253  return false;
254 
255  return true;
256 }
257 
258 template <typename T>
259 bool
260 FrustumTest<T>::isVisible (const Box<Vec3<T>>& box) const noexcept
261 {
262  if (box.isEmpty())
263  return false;
264 
265  Vec3<T> center = (box.min + box.max) / 2;
266  Vec3<T> extent = (box.max - center);
267 
268  // This is a vertical dot-product on three vectors at once.
269  Vec3<T> d0 = planeNormX[0] * center.x + planeNormY[0] * center.y + planeNormZ[0] * center.z -
270  planeNormAbsX[0] * extent.x - planeNormAbsY[0] * extent.y -
271  planeNormAbsZ[0] * extent.z - planeOffsetVec[0];
272 
273  if (d0.x >= 0 || d0.y >= 0 || d0.z >= 0)
274  return false;
275 
276  Vec3<T> d1 = planeNormX[1] * center.x + planeNormY[1] * center.y + planeNormZ[1] * center.z -
277  planeNormAbsX[1] * extent.x - planeNormAbsY[1] * extent.y -
278  planeNormAbsZ[1] * extent.z - planeOffsetVec[1];
279 
280  if (d1.x >= 0 || d1.y >= 0 || d1.z >= 0)
281  return false;
282 
283  return true;
284 }
285 
286 template <typename T>
287 bool
288 FrustumTest<T>::completelyContains (const Box<Vec3<T>>& box) const noexcept
289 {
290  if (box.isEmpty())
291  return false;
292 
293  Vec3<T> center = (box.min + box.max) / 2;
294  Vec3<T> extent = (box.max - center);
295 
296  // This is a vertical dot-product on three vectors at once.
297  Vec3<T> d0 = planeNormX[0] * center.x + planeNormY[0] * center.y + planeNormZ[0] * center.z +
298  planeNormAbsX[0] * extent.x + planeNormAbsY[0] * extent.y +
299  planeNormAbsZ[0] * extent.z - planeOffsetVec[0];
300 
301  if (d0.x >= 0 || d0.y >= 0 || d0.z >= 0)
302  return false;
303 
304  Vec3<T> d1 = planeNormX[1] * center.x + planeNormY[1] * center.y + planeNormZ[1] * center.z +
305  planeNormAbsX[1] * extent.x + planeNormAbsY[1] * extent.y +
306  planeNormAbsZ[1] * extent.z - planeOffsetVec[1];
307 
308  if (d1.x >= 0 || d1.y >= 0 || d1.z >= 0)
309  return false;
310 
311  return true;
312 }
313 
314 template <typename T>
315 bool
316 FrustumTest<T>::isVisible (const Vec3<T>& vec) const noexcept
317 {
318  // This is a vertical dot-product on three vectors at once.
319  Vec3<T> d0 = (planeNormX[0] * vec.x) + (planeNormY[0] * vec.y) + (planeNormZ[0] * vec.z) -
320  planeOffsetVec[0];
321 
322  if (d0.x >= 0 || d0.y >= 0 || d0.z >= 0)
323  return false;
324 
325  Vec3<T> d1 = (planeNormX[1] * vec.x) + (planeNormY[1] * vec.y) + (planeNormZ[1] * vec.z) -
326  planeOffsetVec[1];
327 
328  if (d1.x >= 0 || d1.y >= 0 || d1.z >= 0)
329  return false;
330 
331  return true;
332 }
333 
336 
339 
340 ATOMSMATH_INTERNAL_NAMESPACE_HEADER_EXIT
341 
342 #endif // INCLUDED_ATOMSMATHFRUSTUMTEST_H
Definition: ImathBox.h:36
Definition: ImathFrustum.h:38
Definition: ImathFrustumTest.h:84
ATOMSMATH_INTERNAL_NAMESPACE::Frustum< T > currentFrustum() const noexcept
Return the viewing frustum (primarily for debugging)
Definition: ImathFrustumTest.h:142
bool completelyContains(const Sphere3< T > &sphere) const noexcept
Definition: ImathFrustumTest.h:237
void setFrustum(const Frustum< T > &frustum, const Matrix44< T > &cameraMat) noexcept
Definition: ImathFrustumTest.h:173
bool isVisible(const Sphere3< T > &sphere) const noexcept
Definition: ImathFrustumTest.h:214
ATOMSMATH_INTERNAL_NAMESPACE::Matrix44< T > cameraMat() const noexcept
Return the camera matrix (primarily for debugging)
Definition: ImathFrustumTest.h:139
FrustumTest(const Frustum< T > &frustum, const Matrix44< T > &cameraMat) noexcept
Initialize to a given frustum and camera matrix.
Definition: ImathFrustumTest.h:99
FrustumTest() noexcept
Initialize camera matrix to identity.
Definition: ImathFrustumTest.h:90
Definition: ImathMatrix.h:631
Definition: ImathPlane.h:30
Vec3< T > normal
The normal to the plane.
Definition: ImathPlane.h:37
Definition: ImathSphere.h:25
Definition: ImathVec.h:260