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 #include "pxr/base/tf/hash.h"
42 
43 #include <array>
44 #include <atomic>
45 #include <iosfwd>
46 #include <vector>
47 
48 PXR_NAMESPACE_OPEN_SCOPE
49 
88 class GfFrustum {
89  public:
95  };
96 
105  GF_API GfFrustum();
106 
109  : _position(o._position)
110  , _rotation(o._rotation)
111  , _window(o._window)
112  , _nearFar(o._nearFar)
113  , _viewDistance(o._viewDistance)
114  , _projectionType(o._projectionType)
115  , _planes(nullptr) {
116  if (auto *planes = o._planes.load()) {
117  _planes = new std::array<GfPlane, 6>(*planes);
118  }
119  }
120 
122  GfFrustum(GfFrustum &&o) noexcept
123  : _position(o._position)
124  , _rotation(o._rotation)
125  , _window(o._window)
126  , _nearFar(o._nearFar)
127  , _viewDistance(o._viewDistance)
128  , _projectionType(o._projectionType)
129  , _planes(nullptr) {
130  if (auto *planes =
131  o._planes.exchange(nullptr, std::memory_order_relaxed)) {
132  _planes = planes;
133  }
134  }
135 
138  GF_API GfFrustum(const GfVec3d &position, const GfRotation &rotation,
139  const GfRange2d &window, const GfRange1d &nearFar,
140  GfFrustum::ProjectionType projectionType,
141  double viewDistance = 5.0);
142 
146  GF_API GfFrustum(const GfMatrix4d &camToWorldXf,
147  const GfRange2d &window, const GfRange1d &nearFar,
148  GfFrustum::ProjectionType projectionType,
149  double viewDistance = 5.0);
150 
152  GfFrustum &operator=(GfFrustum const &o) noexcept {
153  if (this == &o) {
154  return *this;
155  }
156  _position = o._position;
157  _rotation = o._rotation;
158  _window = o._window;
159  _nearFar = o._nearFar;
160  _viewDistance = o._viewDistance;
161  _projectionType = o._projectionType;
162  delete _planes.load(std::memory_order_relaxed);
163  if (auto *planes = o._planes.load(std::memory_order_relaxed)) {
164  _planes.store(new std::array<GfPlane, 6>(*planes),
165  std::memory_order_relaxed);
166  }
167  else {
168  _planes.store(nullptr, std::memory_order_relaxed);
169  }
170  return *this;
171  }
172 
174  GfFrustum &operator=(GfFrustum &&o) noexcept {
175  if (this == &o) {
176  return *this;
177  }
178  _position = o._position;
179  _rotation = o._rotation;
180  _window = o._window;
181  _nearFar = o._nearFar;
182  _viewDistance = o._viewDistance;
183  _projectionType = o._projectionType;
184  delete _planes.load(std::memory_order_relaxed);
185  _planes.store(o._planes.load(std::memory_order_relaxed),
186  std::memory_order_relaxed);
187  o._planes.store(nullptr, std::memory_order_relaxed);
188  return *this;
189  }
190 
191  friend inline size_t hash_value(const GfFrustum &f) {
192  return TfHash::Combine(
193  f._position,
194  f._rotation,
195  f._window,
196  f._nearFar,
197  f._viewDistance,
198  f._projectionType
199  );
200  }
201 
202  // Equality operator. true iff all parts match.
203  bool operator ==(const GfFrustum& f) const {
204  if (_position != f._position) return false;
205  if (_rotation != f._rotation) return false;
206  if (_window != f._window) return false;
207  if (_nearFar != f._nearFar) return false;
208  if (_viewDistance != f._viewDistance) return false;
209  if (_projectionType != f._projectionType) return false;
210 
211  return true;
212  }
213 
214  // Inequality operator. true iff not equality.
215  bool operator !=(const GfFrustum& f) const {
216  return !(*this == f);
217  }
218 
220  GF_API ~GfFrustum();
221 
226 
228  void SetPosition(const GfVec3d &position) {
229  _position = position;
230  _DirtyFrustumPlanes();
231  }
232 
234  const GfVec3d & GetPosition() const {
235  return _position;
236  }
237 
241  void SetRotation(const GfRotation &rotation) {
242  _rotation = rotation;
243  _DirtyFrustumPlanes();
244  }
245 
248  const GfRotation & GetRotation() const {
249  return _rotation;
250  }
251 
257  GF_API void SetPositionAndRotationFromMatrix(const GfMatrix4d &camToWorldXf);
258 
261  void SetWindow(const GfRange2d &window) {
262  _window = window;
263  _DirtyFrustumPlanes();
264  }
265 
267  const GfRange2d & GetWindow() const {
268  return _window;
269  }
270 
272  static double GetReferencePlaneDepth() {
273  return 1.0;
274  }
275 
277  void SetNearFar(const GfRange1d &nearFar) {
278  _nearFar = nearFar;
279  _DirtyFrustumPlanes();
280  }
281 
283  const GfRange1d & GetNearFar() const {
284  return _nearFar;
285  }
286 
288  void SetViewDistance(double viewDistance) {
289  _viewDistance = viewDistance;
290  }
291 
293  double GetViewDistance() const {
294  return _viewDistance;
295  }
296 
299  _projectionType = projectionType;
300  _DirtyFrustumPlanes();
301  }
302 
305  return _projectionType;
306  }
307 
309 
317 
335  GF_API void SetPerspective(double fieldOfViewHeight,
336  double aspectRatio,
337  double nearDistance, double farDistance);
338 
366  GF_API void SetPerspective(double fieldOfView,
367  bool isFovVertical,
368  double aspectRatio,
369  double nearDistance, double farDistance);
370 
374  GF_API bool GetPerspective(double *fieldOfViewHeight,
375  double *aspectRatio,
376  double *nearDistance,
377  double *farDistance) const;
378 
382  GF_API bool GetPerspective(bool isFovVertical,
383  double *fieldOfView,
384  double *aspectRatio,
385  double *nearDistance,
386  double *farDistance) const;
387 
399  GF_API double GetFOV(bool isFovVertical = false);
400 
405  GF_API
406  void SetOrthographic(double left, double right,
407  double bottom, double top,
408  double nearPlane, double farPlane);
409 
413  GF_API bool GetOrthographic(double *left, double *right,
414  double *bottom, double *top,
415  double *nearPlane, double *farPlane)
416  const;
417 
423  GF_API void FitToSphere(const GfVec3d &center,
424  double radius,
425  double slack = 0.0);
426 
440  GF_API GfFrustum& Transform(const GfMatrix4d &matrix);
441 
444  GF_API GfVec3d ComputeViewDirection() const;
445 
448  GF_API GfVec3d ComputeUpVector() const;
449 
463  GF_API void ComputeViewFrame(GfVec3d *side,
464  GfVec3d *up,
465  GfVec3d *view) const;
466 
469  GF_API GfVec3d ComputeLookAtPoint() const;
470 
474  GF_API GfMatrix4d ComputeViewMatrix() const;
475 
479  GF_API GfMatrix4d ComputeViewInverse() const;
480 
483  GF_API GfMatrix4d ComputeProjectionMatrix() const;
484 
488  GF_API double ComputeAspectRatio() const;
489 
500  GF_API
501  std::vector<GfVec3d> ComputeCorners() const;
502 
512  GF_API
513  std::vector<GfVec3d> ComputeCornersAtDistance(double d) const;
514 
531  GF_API GfFrustum ComputeNarrowedFrustum(const GfVec2d &windowPos,
532  const GfVec2d &size) const;
533 
553  GF_API GfFrustum ComputeNarrowedFrustum(const GfVec3d &worldPoint,
554  const GfVec2d &size) const;
555 
563  GF_API GfRay ComputeRay(const GfVec2d &windowPos) const;
564 
571  GF_API GfRay ComputeRay(const GfVec3d &worldSpacePos) const;
572 
579  GF_API GfRay ComputePickRay(const GfVec2d &windowPos) const;
580 
583  GF_API GfRay ComputePickRay(const GfVec3d &worldSpacePos) const;
584 
586 
593 
597  GF_API bool Intersects(const GfBBox3d &bbox) const;
598 
601  GF_API bool Intersects(const GfVec3d &point) const;
602 
605  GF_API bool Intersects(const GfVec3d &p0,
606  const GfVec3d &p1) const;
607 
610  GF_API bool Intersects(const GfVec3d &p0,
611  const GfVec3d &p1,
612  const GfVec3d &p2) const;
613 
625  GF_API static bool IntersectsViewVolume(const GfBBox3d &bbox,
626  const GfMatrix4d &vpMat);
627 
629 
630  private:
631  // Dirty the result of _CalculateFrustumPlanes.
632  GF_API void _DirtyFrustumPlanes();
633 
634  // Calculates cached frustum planes used for intersection tests.
635  GF_API void _CalculateFrustumPlanes() const;
636 
637  // Builds and returns a \c GfRay that can be used for picking. Given an
638  // eye position and direction in camera space, offsets the ray to emanate
639  // from the near plane, then transforms into worldspace
640  GF_API GfRay _ComputePickRayOffsetToNearPlane(
641  const GfVec3d &camSpaceFrom,
642  const GfVec3d &camSpaceDir) const;
643 
644  // Returns a frustum that is a narrowed-down version of this frustum. The
645  // new frustum has the same near and far planes, but the other planes are
646  // adjusted to be centered on \p windowPoint with the new width and height
647  // obtained from the existing width and height by multiplying by \p size[0]
648  // and \p size[1], respectively. Finally, the new frustum is clipped
649  // against this frustum so that it is completely contained in the existing
650  // frustum.
651  //
652  // \p windowPoint is given in window coordinates.
653  // \p size is given as a scalar (0 to 1 in both dimensions).
654  //
655  // If the \p size given is outside this range, it may result in returning
656  // a collapsed frustum.
657  //
658  // This method is useful for computing a volume to use for interactive
659  // picking.
660  GfFrustum _ComputeNarrowedFrustumSub(const GfVec2d windowPoint,
661  const GfVec2d &size) const;
662 
663  bool _SegmentIntersects(GfVec3d const &p0, uint32_t p0Mask,
664  GfVec3d const &p1, uint32_t p1Mask) const;
665 
666  // Position of the frustum in world space.
667  GfVec3d _position;
668 
669  // Orientation of the frustum in world space as a rotation to apply to the
670  // -z axis.
671  GfRotation _rotation;
672 
673  // Window rectangle in the image plane.
674  GfRange2d _window;
675 
676  // Near/far interval.
677  GfRange1d _nearFar;
678 
679  // View distance.
680  double _viewDistance;
681 
682  // Projection type.
683  ProjectionType _projectionType;
684 
685  // Cached planes.
686  // If null, the planes have not been calculated.
687  mutable std::atomic<std::array<GfPlane, 6> *> _planes;
688 };
689 
697 GF_API std::ostream& operator<<(std::ostream& out, const GfFrustum& f);
698 
699 PXR_NAMESPACE_CLOSE_SCOPE
700 
701 #endif // PXR_BASE_GF_FRUSTUM_H
const GfVec3d & GetPosition() const
Returns the position of the frustum in world space.
Definition: frustum.h:234
GF_API GfMatrix4d ComputeProjectionMatrix() const
Returns a GL-style projection matrix corresponding to the frustum's projection.
GF_API GfVec3d ComputeUpVector() const
Returns the normalized world-space up vector, which is computed by rotating the y axis by the frustum...
void SetProjectionType(GfFrustum::ProjectionType projectionType)
Sets the projection type.
Definition: frustum.h:298
Basic type: 1-dimensional floating point range.
Definition: range1d.h:61
const GfRange1d & GetNearFar() const
Returns the near/far interval.
Definition: frustum.h:283
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,...
GF_API GfVec3d ComputeLookAtPoint() const
Computes and returns the world-space look-at point from the eye point (position), view direction (rot...
GF_API std::vector< GfVec3d > ComputeCorners() const
Returns the world-space corners of the frustum as a vector of 8 points, ordered as:
const GfRange2d & GetWindow() const
Returns the window rectangle in the reference plane.
Definition: frustum.h:267
GF_API GfFrustum & Transform(const GfMatrix4d &matrix)
Transforms the frustum by the given matrix.
Basic type for a vector of 2 double components.
Definition: vec2d.h:62
GF_API GfMatrix4d ComputeViewMatrix() const
Returns a matrix that represents the viewing transformation for this frustum.
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).
GF_API double ComputeAspectRatio() const
Returns the aspect ratio of the frustum, defined as the width of the window divided by the height.
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,...
static size_t Combine(Args &&... args)
Produce a hash code by combining the hash codes of several objects.
Definition: hash.h:519
GF_API GfMatrix4d ComputeViewInverse() const
Returns a matrix that represents the inverse viewing transformation for this frustum.
void SetWindow(const GfRange2d &window)
Sets the window rectangle in the reference plane that defines the left, right, top,...
Definition: frustum.h:261
void SetViewDistance(double viewDistance)
Sets the view distance.
Definition: frustum.h:288
Stores a 4x4 matrix of double elements.
Definition: matrix4d.h:87
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:63
Basic type: View frustum.
Definition: frustum.h:88
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().
GF_API void SetPerspective(double fieldOfViewHeight, double aspectRatio, double nearDistance, double farDistance)
Sets up the frustum in a manner similar to gluPerspective().
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:248
Perspective projection.
Definition: frustum.h:94
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...
GfFrustum & operator=(GfFrustum &&o) noexcept
Move assignment.
Definition: frustum.h:174
GfFrustum(GfFrustum const &o)
Copy constructor.
Definition: frustum.h:108
void SetNearFar(const GfRange1d &nearFar)
Sets the near/far interval.
Definition: frustum.h:277
ProjectionType
This enum is used to determine the type of projection represented by a frustum.
Definition: frustum.h:92
GfFrustum(GfFrustum &&o) noexcept
Move constructor.
Definition: frustum.h:122
GF_API GfFrustum ComputeNarrowedFrustum(const GfVec2d &windowPos, const GfVec2d &size) const
Returns a frustum that is a narrowed-down version of this frustum.
GF_API ~GfFrustum()
Destructor.
GF_API GfVec3d ComputeViewDirection() const
Returns the normalized world-space view direction vector, which is computed by rotating the -z axis b...
GF_API GfFrustum()
This constructor creates an instance with default viewing parameters:
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 const &o) noexcept
Copy assignment.
Definition: frustum.h:152
void SetPosition(const GfVec3d &position)
Sets the position of the frustum in world space.
Definition: frustum.h:228
Basic type for a vector of 3 double components.
Definition: vec3d.h:62
GF_API std::ostream & operator<<(std::ostream &out, const GfFrustum &f)
Output a GfFrustum using the format [(position) (rotation) [window] [nearFar] viewDistance type].
GfFrustum::ProjectionType GetProjectionType() const
Returns the projection type.
Definition: frustum.h:304
Basic type: Ray used for intersection testing.
Definition: ray.h:61
static double GetReferencePlaneDepth()
Returns the depth of the reference plane.
Definition: frustum.h:272
double GetViewDistance() const
Returns the view distance.
Definition: frustum.h:293
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: 3-space rotation specification.
Definition: rotation.h:54
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:241
Orthographic projection.
Definition: frustum.h:93
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 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...