Panda3D

boundingSphere.cxx

00001 // Filename: boundingSphere.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 "boundingSphere.h"
00016 #include "boundingBox.h"
00017 #include "boundingHexahedron.h"
00018 #include "boundingLine.h"
00019 #include "boundingPlane.h"
00020 #include "config_mathutil.h"
00021 #include "dcast.h"
00022 
00023 #include <math.h>
00024 #include <algorithm>
00025 
00026 TypeHandle BoundingSphere::_type_handle;
00027 
00028 ////////////////////////////////////////////////////////////////////
00029 //     Function: BoundingSphere::make_copy
00030 //       Access: Public, Virtual
00031 //  Description: 
00032 ////////////////////////////////////////////////////////////////////
00033 BoundingVolume *BoundingSphere::
00034 make_copy() const {
00035   return new BoundingSphere(*this);
00036 }
00037 
00038 ////////////////////////////////////////////////////////////////////
00039 //     Function: BoundingSphere::get_min
00040 //       Access: Public, Virtual
00041 //  Description: 
00042 ////////////////////////////////////////////////////////////////////
00043 LPoint3f BoundingSphere::
00044 get_min() const {
00045   nassertr(!is_empty(), LPoint3f(0.0f, 0.0f, 0.0f));
00046   nassertr(!is_infinite(), LPoint3f(0.0f, 0.0f, 0.0f));
00047   return LPoint3f(_center[0] - _radius,
00048                   _center[1] - _radius,
00049                   _center[2] - _radius);
00050 }
00051 
00052 ////////////////////////////////////////////////////////////////////
00053 //     Function: BoundingSphere::get_max
00054 //       Access: Public, Virtual
00055 //  Description: 
00056 ////////////////////////////////////////////////////////////////////
00057 LPoint3f BoundingSphere::
00058 get_max() const {
00059   nassertr(!is_empty(), LPoint3f(0.0f, 0.0f, 0.0f));
00060   nassertr(!is_infinite(), LPoint3f(0.0f, 0.0f, 0.0f));
00061   return LPoint3f(_center[0] + _radius,
00062                   _center[1] + _radius,
00063                   _center[2] + _radius);
00064 }
00065 
00066 ////////////////////////////////////////////////////////////////////
00067 //     Function: BoundingSphere::get_volume
00068 //       Access: Public, Virtual
00069 //  Description: 
00070 ////////////////////////////////////////////////////////////////////
00071 float BoundingSphere::
00072 get_volume() const {
00073   nassertr(!is_infinite(), 0.0f);
00074   if (is_empty()) {
00075     return 0.0f;
00076   }
00077 
00078   // Volume of a sphere: four-thirds pi r cubed.
00079   return 4.0f / 3.0f * MathNumbers::pi_f * _radius * _radius * _radius;
00080 }
00081 
00082 ////////////////////////////////////////////////////////////////////
00083 //     Function: BoundingSphere::get_approx_center
00084 //       Access: Public, Virtual
00085 //  Description: 
00086 ////////////////////////////////////////////////////////////////////
00087 LPoint3f BoundingSphere::
00088 get_approx_center() const {
00089   nassertr(!is_empty(), LPoint3f(0.0f, 0.0f, 0.0f));
00090   nassertr(!is_infinite(), LPoint3f(0.0f, 0.0f, 0.0f));
00091   return get_center();
00092 }
00093 
00094 ////////////////////////////////////////////////////////////////////
00095 //     Function: BoundingSphere::xform
00096 //       Access: Public, Virtual
00097 //  Description: 
00098 ////////////////////////////////////////////////////////////////////
00099 void BoundingSphere::
00100 xform(const LMatrix4f &mat) {
00101   nassertv(!mat.is_nan());
00102 
00103   if (!is_empty() && !is_infinite()) {
00104     // First, determine the longest axis of the matrix, in case it
00105     // contains a non-uniform scale.
00106 
00107 /*
00108     LVector3f x,y,z;
00109         mat.get_row3(x,0);
00110         mat.get_row3(y,1);
00111         mat.get_row3(z,2);
00112 
00113     float xd = dot(x, x);
00114     float yd = dot(y, y);
00115     float zd = dot(z, z);
00116 */
00117     float xd,yd,zd,scale;
00118 
00119 #define ROW_DOTTED(mat,ROWNUM)                        \
00120             (mat._m.m._##ROWNUM##0*mat._m.m._##ROWNUM##0 +    \
00121              mat._m.m._##ROWNUM##1*mat._m.m._##ROWNUM##1 +    \
00122              mat._m.m._##ROWNUM##2*mat._m.m._##ROWNUM##2)
00123     
00124     xd = ROW_DOTTED(mat,0);
00125     yd = ROW_DOTTED(mat,1);
00126     zd = ROW_DOTTED(mat,2);
00127 
00128     scale = max(xd,yd);
00129     scale = max(scale,zd);
00130     scale = sqrtf(scale);
00131 
00132     // Transform the radius
00133     _radius *= scale;
00134 
00135     // Transform the center
00136     _center = _center * mat;
00137   }
00138 }
00139 
00140 ////////////////////////////////////////////////////////////////////
00141 //     Function: BoundingSphere::output
00142 //       Access: Public, Virtual
00143 //  Description: 
00144 ////////////////////////////////////////////////////////////////////
00145 void BoundingSphere::
00146 output(ostream &out) const {
00147   if (is_empty()) {
00148     out << "bsphere, empty";
00149   } else if (is_infinite()) {
00150     out << "bsphere, infinite";
00151   } else {
00152     out << "bsphere, c (" << _center << "), r " << _radius;
00153   }
00154 }
00155 
00156 ////////////////////////////////////////////////////////////////////
00157 //     Function: BoundingSphere::as_bounding_sphere
00158 //       Access: Public, Virtual
00159 //  Description: Virtual downcast method.  Returns this object as a
00160 //               pointer of the indicated type, if it is in fact that
00161 //               type.  Returns NULL if it is not that type.
00162 ////////////////////////////////////////////////////////////////////
00163 const BoundingSphere *BoundingSphere::
00164 as_bounding_sphere() const {
00165   return this;
00166 }
00167 
00168 ////////////////////////////////////////////////////////////////////
00169 //     Function: BoundingSphere::extend_other
00170 //       Access: Protected, Virtual
00171 //  Description: 
00172 ////////////////////////////////////////////////////////////////////
00173 bool BoundingSphere::
00174 extend_other(BoundingVolume *other) const {
00175   return other->extend_by_sphere(this);
00176 }
00177 
00178 ////////////////////////////////////////////////////////////////////
00179 //     Function: BoundingSphere::around_other
00180 //       Access: Protected, Virtual
00181 //  Description: 
00182 ////////////////////////////////////////////////////////////////////
00183 bool BoundingSphere::
00184 around_other(BoundingVolume *other,
00185              const BoundingVolume **first,
00186              const BoundingVolume **last) const {
00187   return other->around_spheres(first, last);
00188 }
00189 
00190 ////////////////////////////////////////////////////////////////////
00191 //     Function: BoundingSphere::contains_other
00192 //       Access: Protected, Virtual
00193 //  Description: 
00194 ////////////////////////////////////////////////////////////////////
00195 int BoundingSphere::
00196 contains_other(const BoundingVolume *other) const {
00197   return other->contains_sphere(this);
00198 }
00199 
00200 
00201 ////////////////////////////////////////////////////////////////////
00202 //     Function: BoundingSphere::extend_by_point
00203 //       Access: Protected, Virtual
00204 //  Description: 
00205 ////////////////////////////////////////////////////////////////////
00206 bool BoundingSphere::
00207 extend_by_point(const LPoint3f &point) {
00208   nassertr(!point.is_nan(), false);
00209 
00210   if (is_empty()) {
00211     _center = point;
00212     _radius = 0.0f;
00213     _flags = 0;
00214   } else if (!is_infinite()) {
00215     LVector3f v = point - _center;
00216     float dist2 = dot(v, v);
00217     if (dist2 > _radius * _radius) {
00218       _radius = sqrtf(dist2);
00219     }
00220   }
00221   return true;
00222 }
00223 
00224 ////////////////////////////////////////////////////////////////////
00225 //     Function: BoundingSphere::extend_by_sphere
00226 //       Access: Protected, Virtual
00227 //  Description: 
00228 ////////////////////////////////////////////////////////////////////
00229 bool BoundingSphere::
00230 extend_by_sphere(const BoundingSphere *sphere) {
00231   nassertr(!sphere->is_empty() && !sphere->is_infinite(), false);
00232   nassertr(!is_infinite(), false);
00233 
00234   if (is_empty()) {
00235     _center = sphere->_center;
00236     _radius = sphere->_radius;
00237     _flags = 0;
00238   } else {
00239     float dist = length(sphere->_center - _center);
00240 
00241     _radius = max(_radius, dist + sphere->_radius);
00242   }
00243   return true;
00244 }
00245 
00246 ////////////////////////////////////////////////////////////////////
00247 //     Function: BoundingSphere::extend_by_box
00248 //       Access: Protected, Virtual
00249 //  Description: 
00250 ////////////////////////////////////////////////////////////////////
00251 bool BoundingSphere::
00252 extend_by_box(const BoundingBox *box) {
00253   const LVector3f &min1 = box->get_minq();
00254   const LVector3f &max1 = box->get_maxq();
00255 
00256   if (is_empty()) {
00257     _center = (min1 + max1) * 0.5f;
00258     _radius = length(LVector3f(max1 - _center));
00259     _flags = 0;
00260 
00261   } else {
00262     // Find the minimum radius necessary to reach the corner.
00263     float max_dist2 = -1.0;
00264     for (int i = 0; i < 8; ++i) {
00265       float dist2 = (box->get_point(i) - _center).length_squared();
00266       if (dist2 > max_dist2) {
00267         max_dist2 = dist2;
00268       }
00269     }
00270     if (max_dist2 > _radius * _radius) {
00271       _radius = csqrt(max_dist2);
00272     }
00273   }
00274 
00275   return true;
00276 }
00277 
00278 ////////////////////////////////////////////////////////////////////
00279 //     Function: BoundingSphere::extend_by_hexahedron
00280 //       Access: Protected, Virtual
00281 //  Description: 
00282 ////////////////////////////////////////////////////////////////////
00283 bool BoundingSphere::
00284 extend_by_hexahedron(const BoundingHexahedron *hexahedron) {
00285   nassertr(!hexahedron->is_empty(), false);
00286 
00287   BoundingBox box(hexahedron->get_min(), hexahedron->get_max());
00288   box.local_object();
00289   return extend_by_box(&box);
00290 }
00291 
00292 ////////////////////////////////////////////////////////////////////
00293 //     Function: BoundingSphere::extend_by_finite
00294 //       Access: Protected
00295 //  Description: 
00296 ////////////////////////////////////////////////////////////////////
00297 bool BoundingSphere::
00298 extend_by_finite(const FiniteBoundingVolume *volume) {
00299   nassertr(!volume->is_empty(), false);
00300 
00301   BoundingBox box(volume->get_min(), volume->get_max());
00302   box.local_object();
00303   return extend_by_box(&box);
00304 }
00305 
00306 ////////////////////////////////////////////////////////////////////
00307 //     Function: BoundingSphere::around_points
00308 //       Access: Protected, Virtual
00309 //  Description: 
00310 ////////////////////////////////////////////////////////////////////
00311 bool BoundingSphere::
00312 around_points(const LPoint3f *first, const LPoint3f *last) {
00313   nassertr(first != last, false);
00314 
00315   // First, get the box of all the points to construct a bounding
00316   // box.
00317   const LPoint3f *p = first;
00318 
00319 #ifndef NDEBUG
00320   // Skip any NaN points.
00321   int skipped_nan = 0;
00322   while (p != last && (*p).is_nan()) {
00323     ++p;
00324     ++skipped_nan;
00325   }
00326   if (p == last) {
00327     mathutil_cat.warning()
00328       << "BoundingSphere around NaN\n";
00329     return false;
00330   }
00331 #endif
00332 
00333   LPoint3f min_box = *p;
00334   LPoint3f max_box = *p;
00335   ++p;
00336 
00337 #ifndef NDEBUG
00338   // Skip more NaN points.
00339   while (p != last && (*p).is_nan()) {
00340     ++p;
00341     ++skipped_nan;
00342   }
00343 #endif
00344 
00345   if (p == last) {
00346     // Only one point; we have a radius of zero.  This is not the same
00347     // thing as an empty sphere, because our volume contains one
00348     // point; an empty sphere contains no points.
00349     _center = min_box;
00350     _radius = 0.0f;
00351 
00352   } else {
00353     // More than one point; we have a nonzero radius.
00354     while (p != last) {
00355 #ifndef NDEBUG
00356       // Skip more NaN points.
00357       if ((*p).is_nan()) {
00358         ++skipped_nan;
00359       } else
00360 #endif
00361         {
00362           min_box.set(min(min_box[0], (*p)[0]),
00363                       min(min_box[1], (*p)[1]),
00364                       min(min_box[2], (*p)[2]));
00365           max_box.set(max(max_box[0], (*p)[0]),
00366                       max(max_box[1], (*p)[1]),
00367                       max(max_box[2], (*p)[2]));
00368         }
00369       ++p;
00370     }
00371 
00372     // Now take the center of the bounding box as the center of the sphere.
00373     _center = (min_box + max_box) * 0.5f;
00374 
00375     // Now walk back through to get the max distance from center.
00376     float max_dist2 = 0.0f;
00377     for (p = first; p != last; ++p) {
00378       LVector3f v = (*p) - _center;
00379       float dist2 = dot(v, v);
00380       max_dist2 = max(max_dist2, dist2);
00381     }
00382 
00383     _radius = sqrtf(max_dist2);
00384   }
00385 
00386 #ifndef NDEBUG
00387   if (skipped_nan != 0) {
00388     mathutil_cat.warning()
00389       << "BoundingSphere ignored " << skipped_nan << " NaN points of "
00390       << (last - first) << " total.\n";
00391   }
00392 #endif
00393 
00394   _flags = 0;
00395 
00396   return true;
00397 }
00398 
00399 ////////////////////////////////////////////////////////////////////
00400 //     Function: BoundingSphere::around_spheres
00401 //       Access: Protected, Virtual
00402 //  Description: 
00403 ////////////////////////////////////////////////////////////////////
00404 bool BoundingSphere::
00405 around_spheres(const BoundingVolume **first,
00406                const BoundingVolume **last) {
00407   return around_finite(first, last);
00408 }
00409 
00410 ////////////////////////////////////////////////////////////////////
00411 //     Function: BoundingSphere::around_boxes
00412 //       Access: Protected, Virtual
00413 //  Description: 
00414 ////////////////////////////////////////////////////////////////////
00415 bool BoundingSphere::
00416 around_boxes(const BoundingVolume **first,
00417              const BoundingVolume **last) {
00418   return around_finite(first, last);
00419 }
00420 
00421 ////////////////////////////////////////////////////////////////////
00422 //     Function: BoundingSphere::around_hexahedrons
00423 //       Access: Protected, Virtual
00424 //  Description: 
00425 ////////////////////////////////////////////////////////////////////
00426 bool BoundingSphere::
00427 around_hexahedrons(const BoundingVolume **first,
00428                    const BoundingVolume **last) {
00429   return around_finite(first, last);
00430 }
00431 
00432 ////////////////////////////////////////////////////////////////////
00433 //     Function: BoundingSphere::around_finite
00434 //       Access: Protected
00435 //  Description: 
00436 ////////////////////////////////////////////////////////////////////
00437 bool BoundingSphere::
00438 around_finite(const BoundingVolume **first,
00439               const BoundingVolume **last) {
00440   nassertr(first != last, false);
00441 
00442   // We're given a set of bounding volumes, all of which are finite,
00443   // and at least the first one of which is guaranteed to be nonempty.
00444   // Some others may not be.
00445 
00446   // First, get the box of all the points to construct a bounding
00447   // box.
00448   const BoundingVolume **p = first;
00449   nassertr(!(*p)->is_empty() && !(*p)->is_infinite(), false);
00450   const FiniteBoundingVolume *vol = (*p)->as_finite_bounding_volume();
00451   nassertr(vol != (FiniteBoundingVolume *)NULL, false);
00452   LPoint3f min_box = vol->get_min();
00453   LPoint3f max_box = vol->get_max();
00454 
00455   bool any_spheres = (vol->as_bounding_sphere() != NULL);
00456 
00457   for (++p; p != last; ++p) {
00458     nassertr(!(*p)->is_infinite(), false);
00459     if (!(*p)->is_empty()) {
00460       vol = (*p)->as_finite_bounding_volume();
00461       if (vol == (FiniteBoundingVolume *)NULL) {
00462         set_infinite();
00463         return true;
00464       }
00465       LPoint3f min1 = vol->get_min();
00466       LPoint3f max1 = vol->get_max();
00467       min_box.set(min(min_box[0], min1[0]),
00468                   min(min_box[1], min1[1]),
00469                   min(min_box[2], min1[2]));
00470       max_box.set(max(max_box[0], max1[0]),
00471                   max(max_box[1], max1[1]),
00472                   max(max_box[2], max1[2]));
00473 
00474       if (vol->as_bounding_sphere() != NULL) {
00475         any_spheres = true;
00476       }
00477     }
00478   }
00479 
00480   // Now take the center of the bounding box as the center of the sphere.
00481   _center = (min_box + max_box) * 0.5f;
00482 
00483   if (!any_spheres) {
00484     // Since there are no spheres in the list, we have to make this
00485     // sphere fully enclose all of the bounding boxes.
00486     _radius = length(max_box - _center);
00487 
00488   } else {
00489     // We might be able to go tighter, by lopping off the corners of
00490     // the spheres.
00491     _radius = 0.0f;
00492     for (p = first; p != last; ++p) {
00493       if (!(*p)->is_empty()) {
00494         const BoundingSphere *sphere = (*p)->as_bounding_sphere();
00495         if (sphere != (BoundingSphere *)NULL) {
00496           // This is a sphere; consider its corner.
00497           float dist = length(sphere->_center - _center);
00498           _radius = max(_radius, dist + sphere->_radius);
00499           
00500         } else {
00501           // This is a nonsphere.  We fit around it.
00502           const FiniteBoundingVolume *vol = (*p)->as_finite_bounding_volume();
00503           nassertr(vol != (FiniteBoundingVolume *)NULL, false);
00504 
00505           BoundingBox box(vol->get_min(), vol->get_max());
00506           box.local_object();
00507           
00508           // Find the minimum radius necessary to reach the corner.
00509           float max_dist2 = -1.0;
00510           for (int i = 0; i < 8; ++i) {
00511             float dist2 = (box.get_point(i) - _center).length_squared();
00512             if (dist2 > max_dist2) {
00513               max_dist2 = dist2;
00514             }
00515           }
00516           _radius = max(_radius, csqrt(max_dist2));
00517         }
00518       }
00519     }
00520   }
00521 
00522   _flags = 0;
00523   return true;
00524 }
00525 
00526 ////////////////////////////////////////////////////////////////////
00527 //     Function: BoundingSphere::contains_point
00528 //       Access: Protected, Virtual
00529 //  Description: 
00530 ////////////////////////////////////////////////////////////////////
00531 int BoundingSphere::
00532 contains_point(const LPoint3f &point) const {
00533   nassertr(!point.is_nan(), IF_no_intersection);
00534 
00535   if (is_empty()) {
00536     return IF_no_intersection;
00537 
00538   } else if (is_infinite()) {
00539     return IF_possible | IF_some | IF_all;
00540 
00541   } else {
00542     LVector3f v = point - _center;
00543     float dist2 = dot(v, v);
00544     return (dist2 <= _radius * _radius) ?
00545       IF_possible | IF_some | IF_all : IF_no_intersection;
00546   }
00547 }
00548 
00549 ////////////////////////////////////////////////////////////////////
00550 //     Function: BoundingSphere::contains_lineseg
00551 //       Access: Protected, Virtual
00552 //  Description: 
00553 ////////////////////////////////////////////////////////////////////
00554 int BoundingSphere::
00555 contains_lineseg(const LPoint3f &a, const LPoint3f &b) const {
00556   nassertr(!a.is_nan() && !b.is_nan(), IF_no_intersection);
00557 
00558   if (a == b) {
00559     return contains_point(a);
00560   }
00561   if (is_empty()) {
00562     return IF_no_intersection;
00563 
00564   } else if (is_infinite()) {
00565     return IF_possible | IF_some | IF_all;
00566 
00567   } else {
00568     LPoint3f from = a;
00569     LVector3f delta = b - a;
00570     float t1, t2;
00571 
00572     // Solve the equation for the intersection of a line with a sphere
00573     // using the quadratic equation.
00574     float A = dot(delta, delta);
00575 
00576     nassertr(A != 0.0f, 0);    // Trivial line segment.
00577 
00578     LVector3f fc = from - _center;
00579     float B = 2.0f * dot(delta, fc);
00580     float C = dot(fc, fc) - _radius * _radius;
00581 
00582     float radical = B*B - 4.0f*A*C;
00583 
00584     if (IS_NEARLY_ZERO(radical)) {
00585       // Tangent.
00586       t1 = t2 = -B / (2.0f*A);
00587       return (t1 >= 0.0f && t1 <= 1.0f) ?
00588                  IF_possible | IF_some : IF_no_intersection;
00589     }
00590 
00591     if (radical < 0.0f) {
00592       // No real roots: no intersection with the line.
00593       return IF_no_intersection;
00594     }
00595 
00596         float reciprocal_2A = 1.0f/(2.0f*A);
00597     float sqrt_radical = sqrtf(radical);
00598 
00599     t1 = ( -B - sqrt_radical ) * reciprocal_2A;
00600     t2 = ( -B + sqrt_radical ) * reciprocal_2A;
00601 
00602     if (t1 >= 0.0f && t2 <= 1.0f) {
00603       return IF_possible | IF_some | IF_all;
00604     } else if (t1 <= 1.0f && t2 >= 0.0f) {
00605       return IF_possible | IF_some;
00606     } else {
00607       return IF_no_intersection;
00608     }
00609   }
00610 }
00611 
00612 ////////////////////////////////////////////////////////////////////
00613 //     Function: BoundingSphere::contains_sphere
00614 //       Access: Protected, Virtual
00615 //  Description: Double-dispatch support: called by contains_other()
00616 //               when the type we're testing for intersection is known
00617 //               to be a sphere.
00618 ////////////////////////////////////////////////////////////////////
00619 int BoundingSphere::
00620 contains_sphere(const BoundingSphere *sphere) const {
00621   nassertr(!is_empty() && !is_infinite(), 0);
00622   nassertr(!sphere->is_empty() && !sphere->is_infinite(), 0);
00623 
00624   LVector3f v = sphere->_center - _center;
00625   float dist2 = dot(v, v);
00626 
00627   if (_radius >= sphere->_radius &&
00628       dist2 <= (_radius - sphere->_radius) * (_radius - sphere->_radius)) {
00629     // The other sphere is completely within this sphere.
00630     return IF_possible | IF_some | IF_all;
00631 
00632   } else if (dist2 > (_radius + sphere->_radius) * (_radius + sphere->_radius)) {
00633     // The other sphere is completely outside this sphere.
00634     return IF_no_intersection;
00635 
00636   } else {
00637     // The other sphere is partially within this sphere.
00638     return IF_possible | IF_some;
00639   }
00640 }
00641 
00642 ////////////////////////////////////////////////////////////////////
00643 //     Function: BoundingSphere::contains_box
00644 //       Access: Protected, Virtual
00645 //  Description: Double-dispatch support: called by contains_other()
00646 //               when the type we're testing for intersection is known
00647 //               to be a box.
00648 ////////////////////////////////////////////////////////////////////
00649 int BoundingSphere::
00650 contains_box(const BoundingBox *box) const {
00651   return box->contains_sphere(this) & ~IF_all;
00652 }
00653 
00654 ////////////////////////////////////////////////////////////////////
00655 //     Function: BoundingSphere::contains_hexahedron
00656 //       Access: Protected, Virtual
00657 //  Description: Double-dispatch support: called by contains_other()
00658 //               when the type we're testing for intersection is known
00659 //               to be a hexahedron.
00660 ////////////////////////////////////////////////////////////////////
00661 int BoundingSphere::
00662 contains_hexahedron(const BoundingHexahedron *hexahedron) const {
00663   return hexahedron->contains_sphere(this) & ~IF_all;
00664 }
00665 
00666 ////////////////////////////////////////////////////////////////////
00667 //     Function: BoundingSphere::contains_line
00668 //       Access: Protected, Virtual
00669 //  Description: Double-dispatch support: called by contains_other()
00670 //               when the type we're testing for intersection is known
00671 //               to be a line.
00672 ////////////////////////////////////////////////////////////////////
00673 int BoundingSphere::
00674 contains_line(const BoundingLine *line) const {
00675   return line->contains_sphere(this) & ~IF_all;
00676 }
00677 
00678 ////////////////////////////////////////////////////////////////////
00679 //     Function: BoundingSphere::contains_plane
00680 //       Access: Protected, Virtual
00681 //  Description: Double-dispatch support: called by contains_other()
00682 //               when the type we're testing for intersection is known
00683 //               to be a plane.
00684 ////////////////////////////////////////////////////////////////////
00685 int BoundingSphere::
00686 contains_plane(const BoundingPlane *plane) const {
00687   return plane->contains_sphere(this) & ~IF_all;
00688 }
 All Classes Functions Variables Enumerations