Panda3D
 All Classes Functions Variables Enumerations
boundingVolume.cxx
00001 // Filename: boundingVolume.cxx
00002 // Created by:  drose (01Oct99)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) Carnegie Mellon University.  All rights reserved.
00008 //
00009 // All use of this software is subject to the terms of the revised BSD
00010 // license.  You should have received a copy of this license along
00011 // with this source code in a file named "LICENSE."
00012 //
00013 ////////////////////////////////////////////////////////////////////
00014 
00015 #include "boundingVolume.h"
00016 #include "finiteBoundingVolume.h"
00017 #include "unionBoundingVolume.h"
00018 #include "intersectionBoundingVolume.h"
00019 
00020 #include "indent.h"
00021 
00022 TypeHandle BoundingVolume::_type_handle;
00023 
00024 
00025 ////////////////////////////////////////////////////////////////////
00026 //     Function: BoundingVolume::around
00027 //       Access: Published
00028 //  Description: Resets the volume to enclose only the volumes
00029 //               indicated.  Returns true if successful, false if the
00030 //               volume doesn't know how to do that or can't do that.
00031 ////////////////////////////////////////////////////////////////////
00032 bool BoundingVolume::
00033 around(const BoundingVolume **first, const BoundingVolume **last) {
00034   _flags = F_empty;
00035 
00036   // Skip any empty volumes at the beginning of the list.  We want to
00037   // get to the first real volume.
00038   while (first != last && (*first)->is_empty()) {
00039     if ((*first)->is_infinite()) {
00040       // If we go around an infinite volume, we're infinite too.
00041       _flags = F_infinite;
00042       return true;
00043     }
00044     ++first;
00045   }
00046 
00047   bool okflag = true;
00048 
00049   if (first != last) {
00050     // Check for more infinite bounding volumes in the list.
00051     const BoundingVolume **bvi;
00052     for (bvi = first; bvi != last; ++bvi) {
00053       if ((*bvi)->is_infinite()) {
00054         _flags = F_infinite;
00055         return true;
00056       }
00057     }
00058 
00059     // This is a double-dispatch.  We call this virtual function on
00060     // the volume we were given, which will in turn call the
00061     // appropriate virtual function in our own class to perform the
00062     // operation.
00063     if (!(*first)->around_other(this, first, last)) {
00064       okflag = false;
00065     }
00066   }
00067 
00068   return okflag;
00069 }
00070 
00071 ////////////////////////////////////////////////////////////////////
00072 //     Function: BoundingVolume::write
00073 //       Access: Published
00074 //  Description:
00075 ////////////////////////////////////////////////////////////////////
00076 void BoundingVolume::
00077 write(ostream &out, int indent_level) const {
00078   indent(out, indent_level) << *this << "\n";
00079 }
00080 
00081 ////////////////////////////////////////////////////////////////////
00082 //     Function: BoundingVolume::as_geometric_bounding_volume
00083 //       Access: Public, Virtual
00084 //  Description: Virtual downcast method.  Returns this object as a
00085 //               pointer of the indicated type, if it is in fact that
00086 //               type.  Returns NULL if it is not that type.
00087 ////////////////////////////////////////////////////////////////////
00088 const GeometricBoundingVolume *BoundingVolume::
00089 as_geometric_bounding_volume() const {
00090   return NULL;
00091 }
00092 
00093 ////////////////////////////////////////////////////////////////////
00094 //     Function: BoundingVolume::as_finite_bounding_volume
00095 //       Access: Public, Virtual
00096 //  Description: Virtual downcast method.  Returns this object as a
00097 //               pointer of the indicated type, if it is in fact that
00098 //               type.  Returns NULL if it is not that type.
00099 ////////////////////////////////////////////////////////////////////
00100 const FiniteBoundingVolume *BoundingVolume::
00101 as_finite_bounding_volume() const {
00102   return NULL;
00103 }
00104 
00105 ////////////////////////////////////////////////////////////////////
00106 //     Function: BoundingVolume::as_bounding_sphere
00107 //       Access: Public, Virtual
00108 //  Description: Virtual downcast method.  Returns this object as a
00109 //               pointer of the indicated type, if it is in fact that
00110 //               type.  Returns NULL if it is not that type.
00111 ////////////////////////////////////////////////////////////////////
00112 const BoundingSphere *BoundingVolume::
00113 as_bounding_sphere() const {
00114   return NULL;
00115 }
00116 
00117 ////////////////////////////////////////////////////////////////////
00118 //     Function: BoundingVolume::as_bounding_box
00119 //       Access: Public, Virtual
00120 //  Description: Virtual downcast method.  Returns this object as a
00121 //               pointer of the indicated type, if it is in fact that
00122 //               type.  Returns NULL if it is not that type.
00123 ////////////////////////////////////////////////////////////////////
00124 const BoundingBox *BoundingVolume::
00125 as_bounding_box() const {
00126   return NULL;
00127 }
00128 
00129 ////////////////////////////////////////////////////////////////////
00130 //     Function: BoundingVolume::as_bounding_hexahedron
00131 //       Access: Public, Virtual
00132 //  Description: Virtual downcast method.  Returns this object as a
00133 //               pointer of the indicated type, if it is in fact that
00134 //               type.  Returns NULL if it is not that type.
00135 ////////////////////////////////////////////////////////////////////
00136 const BoundingHexahedron *BoundingVolume::
00137 as_bounding_hexahedron() const {
00138   return NULL;
00139 }
00140 
00141 ////////////////////////////////////////////////////////////////////
00142 //     Function: BoundingVolume::as_bounding_line
00143 //       Access: Public, Virtual
00144 //  Description: Virtual downcast method.  Returns this object as a
00145 //               pointer of the indicated type, if it is in fact that
00146 //               type.  Returns NULL if it is not that type.
00147 ////////////////////////////////////////////////////////////////////
00148 const BoundingLine *BoundingVolume::
00149 as_bounding_line() const {
00150   return NULL;
00151 }
00152 
00153 ////////////////////////////////////////////////////////////////////
00154 //     Function: BoundingVolume::as_bounding_plane
00155 //       Access: Public, Virtual
00156 //  Description: Virtual downcast method.  Returns this object as a
00157 //               pointer of the indicated type, if it is in fact that
00158 //               type.  Returns NULL if it is not that type.
00159 ////////////////////////////////////////////////////////////////////
00160 const BoundingPlane *BoundingVolume::
00161 as_bounding_plane() const {
00162   return NULL;
00163 }
00164 
00165 ////////////////////////////////////////////////////////////////////
00166 //     Function: BoundingVolume::string_bounds_type
00167 //       Access: Public, Static
00168 //  Description: Returns the BoundsType corresponding to the indicated
00169 //               string.
00170 ////////////////////////////////////////////////////////////////////
00171 BoundingVolume::BoundsType BoundingVolume::
00172 string_bounds_type(const string &str) {
00173   if (strcmp(str.c_str(), "default") == 0) {
00174     return BT_default;
00175 
00176   } else if (strcmp(str.c_str(), "best") == 0) {
00177     return BT_best;
00178 
00179   } else if (strcmp(str.c_str(), "sphere") == 0) {
00180     return BT_sphere;
00181 
00182   } else if (strcmp(str.c_str(), "box") == 0) {
00183     return BT_box;
00184   }
00185 
00186   return BT_default;
00187 }
00188 
00189 ////////////////////////////////////////////////////////////////////
00190 //     Function: BoundingVolume::extend_by_sphere
00191 //       Access: Protected, Virtual
00192 //  Description: Double-dispatch support: called by extend_other()
00193 //               when the type we're extending by is known to be a
00194 //               sphere.
00195 ////////////////////////////////////////////////////////////////////
00196 bool BoundingVolume::
00197 extend_by_sphere(const BoundingSphere *sphere) {
00198   return extend_by_finite(sphere);
00199 }
00200 
00201 ////////////////////////////////////////////////////////////////////
00202 //     Function: BoundingVolume::extend_by_box
00203 //       Access: Protected, Virtual
00204 //  Description: Double-dispatch support: called by extend_other()
00205 //               when the type we're extending by is known to be a
00206 //               box.
00207 ////////////////////////////////////////////////////////////////////
00208 bool BoundingVolume::
00209 extend_by_box(const BoundingBox *box) {
00210   return extend_by_finite(box);
00211 }
00212 
00213 ////////////////////////////////////////////////////////////////////
00214 //     Function: BoundingVolume::extend_by_hexahedron
00215 //       Access: Protected, Virtual
00216 //  Description: Double-dispatch support: called by extend_other()
00217 //               when the type we're extending by is known to be a
00218 //               hexahedron.
00219 ////////////////////////////////////////////////////////////////////
00220 bool BoundingVolume::
00221 extend_by_hexahedron(const BoundingHexahedron *hexahedron) {
00222   return extend_by_finite(hexahedron);
00223 }
00224 
00225 ////////////////////////////////////////////////////////////////////
00226 //     Function: BoundingVolume::extend_by_line
00227 //       Access: Protected, Virtual
00228 //  Description: Double-dispatch support: called by extend_other()
00229 //               when the type we're extending by is known to be a
00230 //               line.
00231 ////////////////////////////////////////////////////////////////////
00232 bool BoundingVolume::
00233 extend_by_line(const BoundingLine *line) {
00234   return extend_by_geometric(line);
00235 }
00236 
00237 ////////////////////////////////////////////////////////////////////
00238 //     Function: BoundingVolume::extend_by_plane
00239 //       Access: Protected, Virtual
00240 //  Description: Double-dispatch support: called by extend_other()
00241 //               when the type we're extending by is known to be a
00242 //               plane.
00243 ////////////////////////////////////////////////////////////////////
00244 bool BoundingVolume::
00245 extend_by_plane(const BoundingPlane *plane) {
00246   return extend_by_geometric(plane);
00247 }
00248 
00249 ////////////////////////////////////////////////////////////////////
00250 //     Function: BoundingVolume::extend_by_union
00251 //       Access: Protected, Virtual
00252 //  Description: Double-dispatch support: called by extend_other()
00253 //               when the type we're extending by is known to be a
00254 //               union.
00255 ////////////////////////////////////////////////////////////////////
00256 bool BoundingVolume::
00257 extend_by_union(const UnionBoundingVolume *unionv) {
00258   return extend_by_geometric(unionv);
00259 }
00260 
00261 ////////////////////////////////////////////////////////////////////
00262 //     Function: BoundingVolume::extend_by_intersection
00263 //       Access: Protected, Virtual
00264 //  Description: Double-dispatch support: called by extend_other()
00265 //               when the type we're extending by is known to be a
00266 //               intersection.
00267 ////////////////////////////////////////////////////////////////////
00268 bool BoundingVolume::
00269 extend_by_intersection(const IntersectionBoundingVolume *intersection) {
00270   return extend_by_geometric(intersection);
00271 }
00272 
00273 ////////////////////////////////////////////////////////////////////
00274 //     Function: BoundingVolume::extend_by_finite
00275 //       Access: Protected, Virtual
00276 //  Description: Generic handler for a FiniteBoundingVolume.
00277 ////////////////////////////////////////////////////////////////////
00278 bool BoundingVolume::
00279 extend_by_finite(const FiniteBoundingVolume *volume) {
00280   return extend_by_geometric(volume);
00281 }
00282 
00283 ////////////////////////////////////////////////////////////////////
00284 //     Function: BoundingVolume::extend_by_geometric
00285 //       Access: Protected, Virtual
00286 //  Description: Generic handler for a GeometricBoundingVolume.
00287 ////////////////////////////////////////////////////////////////////
00288 bool BoundingVolume::
00289 extend_by_geometric(const GeometricBoundingVolume *volume) {
00290   mathutil_cat.warning()
00291     << get_type() << "::extend_by_geometric() called with " << volume->get_type() << "\n";
00292   _flags = F_infinite;
00293   return false;
00294 }
00295 
00296 ////////////////////////////////////////////////////////////////////
00297 //     Function: BoundingVolume::around_spheres
00298 //       Access: Protected, Virtual
00299 //  Description: Double-dispatch support: called by around_other()
00300 //               when the type of the first element in the list is
00301 //               known to be a nonempty sphere.
00302 ////////////////////////////////////////////////////////////////////
00303 bool BoundingVolume::
00304 around_spheres(const BoundingVolume **first, const BoundingVolume **last) {
00305   return around_finite(first, last);
00306 }
00307 
00308 ////////////////////////////////////////////////////////////////////
00309 //     Function: BoundingVolume::around_boxes
00310 //       Access: Protected, Virtual
00311 //  Description: Double-dispatch support: called by around_other()
00312 //               when the type of the first element in the list is
00313 //               known to be a nonempty box.
00314 ////////////////////////////////////////////////////////////////////
00315 bool BoundingVolume::
00316 around_boxes(const BoundingVolume **first, const BoundingVolume **last) {
00317   return around_finite(first, last);
00318 }
00319 
00320 ////////////////////////////////////////////////////////////////////
00321 //     Function: BoundingVolume::around_hexahedrons
00322 //       Access: Protected, Virtual
00323 //  Description: Double-dispatch support: called by around_other()
00324 //               when the type of the first element in the list is
00325 //               known to be a nonempty hexahedron.
00326 ////////////////////////////////////////////////////////////////////
00327 bool BoundingVolume::
00328 around_hexahedrons(const BoundingVolume **first, const BoundingVolume **last) {
00329   return around_finite(first, last);
00330 }
00331 
00332 ////////////////////////////////////////////////////////////////////
00333 //     Function: BoundingVolume::around_lines
00334 //       Access: Protected, Virtual
00335 //  Description: Double-dispatch support: called by around_other()
00336 //               when the type of the first element in the list is
00337 //               known to be a nonempty line.
00338 ////////////////////////////////////////////////////////////////////
00339 bool BoundingVolume::
00340 around_lines(const BoundingVolume **first, const BoundingVolume **last) {
00341   return around_geometric(first, last);
00342 }
00343 
00344 ////////////////////////////////////////////////////////////////////
00345 //     Function: BoundingVolume::around_planes
00346 //       Access: Protected, Virtual
00347 //  Description: Double-dispatch support: called by around_other()
00348 //               when the type of the first element in the list is
00349 //               known to be a nonempty plane.
00350 ////////////////////////////////////////////////////////////////////
00351 bool BoundingVolume::
00352 around_planes(const BoundingVolume **first, const BoundingVolume **last) {
00353   return around_geometric(first, last);
00354 }
00355 
00356 ////////////////////////////////////////////////////////////////////
00357 //     Function: BoundingVolume::around_unions
00358 //       Access: Protected, Virtual
00359 //  Description: Double-dispatch support: called by around_other()
00360 //               when the type of the first element in the list is
00361 //               known to be a union object.
00362 ////////////////////////////////////////////////////////////////////
00363 bool BoundingVolume::
00364 around_unions(const BoundingVolume **first, const BoundingVolume **last) {
00365   return around_geometric(first, last);
00366 }
00367 
00368 ////////////////////////////////////////////////////////////////////
00369 //     Function: BoundingVolume::around_intersections
00370 //       Access: Protected, Virtual
00371 //  Description: Double-dispatch support: called by around_other()
00372 //               when the type of the first element in the list is
00373 //               known to be an intersection object.
00374 ////////////////////////////////////////////////////////////////////
00375 bool BoundingVolume::
00376 around_intersections(const BoundingVolume **first, const BoundingVolume **last) {
00377   return around_geometric(first, last);
00378 }
00379 
00380 ////////////////////////////////////////////////////////////////////
00381 //     Function: BoundingVolume::around_finite
00382 //       Access: Protected, Virtual
00383 //  Description: Generic handler for a FiniteBoundingVolume.
00384 ////////////////////////////////////////////////////////////////////
00385 bool BoundingVolume::
00386 around_finite(const BoundingVolume **first, const BoundingVolume **last) {
00387   return around_geometric(first, last);
00388 }
00389 
00390 ////////////////////////////////////////////////////////////////////
00391 //     Function: BoundingVolume::around_geometric
00392 //       Access: Protected, Virtual
00393 //  Description: Generic handler for a GeometricBoundingVolume.
00394 ////////////////////////////////////////////////////////////////////
00395 bool BoundingVolume::
00396 around_geometric(const BoundingVolume **first, const BoundingVolume **last) {
00397   mathutil_cat.warning()
00398     << get_type() << "::extend_by_geometric() called with " << first[0]->get_type() << "\n";
00399   _flags = F_infinite;
00400   return false;
00401 }
00402 
00403 ////////////////////////////////////////////////////////////////////
00404 //     Function: BoundingVolume::contains_sphere
00405 //       Access: Protected, Virtual
00406 //  Description: Double-dispatch support: called by contains_other()
00407 //               when the type we're testing for intersection is known
00408 //               to be a sphere.
00409 ////////////////////////////////////////////////////////////////////
00410 int BoundingVolume::
00411 contains_sphere(const BoundingSphere *sphere) const {
00412   return contains_finite(sphere);
00413 }
00414 
00415 ////////////////////////////////////////////////////////////////////
00416 //     Function: BoundingVolume::contains_box
00417 //       Access: Protected, Virtual
00418 //  Description: Double-dispatch support: called by contains_other()
00419 //               when the type we're testing for intersection is known
00420 //               to be a box.
00421 ////////////////////////////////////////////////////////////////////
00422 int BoundingVolume::
00423 contains_box(const BoundingBox *box) const {
00424   return contains_finite(box);
00425 }
00426 
00427 ////////////////////////////////////////////////////////////////////
00428 //     Function: BoundingVolume::contains_hexahedron
00429 //       Access: Protected, Virtual
00430 //  Description: Double-dispatch support: called by contains_other()
00431 //               when the type we're testing for intersection is known
00432 //               to be a hexahedron.
00433 ////////////////////////////////////////////////////////////////////
00434 int BoundingVolume::
00435 contains_hexahedron(const BoundingHexahedron *hexahedron) const {
00436   return contains_finite(hexahedron);
00437 }
00438 
00439 ////////////////////////////////////////////////////////////////////
00440 //     Function: BoundingVolume::contains_line
00441 //       Access: Protected, Virtual
00442 //  Description: Double-dispatch support: called by contains_other()
00443 //               when the type we're testing for intersection is known
00444 //               to be a line.
00445 ////////////////////////////////////////////////////////////////////
00446 int BoundingVolume::
00447 contains_line(const BoundingLine *line) const {
00448   return contains_geometric(line);
00449 }
00450 
00451 ////////////////////////////////////////////////////////////////////
00452 //     Function: BoundingVolume::contains_plane
00453 //       Access: Protected, Virtual
00454 //  Description: Double-dispatch support: called by contains_other()
00455 //               when the type we're testing for intersection is known
00456 //               to be a plane.
00457 ////////////////////////////////////////////////////////////////////
00458 int BoundingVolume::
00459 contains_plane(const BoundingPlane *plane) const {
00460   return contains_geometric(plane);
00461 }
00462 
00463 ////////////////////////////////////////////////////////////////////
00464 //     Function: BoundingVolume::contains_union
00465 //       Access: Protected, Virtual
00466 //  Description: Double-dispatch support: called by contains_other()
00467 //               when the type we're testing for intersection is known
00468 //               to be a union object.
00469 ////////////////////////////////////////////////////////////////////
00470 int BoundingVolume::
00471 contains_union(const UnionBoundingVolume *unionv) const {
00472   return unionv->other_contains_union(this);
00473 }
00474 
00475 ////////////////////////////////////////////////////////////////////
00476 //     Function: BoundingVolume::contains_intersection
00477 //       Access: Protected, Virtual
00478 //  Description: Double-dispatch support: called by contains_other()
00479 //               when the type we're testing for intersection is known
00480 //               to be an intersection object.
00481 ////////////////////////////////////////////////////////////////////
00482 int BoundingVolume::
00483 contains_intersection(const IntersectionBoundingVolume *intersection) const {
00484   return intersection->other_contains_intersection(this);
00485 }
00486 
00487 ////////////////////////////////////////////////////////////////////
00488 //     Function: BoundingVolume::contains_finite
00489 //       Access: Protected, Virtual
00490 //  Description: Generic handler for a FiniteBoundingVolume.
00491 ////////////////////////////////////////////////////////////////////
00492 int BoundingVolume::
00493 contains_finite(const FiniteBoundingVolume *volume) const {
00494   return contains_geometric(volume);
00495 }
00496 
00497 ////////////////////////////////////////////////////////////////////
00498 //     Function: BoundingVolume::contains_geometric
00499 //       Access: Protected, Virtual
00500 //  Description: Generic handler for a GeometricBoundingVolume.
00501 ////////////////////////////////////////////////////////////////////
00502 int BoundingVolume::
00503 contains_geometric(const GeometricBoundingVolume *volume) const {
00504   mathutil_cat.warning()
00505     << get_type() << "::contains_geometric() called with " << volume->get_type() << "\n";
00506   return IF_dont_understand;
00507 }
00508 
00509 ostream &
00510 operator << (ostream &out, BoundingVolume::BoundsType type) {
00511   switch (type) {
00512   case BoundingVolume::BT_default:
00513     return out << "default";
00514 
00515   case BoundingVolume::BT_best:
00516     return out << "best";
00517 
00518   case BoundingVolume::BT_sphere:
00519     return out << "sphere";
00520 
00521   case BoundingVolume::BT_box:
00522     return out << "box";
00523   }
00524 
00525   mathutil_cat.error()
00526     << "Invalid BoundingVolume::BoundsType value: " << (int)type << "\n";
00527   nassertr(false, out);
00528   return out;
00529 }
00530 
00531 istream &
00532 operator >> (istream &in, BoundingVolume::BoundsType &type) {
00533   string word;
00534   in >> word;
00535   type = BoundingVolume::string_bounds_type(word);
00536   if (type == BoundingVolume::BT_default) {
00537     mathutil_cat->error()
00538       << "Invalid BoundingVolume::BoundsType string: " << word << "\n";
00539   }
00540   return in;
00541 }
00542 
 All Classes Functions Variables Enumerations