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 27 /// \file gf/frustum.h 28 /// \ingroup group_gf_BasicGeometry 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 51 /// \class GfFrustum 52 /// \ingroup group_gf_BasicGeometry 53 /// 54 /// Basic type: View frustum. 55 /// 56 /// This class represents a viewing frustum in three dimensional eye space. It 57 /// may represent either a parallel (orthographic) or perspective projection. 58 /// One can think of the frustum as being defined by 6 boundary planes. 59 /// 60 /// The frustum is specified using these parameters: 61 /// \li The \em position of the viewpoint. 62 /// \li The \em rotation applied to the default view frame, which is 63 /// looking along the -z axis with the +y axis as the "up" 64 /// direction. 65 /// \li The 2D \em window on the reference plane that defines the left, 66 /// right, top, and bottom planes of the viewing frustum, as 67 /// described below. 68 /// \li The distances to the \em near and \em far planes. 69 /// \li The \em projection \em type 70 /// \li The view distance. 71 /// 72 /// The window and near/far parameters combine to define the view frustum as 73 /// follows. Transform the -z axis and the +y axis by the frustum rotation to 74 /// get the world-space \em view \em direction and \em up \em direction. Now 75 /// consider the \em reference \em plane that is perpendicular to the view 76 /// direction, a distance of referencePlaneDepth from the viewpoint, and whose 77 /// y axis corresponds to the up direction. The window rectangle is specified 78 /// in a 2D coordinate system embedded in this plane. The origin of the 79 /// coordinate system is the point at which the view direction vector 80 /// intersects the plane. Therefore, the point (0,1) in this plane is found by 81 /// moving 1 unit along the up direction vector in this plane. The vector from 82 /// the viewpoint to the resulting point will form a 45-degree angle with the 83 /// view direction. 84 /// 85 /// The view distance is only useful for interactive applications. It can be 86 /// used to compute a look at point which is useful when rotating around an 87 /// object of interest. 88 /// 89 class GfFrustum { 90 public: 91 /// This enum is used to determine the type of projection represented by a 92 /// frustum. 93 enum ProjectionType { 94 Orthographic, ///< Orthographic projection 95 Perspective, ///< Perspective projection 96 }; 97 98 /// This constructor creates an instance with default viewing parameters: 99 /// \li The position is the origin. 100 /// \li The rotation is the identity rotation. (The view is along 101 /// the -z axis, with the +y axis as "up"). 102 /// \li The window is -1 to +1 in both dimensions. 103 /// \li The near/far interval is (1, 10). 104 /// \li The view distance is 5.0. 105 /// \li The projection type is \c GfFrustum::Perspective. 106 GF_API GfFrustum(); 107 108 /// Copy constructor. GfFrustum(GfFrustum const & o)109 GfFrustum(GfFrustum const &o) 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 122 /// Move constructor. GfFrustum(GfFrustum && o)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 137 /// This constructor creates an instance with the given viewing 138 /// parameters. 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 144 /// This constructor creates an instance from a camera matrix (always of a 145 /// y-Up camera, also see SetPositionAndRotationFromMatrix) and the given 146 /// viewing parameters. 147 GF_API GfFrustum(const GfMatrix4d &camToWorldXf, 148 const GfRange2d &window, const GfRange1d &nearFar, 149 GfFrustum::ProjectionType projectionType, 150 double viewDistance = 5.0); 151 152 /// Copy assignment. 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 174 /// Move assignment. 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 hash_value(const GfFrustum & f)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 220 /// Destructor. 221 GF_API ~GfFrustum(); 222 223 /// \name Value setting and access 224 /// The methods in this group set and access the values that are used to 225 /// define a frustum. 226 ///@{ 227 228 /// Sets the position of the frustum in world space. SetPosition(const GfVec3d & position)229 void SetPosition(const GfVec3d &position) { 230 _position = position; 231 _DirtyFrustumPlanes(); 232 } 233 234 /// Returns the position of the frustum in world space. GetPosition()235 const GfVec3d & GetPosition() const { 236 return _position; 237 } 238 239 /// Sets the orientation of the frustum in world space as a rotation to 240 /// apply to the default frame: looking along the -z axis with the +y axis 241 /// as "up". SetRotation(const GfRotation & rotation)242 void SetRotation(const GfRotation &rotation) { 243 _rotation = rotation; 244 _DirtyFrustumPlanes(); 245 } 246 247 /// Returns the orientation of the frustum in world space as a rotation to 248 /// apply to the -z axis. GetRotation()249 const GfRotation & GetRotation() const { 250 return _rotation; 251 } 252 253 /// Sets the position and rotation of the frustum from a camera matrix 254 /// (always from a y-Up camera). The resulting frustum's transform will 255 /// always represent a right-handed and orthonormal coordinate sytem 256 /// (scale, shear, and projection are removed from the given \p 257 /// camToWorldXf). 258 GF_API void SetPositionAndRotationFromMatrix(const GfMatrix4d &camToWorldXf); 259 260 /// Sets the window rectangle in the reference plane that defines the 261 /// left, right, top, and bottom planes of the frustum. SetWindow(const GfRange2d & window)262 void SetWindow(const GfRange2d &window) { 263 _window = window; 264 _DirtyFrustumPlanes(); 265 } 266 267 /// Returns the window rectangle in the reference plane. GetWindow()268 const GfRange2d & GetWindow() const { 269 return _window; 270 } 271 272 /// Returns the depth of the reference plane. GetReferencePlaneDepth()273 static double GetReferencePlaneDepth() { 274 return 1.0; 275 } 276 277 /// Sets the near/far interval. SetNearFar(const GfRange1d & nearFar)278 void SetNearFar(const GfRange1d &nearFar) { 279 _nearFar = nearFar; 280 _DirtyFrustumPlanes(); 281 } 282 283 /// Returns the near/far interval. GetNearFar()284 const GfRange1d & GetNearFar() const { 285 return _nearFar; 286 } 287 288 /// Sets the view distance. SetViewDistance(double viewDistance)289 void SetViewDistance(double viewDistance) { 290 _viewDistance = viewDistance; 291 } 292 293 /// Returns the view distance. GetViewDistance()294 double GetViewDistance() const { 295 return _viewDistance; 296 } 297 298 /// Sets the projection type. SetProjectionType(GfFrustum::ProjectionType projectionType)299 void SetProjectionType(GfFrustum::ProjectionType projectionType) { 300 _projectionType = projectionType; 301 _DirtyFrustumPlanes(); 302 } 303 304 /// Returns the projection type. GetProjectionType()305 GfFrustum::ProjectionType GetProjectionType() const { 306 return _projectionType; 307 } 308 309 ///@} 310 311 /// \name Convenience methods 312 /// 313 /// The methods in this group allow the frustum's data to be accessed and 314 /// modified in terms of different representations that may be more 315 /// convenient for certain applications. 316 /// 317 ///@{ 318 319 /// Sets up the frustum in a manner similar to \c gluPerspective(). 320 /// 321 /// It sets the projection type to \c GfFrustum::Perspective and sets the 322 /// window specification so that the resulting symmetric frustum encloses 323 /// an angle of \p fieldOfViewHeight degrees in the vertical direction, 324 /// with \p aspectRatio used to figure the angle in the horizontal 325 /// direction. The near and far distances are specified as well. The 326 /// window coordinates are computed as: 327 /// \code 328 /// top = tan(fieldOfViewHeight / 2) 329 /// bottom = -top 330 /// right = top * aspectRatio 331 /// left = -right 332 /// near = nearDistance 333 /// far = farDistance 334 /// \endcode 335 /// 336 GF_API void SetPerspective(double fieldOfViewHeight, 337 double aspectRatio, 338 double nearDistance, double farDistance); 339 340 /// Sets up the frustum in a manner similar to gluPerspective(). 341 /// 342 /// It sets the projection type to \c GfFrustum::Perspective and 343 /// sets the window specification so that: 344 /// 345 /// If \a isFovVertical is true, the resulting symmetric frustum encloses 346 /// an angle of \p fieldOfView degrees in the vertical direction, with \p 347 /// aspectRatio used to figure the angle in the horizontal direction. 348 /// 349 /// If \a isFovVertical is false, the resulting symmetric frustum encloses 350 /// an angle of \p fieldOfView degrees in the horizontal direction, with 351 /// \p aspectRatio used to figure the angle in the vertical direction. 352 /// 353 /// The near and far distances are specified as well. The window 354 /// coordinates are computed as follows: 355 /// 356 /// \li if isFovVertical: 357 /// \li top = tan(fieldOfView / 2) 358 /// \li right = top * aspectRatio 359 /// \li if NOT isFovVertical: 360 /// \li right = tan(fieldOfView / 2) 361 /// \li top = right / aspectRation 362 /// \li bottom = -top 363 /// \li left = -right 364 /// \li near = nearDistance 365 /// \li far = farDistance 366 /// 367 GF_API void SetPerspective(double fieldOfView, 368 bool isFovVertical, 369 double aspectRatio, 370 double nearDistance, double farDistance); 371 372 /// Returns the current frustum in the format used by \c SetPerspective(). 373 /// If the current frustum is not a perspective projection, this returns 374 /// \c false and leaves the parameters untouched. 375 GF_API bool GetPerspective(double *fieldOfViewHeight, 376 double *aspectRatio, 377 double *nearDistance, 378 double *farDistance) const; 379 380 /// Returns the current frustum in the format used by \c SetPerspective(). 381 /// If the current frustum is not a perspective projection, this returns 382 /// \c false and leaves the parameters untouched. 383 GF_API bool GetPerspective(bool isFovVertical, 384 double *fieldOfView, 385 double *aspectRatio, 386 double *nearDistance, 387 double *farDistance) const; 388 389 /// Returns the horizontal or vertical fov of the frustum. The fov of the 390 /// frustum is not necessarily the same value as displayed in the viewer. 391 /// The displayed fov is a function of the focal length or FOV avar. The 392 /// frustum's fov may be different due to things like lens breathing. 393 /// 394 /// If the frustum is not of type \c GfFrustum::Perspective, the returned 395 /// FOV will be 0.0. 396 /// 397 /// \note The default value for \c isFovVertical is false so calling \c 398 /// GetFOV without an argument will return the horizontal field of view 399 /// which is compatible with menv2x's old GfFrustum::GetFOV routine. 400 GF_API double GetFOV(bool isFovVertical = false); 401 402 /// Sets up the frustum in a manner similar to \c glOrtho(). 403 /// 404 /// Sets the projection to \c GfFrustum::Orthographic and sets the window 405 /// and near/far specifications based on the given values. 406 GF_API 407 void SetOrthographic(double left, double right, 408 double bottom, double top, 409 double nearPlane, double farPlane); 410 411 /// Returns the current frustum in the format used by \c 412 /// SetOrthographic(). If the current frustum is not an orthographic 413 /// projection, this returns \c false and leaves the parameters untouched. 414 GF_API bool GetOrthographic(double *left, double *right, 415 double *bottom, double *top, 416 double *nearPlane, double *farPlane) 417 const; 418 419 /// Modifies the frustum to tightly enclose a sphere with the given center 420 /// and radius, using the current view direction. The planes of the 421 /// frustum are adjusted as necessary. The given amount of slack is added 422 /// to the sphere's radius is used around the sphere to avoid boundary 423 /// problems. 424 GF_API void FitToSphere(const GfVec3d ¢er, 425 double radius, 426 double slack = 0.0); 427 428 /// Transforms the frustum by the given matrix. 429 /// 430 /// The transformation matrix is applied as follows: the position and the 431 /// direction vector are transformed with the given matrix. Then the 432 /// length of the new direction vector is used to rescale the near and far 433 /// plane and the view distance. Finally, the points that define the 434 /// reference plane are transformed by the matrix. This method assures 435 /// that the frustum will not be sheared or perspective-projected. 436 /// 437 /// \note Note that this definition means that the transformed frustum 438 /// does not preserve scales very well. Do \em not use this function to 439 /// transform a frustum that is to be used for precise operations such as 440 /// intersection testing. 441 GF_API GfFrustum& Transform(const GfMatrix4d &matrix); 442 443 /// Returns the normalized world-space view direction vector, which is 444 /// computed by rotating the -z axis by the frustum's rotation. 445 GF_API GfVec3d ComputeViewDirection() const; 446 447 /// Returns the normalized world-space up vector, which is computed by 448 /// rotating the y axis by the frustum's rotation. 449 GF_API GfVec3d ComputeUpVector() const; 450 451 /// Computes the view frame defined by this frustum. The frame consists of 452 /// the view direction, up vector and side vector, as shown in this 453 /// diagram. 454 /// 455 /// \code 456 /// up 457 /// ^ ^ 458 /// | / 459 /// | / view 460 /// |/ 461 /// +- - - - > side 462 /// \endcode 463 /// 464 GF_API void ComputeViewFrame(GfVec3d *side, 465 GfVec3d *up, 466 GfVec3d *view) const; 467 468 /// Computes and returns the world-space look-at point from the eye point 469 /// (position), view direction (rotation), and view distance. 470 GF_API GfVec3d ComputeLookAtPoint() const; 471 472 /// Returns a matrix that represents the viewing transformation for this 473 /// frustum. That is, it returns the matrix that converts points from 474 /// world space to eye (frustum) space. 475 GF_API GfMatrix4d ComputeViewMatrix() const; 476 477 /// Returns a matrix that represents the inverse viewing transformation 478 /// for this frustum. That is, it returns the matrix that converts points 479 /// from eye (frustum) space to world space. 480 GF_API GfMatrix4d ComputeViewInverse() const; 481 482 /// Returns a GL-style projection matrix corresponding to the frustum's 483 /// projection. 484 GF_API GfMatrix4d ComputeProjectionMatrix() const; 485 486 /// Returns the aspect ratio of the frustum, defined as the width of the 487 /// window divided by the height. If the height is zero or negative, this 488 /// returns 0. 489 GF_API double ComputeAspectRatio() const; 490 491 /// Returns the world-space corners of the frustum as a vector of 8 492 /// points, ordered as: 493 /// \li Left bottom near 494 /// \li Right bottom near 495 /// \li Left top near 496 /// \li Right top near 497 /// \li Left bottom far 498 /// \li Right bottom far 499 /// \li Left top far 500 /// \li Right top far 501 GF_API 502 std::vector<GfVec3d> ComputeCorners() const; 503 504 /// Returns the world-space corners of the intersection of the frustum 505 /// with a plane parallel to the near/far plane at distance d from the 506 /// apex, ordered as: 507 /// \li Left bottom 508 /// \li Right bottom 509 /// \li Left top 510 /// \li Right top 511 /// In particular, it gives the partial result of ComputeCorners when given 512 /// near or far distance. 513 GF_API 514 std::vector<GfVec3d> ComputeCornersAtDistance(double d) const; 515 516 /// Returns a frustum that is a narrowed-down version of this frustum, 517 /// such that the frustum rectangle on the near plane encloses \p point 518 /// with at most \p halfSize[0] distance on the left and right and at most 519 /// \p halfSize[1] distance on the top and bottom. (If \p point is closer 520 /// than the half size to a side of the frustum, that side is left alone. 521 /// The point and sizes are in normalized 2D coordinates; they range from 522 /// (-1, -1) at the lower left corner of the near-plane window rectangle 523 /// to (1,1) at the upper right corner. 524 /// 525 /// \p point is a 2d point expressed as a normalized window position. 526 /// 527 /// This method is useful for computing a volume to use for interactive 528 /// picking. 529 GF_API GfFrustum ComputeNarrowedFrustum(const GfVec2d &point, 530 const GfVec2d &halfSize) const; 531 532 /// Returns a frustum that is a narrowed-down version of this frustum, 533 /// such that the frustum rectangle on the near plane encloses \p point 534 /// with at most \p halfSize[0] distance on the left and right and at most 535 /// \p halfSize[1] distance on the top and bottom. (If \p point is closer 536 /// than the half size to a side of the frustum, that side is left alone. 537 /// The point and sizes are in normalized 2D coordinates; they range from 538 /// (-1, -1) at the lower left corner of the near-plane window rectangle 539 /// to (1,1) at the upper right corner. 540 /// 541 /// \p point is a 3d point expressed in world coordinates 542 /// 543 /// This method is useful for computing a volume to use for interactive 544 /// picking. 545 GF_API GfFrustum ComputeNarrowedFrustum(const GfVec3d &worldPoint, 546 const GfVec2d &halfSize) const; 547 548 /// Builds and returns a \c GfRay that starts at the viewpoint and extends 549 /// through the given \a windowPos given in normalized coords (-1 to +1 in 550 /// both dimensions) window position. 551 /// 552 /// Contrasted with ComputePickRay(), this method returns a ray whose 553 /// origin is the eyepoint, while that method returns a ray whose origin 554 /// is on the near plane. 555 GF_API GfRay ComputeRay(const GfVec2d &windowPos) const; 556 557 /// Builds and returns a \c GfRay that connects the viewpoint to the given 558 /// 3d point in worldspace. 559 /// 560 /// Contrasted with ComputePickRay(), this method returns a ray whose 561 /// origin is the eyepoint, while that method returns a ray whose origin 562 /// is on the near plane. 563 GF_API GfRay ComputeRay(const GfVec3d &worldSpacePos) const; 564 565 /// Builds and returns a \c GfRay that can be used for picking at the 566 /// given normalized (-1 to +1 in both dimensions) window position. 567 /// 568 /// Contrasted with ComputeRay(), that method returns a ray whose origin 569 /// is the eyepoint, while this method returns a ray whose origin is on 570 /// the near plane. 571 GF_API GfRay ComputePickRay(const GfVec2d &windowPos) const; 572 573 /// Builds and returns a \c GfRay that can be used for picking that 574 /// connects the viewpoint to the given 3d point in worldspace. 575 GF_API GfRay ComputePickRay(const GfVec3d &worldSpacePos) const; 576 577 ///@} 578 579 /// \name Intersection methods 580 /// 581 /// The methods in this group implement intersection operations 582 /// between this frustum and a given primitive. 583 /// 584 ///@{ 585 586 /// Returns true if the given axis-aligned bbox is inside or intersecting 587 /// the frustum. Otherwise, it returns false. Useful when doing picking or 588 /// frustum culling. 589 GF_API bool Intersects(const GfBBox3d &bbox) const; 590 591 /// Returns true if the given point is inside or intersecting the frustum. 592 /// Otherwise, it returns false. 593 GF_API bool Intersects(const GfVec3d &point) const; 594 595 /// Returns \c true if the line segment formed by the given points is 596 /// inside or intersecting the frustum. Otherwise, it returns false. 597 GF_API bool Intersects(const GfVec3d &p0, 598 const GfVec3d &p1) const; 599 600 /// Returns \c true if the triangle formed by the given points is inside 601 /// or intersecting the frustum. Otherwise, it returns false. 602 GF_API bool Intersects(const GfVec3d &p0, 603 const GfVec3d &p1, 604 const GfVec3d &p2) const; 605 606 /// Returns \c true if the bbox volume intersects the view volume given by 607 /// the view-projection matrix, erring on the side of false positives for 608 /// efficiency. 609 /// 610 /// This method is intended for cases where a GfFrustum is not available 611 /// or when the view-projection matrix yields a view volume that is not 612 /// expressable as a GfFrustum. 613 /// 614 /// Because it errs on the side of false positives, it is suitable for 615 /// early-out tests such as draw or intersection culling. 616 /// 617 GF_API static bool IntersectsViewVolume(const GfBBox3d &bbox, 618 const GfMatrix4d &vpMat); 619 620 ///@} 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 679 /// Output a GfFrustum using the format [(position) (rotation) [window] 680 /// [nearFar] viewDistance type] 681 /// 682 /// The "type" is "perspective", or "orthographic, depending on the 683 /// projection type of the frustum. 684 /// 685 /// \ingroup group_gf_DebuggingOutput 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 691