open_toontown_panda3d/panda/src/mathutil/boundingPlane.cxx

269 lines
8.3 KiB
C++

// Filename: boundingPlane.cxx
// Created by: drose (19Aug05)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) Carnegie Mellon University. All rights reserved.
//
// All use of this software is subject to the terms of the revised BSD
// license. You should have received a copy of this license along
// with this source code in a file named "LICENSE."
//
////////////////////////////////////////////////////////////////////
#include "boundingPlane.h"
#include "boundingSphere.h"
#include "config_mathutil.h"
TypeHandle BoundingPlane::_type_handle;
////////////////////////////////////////////////////////////////////
// Function: BoundingPlane::make_copy
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
BoundingVolume *BoundingPlane::
make_copy() const {
return new BoundingPlane(*this);
}
////////////////////////////////////////////////////////////////////
// Function: BoundingPlane::get_approx_center
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
LPoint3 BoundingPlane::
get_approx_center() const {
nassertr(!is_empty(), LPoint3(0.0f, 0.0f, 0.0f));
nassertr(!is_infinite(), LPoint3(0.0f, 0.0f, 0.0f));
return _plane.get_point();
}
////////////////////////////////////////////////////////////////////
// Function: BoundingPlane::xform
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
void BoundingPlane::
xform(const LMatrix4 &mat) {
nassertv(!mat.is_nan());
if (!is_empty() && !is_infinite()) {
_plane.xform(mat);
}
}
////////////////////////////////////////////////////////////////////
// Function: BoundingPlane::output
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
void BoundingPlane::
output(ostream &out) const {
if (is_empty()) {
out << "bplane, empty";
} else if (is_infinite()) {
out << "bplane, infinite";
} else {
out << "bplane: " << _plane;
}
}
////////////////////////////////////////////////////////////////////
// Function: BoundingPlane::as_bounding_plane
// Access: Public, Virtual
// Description: Virtual downcast method. Returns this object as a
// pointer of the indicated type, if it is in fact that
// type. Returns NULL if it is not that type.
////////////////////////////////////////////////////////////////////
const BoundingPlane *BoundingPlane::
as_bounding_plane() const {
return this;
}
////////////////////////////////////////////////////////////////////
// Function: BoundingPlane::extend_other
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
bool BoundingPlane::
extend_other(BoundingVolume *other) const {
return other->extend_by_plane(this);
}
////////////////////////////////////////////////////////////////////
// Function: BoundingPlane::around_other
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
bool BoundingPlane::
around_other(BoundingVolume *other,
const BoundingVolume **first,
const BoundingVolume **last) const {
return other->around_planes(first, last);
}
////////////////////////////////////////////////////////////////////
// Function: BoundingPlane::contains_other
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
int BoundingPlane::
contains_other(const BoundingVolume *other) const {
return other->contains_plane(this);
}
////////////////////////////////////////////////////////////////////
// Function: BoundingPlane::extend_by_plane
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
bool BoundingPlane::
extend_by_plane(const BoundingPlane *plane) {
nassertr(!plane->is_empty() && !plane->is_infinite(), false);
nassertr(!is_infinite(), false);
if (is_empty()) {
_plane = plane->get_plane();
_flags = 0;
} else {
_flags = F_infinite;
}
return true;
}
////////////////////////////////////////////////////////////////////
// Function: BoundingPlane::contains_sphere
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
int BoundingPlane::
contains_sphere(const BoundingSphere *sphere) const {
nassertr(!is_empty() && !is_infinite(), 0);
nassertr(!sphere->is_empty() && !sphere->is_infinite(), 0);
PN_stdfloat r = sphere->get_radius();
PN_stdfloat d = _plane.dist_to_plane(sphere->get_center());
if (d <= -r) {
// The sphere is completely behind the plane.
return IF_all | IF_possible | IF_some;
} else if (d <= r) {
// The sphere is intersecting with the plane itself.
return IF_possible | IF_some;
} else {
// The sphere is completely in front of the plane.
return IF_no_intersection;
}
}
////////////////////////////////////////////////////////////////////
// Function: BoundingPlane::contains_box
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
int BoundingPlane::
contains_box(const BoundingBox *box) const {
nassertr(!is_empty() && !is_infinite(), 0);
nassertr(!box->is_empty() && !box->is_infinite(), 0);
// Put the box inside a sphere for the purpose of this test.
const LPoint3 &min = box->get_minq();
const LPoint3 &max = box->get_maxq();
LPoint3 center = (min + max) * 0.5f;
PN_stdfloat radius2 = (max - center).length_squared();
int result = IF_possible | IF_some | IF_all;
PN_stdfloat dist = _plane.dist_to_plane(center);
PN_stdfloat dist2 = dist * dist;
if (dist2 <= radius2) {
// The sphere is not completely behind this plane, but some of
// it is.
// Look a little closer.
bool all_in = true;
bool all_out = true;
for (int i = 0; i < 8 && (all_in || all_out) ; ++i) {
if (_plane.dist_to_plane(box->get_point(i)) < 0.0f) {
// This point is inside the plane.
all_out = false;
} else {
// This point is outside the plane.
all_in = false;
}
}
if (all_out) {
return IF_no_intersection;
} else if (!all_in) {
result &= ~IF_all;
}
} else if (dist >= 0.0f) {
// The sphere is completely in front of this plane.
return IF_no_intersection;
}
return result;
}
////////////////////////////////////////////////////////////////////
// Function: BoundingPlane::contains_line
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
int BoundingPlane::
contains_line(const BoundingLine *line) const {
return IF_possible;
}
////////////////////////////////////////////////////////////////////
// Function: BoundingPlane::contains_plane
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
int BoundingPlane::
contains_plane(const BoundingPlane *plane) const {
return IF_possible;
}
////////////////////////////////////////////////////////////////////
// Function: BoundingPlane::contains_hexahedron
// Access: Protected, Virtual
// Description: Double-dispatch support: called by contains_other()
// when the type we're testing for intersection is known
// to be a hexahedron.
////////////////////////////////////////////////////////////////////
int BoundingPlane::
contains_hexahedron(const BoundingHexahedron *hexahedron) const {
nassertr(!is_empty() && !is_infinite(), 0);
nassertr(!hexahedron->is_empty() && !hexahedron->is_infinite(), 0);
int result = IF_possible | IF_some | IF_all;
bool all_in = true;
bool all_out = true;
for (int i = 0; i < 8 && (all_in || all_out) ; ++i) {
if (_plane.dist_to_plane(hexahedron->get_point(i)) < 0.0f) {
// This point is inside the plane.
all_out = false;
} else {
// This point is outside the plane.
all_in = false;
}
}
if (all_out) {
return IF_no_intersection;
} else if (!all_in) {
result &= ~IF_all;
}
return result;
}