Panda3D
boundingVolume.cxx
Go to the documentation of this file.
1 /**
2  * PANDA 3D SOFTWARE
3  * Copyright (c) Carnegie Mellon University. All rights reserved.
4  *
5  * All use of this software is subject to the terms of the revised BSD
6  * license. You should have received a copy of this license along
7  * with this source code in a file named "LICENSE."
8  *
9  * @file boundingVolume.cxx
10  * @author drose
11  * @date 1999-10-01
12  */
13 
14 #include "boundingVolume.h"
15 #include "finiteBoundingVolume.h"
16 #include "unionBoundingVolume.h"
18 #include "boundingBox.h"
19 #include "boundingLine.h"
20 #include "boundingPlane.h"
21 #include "boundingSphere.h"
22 #include "boundingHexahedron.h"
23 #include "config_mathutil.h"
24 
25 #include "indent.h"
26 
27 using std::istream;
28 using std::ostream;
29 using std::string;
30 
31 TypeHandle BoundingVolume::_type_handle;
32 
33 
34 /**
35  * Resets the volume to enclose only the volumes indicated. Returns true if
36  * successful, false if the volume doesn't know how to do that or can't do
37  * that.
38  */
40 around(const BoundingVolume **first, const BoundingVolume **last) {
41  _flags = F_empty;
42 
43  // Skip any empty volumes at the beginning of the list. We want to get to
44  // the first real volume.
45  while (first != last && (*first)->is_empty()) {
46  if ((*first)->is_infinite()) {
47  // If we go around an infinite volume, we're infinite too.
48  _flags = F_infinite;
49  return true;
50  }
51  ++first;
52  }
53 
54  bool okflag = true;
55 
56  if (first != last) {
57  // Check for more infinite bounding volumes in the list.
58  const BoundingVolume **bvi;
59  for (bvi = first; bvi != last; ++bvi) {
60  if ((*bvi)->is_infinite()) {
61  _flags = F_infinite;
62  return true;
63  }
64  }
65 
66  // This is a double-dispatch. We call this virtual function on the volume
67  // we were given, which will in turn call the appropriate virtual function
68  // in our own class to perform the operation.
69  if (!(*first)->around_other(this, first, last)) {
70  okflag = false;
71  }
72  }
73 
74  return okflag;
75 }
76 
77 /**
78  *
79  */
80 void BoundingVolume::
81 write(ostream &out, int indent_level) const {
82  indent(out, indent_level) << *this << "\n";
83 }
84 
85 /**
86  * Virtual downcast method. Returns this object as a pointer of the indicated
87  * type, if it is in fact that type. Returns NULL if it is not that type.
88  */
91  return nullptr;
92 }
93 
94 /**
95  * Virtual downcast method. Returns this object as a pointer of the indicated
96  * type, if it is in fact that type. Returns NULL if it is not that type.
97  */
100  return nullptr;
101 }
102 
103 /**
104  * Virtual downcast method. Returns this object as a pointer of the indicated
105  * type, if it is in fact that type. Returns NULL if it is not that type.
106  */
109  return nullptr;
110 }
111 
112 /**
113  * Virtual downcast method. Returns this object as a pointer of the indicated
114  * type, if it is in fact that type. Returns NULL if it is not that type.
115  */
118  return nullptr;
119 }
120 
121 /**
122  * Virtual downcast method. Returns this object as a pointer of the indicated
123  * type, if it is in fact that type. Returns NULL if it is not that type.
124  */
127  return nullptr;
128 }
129 
130 /**
131  * Virtual downcast method. Returns this object as a pointer of the indicated
132  * type, if it is in fact that type. Returns NULL if it is not that type.
133  */
136  return nullptr;
137 }
138 
139 /**
140  * Virtual downcast method. Returns this object as a pointer of the indicated
141  * type, if it is in fact that type. Returns NULL if it is not that type.
142  */
145  return nullptr;
146 }
147 
148 /**
149  * Virtual downcast method. Returns this object as a pointer of the indicated
150  * type, if it is in fact that type. Returns NULL if it is not that type.
151  */
154  return nullptr;
155 }
156 
157 /**
158  * Returns the BoundsType corresponding to the indicated string.
159  */
160 BoundingVolume::BoundsType BoundingVolume::
161 string_bounds_type(const string &str) {
162  if (strcmp(str.c_str(), "default") == 0) {
163  return BT_default;
164 
165  } else if (strcmp(str.c_str(), "best") == 0) {
166  return BT_best;
167 
168  } else if (strcmp(str.c_str(), "fastest") == 0) {
169  return BT_fastest;
170 
171  } else if (strcmp(str.c_str(), "sphere") == 0) {
172  return BT_sphere;
173 
174  } else if (strcmp(str.c_str(), "box") == 0) {
175  return BT_box;
176  }
177 
178  return BT_default;
179 }
180 
181 /**
182  * Double-dispatch support: called by extend_other() when the type we're
183  * extending by is known to be a sphere.
184  */
185 bool BoundingVolume::
186 extend_by_sphere(const BoundingSphere *sphere) {
187  return extend_by_finite(sphere);
188 }
189 
190 /**
191  * Double-dispatch support: called by extend_other() when the type we're
192  * extending by is known to be a box.
193  */
194 bool BoundingVolume::
195 extend_by_box(const BoundingBox *box) {
196  return extend_by_finite(box);
197 }
198 
199 /**
200  * Double-dispatch support: called by extend_other() when the type we're
201  * extending by is known to be a hexahedron.
202  */
203 bool BoundingVolume::
204 extend_by_hexahedron(const BoundingHexahedron *hexahedron) {
205  return extend_by_finite(hexahedron);
206 }
207 
208 /**
209  * Double-dispatch support: called by extend_other() when the type we're
210  * extending by is known to be a line.
211  */
212 bool BoundingVolume::
213 extend_by_line(const BoundingLine *line) {
214  return extend_by_geometric(line);
215 }
216 
217 /**
218  * Double-dispatch support: called by extend_other() when the type we're
219  * extending by is known to be a plane.
220  */
221 bool BoundingVolume::
222 extend_by_plane(const BoundingPlane *plane) {
223  return extend_by_geometric(plane);
224 }
225 
226 /**
227  * Double-dispatch support: called by extend_other() when the type we're
228  * extending by is known to be a union.
229  */
230 bool BoundingVolume::
231 extend_by_union(const UnionBoundingVolume *unionv) {
232  return extend_by_geometric(unionv);
233 }
234 
235 /**
236  * Double-dispatch support: called by extend_other() when the type we're
237  * extending by is known to be a intersection.
238  */
239 bool BoundingVolume::
240 extend_by_intersection(const IntersectionBoundingVolume *intersection) {
241  return extend_by_geometric(intersection);
242 }
243 
244 /**
245  * Generic handler for a FiniteBoundingVolume.
246  */
247 bool BoundingVolume::
248 extend_by_finite(const FiniteBoundingVolume *volume) {
249  return extend_by_geometric(volume);
250 }
251 
252 /**
253  * Generic handler for a GeometricBoundingVolume.
254  */
255 bool BoundingVolume::
256 extend_by_geometric(const GeometricBoundingVolume *volume) {
257  mathutil_cat.warning()
258  << get_type() << "::extend_by_geometric() called with " << volume->get_type() << "\n";
259  _flags = F_infinite;
260  return false;
261 }
262 
263 /**
264  * Double-dispatch support: called by around_other() when the type of the
265  * first element in the list is known to be a nonempty sphere.
266  */
267 bool BoundingVolume::
268 around_spheres(const BoundingVolume **first, const BoundingVolume **last) {
269  return around_finite(first, last);
270 }
271 
272 /**
273  * Double-dispatch support: called by around_other() when the type of the
274  * first element in the list is known to be a nonempty box.
275  */
276 bool BoundingVolume::
277 around_boxes(const BoundingVolume **first, const BoundingVolume **last) {
278  return around_finite(first, last);
279 }
280 
281 /**
282  * Double-dispatch support: called by around_other() when the type of the
283  * first element in the list is known to be a nonempty hexahedron.
284  */
285 bool BoundingVolume::
286 around_hexahedrons(const BoundingVolume **first, const BoundingVolume **last) {
287  return around_finite(first, last);
288 }
289 
290 /**
291  * Double-dispatch support: called by around_other() when the type of the
292  * first element in the list is known to be a nonempty line.
293  */
294 bool BoundingVolume::
295 around_lines(const BoundingVolume **first, const BoundingVolume **last) {
296  return around_geometric(first, last);
297 }
298 
299 /**
300  * Double-dispatch support: called by around_other() when the type of the
301  * first element in the list is known to be a nonempty plane.
302  */
303 bool BoundingVolume::
304 around_planes(const BoundingVolume **first, const BoundingVolume **last) {
305  return around_geometric(first, last);
306 }
307 
308 /**
309  * Double-dispatch support: called by around_other() when the type of the
310  * first element in the list is known to be a union object.
311  */
312 bool BoundingVolume::
313 around_unions(const BoundingVolume **first, const BoundingVolume **last) {
314  return around_geometric(first, last);
315 }
316 
317 /**
318  * Double-dispatch support: called by around_other() when the type of the
319  * first element in the list is known to be an intersection object.
320  */
321 bool BoundingVolume::
322 around_intersections(const BoundingVolume **first, const BoundingVolume **last) {
323  return around_geometric(first, last);
324 }
325 
326 /**
327  * Generic handler for a FiniteBoundingVolume.
328  */
329 bool BoundingVolume::
330 around_finite(const BoundingVolume **first, const BoundingVolume **last) {
331  return around_geometric(first, last);
332 }
333 
334 /**
335  * Generic handler for a GeometricBoundingVolume.
336  */
337 bool BoundingVolume::
338 around_geometric(const BoundingVolume **first, const BoundingVolume **last) {
339  mathutil_cat.warning()
340  << get_type() << "::extend_by_geometric() called with " << first[0]->get_type() << "\n";
341  _flags = F_infinite;
342  return false;
343 }
344 
345 /**
346  * Double-dispatch support: called by contains_other() when the type we're
347  * testing for intersection is known to be a sphere.
348  */
349 int BoundingVolume::
350 contains_sphere(const BoundingSphere *sphere) const {
351  return contains_finite(sphere);
352 }
353 
354 /**
355  * Double-dispatch support: called by contains_other() when the type we're
356  * testing for intersection is known to be a box.
357  */
358 int BoundingVolume::
359 contains_box(const BoundingBox *box) const {
360  return contains_finite(box);
361 }
362 
363 /**
364  * Double-dispatch support: called by contains_other() when the type we're
365  * testing for intersection is known to be a hexahedron.
366  */
367 int BoundingVolume::
368 contains_hexahedron(const BoundingHexahedron *hexahedron) const {
369  return contains_finite(hexahedron);
370 }
371 
372 /**
373  * Double-dispatch support: called by contains_other() when the type we're
374  * testing for intersection is known to be a line.
375  */
376 int BoundingVolume::
377 contains_line(const BoundingLine *line) const {
378  return contains_geometric(line);
379 }
380 
381 /**
382  * Double-dispatch support: called by contains_other() when the type we're
383  * testing for intersection is known to be a plane.
384  */
385 int BoundingVolume::
386 contains_plane(const BoundingPlane *plane) const {
387  return contains_geometric(plane);
388 }
389 
390 /**
391  * Double-dispatch support: called by contains_other() when the type we're
392  * testing for intersection is known to be a union object.
393  */
394 int BoundingVolume::
395 contains_union(const UnionBoundingVolume *unionv) const {
396  return unionv->other_contains_union(this);
397 }
398 
399 /**
400  * Double-dispatch support: called by contains_other() when the type we're
401  * testing for intersection is known to be an intersection object.
402  */
403 int BoundingVolume::
404 contains_intersection(const IntersectionBoundingVolume *intersection) const {
405  return intersection->other_contains_intersection(this);
406 }
407 
408 /**
409  * Generic handler for a FiniteBoundingVolume.
410  */
411 int BoundingVolume::
412 contains_finite(const FiniteBoundingVolume *volume) const {
413  return contains_geometric(volume);
414 }
415 
416 /**
417  * Generic handler for a GeometricBoundingVolume.
418  */
419 int BoundingVolume::
420 contains_geometric(const GeometricBoundingVolume *volume) const {
421  mathutil_cat.warning()
422  << get_type() << "::contains_geometric() called with " << volume->get_type() << "\n";
423  return IF_dont_understand;
424 }
425 
426 ostream &
427 operator << (ostream &out, BoundingVolume::BoundsType type) {
428  switch (type) {
429  case BoundingVolume::BT_default:
430  return out << "default";
431 
432  case BoundingVolume::BT_best:
433  return out << "best";
434 
435  case BoundingVolume::BT_fastest:
436  return out << "fastest";
437 
438  case BoundingVolume::BT_sphere:
439  return out << "sphere";
440 
441  case BoundingVolume::BT_box:
442  return out << "box";
443  }
444 
445  mathutil_cat.error()
446  << "Invalid BoundingVolume::BoundsType value: " << (int)type << "\n";
447  nassertr(false, out);
448  return out;
449 }
450 
451 istream &
452 operator >> (istream &in, BoundingVolume::BoundsType &type) {
453  string word;
454  in >> word;
456  if (type == BoundingVolume::BT_default) {
457  mathutil_cat->error()
458  << "Invalid BoundingVolume::BoundsType string: " << word << "\n";
459  }
460  return in;
461 }
An axis-aligned bounding box; that is, a minimum and maximum coordinate triple.
Definition: boundingBox.h:29
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
virtual const BoundingLine * as_bounding_line() const
Virtual downcast method.
bool is_empty() const
Any kind of volume might be empty.
This defines a bounding sphere, consisting of a center and a radius.
virtual const BoundingHexahedron * as_bounding_hexahedron() const
Virtual downcast method.
static BoundsType string_bounds_type(const std::string &str)
Returns the BoundsType corresponding to the indicated string.
virtual const BoundingBox * as_bounding_box() const
Virtual downcast method.
This funny bounding volume is an infinite plane that divides space into two regions: the part behind ...
Definition: boundingPlane.h:28
virtual const BoundingPlane * as_bounding_plane() const
Virtual downcast method.
This is an abstract class for any volume in any sense which can be said to define the locality of ref...
virtual const BoundingSphere * as_bounding_sphere() const
Virtual downcast method.
This is another abstract class, for a general class of bounding volumes that actually enclose points ...
virtual const FiniteBoundingVolume * as_finite_bounding_volume() const
Virtual downcast method.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
This special bounding volume is the intersection of all of its constituent bounding volumes.
This special bounding volume is the union of all of its constituent bounding volumes.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
std::ostream & indent(std::ostream &out, int indent_level)
A handy function for doing text formatting.
Definition: indent.cxx:20
A special kind of GeometricBoundingVolume that is known to be finite.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
bool around(const BoundingVolume **first, const BoundingVolume **last)
Resets the volume to enclose only the volumes indicated.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:81
virtual GeometricBoundingVolume * as_geometric_bounding_volume()
Virtual downcast method.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
This defines a bounding convex hexahedron.
This funny bounding volume is an infinite line with no thickness and extending to infinity in both di...
Definition: boundingLine.h:29
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.