All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
frustum.h
Go to the documentation of this file.
1 //
2 // Copyright 2016 Pixar
3 //
4 // Licensed under the Apache License, Version 2.0 (the "Apache License")
5 // with the following modification; you may not use this file except in
6 // compliance with the Apache License and the following modification to it:
7 // Section 6. Trademarks. is deleted and replaced with:
8 //
9 // 6. Trademarks. This License does not grant permission to use the trade
10 // names, trademarks, service marks, or product names of the Licensor
11 // and its affiliates, except as required to comply with Section 4(c) of
12 // the License and to reproduce the content of the NOTICE file.
13 //
14 // You may obtain a copy of the Apache License at
15 //
16 // http://www.apache.org/licenses/LICENSE-2.0
17 //
18 // Unless required by applicable law or agreed to in writing, software
19 // distributed under the Apache License with the above modification is
20 // distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
21 // KIND, either express or implied. See the Apache License for the specific
22 // language governing permissions and limitations under the Apache License.
23 //
24 #ifndef PXR_BASE_GF_FRUSTUM_H
25 #define PXR_BASE_GF_FRUSTUM_H
26 
29 
30 #include "pxr/pxr.h"
31 #include "pxr/base/gf/bbox3d.h"
32 #include "pxr/base/gf/matrix4d.h"
33 #include "pxr/base/gf/plane.h"
34 #include "pxr/base/gf/ray.h"
35 #include "pxr/base/gf/range1d.h"
36 #include "pxr/base/gf/range2d.h"
37 #include "pxr/base/gf/rotation.h"
38 #include "pxr/base/gf/vec2d.h"
39 #include "pxr/base/gf/vec3d.h"
40 #include "pxr/base/gf/api.h"
41 
42 #include <boost/functional/hash.hpp>
43 
44 #include <array>
45 #include <atomic>
46 #include <iosfwd>
47 #include <vector>
48 
49 PXR_NAMESPACE_OPEN_SCOPE
50 
89 class GfFrustum {
90  public:
96  };
97 
106  GF_API GfFrustum();
107 
110  : _position(o._position)
111  , _rotation(o._rotation)
112  , _window(o._window)
113  , _nearFar(o._nearFar)
114  , _viewDistance(o._viewDistance)
115  , _projectionType(o._projectionType)
116  , _planes(nullptr) {
117  if (auto *planes = o._planes.load()) {
118  _planes = new std::array<GfPlane, 6>(*planes);
119  }
120  }
121 
123  GfFrustum(GfFrustum &&o) noexcept
124  : _position(o._position)
125  , _rotation(o._rotation)
126  , _window(o._window)
127  , _nearFar(o._nearFar)
128  , _viewDistance(o._viewDistance)
129  , _projectionType(o._projectionType)
130  , _planes(nullptr) {
131  if (auto *planes =
132  o._planes.exchange(nullptr, std::memory_order_relaxed)) {
133  _planes = planes;
134  }
135  }
136 
139  GF_API GfFrustum(const GfVec3d &position, const GfRotation &rotation,
140  const GfRange2d &window, const GfRange1d &nearFar,
141  GfFrustum::ProjectionType projectionType,
142  double viewDistance = 5.0);
143 
147  GF_API GfFrustum(const GfMatrix4d &camToWorldXf,
148  const GfRange2d &window, const GfRange1d &nearFar,
149  GfFrustum::ProjectionType projectionType,
150  double viewDistance = 5.0);
151 
153  GfFrustum &operator=(GfFrustum const &o) noexcept {
154  if (this == &o) {
155  return *this;
156  }
157  _position = o._position;
158  _rotation = o._rotation;
159  _window = o._window;
160  _nearFar = o._nearFar;
161  _viewDistance = o._viewDistance;
162  _projectionType = o._projectionType;
163  delete _planes.load(std::memory_order_relaxed);
164  if (auto *planes = o._planes.load(std::memory_order_relaxed)) {
165  _planes.store(new std::array<GfPlane, 6>(*planes),
166  std::memory_order_relaxed);
167  }
168  else {
169  _planes.store(nullptr, std::memory_order_relaxed);
170  }
171  return *this;
172  }
173 
175  GfFrustum &operator=(GfFrustum &&o) noexcept {
176  if (this == &o) {
177  return *this;
178  }
179  _position = o._position;
180  _rotation = o._rotation;
181  _window = o._window;
182  _nearFar = o._nearFar;
183  _viewDistance = o._viewDistance;
184  _projectionType = o._projectionType;
185  delete _planes.load(std::memory_order_relaxed);
186  _planes.store(o._planes.load(std::memory_order_relaxed),
187  std::memory_order_relaxed);
188  o._planes.store(nullptr, std::memory_order_relaxed);
189  return *this;
190  }
191 
192  friend inline size_t hash_value(const GfFrustum &f) {
193  size_t h = 0;
194  boost::hash_combine(h, f._position);
195  boost::hash_combine(h, f._rotation);
196  boost::hash_combine(h, f._window);
197  boost::hash_combine(h, f._nearFar);
198  boost::hash_combine(h, f._viewDistance);
199  boost::hash_combine(h, f._projectionType);
200  return h;
201  }
202 
203  // Equality operator. true iff all parts match.
204  bool operator ==(const GfFrustum& f) const {
205  if (_position != f._position) return false;
206  if (_rotation != f._rotation) return false;
207  if (_window != f._window) return false;
208  if (_nearFar != f._nearFar) return false;
209  if (_viewDistance != f._viewDistance) return false;
210  if (_projectionType != f._projectionType) return false;
211 
212  return true;
213  }
214 
215  // Inequality operator. true iff not equality.
216  bool operator !=(const GfFrustum& f) const {
217  return !(*this == f);
218  }
219 
221  GF_API ~GfFrustum();
222 
227 
229  void SetPosition(const GfVec3d &position) {
230  _position = position;
231  _DirtyFrustumPlanes();
232  }
233 
235  const GfVec3d & GetPosition() const {
236  return _position;
237  }
238 
242  void SetRotation(const GfRotation &rotation) {
243  _rotation = rotation;
244  _DirtyFrustumPlanes();
245  }
246 
249  const GfRotation & GetRotation() const {
250  return _rotation;
251  }
252 
258  GF_API void SetPositionAndRotationFromMatrix(const GfMatrix4d &camToWorldXf);
259 
262  void SetWindow(const GfRange2d &window) {
263  _window = window;
264  _DirtyFrustumPlanes();
265  }
266 
268  const GfRange2d & GetWindow() const {
269  return _window;
270  }
271 
273  static double GetReferencePlaneDepth() {
274  return 1.0;
275  }
276 
278  void SetNearFar(const GfRange1d &nearFar) {
279  _nearFar = nearFar;
280  _DirtyFrustumPlanes();
281  }
282 
284  const GfRange1d & GetNearFar() const {
285  return _nearFar;
286  }
287 
289  void SetViewDistance(double viewDistance) {
290  _viewDistance = viewDistance;
291  }
292 
294  double GetViewDistance() const {
295  return _viewDistance;
296  }
297 
300  _projectionType = projectionType;
301  _DirtyFrustumPlanes();
302  }
303 
306  return _projectionType;
307  }
308 
310 
318 
336  GF_API void SetPerspective(double fieldOfViewHeight,
337  double aspectRatio,
338  double nearDistance, double farDistance);
339 
367  GF_API void SetPerspective(double fieldOfView,
368  bool isFovVertical,
369  double aspectRatio,
370  double nearDistance, double farDistance);
371 
375  GF_API bool GetPerspective(double *fieldOfViewHeight,
376  double *aspectRatio,
377  double *nearDistance,
378  double *farDistance) const;
379 
383  GF_API bool GetPerspective(bool isFovVertical,
384  double *fieldOfView,
385  double *aspectRatio,
386  double *nearDistance,
387  double *farDistance) const;
388 
400  GF_API double GetFOV(bool isFovVertical = false);
401 
406  GF_API
407  void SetOrthographic(double left, double right,
408  double bottom, double top,
409  double nearPlane, double farPlane);
410 
414  GF_API bool GetOrthographic(double *left, double *right,
415  double *bottom, double *top,
416  double *nearPlane, double *farPlane)
417  const;
418 
424  GF_API void FitToSphere(const GfVec3d &center,
425  double radius,
426  double slack = 0.0);
427 
441  GF_API GfFrustum& Transform(const GfMatrix4d &matrix);
442 
445  GF_API GfVec3d ComputeViewDirection() const;
446 
449  GF_API GfVec3d ComputeUpVector() const;
450 
464  GF_API void ComputeViewFrame(GfVec3d *side,
465  GfVec3d *up,
466  GfVec3d *view) const;
467 
470  GF_API GfVec3d ComputeLookAtPoint() const;
471 
475  GF_API GfMatrix4d ComputeViewMatrix() const;
476 
480  GF_API GfMatrix4d ComputeViewInverse() const;
481 
484  GF_API GfMatrix4d ComputeProjectionMatrix() const;
485 
489  GF_API double ComputeAspectRatio() const;
490 
501  GF_API
502  std::vector<GfVec3d> ComputeCorners() const;
503 
513  GF_API
514  std::vector<GfVec3d> ComputeCornersAtDistance(double d) const;
515 
529  GF_API GfFrustum ComputeNarrowedFrustum(const GfVec2d &point,
530  const GfVec2d &halfSize) const;
531 
545  GF_API GfFrustum ComputeNarrowedFrustum(const GfVec3d &worldPoint,
546  const GfVec2d &halfSize) const;
547 
555  GF_API GfRay ComputeRay(const GfVec2d &windowPos) const;
556 
563  GF_API GfRay ComputeRay(const GfVec3d &worldSpacePos) const;
564 
571  GF_API GfRay ComputePickRay(const GfVec2d &windowPos) const;
572 
575  GF_API GfRay ComputePickRay(const GfVec3d &worldSpacePos) const;
576 
578 
585 
589  GF_API bool Intersects(const GfBBox3d &bbox) const;
590 
593  GF_API bool Intersects(const GfVec3d &point) const;
594 
597  GF_API bool Intersects(const GfVec3d &p0,
598  const GfVec3d &p1) const;
599 
602  GF_API bool Intersects(const GfVec3d &p0,
603  const GfVec3d &p1,
604  const GfVec3d &p2) const;
605 
617  GF_API static bool IntersectsViewVolume(const GfBBox3d &bbox,
618  const GfMatrix4d &vpMat);
619 
621 
622  private:
623  // Dirty the result of _CalculateFrustumPlanes.
624  GF_API void _DirtyFrustumPlanes();
625 
626  // Calculates cached frustum planes used for intersection tests.
627  GF_API void _CalculateFrustumPlanes() const;
628 
629  // Builds and returns a \c GfRay that can be used for picking. Given an
630  // eye position and direction in camera space, offsets the ray to emanate
631  // from the near plane, then transforms into worldspace
632  GF_API GfRay _ComputePickRayOffsetToNearPlane(
633  const GfVec3d &camSpaceFrom,
634  const GfVec3d &camSpaceDir) const;
635 
636  // Returns a frustum that is a narrowed-down version of this frustum, such
637  // that the frustum rectangle on the near plane encloses \p point with at
638  // most \p halfSize[0] distance on the left and right and at most \p
639  // halfSize[1] distance on the top and bottom. (If \p point is closer than
640  // the half size to a side of the frustum, that side is left alone. The
641  // point and sizes are in normalized 2D coordinates; they range from (-1,
642  // -1) at the lower left corner of the near-plane window rectangle to
643  // (1,1) at the upper right corner.
644  //
645  // \p windowPoint is expressed in window coordinates
646  //
647  // This method is useful for computing a volume to use for interactive
648  // picking.
649  GfFrustum _ComputeNarrowedFrustumSub(const GfVec2d windowPoint,
650  const GfVec2d &halfSize) const;
651 
652  bool _SegmentIntersects(GfVec3d const &p0, uint32_t p0Mask,
653  GfVec3d const &p1, uint32_t p1Mask) const;
654 
655  // Position of the frustum in world space.
656  GfVec3d _position;
657 
658  // Orientation of the frustum in world space as a rotation to apply to the
659  // -z axis.
660  GfRotation _rotation;
661 
662  // Window rectangle in the image plane.
663  GfRange2d _window;
664 
665  // Near/far interval.
666  GfRange1d _nearFar;
667 
668  // View distance.
669  double _viewDistance;
670 
671  // Projection type.
672  ProjectionType _projectionType;
673 
674  // Cached planes.
675  // If null, the planes have not been calculated.
676  mutable std::atomic<std::array<GfPlane, 6> *> _planes;
677 };
678 
686 GF_API std::ostream& operator<<(std::ostream& out, const GfFrustum& f);
687 
688 PXR_NAMESPACE_CLOSE_SCOPE
689 
690 #endif // PXR_BASE_GF_FRUSTUM_H
GF_API GfVec3d ComputeViewDirection() const
Returns the normalized world-space view direction vector, which is computed by rotating the -z axis b...
GF_API GfMatrix4d ComputeViewInverse() const
Returns a matrix that represents the inverse viewing transformation for this frustum.
GfFrustum::ProjectionType GetProjectionType() const
Returns the projection type.
Definition: frustum.h:305
double GetViewDistance() const
Returns the view distance.
Definition: frustum.h:294
GF_API GfVec3d ComputeLookAtPoint() const
Computes and returns the world-space look-at point from the eye point (position), view direction (rot...
void SetProjectionType(GfFrustum::ProjectionType projectionType)
Sets the projection type.
Definition: frustum.h:299
const GfVec3d & GetPosition() const
Returns the position of the frustum in world space.
Definition: frustum.h:235
Basic type: 1-dimensional floating point range.
Definition: range1d.h:62
GF_API void FitToSphere(const GfVec3d &center, double radius, double slack=0.0)
Modifies the frustum to tightly enclose a sphere with the given center and radius, using the current view direction.
const GfRotation & GetRotation() const
Returns the orientation of the frustum in world space as a rotation to apply to the -z axis...
Definition: frustum.h:249
GF_API GfFrustum & Transform(const GfMatrix4d &matrix)
Transforms the frustum by the given matrix.
GF_API bool GetPerspective(double *fieldOfViewHeight, double *aspectRatio, double *nearDistance, double *farDistance) const
Returns the current frustum in the format used by SetPerspective().
Basic type for a vector of 2 double components.
Definition: vec2d.h:63
GF_API std::vector< GfVec3d > ComputeCornersAtDistance(double d) const
Returns the world-space corners of the intersection of the frustum with a plane parallel to the near/...
GF_API void SetOrthographic(double left, double right, double bottom, double top, double nearPlane, double farPlane)
Sets up the frustum in a manner similar to glOrtho().
GF_API void SetPositionAndRotationFromMatrix(const GfMatrix4d &camToWorldXf)
Sets the position and rotation of the frustum from a camera matrix (always from a y-Up camera)...
static GF_API bool IntersectsViewVolume(const GfBBox3d &bbox, const GfMatrix4d &vpMat)
Returns true if the bbox volume intersects the view volume given by the view-projection matrix...
GF_API GfFrustum ComputeNarrowedFrustum(const GfVec2d &point, const GfVec2d &halfSize) const
Returns a frustum that is a narrowed-down version of this frustum, such that the frustum rectangle on...
GF_API double ComputeAspectRatio() const
Returns the aspect ratio of the frustum, defined as the width of the window divided by the height...
void SetWindow(const GfRange2d &window)
Sets the window rectangle in the reference plane that defines the left, right, top, and bottom planes of the frustum.
Definition: frustum.h:262
void SetViewDistance(double viewDistance)
Sets the view distance.
Definition: frustum.h:289
GF_API GfMatrix4d ComputeViewMatrix() const
Returns a matrix that represents the viewing transformation for this frustum.
Stores a 4x4 matrix of double elements.
Definition: matrix4d.h:88
GF_API double GetFOV(bool isFovVertical=false)
Returns the horizontal or vertical fov of the frustum.
Basic type: 2-dimensional floating point range.
Definition: range2d.h:64
Basic type: View frustum.
Definition: frustum.h:89
GF_API void SetPerspective(double fieldOfViewHeight, double aspectRatio, double nearDistance, double farDistance)
Sets up the frustum in a manner similar to gluPerspective().
GF_API GfRay ComputeRay(const GfVec2d &windowPos) const
Builds and returns a GfRay that starts at the viewpoint and extends through the given windowPos given...
Perspective projection.
Definition: frustum.h:95
GF_API void ComputeViewFrame(GfVec3d *side, GfVec3d *up, GfVec3d *view) const
Computes the view frame defined by this frustum.
GF_API bool Intersects(const GfBBox3d &bbox) const
Returns true if the given axis-aligned bbox is inside or intersecting the frustum.
GfFrustum & operator=(GfFrustum &&o) noexcept
Move assignment.
Definition: frustum.h:175
GfFrustum(GfFrustum const &o)
Copy constructor.
Definition: frustum.h:109
void SetNearFar(const GfRange1d &nearFar)
Sets the near/far interval.
Definition: frustum.h:278
ProjectionType
This enum is used to determine the type of projection represented by a frustum.
Definition: frustum.h:93
GfFrustum(GfFrustum &&o) noexcept
Move constructor.
Definition: frustum.h:123
GF_API std::ostream & operator<<(std::ostream &, const GfBBox3d &)
Output a GfBBox3d using the format [(range) matrix zeroArea].
GF_API ~GfFrustum()
Destructor.
GF_API GfFrustum()
This constructor creates an instance with default viewing parameters:
GfFrustum & operator=(GfFrustum const &o) noexcept
Copy assignment.
Definition: frustum.h:153
void SetPosition(const GfVec3d &position)
Sets the position of the frustum in world space.
Definition: frustum.h:229
Basic type for a vector of 3 double components.
Definition: vec3d.h:63
Basic type: Ray used for intersection testing.
Definition: ray.h:61
GF_API GfRay ComputePickRay(const GfVec2d &windowPos) const
Builds and returns a GfRay that can be used for picking at the given normalized (-1 to +1 in both dim...
static double GetReferencePlaneDepth()
Returns the depth of the reference plane.
Definition: frustum.h:273
const GfRange2d & GetWindow() const
Returns the window rectangle in the reference plane.
Definition: frustum.h:268
const GfRange1d & GetNearFar() const
Returns the near/far interval.
Definition: frustum.h:284
GF_API bool GetOrthographic(double *left, double *right, double *bottom, double *top, double *nearPlane, double *farPlane) const
Returns the current frustum in the format used by SetOrthographic().
Basic type: 3-space rotation specification.
Definition: rotation.h:55
GF_API GfVec3d ComputeUpVector() const
Returns the normalized world-space up vector, which is computed by rotating the y axis by the frustum...
Basic type: arbitrarily oriented 3D bounding box.
Definition: bbox3d.h:84
void SetRotation(const GfRotation &rotation)
Sets the orientation of the frustum in world space as a rotation to apply to the default frame: looki...
Definition: frustum.h:242
GF_API std::vector< GfVec3d > ComputeCorners() const
Returns the world-space corners of the frustum as a vector of 8 points, ordered as: ...
Orthographic projection.
Definition: frustum.h:94
GF_API GfMatrix4d ComputeProjectionMatrix() const
Returns a GL-style projection matrix corresponding to the frustum&#39;s projection.