HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
ImathFrustum.h
Go to the documentation of this file.
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_IMATHFRUSTUM_H
11 #define INCLUDED_IMATHFRUSTUM_H
12 
13 #include "ImathExport.h"
14 #include "ImathNamespace.h"
15 
16 #include "ImathFun.h"
17 #include "ImathLine.h"
18 #include "ImathMatrix.h"
19 #include "ImathPlane.h"
20 #include "ImathVec.h"
21 
22 IMATH_INTERNAL_NAMESPACE_HEADER_ENTER
23 
24 ///
25 /// Template class `Frustum<T>`
26 ///
27 /// The frustum is always located with the eye point at the origin
28 /// facing down -Z. This makes the Frustum class compatable with
29 /// OpenGL (or anything that assumes a camera looks down -Z, hence
30 /// with a right-handed coordinate system) but not with RenderMan
31 /// which assumes the camera looks down +Z. Additional functions are
32 /// provided for conversion from and from various camera coordinate
33 /// spaces.
34 ///
35 /// nearPlane/farPlane: near/far are keywords used by Microsoft's
36 /// compiler, so we use nearPlane/farPlane instead to avoid
37 /// issues.
38 
39 template <class T> class IMATH_EXPORT_TEMPLATE_TYPE Frustum
40 {
41 public:
42  using BaseType = T;
43  using value_type = T;
44 
45  /// @{
46  /// @name Constructors and Assignment
47  ///
48 
49  /// Initialize with default values:
50  /// near=0.1, far=1000.0, left=-1.0, right=1.0, top=1.0, bottom=-1.0, ortho=false
51  IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Frustum () IMATH_NOEXCEPT;
52 
53  /// Copy constructor
54  IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Frustum (const Frustum&) IMATH_NOEXCEPT;
55 
56  /// Initialize to specific values
57  IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Frustum (
58  T nearPlane,
59  T farPlane,
60  T left,
61  T right,
62  T top,
63  T bottom,
64  bool ortho = false) IMATH_NOEXCEPT;
65 
66  /// Initialize with fov and aspect
67  IMATH_HOSTDEVICE IMATH_CONSTEXPR14
68  Frustum (T nearPlane, T farPlane, T fovx, T fovy, T aspect) IMATH_NOEXCEPT;
69 
70  /// Destructor
71  virtual ~Frustum () IMATH_NOEXCEPT;
72 
73  /// Component-wise assignment
74  IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Frustum&
75  operator= (const Frustum&) IMATH_NOEXCEPT;
76 
77  /// @}
78 
79  /// @{
80  /// @name Comparison
81 
82  /// Equality
83  IMATH_HOSTDEVICE constexpr bool
84  operator== (const Frustum<T>& src) const IMATH_NOEXCEPT;
85 
86  /// Inequality
87  IMATH_HOSTDEVICE constexpr bool
88  operator!= (const Frustum<T>& src) const IMATH_NOEXCEPT;
89 
90  /// @}
91 
92  /// @{
93  /// @name Query
94 
95  /// Return true if the frustum is orthographic, false if perspective
96  IMATH_HOSTDEVICE constexpr bool orthographic () const IMATH_NOEXCEPT
97  {
98  return _orthographic;
99  }
100 
101  /// Return the near clipping plane
103  {
104  return _nearPlane;
105  }
106 
107  /// Return the near clipping plane
109  {
110  return _nearPlane;
111  }
112 
113  /// Return the far clipping plane
115  {
116  return _farPlane;
117  }
118 
119  /// Return the far clipping plane
121  {
122  return _farPlane;
123  }
124 
125  /// Return the left of the frustum
126  IMATH_HOSTDEVICE constexpr T left () const IMATH_NOEXCEPT { return _left; }
127 
128  /// Return the right of the frustum
130  {
131  return _right;
132  }
133 
134  /// Return the bottom of the frustum
136  {
137  return _bottom;
138  }
139 
140  /// Return the top of the frustum
141  IMATH_HOSTDEVICE constexpr T top () const IMATH_NOEXCEPT { return _top; }
142 
143  /// Return the field of view in X
144  IMATH_HOSTDEVICE constexpr T fovx () const IMATH_NOEXCEPT;
145 
146  /// Return the field of view in Y
147  IMATH_HOSTDEVICE constexpr T fovy () const IMATH_NOEXCEPT;
148 
149  /// Return the aspect ratio
150  IMATH_HOSTDEVICE IMATH_CONSTEXPR14 T aspect () const IMATH_NOEXCEPT;
151 
152  /// Return the aspect ratio. Throw an exception if the aspect
153  /// ratio is undefined.
154  IMATH_CONSTEXPR14 T aspectExc () const;
155 
156  /// Return the project matrix that the frustum defines
157  IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Matrix44<T>
158  projectionMatrix () const IMATH_NOEXCEPT;
159 
160  /// Return the project matrix that the frustum defines. Throw an
161  /// exception if the frustum is degenerate.
162  IMATH_CONSTEXPR14 Matrix44<T> projectionMatrixExc () const;
163 
164  /// Return true if the frustum is degenerate.
165  IMATH_HOSTDEVICE constexpr bool degenerate () const IMATH_NOEXCEPT;
166 
167  /// @}
168 
169  /// @{
170  /// @name Set Value
171 
172  /// Set functions change the entire state of the Frustum
173  IMATH_HOSTDEVICE void set (
174  T nearPlane,
175  T farPlane,
176  T left,
177  T right,
178  T top,
179  T bottom,
180  bool ortho = false) IMATH_NOEXCEPT;
181 
182  /// Set functions change the entire state of the Frustum using
183  /// field of view and aspect ratio
184  IMATH_HOSTDEVICE void
185  set (T nearPlane, T farPlane, T fovx, T fovy, T aspect) IMATH_NOEXCEPT;
186 
187  /// Set functions change the entire state of the Frustum using
188  /// field of view and aspect ratio. Throw an exception if `fovx`
189  /// and/or `fovy` are invalid.
190  void setExc (T nearPlane, T farPlane, T fovx, T fovy, T aspect);
191 
192  /// Set the near and far clipping planes
193  IMATH_HOSTDEVICE void
194  modifyNearAndFar (T nearPlane, T farPlane) IMATH_NOEXCEPT;
195 
196  /// Set the ortographic state
197  IMATH_HOSTDEVICE void setOrthographic (bool) IMATH_NOEXCEPT;
198 
199  /// Set the planes in p to be the six bounding planes of the frustum, in
200  /// the following order: top, right, bottom, left, near, far.
201  /// Note that the planes have normals that point out of the frustum.
202  IMATH_HOSTDEVICE void planes (Plane3<T> p[6]) const IMATH_NOEXCEPT;
203 
204  /// Set the planes in p to be the six bounding planes of the
205  /// frustum, in the following order: top, right, bottom, left,
206  /// near, far. Note that the planes have normals that point out
207  /// of the frustum. Apply the given matrix to transform the
208  /// frustum before setting the planes.
209  IMATH_HOSTDEVICE void
210  planes (Plane3<T> p[6], const Matrix44<T>& M) const IMATH_NOEXCEPT;
211 
212  /// Takes a rectangle in the screen space (i.e., -1 <= left <= right <= 1
213  /// and -1 <= bottom <= top <= 1) of this Frustum, and returns a new
214  /// Frustum whose near clipping-plane window is that rectangle in local
215  /// space.
216  IMATH_HOSTDEVICE IMATH_CONSTEXPR14 IMATH_HOSTDEVICE Frustum<T>
217  window (T left, T right, T top, T bottom) const IMATH_NOEXCEPT;
218 
219  /// @}
220 
221  /// @{
222  /// @name Utility Methods
223 
224  /// Project a point in screen spaced to 3d ray
225  IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Line3<T>
226  projectScreenToRay (const Vec2<T>&) const IMATH_NOEXCEPT;
227 
228  /// Project a 3D point into screen coordinates
229  IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Vec2<T>
230  projectPointToScreen (const Vec3<T>&) const IMATH_NOEXCEPT;
231 
232  /// Project a 3D point into screen coordinates. Throw an
233  /// exception if the point cannot be projected.
234  IMATH_CONSTEXPR14 Vec2<T> projectPointToScreenExc (const Vec3<T>&) const;
235 
236  /// Map a z value to its depth in the frustum.
237  IMATH_HOSTDEVICE IMATH_CONSTEXPR14 T
238  ZToDepth (long zval, long min, long max) const IMATH_NOEXCEPT;
239  /// Map a z value to its depth in the frustum.
240  IMATH_CONSTEXPR14 T ZToDepthExc (long zval, long min, long max) const;
241 
242  /// Map a normalized z value to its depth in the frustum.
243  IMATH_HOSTDEVICE IMATH_CONSTEXPR14 T
244  normalizedZToDepth (T zval) const IMATH_NOEXCEPT;
245 
246  /// Map a normalized z value to its depth in the frustum. Throw an
247  /// exception on error.
248  IMATH_CONSTEXPR14 T normalizedZToDepthExc (T zval) const;
249 
250  /// Map depth to z value.
251  IMATH_HOSTDEVICE IMATH_CONSTEXPR14 long
252  DepthToZ (T depth, long zmin, long zmax) const IMATH_NOEXCEPT;
253 
254  /// Map depth to z value. Throw an exception on error.
255  IMATH_CONSTEXPR14 long DepthToZExc (T depth, long zmin, long zmax) const;
256 
257  /// Compute worldRadius
258  IMATH_HOSTDEVICE IMATH_CONSTEXPR14 T
259  worldRadius (const Vec3<T>& p, T radius) const IMATH_NOEXCEPT;
260 
261  /// Compute worldRadius. Throw an exception on error.
262  IMATH_CONSTEXPR14 T worldRadiusExc (const Vec3<T>& p, T radius) const;
263 
264  /// Compute screen radius
265  IMATH_HOSTDEVICE IMATH_CONSTEXPR14 T
266  screenRadius (const Vec3<T>& p, T radius) const IMATH_NOEXCEPT;
267 
268  /// Compute screen radius. Throw an exception on error.
269  IMATH_CONSTEXPR14 T screenRadiusExc (const Vec3<T>& p, T radius) const;
270 
271  /// @}
272 
273 protected:
274  /// Map point from screen space to local space
275  IMATH_HOSTDEVICE constexpr Vec2<T>
276  screenToLocal (const Vec2<T>&) const IMATH_NOEXCEPT;
277 
278  /// Map point from local space to screen space
279  IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Vec2<T>
280  localToScreen (const Vec2<T>&) const IMATH_NOEXCEPT;
281 
282  /// Map point from local space to screen space. Throw an exception
283  /// on error.
284  IMATH_CONSTEXPR14 Vec2<T> localToScreenExc (const Vec2<T>&) const;
285 
286 protected:
287  /// @cond Doxygen_Suppress
288 
289  T _nearPlane;
290  T _farPlane;
291  T _left;
292  T _right;
293  T _top;
294  T _bottom;
295  bool _orthographic;
296 
297  /// @endcond
298 };
299 
300 template <class T>
301 IMATH_CONSTEXPR14 inline Frustum<T>::Frustum () IMATH_NOEXCEPT
302 {
303  set (T (0.1), T (1000.0), T (-1.0), T (1.0), T (1.0), T (-1.0), false);
304 }
305 
306 template <class T>
307 IMATH_CONSTEXPR14 inline Frustum<T>::Frustum (const Frustum& f) IMATH_NOEXCEPT
308 {
309  *this = f;
310 }
311 
312 template <class T>
313 IMATH_CONSTEXPR14 inline Frustum<T>::Frustum (
314  T n, T f, T l, T r, T t, T b, bool o) IMATH_NOEXCEPT
315 {
316  set (n, f, l, r, t, b, o);
317 }
318 
319 template <class T>
320 IMATH_CONSTEXPR14 inline Frustum<T>::Frustum (
321  T nearPlane, T farPlane, T fovx, T fovy, T aspect) IMATH_NOEXCEPT
322 {
323  set (nearPlane, farPlane, fovx, fovy, aspect);
324 }
325 
327 {}
328 
329 template <class T>
330 IMATH_CONSTEXPR14 inline const Frustum<T>&
332 {
333  _nearPlane = f._nearPlane;
334  _farPlane = f._farPlane;
335  _left = f._left;
336  _right = f._right;
337  _top = f._top;
338  _bottom = f._bottom;
339  _orthographic = f._orthographic;
340 
341  return *this;
342 }
343 
344 template <class T>
345 constexpr inline bool
347 {
348  return _nearPlane == src._nearPlane && _farPlane == src._farPlane &&
349  _left == src._left && _right == src._right && _top == src._top &&
350  _bottom == src._bottom && _orthographic == src._orthographic;
351 }
352 
353 template <class T>
354 constexpr inline bool
356 {
357  return !operator== (src);
358 }
359 
360 template <class T>
361 inline void
362 Frustum<T>::set (T n, T f, T l, T r, T t, T b, bool o) IMATH_NOEXCEPT
363 {
364  _nearPlane = n;
365  _farPlane = f;
366  _left = l;
367  _right = r;
368  _bottom = b;
369  _top = t;
370  _orthographic = o;
371 }
372 
373 template <class T>
374 inline void
376 {
377  if (_orthographic) { _nearPlane = n; }
378  else
379  {
380  Line3<T> lowerLeft (
381  Vec3<T> (0, 0, 0), Vec3<T> (_left, _bottom, -_nearPlane));
382  Line3<T> upperRight (
383  Vec3<T> (0, 0, 0), Vec3<T> (_right, _top, -_nearPlane));
384  Plane3<T> nearPlane (Vec3<T> (0, 0, -1), n);
385 
386  Vec3<T> ll = Vec3<T> (0, 0, 0);
387  Vec3<T> ur = Vec3<T> (0, 0, 0);
388  nearPlane.intersect (lowerLeft, ll);
389  nearPlane.intersect (upperRight, ur);
390 
391  _left = ll.x;
392  _right = ur.x;
393  _top = ur.y;
394  _bottom = ll.y;
395  _nearPlane = n;
396  _farPlane = f;
397  }
398 
399  _farPlane = f;
400 }
401 
402 template <class T>
403 inline void
405 {
406  _orthographic = ortho;
407 }
408 
409 template <class T>
410 inline void
411 Frustum<T>::setExc (T nearPlane, T farPlane, T fovx, T fovy, T aspect)
412 {
413  if (fovx != T (0) && fovy != T (0))
414  throw std::domain_error ("fovx and fovy cannot both be non-zero.");
415 
416  const T two = static_cast<T> (2);
417 
418  if (fovx != T (0))
419  {
420  _right = nearPlane * std::tan (fovx / two);
421  _left = -_right;
422  _top = ((_right - _left) / aspect) / two;
423  _bottom = -_top;
424  }
425  else
426  {
427  _top = nearPlane * std::tan (fovy / two);
428  _bottom = -_top;
429  _right = (_top - _bottom) * aspect / two;
430  _left = -_right;
431  }
432  _nearPlane = nearPlane;
433  _farPlane = farPlane;
434  _orthographic = false;
435 }
436 
437 template <class T>
438 inline void
439 Frustum<T>::set (T nearPlane, T farPlane, T fovx, T fovy, T aspect)
441 {
442  const T two = static_cast<T> (2);
443 
444  if (fovx != T (0))
445  {
446  _right = nearPlane * std::tan (fovx / two);
447  _left = -_right;
448  _top = ((_right - _left) / aspect) / two;
449  _bottom = -_top;
450  }
451  else
452  {
453  _top = nearPlane * std::tan (fovy / two);
454  _bottom = -_top;
455  _right = (_top - _bottom) * aspect / two;
456  _left = -_right;
457  }
458  _nearPlane = nearPlane;
459  _farPlane = farPlane;
460  _orthographic = false;
461 }
462 
463 template <class T>
464 constexpr inline T
466 {
467  return std::atan2 (_right, _nearPlane) - std::atan2 (_left, _nearPlane);
468 }
469 
470 template <class T>
471 constexpr inline T
473 {
474  return std::atan2 (_top, _nearPlane) - std::atan2 (_bottom, _nearPlane);
475 }
476 
477 template <class T>
478 IMATH_CONSTEXPR14 inline T
480 {
481  T rightMinusLeft = _right - _left;
482  T topMinusBottom = _top - _bottom;
483 
484  if (abs (topMinusBottom) < T (1) &&
485  abs (rightMinusLeft) >
486  std::numeric_limits<T>::max () * abs (topMinusBottom))
487  {
488  throw std::domain_error ("Bad viewing frustum: "
489  "aspect ratio cannot be computed.");
490  }
491 
492  return rightMinusLeft / topMinusBottom;
493 }
494 
495 template <class T>
496 IMATH_CONSTEXPR14 inline T
498 {
499  T rightMinusLeft = _right - _left;
500  T topMinusBottom = _top - _bottom;
501  return rightMinusLeft / topMinusBottom;
502 }
503 
504 template <class T>
505 IMATH_CONSTEXPR14 inline Matrix44<T>
507 {
508  T rightPlusLeft = _right + _left;
509  T rightMinusLeft = _right - _left;
510 
511  T topPlusBottom = _top + _bottom;
512  T topMinusBottom = _top - _bottom;
513 
514  T farPlusNear = _farPlane + _nearPlane;
515  T farMinusNear = _farPlane - _nearPlane;
516 
517  if ((abs (rightMinusLeft) < T (1) &&
518  abs (rightPlusLeft) >
519  std::numeric_limits<T>::max () * abs (rightMinusLeft)) ||
520  (abs (topMinusBottom) < T (1) &&
521  abs (topPlusBottom) >
522  std::numeric_limits<T>::max () * abs (topMinusBottom)) ||
523  (abs (farMinusNear) < 1 &&
524  abs (farPlusNear) >
525  std::numeric_limits<T>::max () * abs (farMinusNear)))
526  {
527  throw std::domain_error ("Bad viewing frustum: "
528  "projection matrix cannot be computed.");
529  }
530 
531  if (_orthographic)
532  {
533  T tx = -rightPlusLeft / rightMinusLeft;
534  T ty = -topPlusBottom / topMinusBottom;
535  T tz = -farPlusNear / farMinusNear;
536 
537  if ((abs (rightMinusLeft) < T (1) &&
538  T (2) > std::numeric_limits<T>::max () * abs (rightMinusLeft)) ||
539  (abs (topMinusBottom) < T (1) &&
540  T (2) > std::numeric_limits<T>::max () * abs (topMinusBottom)) ||
541  (abs (farMinusNear) < T (1) &&
542  T (2) > std::numeric_limits<T>::max () * abs (farMinusNear)))
543  {
544  throw std::domain_error ("Bad viewing frustum: "
545  "projection matrix cannot be computed.");
546  }
547 
548  T A = T (2) / rightMinusLeft;
549  T B = T (2) / topMinusBottom;
550  T C = T (-2) / farMinusNear;
551 
552  return Matrix44<T> (
553  A, 0, 0, 0, 0, B, 0, 0, 0, 0, C, 0, tx, ty, tz, 1.f);
554  }
555  else
556  {
557  T A = rightPlusLeft / rightMinusLeft;
558  T B = topPlusBottom / topMinusBottom;
559  T C = -farPlusNear / farMinusNear;
560 
561  T farTimesNear = T (-2) * _farPlane * _nearPlane;
562  if (abs (farMinusNear) < T (1) &&
563  abs (farTimesNear) >
564  std::numeric_limits<T>::max () * abs (farMinusNear))
565  {
566  // impossible condition: already tested above
567  throw std::domain_error ("Bad viewing frustum: "
568  "projection matrix cannot be computed.");
569  }
570 
571  T D = farTimesNear / farMinusNear;
572 
573  T twoTimesNear = T (2) * _nearPlane;
574 
575  if ((abs (rightMinusLeft) < T (1) &&
576  abs (twoTimesNear) >
577  std::numeric_limits<T>::max () * abs (rightMinusLeft)) ||
578  (abs (topMinusBottom) < T (1) &&
579  abs (twoTimesNear) >
580  std::numeric_limits<T>::max () * abs (topMinusBottom)))
581  {
582  // impossible condition: already tested above
583  throw std::domain_error ("Bad viewing frustum: "
584  "projection matrix cannot be computed.");
585  }
586 
587  T E = twoTimesNear / rightMinusLeft;
588  T F = twoTimesNear / topMinusBottom;
589 
590  return Matrix44<T> (E, 0, 0, 0, 0, F, 0, 0, A, B, C, -1, 0, 0, D, 0);
591  }
592 }
593 
594 template <class T>
595 IMATH_CONSTEXPR14 inline Matrix44<T>
597 {
598  T rightPlusLeft = _right + _left;
599  T rightMinusLeft = _right - _left;
600 
601  T topPlusBottom = _top + _bottom;
602  T topMinusBottom = _top - _bottom;
603 
604  T farPlusNear = _farPlane + _nearPlane;
605  T farMinusNear = _farPlane - _nearPlane;
606 
607  if (_orthographic)
608  {
609  T tx = -rightPlusLeft / rightMinusLeft;
610  T ty = -topPlusBottom / topMinusBottom;
611  T tz = -farPlusNear / farMinusNear;
612 
613  T A = T (2) / rightMinusLeft;
614  T B = T (2) / topMinusBottom;
615  T C = T (-2) / farMinusNear;
616 
617  return Matrix44<T> (
618  A, 0, 0, 0, 0, B, 0, 0, 0, 0, C, 0, tx, ty, tz, 1.f);
619  }
620  else
621  {
622  T A = rightPlusLeft / rightMinusLeft;
623  T B = topPlusBottom / topMinusBottom;
624  T C = -farPlusNear / farMinusNear;
625 
626  T farTimesNear = T (-2) * _farPlane * _nearPlane;
627 
628  T D = farTimesNear / farMinusNear;
629 
630  T twoTimesNear = T (2) * _nearPlane;
631 
632  T E = twoTimesNear / rightMinusLeft;
633  T F = twoTimesNear / topMinusBottom;
634 
635  return Matrix44<T> (E, 0, 0, 0, 0, F, 0, 0, A, B, C, -1, 0, 0, D, 0);
636  }
637 }
638 
639 template <class T>
640 constexpr inline bool
642 {
643  return (_nearPlane == _farPlane) || (_left == _right) || (_top == _bottom);
644 }
645 
646 template <class T>
647 IMATH_CONSTEXPR14 inline Frustum<T>
649 {
650  // move it to 0->1 space
651 
652  Vec2<T> bl = screenToLocal (Vec2<T> (l, b));
653  Vec2<T> tr = screenToLocal (Vec2<T> (r, t));
654 
655  return Frustum<T> (
656  _nearPlane, _farPlane, bl.x, tr.x, tr.y, bl.y, _orthographic);
657 }
658 
659 template <class T>
660 constexpr inline Vec2<T>
662 {
663  return Vec2<T> (
664  _left + (_right - _left) * (1.f + s.x) / 2.f,
665  _bottom + (_top - _bottom) * (1.f + s.y) / 2.f);
666 }
667 
668 template <class T>
669 IMATH_CONSTEXPR14 inline Vec2<T>
671 {
672  T leftPlusRight = _left - T (2) * p.x + _right;
673  T leftMinusRight = _left - _right;
674  T bottomPlusTop = _bottom - T (2) * p.y + _top;
675  T bottomMinusTop = _bottom - _top;
676 
677  if ((abs (leftMinusRight) < T (1) &&
678  abs (leftPlusRight) >
679  std::numeric_limits<T>::max () * abs (leftMinusRight)) ||
680  (abs (bottomMinusTop) < T (1) &&
681  abs (bottomPlusTop) >
682  std::numeric_limits<T>::max () * abs (bottomMinusTop)))
683  {
684  throw std::domain_error (
685  "Bad viewing frustum: "
686  "local-to-screen transformation cannot be computed");
687  }
688 
689  return Vec2<T> (
690  leftPlusRight / leftMinusRight, bottomPlusTop / bottomMinusTop);
691 }
692 
693 template <class T>
694 IMATH_CONSTEXPR14 inline Vec2<T>
696 {
697  T leftPlusRight = _left - T (2) * p.x + _right;
698  T leftMinusRight = _left - _right;
699  T bottomPlusTop = _bottom - T (2) * p.y + _top;
700  T bottomMinusTop = _bottom - _top;
701 
702  return Vec2<T> (
703  leftPlusRight / leftMinusRight, bottomPlusTop / bottomMinusTop);
704 }
705 
706 template <class T>
707 IMATH_CONSTEXPR14 inline Line3<T>
709 {
710  Vec2<T> point = screenToLocal (p);
711  if (orthographic ())
712  return Line3<T> (
713  Vec3<T> (point.x, point.y, 0.0), Vec3<T> (point.x, point.y, -1.0));
714  else
715  return Line3<T> (
716  Vec3<T> (0, 0, 0), Vec3<T> (point.x, point.y, -_nearPlane));
717 }
718 
719 template <class T>
720 IMATH_CONSTEXPR14 Vec2<T>
722 {
723  if (orthographic () || point.z == T (0))
724  return localToScreenExc (Vec2<T> (point.x, point.y));
725  else
726  return localToScreenExc (Vec2<T> (
727  point.x * _nearPlane / -point.z, point.y * _nearPlane / -point.z));
728 }
729 
730 template <class T>
731 IMATH_CONSTEXPR14 Vec2<T>
733 {
734  if (orthographic () || point.z == T (0))
735  return localToScreen (Vec2<T> (point.x, point.y));
736  else
737  return localToScreen (Vec2<T> (
738  point.x * _nearPlane / -point.z, point.y * _nearPlane / -point.z));
739 }
740 
741 template <class T>
742 IMATH_CONSTEXPR14 T
743 Frustum<T>::ZToDepthExc (long zval, long zmin, long zmax) const
744 {
745  int zdiff = zmax - zmin;
746 
747  if (zdiff == 0)
748  {
749  throw std::domain_error ("Bad call to Frustum::ZToDepth: zmax == zmin");
750  }
751 
752  if (zval > zmax + 1) zval -= zdiff;
753 
754  T fzval = (T (zval) - T (zmin)) / T (zdiff);
755  return normalizedZToDepthExc (fzval);
756 }
757 
758 template <class T>
759 IMATH_CONSTEXPR14 T
760 Frustum<T>::ZToDepth (long zval, long zmin, long zmax) const IMATH_NOEXCEPT
761 {
762  int zdiff = zmax - zmin;
763 
764  if (zval > zmax + 1) zval -= zdiff;
765 
766  T fzval = (T (zval) - T (zmin)) / T (zdiff);
767  return normalizedZToDepth (fzval);
768 }
769 
770 template <class T>
771 IMATH_CONSTEXPR14 T
773 {
774  T Zp = zval * T (2) - T (1);
775 
776  if (_orthographic)
777  {
778  return -(Zp * (_farPlane - _nearPlane) + (_farPlane + _nearPlane)) /
779  T (2);
780  }
781  else
782  {
783  T farTimesNear = 2 * _farPlane * _nearPlane;
784  T farMinusNear = Zp * (_farPlane - _nearPlane) - _farPlane - _nearPlane;
785 
786  if (abs (farMinusNear) < 1 &&
787  abs (farTimesNear) >
788  std::numeric_limits<T>::max () * abs (farMinusNear))
789  {
790  throw std::domain_error (
791  "Frustum::normalizedZToDepth cannot be computed: "
792  "near and far clipping planes of the viewing frustum "
793  "may be too close to each other");
794  }
795 
796  return farTimesNear / farMinusNear;
797  }
798 }
799 
800 template <class T>
801 IMATH_CONSTEXPR14 T
803 {
804  T Zp = zval * T (2) - T (1);
805 
806  if (_orthographic)
807  {
808  return -(Zp * (_farPlane - _nearPlane) + (_farPlane + _nearPlane)) /
809  T (2);
810  }
811  else
812  {
813  T farTimesNear = 2 * _farPlane * _nearPlane;
814  T farMinusNear = Zp * (_farPlane - _nearPlane) - _farPlane - _nearPlane;
815 
816  return farTimesNear / farMinusNear;
817  }
818 }
819 
820 template <class T>
821 IMATH_CONSTEXPR14 long
822 Frustum<T>::DepthToZExc (T depth, long zmin, long zmax) const
823 {
824  long zdiff = zmax - zmin;
825  T farMinusNear = _farPlane - _nearPlane;
826 
827  if (_orthographic)
828  {
829  T farPlusNear = T (2) * depth + _farPlane + _nearPlane;
830 
831  if (abs (farMinusNear) < T (1) &&
832  abs (farPlusNear) >
833  std::numeric_limits<T>::max () * abs (farMinusNear))
834  {
835  throw std::domain_error ("Bad viewing frustum: "
836  "near and far clipping planes "
837  "are too close to each other");
838  }
839 
840  T Zp = -farPlusNear / farMinusNear;
841  return long (0.5 * (Zp + 1) * zdiff) + zmin;
842  }
843  else
844  {
845  // Perspective
846 
847  T farTimesNear = T (2) * _farPlane * _nearPlane;
848  if (abs (depth) < T (1) &&
849  abs (farTimesNear) > std::numeric_limits<T>::max () * abs (depth))
850  {
851  throw std::domain_error ("Bad call to DepthToZ function: "
852  "value of `depth' is too small");
853  }
854 
855  T farPlusNear = farTimesNear / depth + _farPlane + _nearPlane;
856  if (abs (farMinusNear) < T (1) &&
857  abs (farPlusNear) >
858  std::numeric_limits<T>::max () * abs (farMinusNear))
859  {
860  throw std::domain_error ("Bad viewing frustum: "
861  "near and far clipping planes "
862  "are too close to each other");
863  }
864 
865  T Zp = farPlusNear / farMinusNear;
866  return long (0.5 * (Zp + 1) * zdiff) + zmin;
867  }
868 }
869 
870 template <class T>
871 IMATH_CONSTEXPR14 long
872 Frustum<T>::DepthToZ (T depth, long zmin, long zmax) const IMATH_NOEXCEPT
873 {
874  long zdiff = zmax - zmin;
875  T farMinusNear = _farPlane - _nearPlane;
876 
877  if (_orthographic)
878  {
879  T farPlusNear = T (2) * depth + _farPlane + _nearPlane;
880 
881  T Zp = -farPlusNear / farMinusNear;
882  return long (0.5 * (Zp + 1) * zdiff) + zmin;
883  }
884  else
885  {
886  // Perspective
887 
888  T farTimesNear = T (2) * _farPlane * _nearPlane;
889 
890  T farPlusNear = farTimesNear / depth + _farPlane + _nearPlane;
891 
892  T Zp = farPlusNear / farMinusNear;
893  return long (0.5 * (Zp + 1) * zdiff) + zmin;
894  }
895 }
896 
897 template <class T>
898 IMATH_CONSTEXPR14 T
899 Frustum<T>::screenRadiusExc (const Vec3<T>& p, T radius) const
900 {
901  // Derivation:
902  // Consider X-Z plane.
903  // X coord of projection of p = xp = p.x * (-_nearPlane / p.z)
904  // Let q be p + (radius, 0, 0).
905  // X coord of projection of q = xq = (p.x - radius) * (-_nearPlane / p.z)
906  // X coord of projection of segment from p to q = r = xp - xq
907  // = radius * (-_nearPlane / p.z)
908  // A similar analysis holds in the Y-Z plane.
909  // So r is the quantity we want to return.
910 
911  if (abs (p.z) > T (1) ||
912  abs (-_nearPlane) < std::numeric_limits<T>::max () * abs (p.z))
913  {
914  return radius * (-_nearPlane / p.z);
915  }
916  else
917  {
918  throw std::domain_error ("Bad call to Frustum::screenRadius: "
919  "magnitude of `p' is too small");
920  }
921 
922  return radius * (-_nearPlane / p.z);
923 }
924 
925 template <class T>
926 IMATH_CONSTEXPR14 T
928 {
929  // Derivation:
930  // Consider X-Z plane.
931  // X coord of projection of p = xp = p.x * (-_nearPlane / p.z)
932  // Let q be p + (radius, 0, 0).
933  // X coord of projection of q = xq = (p.x - radius) * (-_nearPlane / p.z)
934  // X coord of projection of segment from p to q = r = xp - xq
935  // = radius * (-_nearPlane / p.z)
936  // A similar analysis holds in the Y-Z plane.
937  // So r is the quantity we want to return.
938 
939  return radius * (-_nearPlane / p.z);
940 }
941 
942 template <class T>
943 IMATH_CONSTEXPR14 T
944 Frustum<T>::worldRadiusExc (const Vec3<T>& p, T radius) const
945 {
946  if (abs (-_nearPlane) > T (1) ||
947  abs (p.z) < std::numeric_limits<T>::max () * abs (-_nearPlane))
948  {
949  return radius * (p.z / -_nearPlane);
950  }
951  else
952  {
953  throw std::domain_error ("Bad viewing frustum: "
954  "near clipping plane is too close to zero");
955  }
956 }
957 
958 template <class T>
959 IMATH_CONSTEXPR14 T
961 {
962  return radius * (p.z / -_nearPlane);
963 }
964 
965 template <class T>
966 void
968 {
969  //
970  // Plane order: Top, Right, Bottom, Left, Near, Far.
971  // Normals point outwards.
972  //
973 
974  if (!_orthographic)
975  {
976  Vec3<T> a (_left, _bottom, -_nearPlane);
977  Vec3<T> b (_left, _top, -_nearPlane);
978  Vec3<T> c (_right, _top, -_nearPlane);
979  Vec3<T> d (_right, _bottom, -_nearPlane);
980  Vec3<T> o (0, 0, 0);
981 
982  p[0].set (o, c, b);
983  p[1].set (o, d, c);
984  p[2].set (o, a, d);
985  p[3].set (o, b, a);
986  }
987  else
988  {
989  p[0].set (Vec3<T> (0, 1, 0), _top);
990  p[1].set (Vec3<T> (1, 0, 0), _right);
991  p[2].set (Vec3<T> (0, -1, 0), -_bottom);
992  p[3].set (Vec3<T> (-1, 0, 0), -_left);
993  }
994  p[4].set (Vec3<T> (0, 0, 1), -_nearPlane);
995  p[5].set (Vec3<T> (0, 0, -1), _farPlane);
996 }
997 
998 template <class T>
999 void
1001 {
1002  //
1003  // Plane order: Top, Right, Bottom, Left, Near, Far.
1004  // Normals point outwards.
1005  //
1006 
1007  Vec3<T> a = Vec3<T> (_left, _bottom, -_nearPlane) * M;
1008  Vec3<T> b = Vec3<T> (_left, _top, -_nearPlane) * M;
1009  Vec3<T> c = Vec3<T> (_right, _top, -_nearPlane) * M;
1010  Vec3<T> d = Vec3<T> (_right, _bottom, -_nearPlane) * M;
1011  if (!_orthographic)
1012  {
1013  double s = _farPlane / double (_nearPlane);
1014  T farLeft = (T) (s * _left);
1015  T farRight = (T) (s * _right);
1016  T farTop = (T) (s * _top);
1017  T farBottom = (T) (s * _bottom);
1018  Vec3<T> e = Vec3<T> (farLeft, farBottom, -_farPlane) * M;
1019  Vec3<T> f = Vec3<T> (farLeft, farTop, -_farPlane) * M;
1020  Vec3<T> g = Vec3<T> (farRight, farTop, -_farPlane) * M;
1021  Vec3<T> o = Vec3<T> (0, 0, 0) * M;
1022  p[0].set (o, c, b);
1023  p[1].set (o, d, c);
1024  p[2].set (o, a, d);
1025  p[3].set (o, b, a);
1026  p[4].set (a, d, c);
1027  p[5].set (e, f, g);
1028  }
1029  else
1030  {
1031  Vec3<T> e = Vec3<T> (_left, _bottom, -_farPlane) * M;
1032  Vec3<T> f = Vec3<T> (_left, _top, -_farPlane) * M;
1033  Vec3<T> g = Vec3<T> (_right, _top, -_farPlane) * M;
1034  Vec3<T> h = Vec3<T> (_right, _bottom, -_farPlane) * M;
1035  p[0].set (c, g, f);
1036  p[1].set (d, h, g);
1037  p[2].set (a, e, h);
1038  p[3].set (b, f, e);
1039  p[4].set (a, d, c);
1040  p[5].set (e, f, g);
1041  }
1042 }
1043 
1044 /// Frustum of type float
1046 
1047 /// Frustum of type double
1049 
1050 IMATH_INTERNAL_NAMESPACE_HEADER_EXIT
1051 
1052 #if defined _WIN32 || defined _WIN64
1053 # ifdef _redef_near
1054 # define near
1055 # endif
1056 # ifdef _redef_far
1057 # define far
1058 # endif
1059 #endif
1060 
1061 #endif // INCLUDED_IMATHFRUSTUM_H
IMATH_HOSTDEVICE constexpr T hither() const IMATH_NOEXCEPT
Return the near clipping plane.
Definition: ImathFrustum.h:108
T z
Definition: ImathVec.h:368
IMATH_CONSTEXPR14 T screenRadiusExc(const Vec3< T > &p, T radius) const
Compute screen radius. Throw an exception on error.
Definition: ImathFrustum.h:899
IMATH_HOSTDEVICE constexpr bool operator!=(const Frustum< T > &src) const IMATH_NOEXCEPT
Inequality.
Definition: ImathFrustum.h:355
#define IMATH_NOEXCEPT
Definition: ImathConfig.h:78
IMATH_HOSTDEVICE IMATH_CONSTEXPR14 bool intersect(const Line3< T > &line, Vec3< T > &intersection) const IMATH_NOEXCEPT
Definition: ImathPlane.h:203
Definition: ImathVec.h:40
*get result *(waiting if necessary)*A common idiom is to fire a bunch of sub tasks at the and then *wait for them to all complete We provide a helper class
Definition: thread.h:632
IMATH_HOSTDEVICE void set(T nearPlane, T farPlane, T left, T right, T top, T bottom, bool ortho=false) IMATH_NOEXCEPT
Set functions change the entire state of the Frustum.
Definition: ImathFrustum.h:362
IMATH_HOSTDEVICE void setOrthographic(bool) IMATH_NOEXCEPT
Set the ortographic state.
Definition: ImathFrustum.h:404
GLint left
Definition: glcorearb.h:2005
IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Vec2< T > localToScreen(const Vec2< T > &) const IMATH_NOEXCEPT
Map point from local space to screen space.
Definition: ImathFrustum.h:695
GLdouble right
Definition: glad.h:2817
GLboolean GLboolean g
Definition: glcorearb.h:1222
IMATH_HOSTDEVICE constexpr T fovx() const IMATH_NOEXCEPT
Return the field of view in X.
Definition: ImathFrustum.h:465
GLboolean GLboolean GLboolean GLboolean a
Definition: glcorearb.h:1222
GLdouble s
Definition: glad.h:3009
IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Frustum & operator=(const Frustum &) IMATH_NOEXCEPT
Component-wise assignment.
Definition: ImathFrustum.h:331
ImageBuf OIIO_API min(Image_or_Const A, Image_or_Const B, ROI roi={}, int nthreads=0)
IMATH_HOSTDEVICE constexpr bool operator==(const Frustum< T > &src) const IMATH_NOEXCEPT
Equality.
Definition: ImathFrustum.h:346
#define IMATH_HOSTDEVICE
Definition: ImathConfig.h:108
IMATH_CONSTEXPR14 T normalizedZToDepthExc(T zval) const
Definition: ImathFrustum.h:772
IMATH_HOSTDEVICE constexpr bool degenerate() const IMATH_NOEXCEPT
Return true if the frustum is degenerate.
Definition: ImathFrustum.h:641
IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Vec2< T > projectPointToScreen(const Vec3< T > &) const IMATH_NOEXCEPT
Project a 3D point into screen coordinates.
Definition: ImathFrustum.h:732
bool operator==(const BaseDimensions< T > &a, const BaseDimensions< Y > &b)
Definition: Dimensions.h:137
GLdouble n
Definition: glcorearb.h:2008
GLfloat f
Definition: glcorearb.h:1926
T x
Definition: ImathVec.h:59
T x
Definition: ImathVec.h:368
IMATH_HOSTDEVICE constexpr T left() const IMATH_NOEXCEPT
Return the left of the frustum.
Definition: ImathFrustum.h:126
constexpr auto set(type rhs) -> int
Definition: core.h:610
T y
Definition: ImathVec.h:59
IMATH_HOSTDEVICE constexpr T nearPlane() const IMATH_NOEXCEPT
Return the near clipping plane.
Definition: ImathFrustum.h:102
IMATH_HOSTDEVICE constexpr Vec2< T > screenToLocal(const Vec2< T > &) const IMATH_NOEXCEPT
Map point from screen space to local space.
Definition: ImathFrustum.h:661
IMATH_HOSTDEVICE IMATH_CONSTEXPR14 IMATH_HOSTDEVICE Frustum< T > window(T left, T right, T top, T bottom) const IMATH_NOEXCEPT
Definition: ImathFrustum.h:648
Frustum< double > Frustumd
Frustum of type double.
IMATH_HOSTDEVICE IMATH_CONSTEXPR14 T normalizedZToDepth(T zval) const IMATH_NOEXCEPT
Map a normalized z value to its depth in the frustum.
Definition: ImathFrustum.h:802
Frustum< float > Frustumf
Frustum of type float.
IMATH_CONSTEXPR14 Vec2< T > localToScreenExc(const Vec2< T > &) const
Definition: ImathFrustum.h:670
IMATH_HOSTDEVICE constexpr T bottom() const IMATH_NOEXCEPT
Return the bottom of the frustum.
Definition: ImathFrustum.h:135
IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Frustum() IMATH_NOEXCEPT
Definition: ImathFrustum.h:301
GLboolean GLboolean GLboolean b
Definition: glcorearb.h:1222
IMATH_CONSTEXPR14 long DepthToZExc(T depth, long zmin, long zmax) const
Map depth to z value. Throw an exception on error.
Definition: ImathFrustum.h:822
GLdouble t
Definition: glad.h:2397
IMATH_CONSTEXPR14 Matrix44< T > projectionMatrixExc() const
Definition: ImathFrustum.h:506
GLint GLint GLsizei GLsizei GLsizei depth
Definition: glcorearb.h:476
GLint GLint bottom
Definition: glcorearb.h:2005
IMATH_HOSTDEVICE IMATH_CONSTEXPR14 T screenRadius(const Vec3< T > &p, T radius) const IMATH_NOEXCEPT
Compute screen radius.
Definition: ImathFrustum.h:927
IMATH_HOSTDEVICE void planes(Plane3< T > p[6]) const IMATH_NOEXCEPT
Definition: ImathFrustum.h:967
GLfloat GLfloat GLfloat GLfloat h
Definition: glcorearb.h:2002
IMATH_CONSTEXPR14 Vec2< T > projectPointToScreenExc(const Vec3< T > &) const
Definition: ImathFrustum.h:721
T value_type
Definition: ImathFrustum.h:43
Definition: ImathVec.h:39
IMATH_HOSTDEVICE constexpr T top() const IMATH_NOEXCEPT
Return the top of the frustum.
Definition: ImathFrustum.h:141
IMATH_HOSTDEVICE constexpr T yon() const IMATH_NOEXCEPT
Return the far clipping plane.
Definition: ImathFrustum.h:120
IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Line3< T > projectScreenToRay(const Vec2< T > &) const IMATH_NOEXCEPT
Project a point in screen spaced to 3d ray.
Definition: ImathFrustum.h:708
#define IMATH_EXPORT_TEMPLATE_TYPE
Definition: ImathExport.h:61
ImageBuf OIIO_API max(Image_or_Const A, Image_or_Const B, ROI roi={}, int nthreads=0)
IMATH_HOSTDEVICE IMATH_CONSTEXPR14 long DepthToZ(T depth, long zmin, long zmax) const IMATH_NOEXCEPT
Map depth to z value.
Definition: ImathFrustum.h:872
IMATH_HOSTDEVICE IMATH_CONSTEXPR14 T ZToDepth(long zval, long min, long max) const IMATH_NOEXCEPT
Map a z value to its depth in the frustum.
Definition: ImathFrustum.h:760
GLdouble GLdouble GLdouble top
Definition: glad.h:2817
IMATH_HOSTDEVICE constexpr T fovy() const IMATH_NOEXCEPT
Return the field of view in Y.
Definition: ImathFrustum.h:472
T y
Definition: ImathVec.h:368
IMATH_CONSTEXPR14 T aspectExc() const
Definition: ImathFrustum.h:479
IMATH_INTERNAL_NAMESPACE_HEADER_ENTER IMATH_HOSTDEVICE constexpr T abs(T a) IMATH_NOEXCEPT
Definition: ImathFun.h:26
IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Matrix44< T > projectionMatrix() const IMATH_NOEXCEPT
Return the project matrix that the frustum defines.
Definition: ImathFrustum.h:596
GLboolean r
Definition: glcorearb.h:1222
virtual ~Frustum() IMATH_NOEXCEPT
Destructor.
Definition: ImathFrustum.h:326
IMATH_HOSTDEVICE IMATH_CONSTEXPR14 T aspect() const IMATH_NOEXCEPT
Return the aspect ratio.
Definition: ImathFrustum.h:497
IMATH_CONSTEXPR14 T worldRadiusExc(const Vec3< T > &p, T radius) const
Compute worldRadius. Throw an exception on error.
Definition: ImathFrustum.h:944
IMATH_HOSTDEVICE void modifyNearAndFar(T nearPlane, T farPlane) IMATH_NOEXCEPT
Set the near and far clipping planes.
Definition: ImathFrustum.h:375
IMATH_HOSTDEVICE constexpr T right() const IMATH_NOEXCEPT
Return the right of the frustum.
Definition: ImathFrustum.h:129
void setExc(T nearPlane, T farPlane, T fovx, T fovy, T aspect)
Definition: ImathFrustum.h:411
IMATH_HOSTDEVICE constexpr T farPlane() const IMATH_NOEXCEPT
Return the far clipping plane.
Definition: ImathFrustum.h:114
IMATH_CONSTEXPR14 T ZToDepthExc(long zval, long min, long max) const
Map a z value to its depth in the frustum.
Definition: ImathFrustum.h:743
IMATH_HOSTDEVICE IMATH_CONSTEXPR14 T worldRadius(const Vec3< T > &p, T radius) const IMATH_NOEXCEPT
Compute worldRadius.
Definition: ImathFrustum.h:960
GLenum src
Definition: glcorearb.h:1793