HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
bbox3d.h
Go to the documentation of this file.
1 //
2 // Copyright 2016 Pixar
3 //
4 // Licensed under the terms set forth in the LICENSE.txt file available at
5 // https://openusd.org/license.
6 //
7 #ifndef PXR_BASE_GF_BBOX3D_H
8 #define PXR_BASE_GF_BBOX3D_H
9 
10 /// \file gf/bbox3d.h
11 /// \ingroup group_gf_BasicGeometry
12 
13 #include "pxr/pxr.h"
14 #include "pxr/base/gf/matrix4d.h"
15 #include "pxr/base/gf/range3d.h"
16 #include "pxr/base/gf/api.h"
17 
18 #include <iosfwd>
19 
21 
22 /// \class GfBBox3d
23 /// \ingroup group_gf_BasicGeometry
24 /// Basic type: arbitrarily oriented 3D bounding box.
25 ///
26 /// This class represents a three-dimensional bounding box as an
27 /// axis-aligned box (\c GfRange3d) and a matrix (\c GfMatrix4d) to
28 /// transform it into the correct space.
29 ///
30 /// A \c GfBBox3d is more useful than using just \c GfRange3d instances
31 /// (which are always axis-aligned) for these reasons:
32 ///
33 /// \li When an axis-aligned bounding box is transformed several times,
34 /// each transformation can result in inordinate growth of the bounding
35 /// box. By storing the transformation separately, it can be applied once
36 /// at the end, resulting in a much better fit. For example, if the
37 /// bounding box at the leaf of a scene graph is transformed through
38 /// several levels of the graph hierarchy to the coordinate space at the
39 /// root, a \c GfBBox3d is generally much smaller than the \c GfRange3d
40 /// computed by transforming the box at each level.
41 ///
42 /// \li When two or more such bounding boxes are combined, having the
43 /// transformations stored separately means that there is a better
44 /// opportunity to choose a better coordinate space in which to combine
45 /// the boxes.
46 ///
47 /// \anchor bbox3d_zeroAreaFlag
48 /// <b> The Zero-area Primitives Flag </b>
49 ///
50 /// When bounding boxes are used in intersection test culling, it is
51 /// sometimes useful to extend them a little bit to allow
52 /// lower-dimensional objects with zero area, such as lines and points,
53 /// to be intersected. For example, consider a cube constructed of line
54 /// segments. The bounding box for this shape fits the cube exactly. If
55 /// an application wants to allow a near-miss of the silhouette edges of
56 /// the cube to be considered an intersection, it has to loosen the bbox
57 /// culling test a little bit.
58 ///
59 /// To distinguish when this loosening is necessary, each \c GfBBox3d
60 /// instance maintains a flag indicating whether any zero-area primitives
61 /// are contained within it. The application is responsible for setting
62 /// this flag correctly by calling \c SetHasZeroAreaPrimitives(). The
63 /// flag can be accessed during intersection tests by calling \c
64 /// HasZeroAreaPrimitives(). This flag is set by default in all
65 /// constructors to \c false.
66 ///
67 class GfBBox3d {
68 
69  public:
70 
71  /// The default constructor leaves the box empty, the transformation
72  /// matrix identity, and the \ref bbox3d_zeroAreaFlag "zero-area
73  /// primitives flag" \c false.
75  _matrix.SetIdentity();
76  _inverse.SetIdentity();
77  _isDegenerate = false;
78  _hasZeroAreaPrimitives = false;
79  }
80 
81  /// This constructor takes a box and sets the matrix to identity.
82  GfBBox3d(const GfRange3d &box) :
83  _box(box) {
84  _matrix.SetIdentity();
85  _inverse.SetIdentity();
86  _isDegenerate = false;
87  _hasZeroAreaPrimitives = false;
88  }
89 
90  /// This constructor takes a box and a transformation matrix.
91  GfBBox3d(const GfRange3d &box, const GfMatrix4d &matrix) {
92  Set(box, matrix);
93  _hasZeroAreaPrimitives = false;
94  }
95 
96  /// Sets the axis-aligned box and transformation matrix.
97  void Set(const GfRange3d &box, const GfMatrix4d &matrix) {
98  _box = box;
99  _SetMatrices(matrix);
100  }
101 
102  /// Sets the transformation matrix only. The axis-aligned box is not
103  /// modified.
104  void SetMatrix(const GfMatrix4d& matrix) {
105  _SetMatrices(matrix);
106  }
107 
108  /// Sets the range of the axis-aligned box only. The transformation
109  /// matrix is not modified.
110  void SetRange(const GfRange3d& box) {
111  _box = box;
112  }
113 
114  /// Returns the range of the axis-aligned untransformed box.
115  const GfRange3d & GetRange() const {
116  return _box;
117  }
118 
119  /// Returns the range of the axis-aligned untransformed box.
120  /// This synonym of \c GetRange exists for compatibility purposes.
121  const GfRange3d & GetBox() const {
122  return GetRange();
123  }
124 
125  /// Returns the transformation matrix.
126  const GfMatrix4d & GetMatrix() const {
127  return _matrix;
128  }
129 
130  /// Returns the inverse of the transformation matrix. This will be the
131  /// identity matrix if the transformation matrix is not invertible.
132  const GfMatrix4d & GetInverseMatrix() const {
133  return _inverse;
134  }
135 
136  /// Sets the \ref bbox3d_zeroAreaFlag "zero-area primitives flag" to the
137  /// given value.
138  void SetHasZeroAreaPrimitives(bool hasThem) {
139  _hasZeroAreaPrimitives = hasThem;
140  }
141 
142  /// Returns the current state of the \ref bbox3d_zeroAreaFlag "zero-area
143  /// primitives flag".
144  bool HasZeroAreaPrimitives() const {
145  return _hasZeroAreaPrimitives;
146  }
147 
148  /// Returns the volume of the box (0 for an empty box).
149  GF_API
150  double GetVolume() const;
151 
152  /// Transforms the bounding box by the given matrix, which is assumed to
153  /// be a global transformation to apply to the box. Therefore, this just
154  /// post-multiplies the box's matrix by \p matrix.
155  void Transform(const GfMatrix4d &matrix) {
156  _SetMatrices(_matrix * matrix);
157  }
158 
159  /// Returns the axis-aligned range (as a \c GfRange3d) that results from
160  /// applying the transformation matrix to the wxis-aligned box and
161  /// aligning the result.
162  GF_API
164 
165  /// Returns the axis-aligned range (as a \c GfRange3d) that results from
166  /// applying the transformation matrix to the axis-aligned box and
167  /// aligning the result. This synonym for \c ComputeAlignedRange exists
168  /// for compatibility purposes.
170  return ComputeAlignedRange();
171  }
172 
173  /// Combines two bboxes, returning a new bbox that contains both. This
174  /// uses the coordinate space of one of the two original boxes as the
175  /// space of the result; it uses the one that produces whe smaller of the
176  /// two resulting boxes.
177  GF_API
178  static GfBBox3d Combine(const GfBBox3d &b1, const GfBBox3d &b2);
179 
180  /// Returns the centroid of the bounding box.
181  /// The centroid is computed as the transformed centroid of the range.
182  GF_API
183  GfVec3d ComputeCentroid() const;
184 
185  /// Hash.
186  friend inline size_t hash_value(const GfBBox3d &b) {
187  return TfHash::Combine(
188  b._box,
189  b._matrix
190  );
191  }
192 
193  /// Component-wise equality test. The axis-aligned boxes and
194  /// transformation matrices match exactly for bboxes to be considered
195  /// equal. (To compare equality of the actual boxes, you can compute both
196  /// aligned boxes and test the results for equality.)
197  bool operator ==(const GfBBox3d &b) const {
198  return (_box == b._box &&
199  _matrix == b._matrix);
200  }
201 
202  /// Component-wise inequality test. The axis-aligned boxes and
203  /// transformation matrices match exactly for bboxes to be considered
204  /// equal. (To compare equality of the actual boxes, you can compute both
205  /// aligned boxes and test the results for equality.)
206  bool operator !=(const GfBBox3d &that) const {
207  return !(*this == that);
208  }
209 
210  private:
211  /// The axis-aligned box.
212  GfRange3d _box;
213  /// Transformation matrix.
214  GfMatrix4d _matrix;
215  /// Inverse of the transformation matrix.
216  GfMatrix4d _inverse;
217  /// Flag indicating whether the matrix is degenerate.
218  bool _isDegenerate;
219  /// Flag indicating whether the bbox contains zero-area primitives.
220  bool _hasZeroAreaPrimitives;
221 
222  /// Sets the transformation matrix and the inverse, checking for
223  /// degeneracies.
224  GF_API
225  void _SetMatrices(const GfMatrix4d &matrix);
226 
227  /// This is used by \c Combine() when it is determined which coordinate
228  /// space to use to combine two boxes: \p b2 is transformed into the space
229  /// of \p b1 and the results are merged in that space.
230  static GfBBox3d _CombineInOrder(const GfBBox3d &b1, const GfBBox3d &b2);
231 };
232 
233 /// Output a GfBBox3d using the format [(range) matrix zeroArea]
234 ///
235 /// The zeroArea flag is true or false and indicates whether the
236 /// bbox has zero area primitives in it.
237 ///
238 /// \ingroup group_gf_DebuggingOutput
239 GF_API std::ostream& operator<<(std::ostream&, const GfBBox3d&);
240 
242 
243 #endif // PXR_BASE_GF_BBOX3D_H
GF_API GfVec3d ComputeCentroid() const
GfMatrix4d & SetIdentity()
Sets the matrix to the identity matrix.
Definition: matrix4d.h:232
const GfMatrix4d & GetInverseMatrix() const
Definition: bbox3d.h:132
void SetRange(const GfRange3d &box)
Definition: bbox3d.h:110
friend size_t hash_value(const GfBBox3d &b)
Hash.
Definition: bbox3d.h:186
bool operator==(const GfBBox3d &b) const
Definition: bbox3d.h:197
void SetMatrix(const GfMatrix4d &matrix)
Definition: bbox3d.h:104
GF_API double GetVolume() const
Returns the volume of the box (0 for an empty box).
GfBBox3d()
Definition: bbox3d.h:74
GfBBox3d(const GfRange3d &box)
This constructor takes a box and sets the matrix to identity.
Definition: bbox3d.h:82
GF_API GfRange3d ComputeAlignedRange() const
GfRange3d ComputeAlignedBox() const
Definition: bbox3d.h:169
const GfRange3d & GetRange() const
Returns the range of the axis-aligned untransformed box.
Definition: bbox3d.h:115
GLboolean GLboolean GLboolean b
Definition: glcorearb.h:1222
void Set(const GfRange3d &box, const GfMatrix4d &matrix)
Sets the axis-aligned box and transformation matrix.
Definition: bbox3d.h:97
static size_t Combine(Args &&...args)
Produce a hash code by combining the hash codes of several objects.
Definition: hash.h:487
GF_API std::ostream & operator<<(std::ostream &, const GfBBox3d &)
PXR_NAMESPACE_CLOSE_SCOPE PXR_NAMESPACE_OPEN_SCOPE
Definition: path.h:1425
GfBBox3d(const GfRange3d &box, const GfMatrix4d &matrix)
This constructor takes a box and a transformation matrix.
Definition: bbox3d.h:91
bool HasZeroAreaPrimitives() const
Definition: bbox3d.h:144
Definition: vec3d.h:45
#define PXR_NAMESPACE_CLOSE_SCOPE
Definition: pxr.h:74
void Transform(const GfMatrix4d &matrix)
Definition: bbox3d.h:155
void SetHasZeroAreaPrimitives(bool hasThem)
Definition: bbox3d.h:138
static GF_API GfBBox3d Combine(const GfBBox3d &b1, const GfBBox3d &b2)
#define GF_API
Definition: api.h:23
bool operator!=(const GfBBox3d &that) const
Definition: bbox3d.h:206
const GfRange3d & GetBox() const
Definition: bbox3d.h:121
const GfMatrix4d & GetMatrix() const
Returns the transformation matrix.
Definition: bbox3d.h:126