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