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 GF_BBOX3D_H
25 #define 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  /// Copy constructor
99  GfBBox3d(const GfBBox3d& rhs) :
100  _box(rhs._box) {
101  _matrix = rhs._matrix;
102  _inverse = rhs._inverse;
103  _isDegenerate = rhs._isDegenerate;
104  _hasZeroAreaPrimitives = rhs._hasZeroAreaPrimitives;
105  }
106 
107  /// This constructor takes a box and sets the matrix to identity.
108  GfBBox3d(const GfRange3d &box) :
109  _box(box) {
110  _matrix.SetIdentity();
111  _inverse.SetIdentity();
112  _isDegenerate = false;
113  _hasZeroAreaPrimitives = false;
114  }
115 
116  /// This constructor takes a box and a transformation matrix.
117  GfBBox3d(const GfRange3d &box, const GfMatrix4d &matrix) {
118  Set(box, matrix);
119  _hasZeroAreaPrimitives = false;
120  }
121 
122  /// Sets the axis-aligned box and transformation matrix.
123  void Set(const GfRange3d &box, const GfMatrix4d &matrix) {
124  _box = box;
125  _SetMatrices(matrix);
126  }
127 
128  /// Sets the transformation matrix only. The axis-aligned box is not
129  /// modified.
130  void SetMatrix(const GfMatrix4d& matrix) {
131  _SetMatrices(matrix);
132  }
133 
134  /// Sets the range of the axis-aligned box only. The transformation
135  /// matrix is not modified.
136  void SetRange(const GfRange3d& box) {
137  _box = box;
138  }
139 
140  /// Returns the range of the axis-aligned untransformed box.
141  const GfRange3d & GetRange() const {
142  return _box;
143  }
144 
145  /// Returns the range of the axis-aligned untransformed box.
146  /// This synonym of \c GetRange exists for compatibility purposes.
147  const GfRange3d & GetBox() const {
148  return GetRange();
149  }
150 
151  /// Returns the transformation matrix.
152  const GfMatrix4d & GetMatrix() const {
153  return _matrix;
154  }
155 
156  /// Returns the inverse of the transformation matrix. This will be the
157  /// identity matrix if the transformation matrix is not invertible.
158  const GfMatrix4d & GetInverseMatrix() const {
159  return _inverse;
160  }
161 
162  /// Sets the \ref bbox3d_zeroAreaFlag "zero-area primitives flag" to the
163  /// given value.
164  void SetHasZeroAreaPrimitives(bool hasThem) {
165  _hasZeroAreaPrimitives = hasThem;
166  }
167 
168  /// Returns the current state of the \ref bbox3d_zeroAreaFlag "zero-area
169  /// primitives flag".
170  bool HasZeroAreaPrimitives() const {
171  return _hasZeroAreaPrimitives;
172  }
173 
174  /// Returns the volume of the box (0 for an empty box).
175  GF_API
176  double GetVolume() const;
177 
178  /// Transforms the bounding box by the given matrix, which is assumed to
179  /// be a global transformation to apply to the box. Therefore, this just
180  /// post-multiplies the box's matrix by \p matrix.
181  void Transform(const GfMatrix4d &matrix) {
182  _SetMatrices(_matrix * matrix);
183  }
184 
185  /// Returns the axis-aligned range (as a \c GfRange3d) that results from
186  /// applying the transformation matrix to the wxis-aligned box and
187  /// aligning the result.
188  GF_API
190 
191  /// Returns the axis-aligned range (as a \c GfRange3d) that results from
192  /// applying the transformation matrix to the axis-aligned box and
193  /// aligning the result. This synonym for \c ComputeAlignedRange exists
194  /// for compatibility purposes.
196  return ComputeAlignedRange();
197  }
198 
199  /// Combines two bboxes, returning a new bbox that contains both. This
200  /// uses the coordinate space of one of the two original boxes as the
201  /// space of the result; it uses the one that produces whe smaller of the
202  /// two resulting boxes.
203  GF_API
204  static GfBBox3d Combine(const GfBBox3d &b1, const GfBBox3d &b2);
205 
206  /// Returns the centroid of the bounding box.
207  /// The centroid is computed as the transformed centroid of the range.
208  GF_API
209  GfVec3d ComputeCentroid() const;
210 
211  /// Hash.
212  friend inline size_t hash_value(const GfBBox3d &b) {
213  size_t h = 0;
214  hboost::hash_combine(h, b._box);
215  hboost::hash_combine(h, b._matrix);
216  return h;
217  }
218 
219  /// Component-wise equality 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 &b) const {
224  return (_box == b._box &&
225  _matrix == b._matrix);
226  }
227 
228  /// Component-wise inequality test. The axis-aligned boxes and
229  /// transformation matrices match exactly for bboxes to be considered
230  /// equal. (To compare equality of the actual boxes, you can compute both
231  /// aligned boxes and test the results for equality.)
232  bool operator !=(const GfBBox3d &that) const {
233  return !(*this == that);
234  }
235 
236  private:
237  /// The axis-aligned box.
238  GfRange3d _box;
239  /// Transformation matrix.
240  GfMatrix4d _matrix;
241  /// Inverse of the transformation matrix.
242  GfMatrix4d _inverse;
243  /// Flag indicating whether the matrix is degenerate.
244  bool _isDegenerate;
245  /// Flag indicating whether the bbox contains zero-area primitives.
246  bool _hasZeroAreaPrimitives;
247 
248  /// Sets the transformation matrix and the inverse, checking for
249  /// degeneracies.
250  GF_API
251  void _SetMatrices(const GfMatrix4d &matrix);
252 
253  /// This is used by \c Combine() when it is determined which coordinate
254  /// space to use to combine two boxes: \p b2 is transformed into the space
255  /// of \p b1 and the results are merged in that space.
256  static GfBBox3d _CombineInOrder(const GfBBox3d &b1, const GfBBox3d &b2);
257 };
258 
259 /// Output a GfBBox3d using the format [(range) matrix zeroArea]
260 ///
261 /// The zeroArea flag is true or false and indicates whether the
262 /// bbox has zero area primitives in it.
263 ///
264 /// \ingroup group_gf_DebuggingOutput
265 GF_API std::ostream& operator<<(std::ostream&, const GfBBox3d&);
266 
268 
269 #endif // GF_BBOX3D_H
GF_API GfVec3d ComputeCentroid() const
GfMatrix4d & SetIdentity()
Sets the matrix to the identity matrix.
Definition: matrix4d.h:250
const GfMatrix4d & GetInverseMatrix() const
Definition: bbox3d.h:158
void SetRange(const GfRange3d &box)
Definition: bbox3d.h:136
friend size_t hash_value(const GfBBox3d &b)
Hash.
Definition: bbox3d.h:212
bool operator==(const GfBBox3d &b) const
Definition: bbox3d.h:223
void SetMatrix(const GfMatrix4d &matrix)
Definition: bbox3d.h:130
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:108
GF_API GfRange3d ComputeAlignedRange() const
GfRange3d ComputeAlignedBox() const
Definition: bbox3d.h:195
const GfRange3d & GetRange() const
Returns the range of the axis-aligned untransformed box.
Definition: bbox3d.h:141
GLfloat GLfloat GLfloat GLfloat h
Definition: glew.h:8011
void Set(const GfRange3d &box, const GfMatrix4d &matrix)
Sets the axis-aligned box and transformation matrix.
Definition: bbox3d.h:123
GfBBox3d(const GfBBox3d &rhs)
Copy constructor.
Definition: bbox3d.h:99
GLdouble GLdouble GLdouble b
Definition: glew.h:9122
GF_API std::ostream & operator<<(std::ostream &, const GfBBox3d &)
PXR_NAMESPACE_CLOSE_SCOPE PXR_NAMESPACE_OPEN_SCOPE
Definition: path.h:1245
GfBBox3d(const GfRange3d &box, const GfMatrix4d &matrix)
This constructor takes a box and a transformation matrix.
Definition: bbox3d.h:117
bool HasZeroAreaPrimitives() const
Definition: bbox3d.h:170
Definition: vec3d.h:63
#define PXR_NAMESPACE_CLOSE_SCOPE
Definition: pxr.h:83
void Transform(const GfMatrix4d &matrix)
Definition: bbox3d.h:181
void SetHasZeroAreaPrimitives(bool hasThem)
Definition: bbox3d.h:164
static GF_API GfBBox3d Combine(const GfBBox3d &b1, const GfBBox3d &b2)
GLuint GLenum matrix
Definition: glew.h:14742
#define GF_API
Definition: api.h:40
bool operator!=(const GfBBox3d &that) const
Definition: bbox3d.h:232
const GfRange3d & GetBox() const
Definition: bbox3d.h:147
const GfMatrix4d & GetMatrix() const
Returns the transformation matrix.
Definition: bbox3d.h:152