41LPoint3 BoundingSphere::
43 nassertr(!
is_empty(), LPoint3::zero());
45 return LPoint3(_center[0] - _radius,
47 _center[2] - _radius);
53LPoint3 BoundingSphere::
55 nassertr(!
is_empty(), LPoint3::zero());
57 return LPoint3(_center[0] + _radius,
59 _center[2] + _radius);
65PN_stdfloat BoundingSphere::
73 return 4.0f / 3.0f * MathNumbers::pi_f * _radius * _radius * _radius;
79LPoint3 BoundingSphere::
80get_approx_center()
const {
81 nassertr(!
is_empty(), LPoint3::zero());
90xform(
const LMatrix4 &mat) {
91 nassertv(!mat.is_nan());
102 PN_stdfloat xd = dot(x, x);
103 PN_stdfloat yd = dot(y, y);
104 PN_stdfloat zd = dot(z, z);
106 PN_stdfloat scale = max(xd, yd);
107 scale = max(scale, zd);
108 scale = csqrt(scale);
114 _center = _center * mat;
126output(std::ostream &out)
const {
128 out <<
"bsphere, empty";
130 out <<
"bsphere, infinite";
132 out <<
"bsphere, c (" << _center <<
"), r " << _radius;
150 return other->extend_by_sphere(
this);
160 return other->around_spheres(first, last);
168 return other->contains_sphere(
this);
176extend_by_point(
const LPoint3 &point) {
177 nassertr(!point.is_nan(),
false);
184 LVector3 v = point - _center;
185 PN_stdfloat dist2 = dot(v, v);
186 if (dist2 > _radius * _radius) {
187 _radius = csqrt(dist2);
202 _center = sphere->_center;
203 _radius = sphere->_radius;
206 PN_stdfloat dist = length(sphere->_center - _center);
208 _radius = max(_radius, dist + sphere->_radius);
218 const LVector3 &min1 = box->
get_minq();
219 const LVector3 &max1 = box->
get_maxq();
222 _center = (min1 + max1) * 0.5f;
223 _radius = length(LVector3(max1 - _center));
228 PN_stdfloat max_dist2 = -1.0;
229 for (
int i = 0; i < 8; ++i) {
230 PN_stdfloat dist2 = (box->
get_point(i) - _center).length_squared();
231 if (dist2 > max_dist2) {
235 if (max_dist2 > _radius * _radius) {
236 _radius = csqrt(max_dist2);
248 nassertr(!hexahedron->
is_empty(),
false);
250 BoundingBox box(hexahedron->get_min(), hexahedron->get_max());
252 return extend_by_box(&box);
260 nassertr(!volume->
is_empty(),
false);
262 BoundingBox box(volume->get_min(), volume->get_max());
264 return extend_by_box(&box);
271around_points(
const LPoint3 *first,
const LPoint3 *last) {
272 nassertr(first != last,
false);
275 const LPoint3 *p = first;
280 while (p != last && (*p).is_nan()) {
285 mathutil_cat.warning()
286 <<
"BoundingSphere around NaN\n";
297 while (p != last && (*p).is_nan()) {
320 min_box.set(min(min_box[0], (*p)[0]),
321 min(min_box[1], (*p)[1]),
322 min(min_box[2], (*p)[2]));
323 max_box.set(max(max_box[0], (*p)[0]),
324 max(max_box[1], (*p)[1]),
325 max(max_box[2], (*p)[2]));
331 _center = (min_box + max_box) * 0.5f;
334 PN_stdfloat max_dist2 = 0.0f;
335 for (p = first; p != last; ++p) {
336 LVector3 v = (*p) - _center;
337 PN_stdfloat dist2 = dot(v, v);
338 max_dist2 = max(max_dist2, dist2);
341 _radius = csqrt(max_dist2);
345 if (skipped_nan != 0) {
346 mathutil_cat.warning()
347 <<
"BoundingSphere ignored " << skipped_nan <<
" NaN points of "
348 << (last - first) <<
" total.\n";
363 nassertr(first != last,
false);
371 nassertr(!(*p)->is_empty() && !(*p)->is_infinite(),
false);
373 nassertr(vol !=
nullptr,
false);
374 LPoint3 min_box = vol->get_min();
375 LPoint3 max_box = vol->get_max();
379 for (++p; p != last; ++p) {
380 nassertr(!(*p)->is_infinite(),
false);
381 if (!(*p)->is_empty()) {
383 if (vol ==
nullptr) {
387 LPoint3 min1 = vol->get_min();
388 LPoint3 max1 = vol->get_max();
389 min_box.set(min(min_box[0], min1[0]),
390 min(min_box[1], min1[1]),
391 min(min_box[2], min1[2]));
392 max_box.set(max(max_box[0], max1[0]),
393 max(max_box[1], max1[1]),
394 max(max_box[2], max1[2]));
403 _center = (min_box + max_box) * 0.5f;
408 _radius = length(max_box - _center);
414 for (p = first; p != last; ++p) {
415 if (!(*p)->is_empty()) {
417 if (sphere !=
nullptr) {
419 PN_stdfloat dist = length(sphere->_center - _center);
420 _radius = max(_radius, dist + sphere->_radius);
425 nassertr(vol !=
nullptr,
false);
431 PN_stdfloat max_dist2 = -1.0;
432 for (
int i = 0; i < 8; ++i) {
433 PN_stdfloat dist2 = (box.
get_point(i) - _center).length_squared();
434 if (dist2 > max_dist2) {
438 _radius = max(_radius, csqrt(max_dist2));
452contains_point(
const LPoint3 &point)
const {
453 nassertr(!point.is_nan(), IF_no_intersection);
456 return IF_no_intersection;
459 return IF_possible | IF_some | IF_all;
462 LVector3 v = point - _center;
463 PN_stdfloat dist2 = dot(v, v);
464 return (dist2 <= _radius * _radius) ?
465 IF_possible | IF_some | IF_all : IF_no_intersection;
473contains_lineseg(
const LPoint3 &a,
const LPoint3 &b)
const {
474 nassertr(!a.is_nan() && !b.is_nan(), IF_no_intersection);
477 return contains_point(a);
480 return IF_no_intersection;
483 return IF_possible | IF_some | IF_all;
487 LVector3 delta = b - a;
492 PN_stdfloat A = dot(delta, delta);
494 nassertr(A != 0.0f, 0);
496 LVector3 fc = from - _center;
497 PN_stdfloat B = 2.0f * dot(delta, fc);
498 PN_stdfloat C = dot(fc, fc) - _radius * _radius;
500 PN_stdfloat radical = B*B - 4.0f*A*C;
502 if (IS_NEARLY_ZERO(radical)) {
504 t1 = t2 = -B / (2.0f*A);
505 return (t1 >= 0.0f && t1 <= 1.0f) ?
506 IF_possible | IF_some : IF_no_intersection;
509 if (radical < 0.0f) {
511 return IF_no_intersection;
514 PN_stdfloat reciprocal_2A = 1.0f/(2.0f*A);
515 PN_stdfloat sqrt_radical = csqrt(radical);
517 t1 = ( -B - sqrt_radical ) * reciprocal_2A;
518 t2 = ( -B + sqrt_radical ) * reciprocal_2A;
520 if (t1 >= 0.0f && t2 <= 1.0f) {
521 return IF_possible | IF_some | IF_all;
522 }
else if (t1 <= 1.0f && t2 >= 0.0f) {
523 return IF_possible | IF_some;
525 return IF_no_intersection;
539 LVector3 v = sphere->_center - _center;
540 PN_stdfloat dist2 = dot(v, v);
542 if (_radius >= sphere->_radius &&
543 dist2 <= (_radius - sphere->_radius) * (_radius - sphere->_radius)) {
545 return IF_possible | IF_some | IF_all;
547 }
else if (dist2 > (_radius + sphere->_radius) * (_radius + sphere->_radius)) {
549 return IF_no_intersection;
553 return IF_possible | IF_some;
563 return box->contains_sphere(
this) & ~IF_all;
572 return hexahedron->contains_sphere(
this) & ~IF_all;
581 return line->contains_sphere(
this) & ~IF_all;
590 return plane->contains_sphere(
this) & ~IF_all;
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
An axis-aligned bounding box; that is, a minimum and maximum coordinate triple.
const LPoint3 & get_minq() const
An inline accessor for the minimum value.
get_point
Returns the nth vertex of the rectangular solid.
const LPoint3 & get_maxq() const
An inline accessor for the maximum value.
This defines a bounding convex hexahedron.
This funny bounding volume is an infinite line with no thickness and extending to infinity in both di...
This funny bounding volume is an infinite plane that divides space into two regions: the part behind ...
This defines a bounding sphere, consisting of a center and a radius.
virtual const BoundingSphere * as_bounding_sphere() const
Virtual downcast method.
BoundingSphere()
Constructs an empty sphere.
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.
bool is_empty() const
Any kind of volume might be empty.
virtual const BoundingSphere * as_bounding_sphere() const
Virtual downcast method.
bool is_infinite() const
The other side of the empty coin is an infinite volume.
A special kind of GeometricBoundingVolume that is known to be finite.
virtual const FiniteBoundingVolume * as_finite_bounding_volume() const
Virtual downcast method.
void local_object()
This function should be called, once, immediately after creating a new instance of some ReferenceCoun...
TypeHandle is the identifier used to differentiate C++ class types.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.