Atoms Crowd  7.0.0
ImathFrustum.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 
10 #ifndef INCLUDED_ATOMSMATHFRUSTUM_H
11 #define INCLUDED_ATOMSMATHFRUSTUM_H
12 
13 #include <AtomsMath/ImathFun.h>
14 #include <AtomsMath/ImathLine.h>
15 #include <AtomsMath/ImathMatrix.h>
16 #include <AtomsMath/ImathNamespace.h>
17 #include <AtomsMath/ImathPlane.h>
18 #include <AtomsMath/ImathVec.h>
19 
20 ATOMSMATH_INTERNAL_NAMESPACE_HEADER_ENTER
21 
36 
37 template <class T> class Frustum
38 {
39  public:
40 
44 
47  ATOMSMATH_HOSTDEVICE ATOMSMATH_CONSTEXPR14 Frustum() noexcept;
48 
50  ATOMSMATH_HOSTDEVICE ATOMSMATH_CONSTEXPR14 Frustum (const Frustum&) noexcept;
51 
53  ATOMSMATH_HOSTDEVICE ATOMSMATH_CONSTEXPR14
54  Frustum (T nearPlane, T farPlane, T left, T right, T top, T bottom, bool ortho = false) noexcept;
55 
57  ATOMSMATH_HOSTDEVICE ATOMSMATH_CONSTEXPR14 Frustum (T nearPlane, T farPlane, T fovx, T fovy, T aspect) noexcept;
58 
60  virtual ~Frustum() noexcept;
61 
63  ATOMSMATH_HOSTDEVICE ATOMSMATH_CONSTEXPR14 const Frustum& operator= (const Frustum&) noexcept;
64 
66 
69 
71  ATOMSMATH_HOSTDEVICE constexpr bool operator== (const Frustum<T>& src) const noexcept;
72 
74  ATOMSMATH_HOSTDEVICE constexpr bool operator!= (const Frustum<T>& src) const noexcept;
75 
77 
80 
82  ATOMSMATH_HOSTDEVICE constexpr bool orthographic() const noexcept { return _orthographic; }
83 
85  ATOMSMATH_HOSTDEVICE constexpr T nearPlane() const noexcept { return _nearPlane; }
86 
88  ATOMSMATH_HOSTDEVICE constexpr T hither() const noexcept { return _nearPlane; }
89 
91  ATOMSMATH_HOSTDEVICE constexpr T farPlane() const noexcept { return _farPlane; }
92 
94  ATOMSMATH_HOSTDEVICE constexpr T yon() const noexcept { return _farPlane; }
95 
97  ATOMSMATH_HOSTDEVICE constexpr T left() const noexcept { return _left; }
98 
100  ATOMSMATH_HOSTDEVICE constexpr T right() const noexcept { return _right; }
101 
103  ATOMSMATH_HOSTDEVICE constexpr T bottom() const noexcept { return _bottom; }
104 
106  ATOMSMATH_HOSTDEVICE constexpr T top() const noexcept { return _top; }
107 
109  ATOMSMATH_HOSTDEVICE constexpr T fovx() const noexcept;
110 
112  ATOMSMATH_HOSTDEVICE constexpr T fovy() const noexcept;
113 
115  ATOMSMATH_HOSTDEVICE ATOMSMATH_CONSTEXPR14 T aspect() const noexcept;
116 
119  ATOMSMATH_CONSTEXPR14 T aspectExc() const;
120 
122  ATOMSMATH_HOSTDEVICE ATOMSMATH_CONSTEXPR14 Matrix44<T> projectionMatrix() const noexcept;
123 
126  ATOMSMATH_CONSTEXPR14 Matrix44<T> projectionMatrixExc() const;
127 
129  ATOMSMATH_HOSTDEVICE constexpr bool degenerate() const noexcept;
130 
132 
135 
137  ATOMSMATH_HOSTDEVICE void
138  set (T nearPlane, T farPlane, T left, T right, T top, T bottom, bool ortho = false) noexcept;
139 
142  ATOMSMATH_HOSTDEVICE void set (T nearPlane, T farPlane, T fovx, T fovy, T aspect) noexcept;
143 
147  void setExc (T nearPlane, T farPlane, T fovx, T fovy, T aspect);
148 
150  ATOMSMATH_HOSTDEVICE void modifyNearAndFar (T nearPlane, T farPlane) noexcept;
151 
153  ATOMSMATH_HOSTDEVICE void setOrthographic (bool) noexcept;
154 
158  ATOMSMATH_HOSTDEVICE void planes (Plane3<T> p[6]) const noexcept;
159 
165  ATOMSMATH_HOSTDEVICE void planes (Plane3<T> p[6], const Matrix44<T>& M) const noexcept;
166 
171  ATOMSMATH_HOSTDEVICE ATOMSMATH_CONSTEXPR14 ATOMSMATH_HOSTDEVICE Frustum<T>
172  window (T left, T right, T top, T bottom) const noexcept;
173 
175 
178 
180  ATOMSMATH_HOSTDEVICE ATOMSMATH_CONSTEXPR14 Line3<T> projectScreenToRay (const Vec2<T>&) const noexcept;
181 
183  ATOMSMATH_HOSTDEVICE ATOMSMATH_CONSTEXPR14 Vec2<T> projectPointToScreen (const Vec3<T>&) const noexcept;
184 
187  ATOMSMATH_CONSTEXPR14 Vec2<T> projectPointToScreenExc (const Vec3<T>&) const;
188 
190  ATOMSMATH_HOSTDEVICE ATOMSMATH_CONSTEXPR14 T ZToDepth (long zval,
191  long min,
192  long max) const noexcept;
194  ATOMSMATH_CONSTEXPR14 T ZToDepthExc (long zval, long min, long max) const;
195 
197  ATOMSMATH_HOSTDEVICE ATOMSMATH_CONSTEXPR14 T normalizedZToDepth (T zval) const noexcept;
198 
201  ATOMSMATH_CONSTEXPR14 T normalizedZToDepthExc (T zval) const;
202 
204  ATOMSMATH_HOSTDEVICE ATOMSMATH_CONSTEXPR14 long
205  DepthToZ (T depth, long zmin, long zmax) const noexcept;
206 
208  ATOMSMATH_CONSTEXPR14 long DepthToZExc (T depth, long zmin, long zmax) const;
209 
211  ATOMSMATH_HOSTDEVICE ATOMSMATH_CONSTEXPR14 T worldRadius (const Vec3<T>& p, T radius) const noexcept;
212 
214  ATOMSMATH_CONSTEXPR14 T worldRadiusExc (const Vec3<T>& p, T radius) const;
215 
217  ATOMSMATH_HOSTDEVICE ATOMSMATH_CONSTEXPR14 T screenRadius (const Vec3<T>& p, T radius) const noexcept;
218 
220  ATOMSMATH_CONSTEXPR14 T screenRadiusExc (const Vec3<T>& p, T radius) const;
221 
223 
224  protected:
225 
227  ATOMSMATH_HOSTDEVICE constexpr Vec2<T> screenToLocal (const Vec2<T>&) const noexcept;
228 
230  ATOMSMATH_HOSTDEVICE ATOMSMATH_CONSTEXPR14 Vec2<T>
231  localToScreen (const Vec2<T>&) const noexcept;
232 
235  ATOMSMATH_CONSTEXPR14 Vec2<T> localToScreenExc (const Vec2<T>&) const;
236 
237  protected:
238 
240 
241  T _nearPlane;
242  T _farPlane;
243  T _left;
244  T _right;
245  T _top;
246  T _bottom;
247  bool _orthographic;
248 
250 };
251 
252 template <class T> ATOMSMATH_CONSTEXPR14 inline Frustum<T>::Frustum() noexcept
253 {
254  set (T (0.1), T (1000.0), T (-1.0), T (1.0), T (1.0), T (-1.0), false);
255 }
256 
257 template <class T> ATOMSMATH_CONSTEXPR14 inline Frustum<T>::Frustum (const Frustum& f) noexcept
258 {
259  *this = f;
260 }
261 
262 template <class T>
263 ATOMSMATH_CONSTEXPR14 inline Frustum<T>::Frustum (T n, T f, T l, T r, T t, T b, bool o) noexcept
264 {
265  set (n, f, l, r, t, b, o);
266 }
267 
268 template <class T>
269 ATOMSMATH_CONSTEXPR14 inline Frustum<T>::Frustum (T nearPlane, T farPlane, T fovx, T fovy, T aspect) noexcept
270 {
272 }
273 
274 template <class T> Frustum<T>::~Frustum() noexcept
275 {}
276 
277 template <class T>
278 ATOMSMATH_CONSTEXPR14 inline const Frustum<T>&
279 Frustum<T>::operator= (const Frustum& f) noexcept
280 {
281  _nearPlane = f._nearPlane;
282  _farPlane = f._farPlane;
283  _left = f._left;
284  _right = f._right;
285  _top = f._top;
286  _bottom = f._bottom;
287  _orthographic = f._orthographic;
288 
289  return *this;
290 }
291 
292 template <class T>
293 constexpr inline bool
294 Frustum<T>::operator== (const Frustum<T>& src) const noexcept
295 {
296  return _nearPlane == src._nearPlane && _farPlane == src._farPlane && _left == src._left &&
297  _right == src._right && _top == src._top && _bottom == src._bottom &&
298  _orthographic == src._orthographic;
299 }
300 
301 template <class T>
302 constexpr inline bool
303 Frustum<T>::operator!= (const Frustum<T>& src) const noexcept
304 {
305  return !operator== (src);
306 }
307 
308 template <class T>
309 inline void
310 Frustum<T>::set (T n, T f, T l, T r, T t, T b, bool o) noexcept
311 {
312  _nearPlane = n;
313  _farPlane = f;
314  _left = l;
315  _right = r;
316  _bottom = b;
317  _top = t;
318  _orthographic = o;
319 }
320 
321 template <class T>
322 inline void
323 Frustum<T>::modifyNearAndFar (T n, T f) noexcept
324 {
325  if (_orthographic)
326  {
327  _nearPlane = n;
328  }
329  else
330  {
331  Line3<T> lowerLeft (Vec3<T> (0, 0, 0), Vec3<T> (_left, _bottom, -_nearPlane));
332  Line3<T> upperRight (Vec3<T> (0, 0, 0), Vec3<T> (_right, _top, -_nearPlane));
333  Plane3<T> nearPlane (Vec3<T> (0, 0, -1), n);
334 
335  Vec3<T> ll = Vec3<T> (0, 0, 0);
336  Vec3<T> ur = Vec3<T> (0, 0, 0);
337  nearPlane.intersect (lowerLeft, ll);
338  nearPlane.intersect (upperRight, ur);
339 
340  _left = ll.x;
341  _right = ur.x;
342  _top = ur.y;
343  _bottom = ll.y;
344  _nearPlane = n;
345  _farPlane = f;
346  }
347 
348  _farPlane = f;
349 }
350 
351 template <class T>
352 inline void
353 Frustum<T>::setOrthographic (bool ortho) noexcept
354 {
355  _orthographic = ortho;
356 }
357 
358 template <class T>
359 inline void
361 {
362 #ifdef ATOMS_USE_EXCEPTIONS
363  if (fovx != T (0) && fovy != T (0))
364  throw std::domain_error ("fovx and fovy cannot both be non-zero.");
365 #endif
366  const T two = static_cast<T> (2);
367 
368  if (fovx != T (0))
369  {
370  _right = nearPlane * std::tan (fovx / two);
371  _left = -_right;
372  _top = ((_right - _left) / aspect) / two;
373  _bottom = -_top;
374  }
375  else
376  {
377  _top = nearPlane * std::tan (fovy / two);
378  _bottom = -_top;
379  _right = (_top - _bottom) * aspect / two;
380  _left = -_right;
381  }
382  _nearPlane = nearPlane;
383  _farPlane = farPlane;
384  _orthographic = false;
385 }
386 
387 template <class T>
388 inline void
390 {
391  const T two = static_cast<T> (2);
392 
393  if (fovx != T (0))
394  {
395  _right = nearPlane * std::tan (fovx / two);
396  _left = -_right;
397  _top = ((_right - _left) / aspect) / two;
398  _bottom = -_top;
399  }
400  else
401  {
402  _top = nearPlane * std::tan (fovy / two);
403  _bottom = -_top;
404  _right = (_top - _bottom) * aspect / two;
405  _left = -_right;
406  }
407  _nearPlane = nearPlane;
408  _farPlane = farPlane;
409  _orthographic = false;
410 }
411 
412 template <class T>
413 constexpr inline T
414 Frustum<T>::fovx() const noexcept
415 {
416  return std::atan2 (_right, _nearPlane) - std::atan2 (_left, _nearPlane);
417 }
418 
419 template <class T>
420 constexpr inline T
421 Frustum<T>::fovy() const noexcept
422 {
423  return std::atan2 (_top, _nearPlane) - std::atan2 (_bottom, _nearPlane);
424 }
425 
426 template <class T>
427 ATOMSMATH_CONSTEXPR14 inline T
429 {
430  T rightMinusLeft = _right - _left;
431  T topMinusBottom = _top - _bottom;
432 
433 #ifdef ATOMS_USE_EXCEPTIONS
434  if (abs (topMinusBottom) < T (1) && abs (rightMinusLeft) > std::numeric_limits<T>::max() * abs (topMinusBottom))
435  {
436  throw std::domain_error ("Bad viewing frustum: "
437  "aspect ratio cannot be computed.");
438  }
439 #endif
440  return rightMinusLeft / topMinusBottom;
441 }
442 
443 template <class T>
444 ATOMSMATH_CONSTEXPR14 inline T
445 Frustum<T>::aspect() const noexcept
446 {
447  T rightMinusLeft = _right - _left;
448  T topMinusBottom = _top - _bottom;
449  return rightMinusLeft / topMinusBottom;
450 }
451 
452 template <class T>
453 ATOMSMATH_CONSTEXPR14 inline Matrix44<T>
455 {
456  T rightPlusLeft = _right + _left;
457  T rightMinusLeft = _right - _left;
458 
459  T topPlusBottom = _top + _bottom;
460  T topMinusBottom = _top - _bottom;
461 
462  T farPlusNear = _farPlane + _nearPlane;
463  T farMinusNear = _farPlane - _nearPlane;
464 #ifdef ATOMS_USE_EXCEPTIONS
465  if ((abs (rightMinusLeft) < T (1) &&
466  abs (rightPlusLeft) > std::numeric_limits<T>::max() * abs (rightMinusLeft)) ||
467  (abs (topMinusBottom) < T (1) &&
468  abs (topPlusBottom) > std::numeric_limits<T>::max() * abs (topMinusBottom)) ||
469  (abs (farMinusNear) < 1 && abs (farPlusNear) > std::numeric_limits<T>::max() * abs (farMinusNear)))
470  {
471  throw std::domain_error ("Bad viewing frustum: "
472  "projection matrix cannot be computed.");
473  }
474 #endif
475  if (_orthographic)
476  {
477  T tx = -rightPlusLeft / rightMinusLeft;
478  T ty = -topPlusBottom / topMinusBottom;
479  T tz = -farPlusNear / farMinusNear;
480 #ifdef ATOMS_USE_EXCEPTIONS
481  if ((abs (rightMinusLeft) < T (1) && T (2) > std::numeric_limits<T>::max() * abs (rightMinusLeft)) ||
482  (abs (topMinusBottom) < T (1) && T (2) > std::numeric_limits<T>::max() * abs (topMinusBottom)) ||
483  (abs (farMinusNear) < T (1) && T (2) > std::numeric_limits<T>::max() * abs (farMinusNear)))
484  {
485  throw std::domain_error ("Bad viewing frustum: "
486  "projection matrix cannot be computed.");
487  }
488 #endif
489  T A = T (2) / rightMinusLeft;
490  T B = T (2) / topMinusBottom;
491  T C = T (-2) / farMinusNear;
492 
493  return Matrix44<T> (A, 0, 0, 0, 0, B, 0, 0, 0, 0, C, 0, tx, ty, tz, 1.f);
494  }
495  else
496  {
497  T A = rightPlusLeft / rightMinusLeft;
498  T B = topPlusBottom / topMinusBottom;
499  T C = -farPlusNear / farMinusNear;
500 
501  T farTimesNear = T (-2) * _farPlane * _nearPlane;
502  #ifdef ATOMS_USE_EXCEPTIONS
503  if (abs (farMinusNear) < T (1) && abs (farTimesNear) > std::numeric_limits<T>::max() * abs (farMinusNear))
504  {
505  throw std::domain_error ("Bad viewing frustum: "
506  "projection matrix cannot be computed.");
507  }
508  #endif
509  T D = farTimesNear / farMinusNear;
510 
511  T twoTimesNear = T (2) * _nearPlane;
512  #ifdef ATOMS_USE_EXCEPTIONS
513  if ((abs (rightMinusLeft) < T (1) &&
514  abs (twoTimesNear) > std::numeric_limits<T>::max() * abs (rightMinusLeft)) ||
515  (abs (topMinusBottom) < T (1) &&
516  abs (twoTimesNear) > std::numeric_limits<T>::max() * abs (topMinusBottom)))
517  {
518  throw std::domain_error ("Bad viewing frustum: "
519  "projection matrix cannot be computed.");
520  }
521  #endif
522  T E = twoTimesNear / rightMinusLeft;
523  T F = twoTimesNear / topMinusBottom;
524 
525  return Matrix44<T> (E, 0, 0, 0, 0, F, 0, 0, A, B, C, -1, 0, 0, D, 0);
526  }
527 }
528 
529 template <class T>
530 ATOMSMATH_CONSTEXPR14 inline Matrix44<T>
532 {
533  T rightPlusLeft = _right + _left;
534  T rightMinusLeft = _right - _left;
535 
536  T topPlusBottom = _top + _bottom;
537  T topMinusBottom = _top - _bottom;
538 
539  T farPlusNear = _farPlane + _nearPlane;
540  T farMinusNear = _farPlane - _nearPlane;
541 
542  if (_orthographic)
543  {
544  T tx = -rightPlusLeft / rightMinusLeft;
545  T ty = -topPlusBottom / topMinusBottom;
546  T tz = -farPlusNear / farMinusNear;
547 
548  T A = T (2) / rightMinusLeft;
549  T B = T (2) / topMinusBottom;
550  T C = T (-2) / farMinusNear;
551 
552  return Matrix44<T> (A, 0, 0, 0, 0, B, 0, 0, 0, 0, C, 0, tx, ty, tz, 1.f);
553  }
554  else
555  {
556  T A = rightPlusLeft / rightMinusLeft;
557  T B = topPlusBottom / topMinusBottom;
558  T C = -farPlusNear / farMinusNear;
559 
560  T farTimesNear = T (-2) * _farPlane * _nearPlane;
561 
562  T D = farTimesNear / farMinusNear;
563 
564  T twoTimesNear = T (2) * _nearPlane;
565 
566  T E = twoTimesNear / rightMinusLeft;
567  T F = twoTimesNear / topMinusBottom;
568 
569  return Matrix44<T> (E, 0, 0, 0, 0, F, 0, 0, A, B, C, -1, 0, 0, D, 0);
570  }
571 }
572 
573 template <class T>
574 constexpr inline bool
575 Frustum<T>::degenerate() const noexcept
576 {
577  return (_nearPlane == _farPlane) || (_left == _right) || (_top == _bottom);
578 }
579 
580 template <class T>
581 ATOMSMATH_CONSTEXPR14 inline Frustum<T>
582 Frustum<T>::window (T l, T r, T t, T b) const noexcept
583 {
584  // move it to 0->1 space
585 
586  Vec2<T> bl = screenToLocal (Vec2<T> (l, b));
587  Vec2<T> tr = screenToLocal (Vec2<T> (r, t));
588 
589  return Frustum<T> (_nearPlane, _farPlane, bl.x, tr.x, tr.y, bl.y, _orthographic);
590 }
591 
592 template <class T>
593 constexpr inline Vec2<T>
594 Frustum<T>::screenToLocal (const Vec2<T>& s) const noexcept
595 {
596  return Vec2<T> (_left + (_right - _left) * (1.f + s.x) / 2.f,
597  _bottom + (_top - _bottom) * (1.f + s.y) / 2.f);
598 }
599 
600 template <class T>
601 ATOMSMATH_CONSTEXPR14 inline Vec2<T>
603 {
604  T leftPlusRight = _left - T (2) * p.x + _right;
605  T leftMinusRight = _left - _right;
606  T bottomPlusTop = _bottom - T (2) * p.y + _top;
607  T bottomMinusTop = _bottom - _top;
608 #ifdef ATOMS_USE_EXCEPTIONS
609  if ((abs (leftMinusRight) < T (1) &&
610  abs (leftPlusRight) > std::numeric_limits<T>::max() * abs (leftMinusRight)) ||
611  (abs (bottomMinusTop) < T (1) &&
612  abs (bottomPlusTop) > std::numeric_limits<T>::max() * abs (bottomMinusTop)))
613  {
614  throw std::domain_error ("Bad viewing frustum: "
615  "local-to-screen transformation cannot be computed");
616  }
617 #endif
618  return Vec2<T> (leftPlusRight / leftMinusRight, bottomPlusTop / bottomMinusTop);
619 }
620 
621 template <class T>
622 ATOMSMATH_CONSTEXPR14 inline Vec2<T>
623 Frustum<T>::localToScreen (const Vec2<T>& p) const noexcept
624 {
625  T leftPlusRight = _left - T (2) * p.x + _right;
626  T leftMinusRight = _left - _right;
627  T bottomPlusTop = _bottom - T (2) * p.y + _top;
628  T bottomMinusTop = _bottom - _top;
629 
630  return Vec2<T> (leftPlusRight / leftMinusRight, bottomPlusTop / bottomMinusTop);
631 }
632 
633 template <class T>
634 ATOMSMATH_CONSTEXPR14 inline Line3<T>
635 Frustum<T>::projectScreenToRay (const Vec2<T>& p) const noexcept
636 {
637  Vec2<T> point = screenToLocal (p);
638  if (orthographic())
639  return Line3<T> (Vec3<T> (point.x, point.y, 0.0), Vec3<T> (point.x, point.y, -1.0));
640  else
641  return Line3<T> (Vec3<T> (0, 0, 0), Vec3<T> (point.x, point.y, -_nearPlane));
642 }
643 
644 template <class T>
645 ATOMSMATH_CONSTEXPR14 Vec2<T>
647 {
648  if (orthographic() || point.z == T (0))
649  return localToScreenExc (Vec2<T> (point.x, point.y));
650  else
651  return localToScreenExc (
652  Vec2<T> (point.x * _nearPlane / -point.z, point.y * _nearPlane / -point.z));
653 }
654 
655 template <class T>
656 ATOMSMATH_CONSTEXPR14 Vec2<T>
657 Frustum<T>::projectPointToScreen (const Vec3<T>& point) const noexcept
658 {
659  if (orthographic() || point.z == T (0))
660  return localToScreen (Vec2<T> (point.x, point.y));
661  else
662  return localToScreen (
663  Vec2<T> (point.x * _nearPlane / -point.z, point.y * _nearPlane / -point.z));
664 }
665 
666 template <class T>
667 ATOMSMATH_CONSTEXPR14 T
668 Frustum<T>::ZToDepthExc (long zval, long zmin, long zmax) const
669 {
670  int zdiff = zmax - zmin;
671 #ifdef ATOMS_USE_EXCEPTIONS
672  if (zdiff == 0)
673  {
674  throw std::domain_error ("Bad call to Frustum::ZToDepth: zmax == zmin");
675  }
676 #endif
677  if (zval > zmax + 1)
678  zval -= zdiff;
679 
680  T fzval = (T (zval) - T (zmin)) / T (zdiff);
681  return normalizedZToDepthExc (fzval);
682 }
683 
684 template <class T>
685 ATOMSMATH_CONSTEXPR14 T
686 Frustum<T>::ZToDepth (long zval, long zmin, long zmax) const noexcept
687 {
688  int zdiff = zmax - zmin;
689 
690  if (zval > zmax + 1)
691  zval -= zdiff;
692 
693  T fzval = (T (zval) - T (zmin)) / T (zdiff);
694  return normalizedZToDepth (fzval);
695 }
696 
697 template <class T>
698 ATOMSMATH_CONSTEXPR14 T
700 {
701  T Zp = zval * T (2) - T (1);
702 
703  if (_orthographic)
704  {
705  return -(Zp * (_farPlane - _nearPlane) + (_farPlane + _nearPlane)) / T (2);
706  }
707  else
708  {
709  T farTimesNear = 2 * _farPlane * _nearPlane;
710  T farMinusNear = Zp * (_farPlane - _nearPlane) - _farPlane - _nearPlane;
711 #ifdef ATOMS_USE_EXCEPTIONS
712  if (abs (farMinusNear) < 1 && abs (farTimesNear) > std::numeric_limits<T>::max() * abs (farMinusNear))
713  {
714  throw std::domain_error ("Frustum::normalizedZToDepth cannot be computed: "
715  "near and far clipping planes of the viewing frustum "
716  "may be too close to each other");
717  }
718 #endif
719  return farTimesNear / farMinusNear;
720  }
721 }
722 
723 template <class T>
724 ATOMSMATH_CONSTEXPR14 T
725 Frustum<T>::normalizedZToDepth (T zval) const noexcept
726 {
727  T Zp = zval * T (2) - T (1);
728 
729  if (_orthographic)
730  {
731  return -(Zp * (_farPlane - _nearPlane) + (_farPlane + _nearPlane)) / T (2);
732  }
733  else
734  {
735  T farTimesNear = 2 * _farPlane * _nearPlane;
736  T farMinusNear = Zp * (_farPlane - _nearPlane) - _farPlane - _nearPlane;
737 
738  return farTimesNear / farMinusNear;
739  }
740 }
741 
742 template <class T>
743 ATOMSMATH_CONSTEXPR14 long
744 Frustum<T>::DepthToZExc (T depth, long zmin, long zmax) const
745 {
746  long zdiff = zmax - zmin;
747  T farMinusNear = _farPlane - _nearPlane;
748 
749  if (_orthographic)
750  {
751  T farPlusNear = T (2) * depth + _farPlane + _nearPlane;
752  #ifdef ATOMS_USE_EXCEPTIONS
753  if (abs (farMinusNear) < T (1) && abs (farPlusNear) > std::numeric_limits<T>::max() * abs (farMinusNear))
754  {
755  throw std::domain_error ("Bad viewing frustum: "
756  "near and far clipping planes "
757  "are too close to each other");
758  }
759 #endif
760  T Zp = -farPlusNear / farMinusNear;
761  return long (0.5 * (Zp + 1) * zdiff) + zmin;
762  }
763  else
764  {
765  // Perspective
766 
767  T farTimesNear = T (2) * _farPlane * _nearPlane;
768 #ifdef ATOMS_USE_EXCEPTIONS
769  if (abs (depth) < T (1) && abs (farTimesNear) > std::numeric_limits<T>::max() * abs (depth))
770  {
771  throw std::domain_error ("Bad call to DepthToZ function: "
772  "value of `depth' is too small");
773  }
774 #endif
775  T farPlusNear = farTimesNear / depth + _farPlane + _nearPlane;
776 #ifdef ATOMS_USE_EXCEPTIONS
777  if (abs (farMinusNear) < T (1) && abs (farPlusNear) > std::numeric_limits<T>::max() * abs (farMinusNear))
778  {
779  throw std::domain_error ("Bad viewing frustum: "
780  "near and far clipping planes "
781  "are too close to each other");
782  }
783 #endif
784  T Zp = farPlusNear / farMinusNear;
785  return long (0.5 * (Zp + 1) * zdiff) + zmin;
786  }
787 }
788 
789 template <class T>
790 ATOMSMATH_CONSTEXPR14 long
791 Frustum<T>::DepthToZ (T depth, long zmin, long zmax) const noexcept
792 {
793  long zdiff = zmax - zmin;
794  T farMinusNear = _farPlane - _nearPlane;
795 
796  if (_orthographic)
797  {
798  T farPlusNear = T (2) * depth + _farPlane + _nearPlane;
799 
800  T Zp = -farPlusNear / farMinusNear;
801  return long (0.5 * (Zp + 1) * zdiff) + zmin;
802  }
803  else
804  {
805  // Perspective
806 
807  T farTimesNear = T (2) * _farPlane * _nearPlane;
808 
809  T farPlusNear = farTimesNear / depth + _farPlane + _nearPlane;
810 
811  T Zp = farPlusNear / farMinusNear;
812  return long (0.5 * (Zp + 1) * zdiff) + zmin;
813  }
814 }
815 
816 template <class T>
817 ATOMSMATH_CONSTEXPR14 T
818 Frustum<T>::screenRadiusExc (const Vec3<T>& p, T radius) const
819 {
820  // Derivation:
821  // Consider X-Z plane.
822  // X coord of projection of p = xp = p.x * (-_nearPlane / p.z)
823  // Let q be p + (radius, 0, 0).
824  // X coord of projection of q = xq = (p.x - radius) * (-_nearPlane / p.z)
825  // X coord of projection of segment from p to q = r = xp - xq
826  // = radius * (-_nearPlane / p.z)
827  // A similar analysis holds in the Y-Z plane.
828  // So r is the quantity we want to return.
829 
830  if (abs (p.z) > T (1) || abs (-_nearPlane) < std::numeric_limits<T>::max() * abs (p.z))
831  {
832  return radius * (-_nearPlane / p.z);
833  }
834  else
835  {
836  #ifdef ATOMS_USE_EXCEPTIONS
837  throw std::domain_error ("Bad call to Frustum::screenRadius: "
838  "magnitude of `p' is too small");
839  #endif
840  }
841 
842  return radius * (-_nearPlane / p.z);
843 }
844 
845 template <class T>
846 ATOMSMATH_CONSTEXPR14 T
847 Frustum<T>::screenRadius (const Vec3<T>& p, T radius) const noexcept
848 {
849  // Derivation:
850  // Consider X-Z plane.
851  // X coord of projection of p = xp = p.x * (-_nearPlane / p.z)
852  // Let q be p + (radius, 0, 0).
853  // X coord of projection of q = xq = (p.x - radius) * (-_nearPlane / p.z)
854  // X coord of projection of segment from p to q = r = xp - xq
855  // = radius * (-_nearPlane / p.z)
856  // A similar analysis holds in the Y-Z plane.
857  // So r is the quantity we want to return.
858 
859  return radius * (-_nearPlane / p.z);
860 }
861 
862 template <class T>
863 ATOMSMATH_CONSTEXPR14 T
864 Frustum<T>::worldRadiusExc (const Vec3<T>& p, T radius) const
865 {
866  if (abs (-_nearPlane) > T (1) || abs (p.z) < std::numeric_limits<T>::max() * abs (-_nearPlane))
867  {
868  return radius * (p.z / -_nearPlane);
869  }
870  else
871  {
872  #ifdef ATOMS_USE_EXCEPTIONS
873  throw std::domain_error ("Bad viewing frustum: "
874  "near clipping plane is too close to zero");
875  #endif
876  }
877 }
878 
879 template <class T>
880 ATOMSMATH_CONSTEXPR14 T
881 Frustum<T>::worldRadius (const Vec3<T>& p, T radius) const noexcept
882 {
883  return radius * (p.z / -_nearPlane);
884 }
885 
886 template <class T>
887 void
888 Frustum<T>::planes (Plane3<T> p[6]) const noexcept
889 {
890  //
891  // Plane order: Top, Right, Bottom, Left, Near, Far.
892  // Normals point outwards.
893  //
894 
895  if (!_orthographic)
896  {
897  Vec3<T> a (_left, _bottom, -_nearPlane);
898  Vec3<T> b (_left, _top, -_nearPlane);
899  Vec3<T> c (_right, _top, -_nearPlane);
900  Vec3<T> d (_right, _bottom, -_nearPlane);
901  Vec3<T> o (0, 0, 0);
902 
903  p[0].set (o, c, b);
904  p[1].set (o, d, c);
905  p[2].set (o, a, d);
906  p[3].set (o, b, a);
907  }
908  else
909  {
910  p[0].set (Vec3<T> (0, 1, 0), _top);
911  p[1].set (Vec3<T> (1, 0, 0), _right);
912  p[2].set (Vec3<T> (0, -1, 0), -_bottom);
913  p[3].set (Vec3<T> (-1, 0, 0), -_left);
914  }
915  p[4].set (Vec3<T> (0, 0, 1), -_nearPlane);
916  p[5].set (Vec3<T> (0, 0, -1), _farPlane);
917 }
918 
919 template <class T>
920 void
921 Frustum<T>::planes (Plane3<T> p[6], const Matrix44<T>& M) const noexcept
922 {
923  //
924  // Plane order: Top, Right, Bottom, Left, Near, Far.
925  // Normals point outwards.
926  //
927 
928  Vec3<T> a = Vec3<T> (_left, _bottom, -_nearPlane) * M;
929  Vec3<T> b = Vec3<T> (_left, _top, -_nearPlane) * M;
930  Vec3<T> c = Vec3<T> (_right, _top, -_nearPlane) * M;
931  Vec3<T> d = Vec3<T> (_right, _bottom, -_nearPlane) * M;
932  if (!_orthographic)
933  {
934  double s = _farPlane / double (_nearPlane);
935  T farLeft = (T) (s * _left);
936  T farRight = (T) (s * _right);
937  T farTop = (T) (s * _top);
938  T farBottom = (T) (s * _bottom);
939  Vec3<T> e = Vec3<T> (farLeft, farBottom, -_farPlane) * M;
940  Vec3<T> f = Vec3<T> (farLeft, farTop, -_farPlane) * M;
941  Vec3<T> g = Vec3<T> (farRight, farTop, -_farPlane) * M;
942  Vec3<T> o = Vec3<T> (0, 0, 0) * M;
943  p[0].set (o, c, b);
944  p[1].set (o, d, c);
945  p[2].set (o, a, d);
946  p[3].set (o, b, a);
947  p[4].set (a, d, c);
948  p[5].set (e, f, g);
949  }
950  else
951  {
952  Vec3<T> e = Vec3<T> (_left, _bottom, -_farPlane) * M;
953  Vec3<T> f = Vec3<T> (_left, _top, -_farPlane) * M;
954  Vec3<T> g = Vec3<T> (_right, _top, -_farPlane) * M;
955  Vec3<T> h = Vec3<T> (_right, _bottom, -_farPlane) * M;
956  p[0].set (c, g, f);
957  p[1].set (d, h, g);
958  p[2].set (a, e, h);
959  p[3].set (b, f, e);
960  p[4].set (a, d, c);
961  p[5].set (e, f, g);
962  }
963 }
964 
966 typedef Frustum<float> Frustumf;
967 
969 typedef Frustum<double> Frustumd;
970 
971 ATOMSMATH_INTERNAL_NAMESPACE_HEADER_EXIT
972 
973 #if defined _WIN32 || defined _WIN64
974 # ifdef _redef_near
975 # define near
976 # endif
977 # ifdef _redef_far
978 # define far
979 # endif
980 #endif
981 
982 #endif // INCLUDED_ATOMSMATHFRUSTUM_H
Definition: ImathFrustum.h:38
ATOMSMATH_CONSTEXPR14 Vec2< T > projectPointToScreenExc(const Vec3< T > &) const
Definition: ImathFrustum.h:646
constexpr ATOMSMATH_HOSTDEVICE T bottom() const noexcept
Return the bottom of the frustum.
Definition: ImathFrustum.h:103
ATOMSMATH_HOSTDEVICE ATOMSMATH_CONSTEXPR14 T aspect() const noexcept
Return the aspect ratio.
Definition: ImathFrustum.h:445
constexpr ATOMSMATH_HOSTDEVICE T hither() const noexcept
Return the near clipping plane.
Definition: ImathFrustum.h:88
void setExc(T nearPlane, T farPlane, T fovx, T fovy, T aspect)
Definition: ImathFrustum.h:360
virtual ~Frustum() noexcept
Destructor.
Definition: ImathFrustum.h:274
ATOMSMATH_HOSTDEVICE void modifyNearAndFar(T nearPlane, T farPlane) noexcept
Set the near and far clipping planes.
Definition: ImathFrustum.h:323
ATOMSMATH_HOSTDEVICE ATOMSMATH_CONSTEXPR14 Matrix44< T > projectionMatrix() const noexcept
Return the project matrix that the frustum defines.
Definition: ImathFrustum.h:531
ATOMSMATH_HOSTDEVICE ATOMSMATH_CONSTEXPR14 Line3< T > projectScreenToRay(const Vec2< T > &) const noexcept
Project a point in screen spaced to 3d ray.
Definition: ImathFrustum.h:635
ATOMSMATH_HOSTDEVICE void planes(Plane3< T > p[6]) const noexcept
Definition: ImathFrustum.h:888
ATOMSMATH_HOSTDEVICE ATOMSMATH_CONSTEXPR14 Vec2< T > localToScreen(const Vec2< T > &) const noexcept
Map point from local space to screen space.
Definition: ImathFrustum.h:623
ATOMSMATH_HOSTDEVICE ATOMSMATH_CONSTEXPR14 T normalizedZToDepth(T zval) const noexcept
Map a normalized z value to its depth in the frustum.
Definition: ImathFrustum.h:725
ATOMSMATH_CONSTEXPR14 long DepthToZExc(T depth, long zmin, long zmax) const
Map depth to z value. Throw an exception on error.
Definition: ImathFrustum.h:744
constexpr ATOMSMATH_HOSTDEVICE bool orthographic() const noexcept
Return true if the frustum is orthographic, false if perspective.
Definition: ImathFrustum.h:82
ATOMSMATH_HOSTDEVICE ATOMSMATH_CONSTEXPR14 Frustum() noexcept
Definition: ImathFrustum.h:252
ATOMSMATH_HOSTDEVICE ATOMSMATH_CONSTEXPR14 Vec2< T > projectPointToScreen(const Vec3< T > &) const noexcept
Project a 3D point into screen coordinates.
Definition: ImathFrustum.h:657
constexpr ATOMSMATH_HOSTDEVICE bool degenerate() const noexcept
Return true if the frustum is degenerate.
Definition: ImathFrustum.h:575
ATOMSMATH_CONSTEXPR14 Vec2< T > localToScreenExc(const Vec2< T > &) const
Definition: ImathFrustum.h:602
constexpr ATOMSMATH_HOSTDEVICE T yon() const noexcept
Return the far clipping plane.
Definition: ImathFrustum.h:94
ATOMSMATH_HOSTDEVICE ATOMSMATH_CONSTEXPR14 T ZToDepth(long zval, long min, long max) const noexcept
Map a z value to its depth in the frustum.
Definition: ImathFrustum.h:686
ATOMSMATH_HOSTDEVICE ATOMSMATH_CONSTEXPR14 long DepthToZ(T depth, long zmin, long zmax) const noexcept
Map depth to z value.
Definition: ImathFrustum.h:791
constexpr ATOMSMATH_HOSTDEVICE Vec2< T > screenToLocal(const Vec2< T > &) const noexcept
Map point from screen space to local space.
Definition: ImathFrustum.h:594
constexpr ATOMSMATH_HOSTDEVICE T farPlane() const noexcept
Return the far clipping plane.
Definition: ImathFrustum.h:91
ATOMSMATH_HOSTDEVICE void set(T nearPlane, T farPlane, T left, T right, T top, T bottom, bool ortho=false) noexcept
Set functions change the entire state of the Frustum.
Definition: ImathFrustum.h:310
ATOMSMATH_CONSTEXPR14 T screenRadiusExc(const Vec3< T > &p, T radius) const
Compute screen radius. Throw an exception on error.
Definition: ImathFrustum.h:818
constexpr ATOMSMATH_HOSTDEVICE bool operator==(const Frustum< T > &src) const noexcept
Equality.
Definition: ImathFrustum.h:294
ATOMSMATH_CONSTEXPR14 Matrix44< T > projectionMatrixExc() const
Definition: ImathFrustum.h:454
ATOMSMATH_HOSTDEVICE void setOrthographic(bool) noexcept
Set the ortographic state.
Definition: ImathFrustum.h:353
ATOMSMATH_HOSTDEVICE ATOMSMATH_CONSTEXPR14 T screenRadius(const Vec3< T > &p, T radius) const noexcept
Compute screen radius.
Definition: ImathFrustum.h:847
ATOMSMATH_CONSTEXPR14 T normalizedZToDepthExc(T zval) const
Definition: ImathFrustum.h:699
ATOMSMATH_HOSTDEVICE ATOMSMATH_CONSTEXPR14 ATOMSMATH_HOSTDEVICE Frustum< T > window(T left, T right, T top, T bottom) const noexcept
Definition: ImathFrustum.h:582
constexpr ATOMSMATH_HOSTDEVICE T left() const noexcept
Return the left of the frustum.
Definition: ImathFrustum.h:97
ATOMSMATH_CONSTEXPR14 T aspectExc() const
Definition: ImathFrustum.h:428
constexpr ATOMSMATH_HOSTDEVICE T fovx() const noexcept
Return the field of view in X.
Definition: ImathFrustum.h:414
ATOMSMATH_HOSTDEVICE ATOMSMATH_CONSTEXPR14 T worldRadius(const Vec3< T > &p, T radius) const noexcept
Compute worldRadius.
Definition: ImathFrustum.h:881
ATOMSMATH_CONSTEXPR14 T ZToDepthExc(long zval, long min, long max) const
Map a z value to its depth in the frustum.
Definition: ImathFrustum.h:668
constexpr ATOMSMATH_HOSTDEVICE bool operator!=(const Frustum< T > &src) const noexcept
Inequality.
Definition: ImathFrustum.h:303
constexpr ATOMSMATH_HOSTDEVICE T fovy() const noexcept
Return the field of view in Y.
Definition: ImathFrustum.h:421
ATOMSMATH_CONSTEXPR14 T worldRadiusExc(const Vec3< T > &p, T radius) const
Compute worldRadius. Throw an exception on error.
Definition: ImathFrustum.h:864
constexpr ATOMSMATH_HOSTDEVICE T nearPlane() const noexcept
Return the near clipping plane.
Definition: ImathFrustum.h:85
constexpr ATOMSMATH_HOSTDEVICE T top() const noexcept
Return the top of the frustum.
Definition: ImathFrustum.h:106
constexpr ATOMSMATH_HOSTDEVICE T right() const noexcept
Return the right of the frustum.
Definition: ImathFrustum.h:100
ATOMSMATH_HOSTDEVICE ATOMSMATH_CONSTEXPR14 const Frustum & operator=(const Frustum &) noexcept
Component-wise assignment.
Definition: ImathFrustum.h:279
Definition: ImathLine.h:25
Definition: ImathMatrix.h:631
Definition: ImathPlane.h:30
Definition: ImathVec.h:43
Definition: ImathVec.h:260