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