Panda3D
boundingVolume.cxx
1 // Filename: boundingVolume.cxx
2 // Created by: drose (01Oct99)
3 //
4 ////////////////////////////////////////////////////////////////////
5 //
6 // PANDA 3D SOFTWARE
7 // Copyright (c) Carnegie Mellon University. All rights reserved.
8 //
9 // All use of this software is subject to the terms of the revised BSD
10 // license. You should have received a copy of this license along
11 // with this source code in a file named "LICENSE."
12 //
13 ////////////////////////////////////////////////////////////////////
14 
15 #include "boundingVolume.h"
16 #include "finiteBoundingVolume.h"
17 #include "unionBoundingVolume.h"
18 #include "intersectionBoundingVolume.h"
19 #include "boundingBox.h"
20 #include "boundingLine.h"
21 #include "boundingPlane.h"
22 #include "boundingSphere.h"
23 #include "boundingHexahedron.h"
24 #include "config_mathutil.h"
25 
26 #include "indent.h"
27 
28 TypeHandle BoundingVolume::_type_handle;
29 
30 
31 ////////////////////////////////////////////////////////////////////
32 // Function: BoundingVolume::around
33 // Access: Published
34 // Description: Resets the volume to enclose only the volumes
35 // indicated. Returns true if successful, false if the
36 // volume doesn't know how to do that or can't do that.
37 ////////////////////////////////////////////////////////////////////
39 around(const BoundingVolume **first, const BoundingVolume **last) {
40  _flags = F_empty;
41 
42  // Skip any empty volumes at the beginning of the list. We want to
43  // get to the first real volume.
44  while (first != last && (*first)->is_empty()) {
45  if ((*first)->is_infinite()) {
46  // If we go around an infinite volume, we're infinite too.
47  _flags = F_infinite;
48  return true;
49  }
50  ++first;
51  }
52 
53  bool okflag = true;
54 
55  if (first != last) {
56  // Check for more infinite bounding volumes in the list.
57  const BoundingVolume **bvi;
58  for (bvi = first; bvi != last; ++bvi) {
59  if ((*bvi)->is_infinite()) {
60  _flags = F_infinite;
61  return true;
62  }
63  }
64 
65  // This is a double-dispatch. We call this virtual function on
66  // the volume we were given, which will in turn call the
67  // appropriate virtual function in our own class to perform the
68  // operation.
69  if (!(*first)->around_other(this, first, last)) {
70  okflag = false;
71  }
72  }
73 
74  return okflag;
75 }
76 
77 ////////////////////////////////////////////////////////////////////
78 // Function: BoundingVolume::write
79 // Access: Published
80 // Description:
81 ////////////////////////////////////////////////////////////////////
82 void BoundingVolume::
83 write(ostream &out, int indent_level) const {
84  indent(out, indent_level) << *this << "\n";
85 }
86 
87 ////////////////////////////////////////////////////////////////////
88 // Function: BoundingVolume::as_geometric_bounding_volume
89 // Access: Public, Virtual
90 // Description: Virtual downcast method. Returns this object as a
91 // pointer of the indicated type, if it is in fact that
92 // type. Returns NULL if it is not that type.
93 ////////////////////////////////////////////////////////////////////
96  return NULL;
97 }
98 
99 ////////////////////////////////////////////////////////////////////
100 // Function: BoundingVolume::as_finite_bounding_volume
101 // Access: Public, Virtual
102 // Description: Virtual downcast method. Returns this object as a
103 // pointer of the indicated type, if it is in fact that
104 // type. Returns NULL if it is not that type.
105 ////////////////////////////////////////////////////////////////////
108  return NULL;
109 }
110 
111 ////////////////////////////////////////////////////////////////////
112 // Function: BoundingVolume::as_bounding_sphere
113 // Access: Public, Virtual
114 // Description: Virtual downcast method. Returns this object as a
115 // pointer of the indicated type, if it is in fact that
116 // type. Returns NULL if it is not that type.
117 ////////////////////////////////////////////////////////////////////
120  return NULL;
121 }
122 
123 ////////////////////////////////////////////////////////////////////
124 // Function: BoundingVolume::as_bounding_box
125 // Access: Public, Virtual
126 // Description: Virtual downcast method. Returns this object as a
127 // pointer of the indicated type, if it is in fact that
128 // type. Returns NULL if it is not that type.
129 ////////////////////////////////////////////////////////////////////
132  return NULL;
133 }
134 
135 ////////////////////////////////////////////////////////////////////
136 // Function: BoundingVolume::as_bounding_hexahedron
137 // Access: Public, Virtual
138 // Description: Virtual downcast method. Returns this object as a
139 // pointer of the indicated type, if it is in fact that
140 // type. Returns NULL if it is not that type.
141 ////////////////////////////////////////////////////////////////////
144  return NULL;
145 }
146 
147 ////////////////////////////////////////////////////////////////////
148 // Function: BoundingVolume::as_bounding_line
149 // Access: Public, Virtual
150 // Description: Virtual downcast method. Returns this object as a
151 // pointer of the indicated type, if it is in fact that
152 // type. Returns NULL if it is not that type.
153 ////////////////////////////////////////////////////////////////////
156  return NULL;
157 }
158 
159 ////////////////////////////////////////////////////////////////////
160 // Function: BoundingVolume::as_bounding_plane
161 // Access: Public, Virtual
162 // Description: Virtual downcast method. Returns this object as a
163 // pointer of the indicated type, if it is in fact that
164 // type. Returns NULL if it is not that type.
165 ////////////////////////////////////////////////////////////////////
168  return NULL;
169 }
170 
171 ////////////////////////////////////////////////////////////////////
172 // Function: BoundingVolume::string_bounds_type
173 // Access: Public, Static
174 // Description: Returns the BoundsType corresponding to the indicated
175 // string.
176 ////////////////////////////////////////////////////////////////////
177 BoundingVolume::BoundsType BoundingVolume::
178 string_bounds_type(const string &str) {
179  if (strcmp(str.c_str(), "default") == 0) {
180  return BT_default;
181 
182  } else if (strcmp(str.c_str(), "best") == 0) {
183  return BT_best;
184 
185  } else if (strcmp(str.c_str(), "fastest") == 0) {
186  return BT_fastest;
187 
188  } else if (strcmp(str.c_str(), "sphere") == 0) {
189  return BT_sphere;
190 
191  } else if (strcmp(str.c_str(), "box") == 0) {
192  return BT_box;
193  }
194 
195  return BT_default;
196 }
197 
198 ////////////////////////////////////////////////////////////////////
199 // Function: BoundingVolume::extend_by_sphere
200 // Access: Protected, Virtual
201 // Description: Double-dispatch support: called by extend_other()
202 // when the type we're extending by is known to be a
203 // sphere.
204 ////////////////////////////////////////////////////////////////////
205 bool BoundingVolume::
206 extend_by_sphere(const BoundingSphere *sphere) {
207  return extend_by_finite(sphere);
208 }
209 
210 ////////////////////////////////////////////////////////////////////
211 // Function: BoundingVolume::extend_by_box
212 // Access: Protected, Virtual
213 // Description: Double-dispatch support: called by extend_other()
214 // when the type we're extending by is known to be a
215 // box.
216 ////////////////////////////////////////////////////////////////////
217 bool BoundingVolume::
218 extend_by_box(const BoundingBox *box) {
219  return extend_by_finite(box);
220 }
221 
222 ////////////////////////////////////////////////////////////////////
223 // Function: BoundingVolume::extend_by_hexahedron
224 // Access: Protected, Virtual
225 // Description: Double-dispatch support: called by extend_other()
226 // when the type we're extending by is known to be a
227 // hexahedron.
228 ////////////////////////////////////////////////////////////////////
229 bool BoundingVolume::
230 extend_by_hexahedron(const BoundingHexahedron *hexahedron) {
231  return extend_by_finite(hexahedron);
232 }
233 
234 ////////////////////////////////////////////////////////////////////
235 // Function: BoundingVolume::extend_by_line
236 // Access: Protected, Virtual
237 // Description: Double-dispatch support: called by extend_other()
238 // when the type we're extending by is known to be a
239 // line.
240 ////////////////////////////////////////////////////////////////////
241 bool BoundingVolume::
242 extend_by_line(const BoundingLine *line) {
243  return extend_by_geometric(line);
244 }
245 
246 ////////////////////////////////////////////////////////////////////
247 // Function: BoundingVolume::extend_by_plane
248 // Access: Protected, Virtual
249 // Description: Double-dispatch support: called by extend_other()
250 // when the type we're extending by is known to be a
251 // plane.
252 ////////////////////////////////////////////////////////////////////
253 bool BoundingVolume::
254 extend_by_plane(const BoundingPlane *plane) {
255  return extend_by_geometric(plane);
256 }
257 
258 ////////////////////////////////////////////////////////////////////
259 // Function: BoundingVolume::extend_by_union
260 // Access: Protected, Virtual
261 // Description: Double-dispatch support: called by extend_other()
262 // when the type we're extending by is known to be a
263 // union.
264 ////////////////////////////////////////////////////////////////////
265 bool BoundingVolume::
266 extend_by_union(const UnionBoundingVolume *unionv) {
267  return extend_by_geometric(unionv);
268 }
269 
270 ////////////////////////////////////////////////////////////////////
271 // Function: BoundingVolume::extend_by_intersection
272 // Access: Protected, Virtual
273 // Description: Double-dispatch support: called by extend_other()
274 // when the type we're extending by is known to be a
275 // intersection.
276 ////////////////////////////////////////////////////////////////////
277 bool BoundingVolume::
278 extend_by_intersection(const IntersectionBoundingVolume *intersection) {
279  return extend_by_geometric(intersection);
280 }
281 
282 ////////////////////////////////////////////////////////////////////
283 // Function: BoundingVolume::extend_by_finite
284 // Access: Protected, Virtual
285 // Description: Generic handler for a FiniteBoundingVolume.
286 ////////////////////////////////////////////////////////////////////
287 bool BoundingVolume::
288 extend_by_finite(const FiniteBoundingVolume *volume) {
289  return extend_by_geometric(volume);
290 }
291 
292 ////////////////////////////////////////////////////////////////////
293 // Function: BoundingVolume::extend_by_geometric
294 // Access: Protected, Virtual
295 // Description: Generic handler for a GeometricBoundingVolume.
296 ////////////////////////////////////////////////////////////////////
297 bool BoundingVolume::
298 extend_by_geometric(const GeometricBoundingVolume *volume) {
299  mathutil_cat.warning()
300  << get_type() << "::extend_by_geometric() called with " << volume->get_type() << "\n";
301  _flags = F_infinite;
302  return false;
303 }
304 
305 ////////////////////////////////////////////////////////////////////
306 // Function: BoundingVolume::around_spheres
307 // Access: Protected, Virtual
308 // Description: Double-dispatch support: called by around_other()
309 // when the type of the first element in the list is
310 // known to be a nonempty sphere.
311 ////////////////////////////////////////////////////////////////////
312 bool BoundingVolume::
313 around_spheres(const BoundingVolume **first, const BoundingVolume **last) {
314  return around_finite(first, last);
315 }
316 
317 ////////////////////////////////////////////////////////////////////
318 // Function: BoundingVolume::around_boxes
319 // Access: Protected, Virtual
320 // Description: Double-dispatch support: called by around_other()
321 // when the type of the first element in the list is
322 // known to be a nonempty box.
323 ////////////////////////////////////////////////////////////////////
324 bool BoundingVolume::
325 around_boxes(const BoundingVolume **first, const BoundingVolume **last) {
326  return around_finite(first, last);
327 }
328 
329 ////////////////////////////////////////////////////////////////////
330 // Function: BoundingVolume::around_hexahedrons
331 // Access: Protected, Virtual
332 // Description: Double-dispatch support: called by around_other()
333 // when the type of the first element in the list is
334 // known to be a nonempty hexahedron.
335 ////////////////////////////////////////////////////////////////////
336 bool BoundingVolume::
337 around_hexahedrons(const BoundingVolume **first, const BoundingVolume **last) {
338  return around_finite(first, last);
339 }
340 
341 ////////////////////////////////////////////////////////////////////
342 // Function: BoundingVolume::around_lines
343 // Access: Protected, Virtual
344 // Description: Double-dispatch support: called by around_other()
345 // when the type of the first element in the list is
346 // known to be a nonempty line.
347 ////////////////////////////////////////////////////////////////////
348 bool BoundingVolume::
349 around_lines(const BoundingVolume **first, const BoundingVolume **last) {
350  return around_geometric(first, last);
351 }
352 
353 ////////////////////////////////////////////////////////////////////
354 // Function: BoundingVolume::around_planes
355 // Access: Protected, Virtual
356 // Description: Double-dispatch support: called by around_other()
357 // when the type of the first element in the list is
358 // known to be a nonempty plane.
359 ////////////////////////////////////////////////////////////////////
360 bool BoundingVolume::
361 around_planes(const BoundingVolume **first, const BoundingVolume **last) {
362  return around_geometric(first, last);
363 }
364 
365 ////////////////////////////////////////////////////////////////////
366 // Function: BoundingVolume::around_unions
367 // Access: Protected, Virtual
368 // Description: Double-dispatch support: called by around_other()
369 // when the type of the first element in the list is
370 // known to be a union object.
371 ////////////////////////////////////////////////////////////////////
372 bool BoundingVolume::
373 around_unions(const BoundingVolume **first, const BoundingVolume **last) {
374  return around_geometric(first, last);
375 }
376 
377 ////////////////////////////////////////////////////////////////////
378 // Function: BoundingVolume::around_intersections
379 // Access: Protected, Virtual
380 // Description: Double-dispatch support: called by around_other()
381 // when the type of the first element in the list is
382 // known to be an intersection object.
383 ////////////////////////////////////////////////////////////////////
384 bool BoundingVolume::
385 around_intersections(const BoundingVolume **first, const BoundingVolume **last) {
386  return around_geometric(first, last);
387 }
388 
389 ////////////////////////////////////////////////////////////////////
390 // Function: BoundingVolume::around_finite
391 // Access: Protected, Virtual
392 // Description: Generic handler for a FiniteBoundingVolume.
393 ////////////////////////////////////////////////////////////////////
394 bool BoundingVolume::
395 around_finite(const BoundingVolume **first, const BoundingVolume **last) {
396  return around_geometric(first, last);
397 }
398 
399 ////////////////////////////////////////////////////////////////////
400 // Function: BoundingVolume::around_geometric
401 // Access: Protected, Virtual
402 // Description: Generic handler for a GeometricBoundingVolume.
403 ////////////////////////////////////////////////////////////////////
404 bool BoundingVolume::
405 around_geometric(const BoundingVolume **first, const BoundingVolume **last) {
406  mathutil_cat.warning()
407  << get_type() << "::extend_by_geometric() called with " << first[0]->get_type() << "\n";
408  _flags = F_infinite;
409  return false;
410 }
411 
412 ////////////////////////////////////////////////////////////////////
413 // Function: BoundingVolume::contains_sphere
414 // Access: Protected, Virtual
415 // Description: Double-dispatch support: called by contains_other()
416 // when the type we're testing for intersection is known
417 // to be a sphere.
418 ////////////////////////////////////////////////////////////////////
419 int BoundingVolume::
420 contains_sphere(const BoundingSphere *sphere) const {
421  return contains_finite(sphere);
422 }
423 
424 ////////////////////////////////////////////////////////////////////
425 // Function: BoundingVolume::contains_box
426 // Access: Protected, Virtual
427 // Description: Double-dispatch support: called by contains_other()
428 // when the type we're testing for intersection is known
429 // to be a box.
430 ////////////////////////////////////////////////////////////////////
431 int BoundingVolume::
432 contains_box(const BoundingBox *box) const {
433  return contains_finite(box);
434 }
435 
436 ////////////////////////////////////////////////////////////////////
437 // Function: BoundingVolume::contains_hexahedron
438 // Access: Protected, Virtual
439 // Description: Double-dispatch support: called by contains_other()
440 // when the type we're testing for intersection is known
441 // to be a hexahedron.
442 ////////////////////////////////////////////////////////////////////
443 int BoundingVolume::
444 contains_hexahedron(const BoundingHexahedron *hexahedron) const {
445  return contains_finite(hexahedron);
446 }
447 
448 ////////////////////////////////////////////////////////////////////
449 // Function: BoundingVolume::contains_line
450 // Access: Protected, Virtual
451 // Description: Double-dispatch support: called by contains_other()
452 // when the type we're testing for intersection is known
453 // to be a line.
454 ////////////////////////////////////////////////////////////////////
455 int BoundingVolume::
456 contains_line(const BoundingLine *line) const {
457  return contains_geometric(line);
458 }
459 
460 ////////////////////////////////////////////////////////////////////
461 // Function: BoundingVolume::contains_plane
462 // Access: Protected, Virtual
463 // Description: Double-dispatch support: called by contains_other()
464 // when the type we're testing for intersection is known
465 // to be a plane.
466 ////////////////////////////////////////////////////////////////////
467 int BoundingVolume::
468 contains_plane(const BoundingPlane *plane) const {
469  return contains_geometric(plane);
470 }
471 
472 ////////////////////////////////////////////////////////////////////
473 // Function: BoundingVolume::contains_union
474 // Access: Protected, Virtual
475 // Description: Double-dispatch support: called by contains_other()
476 // when the type we're testing for intersection is known
477 // to be a union object.
478 ////////////////////////////////////////////////////////////////////
479 int BoundingVolume::
480 contains_union(const UnionBoundingVolume *unionv) const {
481  return unionv->other_contains_union(this);
482 }
483 
484 ////////////////////////////////////////////////////////////////////
485 // Function: BoundingVolume::contains_intersection
486 // Access: Protected, Virtual
487 // Description: Double-dispatch support: called by contains_other()
488 // when the type we're testing for intersection is known
489 // to be an intersection object.
490 ////////////////////////////////////////////////////////////////////
491 int BoundingVolume::
492 contains_intersection(const IntersectionBoundingVolume *intersection) const {
493  return intersection->other_contains_intersection(this);
494 }
495 
496 ////////////////////////////////////////////////////////////////////
497 // Function: BoundingVolume::contains_finite
498 // Access: Protected, Virtual
499 // Description: Generic handler for a FiniteBoundingVolume.
500 ////////////////////////////////////////////////////////////////////
501 int BoundingVolume::
502 contains_finite(const FiniteBoundingVolume *volume) const {
503  return contains_geometric(volume);
504 }
505 
506 ////////////////////////////////////////////////////////////////////
507 // Function: BoundingVolume::contains_geometric
508 // Access: Protected, Virtual
509 // Description: Generic handler for a GeometricBoundingVolume.
510 ////////////////////////////////////////////////////////////////////
511 int BoundingVolume::
512 contains_geometric(const GeometricBoundingVolume *volume) const {
513  mathutil_cat.warning()
514  << get_type() << "::contains_geometric() called with " << volume->get_type() << "\n";
515  return IF_dont_understand;
516 }
517 
518 ostream &
519 operator << (ostream &out, BoundingVolume::BoundsType type) {
520  switch (type) {
521  case BoundingVolume::BT_default:
522  return out << "default";
523 
524  case BoundingVolume::BT_best:
525  return out << "best";
526 
527  case BoundingVolume::BT_fastest:
528  return out << "fastest";
529 
530  case BoundingVolume::BT_sphere:
531  return out << "sphere";
532 
533  case BoundingVolume::BT_box:
534  return out << "box";
535  }
536 
537  mathutil_cat.error()
538  << "Invalid BoundingVolume::BoundsType value: " << (int)type << "\n";
539  nassertr(false, out);
540  return out;
541 }
542 
543 istream &
544 operator >> (istream &in, BoundingVolume::BoundsType &type) {
545  string word;
546  in >> word;
548  if (type == BoundingVolume::BT_default) {
549  mathutil_cat->error()
550  << "Invalid BoundingVolume::BoundsType string: " << word << "\n";
551  }
552  return in;
553 }
554 
virtual const GeometricBoundingVolume * as_geometric_bounding_volume() const
Virtual downcast method.
An axis-aligned bounding box; that is, a minimum and maximum coordinate triple.
Definition: boundingBox.h:31
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.
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:31
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.
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.
static BoundsType string_bounds_type(const string &str)
Returns the BoundsType corresponding to the indicated string.
A special kind of GeometricBoundingVolume that is known to be finite.
bool around(const BoundingVolume **first, const BoundingVolume **last)
Resets the volume to enclose only the volumes indicated.
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:85
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:33