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