15 #include "boundingSphere.h" 16 #include "boundingBox.h" 17 #include "boundingHexahedron.h" 18 #include "boundingLine.h" 19 #include "boundingPlane.h" 20 #include "config_mathutil.h" 47 return LPoint3(_center[0] - _radius,
49 _center[2] - _radius);
61 return LPoint3(_center[0] + _radius,
63 _center[2] + _radius);
71 PN_stdfloat BoundingSphere::
79 return 4.0f / 3.0f * MathNumbers::pi_f * _radius * _radius * _radius;
88 get_approx_center()
const {
112 PN_stdfloat xd = dot(x, x);
113 PN_stdfloat yd = dot(y, y);
114 PN_stdfloat zd = dot(z, z);
116 PN_stdfloat scale = max(xd, yd);
117 scale = max(scale, zd);
118 scale = csqrt(scale);
124 _center = _center * mat;
133 void BoundingSphere::
134 output(ostream &out)
const {
136 out <<
"bsphere, empty";
138 out <<
"bsphere, infinite";
140 out <<
"bsphere, c (" << _center <<
"), r " << _radius;
161 bool BoundingSphere::
163 return other->extend_by_sphere(
this);
171 bool BoundingSphere::
175 return other->around_spheres(first, last);
185 return other->contains_sphere(
this);
194 bool BoundingSphere::
195 extend_by_point(
const LPoint3 &point) {
196 nassertr(!point.
is_nan(),
false);
204 PN_stdfloat dist2 = dot(v, v);
205 if (dist2 > _radius * _radius) {
206 _radius = csqrt(dist2);
217 bool BoundingSphere::
223 _center = sphere->_center;
224 _radius = sphere->_radius;
227 PN_stdfloat dist = length(sphere->_center - _center);
229 _radius = max(_radius, dist + sphere->_radius);
239 bool BoundingSphere::
245 _center = (min1 + max1) * 0.5f;
246 _radius = length(
LVector3(max1 - _center));
251 PN_stdfloat max_dist2 = -1.0;
252 for (
int i = 0; i < 8; ++i) {
253 PN_stdfloat dist2 = (box->
get_point(i) - _center).length_squared();
254 if (dist2 > max_dist2) {
258 if (max_dist2 > _radius * _radius) {
259 _radius = csqrt(max_dist2);
271 bool BoundingSphere::
273 nassertr(!hexahedron->
is_empty(),
false);
275 BoundingBox box(hexahedron->get_min(), hexahedron->get_max());
277 return extend_by_box(&box);
285 bool BoundingSphere::
287 nassertr(!volume->
is_empty(),
false);
289 BoundingBox box(volume->get_min(), volume->get_max());
291 return extend_by_box(&box);
299 bool BoundingSphere::
301 nassertr(first != last,
false);
310 while (p != last && (*p).
is_nan()) {
315 mathutil_cat.warning()
316 <<
"BoundingSphere around NaN\n";
327 while (p != last && (*p).
is_nan()) {
350 min_box.set(min(min_box[0], (*p)[0]),
351 min(min_box[1], (*p)[1]),
352 min(min_box[2], (*p)[2]));
353 max_box.set(max(max_box[0], (*p)[0]),
354 max(max_box[1], (*p)[1]),
355 max(max_box[2], (*p)[2]));
361 _center = (min_box + max_box) * 0.5f;
364 PN_stdfloat max_dist2 = 0.0f;
365 for (p = first; p != last; ++p) {
367 PN_stdfloat dist2 = dot(v, v);
368 max_dist2 = max(max_dist2, dist2);
371 _radius = csqrt(max_dist2);
375 if (skipped_nan != 0) {
376 mathutil_cat.warning()
377 <<
"BoundingSphere ignored " << skipped_nan <<
" NaN points of " 378 << (last - first) <<
" total.\n";
392 bool BoundingSphere::
395 nassertr(first != last,
false);
404 nassertr(!(*p)->is_empty() && !(*p)->is_infinite(),
false);
407 LPoint3 min_box = vol->get_min();
408 LPoint3 max_box = vol->get_max();
410 bool any_spheres = (vol->as_bounding_sphere() != NULL);
412 for (++p; p != last; ++p) {
413 nassertr(!(*p)->is_infinite(),
false);
414 if (!(*p)->is_empty()) {
415 vol = (*p)->as_finite_bounding_volume();
422 min_box.set(min(min_box[0], min1[0]),
423 min(min_box[1], min1[1]),
424 min(min_box[2], min1[2]));
425 max_box.set(max(max_box[0], max1[0]),
426 max(max_box[1], max1[1]),
427 max(max_box[2], max1[2]));
429 if (vol->as_bounding_sphere() != NULL) {
436 _center = (min_box + max_box) * 0.5f;
441 _radius = length(max_box - _center);
447 for (p = first; p != last; ++p) {
448 if (!(*p)->is_empty()) {
452 PN_stdfloat dist = length(sphere->_center - _center);
453 _radius = max(_radius, dist + sphere->_radius);
464 PN_stdfloat max_dist2 = -1.0;
465 for (
int i = 0; i < 8; ++i) {
466 PN_stdfloat dist2 = (box.
get_point(i) - _center).length_squared();
467 if (dist2 > max_dist2) {
471 _radius = max(_radius, csqrt(max_dist2));
487 contains_point(
const LPoint3 &point)
const {
488 nassertr(!point.
is_nan(), IF_no_intersection);
491 return IF_no_intersection;
494 return IF_possible | IF_some | IF_all;
498 PN_stdfloat dist2 = dot(v, v);
499 return (dist2 <= _radius * _radius) ?
500 IF_possible | IF_some | IF_all : IF_no_intersection;
511 nassertr(!a.
is_nan() && !b.
is_nan(), IF_no_intersection);
514 return contains_point(a);
517 return IF_no_intersection;
520 return IF_possible | IF_some | IF_all;
529 PN_stdfloat A = dot(delta, delta);
531 nassertr(A != 0.0f, 0);
534 PN_stdfloat B = 2.0f * dot(delta, fc);
535 PN_stdfloat C = dot(fc, fc) - _radius * _radius;
537 PN_stdfloat radical = B*B - 4.0f*A*C;
539 if (IS_NEARLY_ZERO(radical)) {
541 t1 = t2 = -B / (2.0f*A);
542 return (t1 >= 0.0f && t1 <= 1.0f) ?
543 IF_possible | IF_some : IF_no_intersection;
546 if (radical < 0.0f) {
548 return IF_no_intersection;
551 PN_stdfloat reciprocal_2A = 1.0f/(2.0f*A);
552 PN_stdfloat sqrt_radical = csqrt(radical);
554 t1 = ( -B - sqrt_radical ) * reciprocal_2A;
555 t2 = ( -B + sqrt_radical ) * reciprocal_2A;
557 if (t1 >= 0.0f && t2 <= 1.0f) {
558 return IF_possible | IF_some | IF_all;
559 }
else if (t1 <= 1.0f && t2 >= 0.0f) {
560 return IF_possible | IF_some;
562 return IF_no_intersection;
579 LVector3 v = sphere->_center - _center;
580 PN_stdfloat dist2 = dot(v, v);
582 if (_radius >= sphere->_radius &&
583 dist2 <= (_radius - sphere->_radius) * (_radius - sphere->_radius)) {
585 return IF_possible | IF_some | IF_all;
587 }
else if (dist2 > (_radius + sphere->_radius) * (_radius + sphere->_radius)) {
589 return IF_no_intersection;
593 return IF_possible | IF_some;
606 return box->contains_sphere(
this) & ~IF_all;
618 return hexahedron->contains_sphere(
this) & ~IF_all;
630 return line->contains_sphere(
this) & ~IF_all;
642 return plane->contains_sphere(
this) & ~IF_all;
An axis-aligned bounding box; that is, a minimum and maximum coordinate triple.
This is the base class for all three-component vectors and points.
virtual const BoundingSphere * as_bounding_sphere() 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.
bool is_infinite() const
The other side of the empty coin is an infinite volume.
static const LPoint3f & zero()
Returns a zero-length point.
This is a three-component vector distance (as opposed to a three-component point, which represents a ...
This is a three-component point in space (as opposed to a three-component vector, which represents a ...
bool is_nan() const
Returns true if any component of the vector is not-a-number, false otherwise.
bool is_nan() const
Returns true if any component of the matrix is not-a-number, false otherwise.
This funny bounding volume is an infinite plane that divides space into two regions: the part behind ...
This is an abstract class for any volume in any sense which can be said to define the locality of ref...
void set_infinite()
Marks the volume as infinite, even if it is normally finite.
This is a 4-by-4 transform matrix.
const LPoint3 & get_maxq() const
An inline accessor for the maximum value.
LPoint3 get_point(int n) const
Returns the nth vertex of the rectangular solid.
void local_object()
This function should be called, once, immediately after creating a new instance of some ReferenceCoun...
A special kind of GeometricBoundingVolume that is known to be finite.
BoundingSphere()
Constructs an empty sphere.
TypeHandle is the identifier used to differentiate C++ class types.
virtual const FiniteBoundingVolume * as_finite_bounding_volume() const
Virtual downcast method.
LVecBase3f get_row3(int row) const
Retrieves the row column of the matrix as a 3-component vector, ignoring the last column...
This defines a bounding convex hexahedron.
This funny bounding volume is an infinite line with no thickness and extending to infinity in both di...
const LPoint3 & get_minq() const
An inline accessor for the minimum value.