open_toontown_panda3d/panda/src/mathutil/boundingVolume.cxx

462 lines
12 KiB
C++

/**
* 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."
*
* @file boundingVolume.cxx
* @author drose
* @date 1999-10-01
*/
#include "boundingVolume.h"
#include "finiteBoundingVolume.h"
#include "unionBoundingVolume.h"
#include "intersectionBoundingVolume.h"
#include "boundingBox.h"
#include "boundingLine.h"
#include "boundingPlane.h"
#include "boundingSphere.h"
#include "boundingHexahedron.h"
#include "config_mathutil.h"
#include "indent.h"
using std::istream;
using std::ostream;
using std::string;
TypeHandle BoundingVolume::_type_handle;
/**
* Resets the volume to enclose only the volumes indicated. Returns true if
* successful, false if the volume doesn't know how to do that or can't do
* that.
*/
bool BoundingVolume::
around(const BoundingVolume **first, const BoundingVolume **last) {
_flags = F_empty;
// Skip any empty volumes at the beginning of the list. We want to get to
// the first real volume.
while (first != last && (*first)->is_empty()) {
if ((*first)->is_infinite()) {
// If we go around an infinite volume, we're infinite too.
_flags = F_infinite;
return true;
}
++first;
}
bool okflag = true;
if (first != last) {
// Check for more infinite bounding volumes in the list.
const BoundingVolume **bvi;
for (bvi = first; bvi != last; ++bvi) {
if ((*bvi)->is_infinite()) {
_flags = F_infinite;
return true;
}
}
// This is a double-dispatch. We call this virtual function on the volume
// we were given, which will in turn call the appropriate virtual function
// in our own class to perform the operation.
if (!(*first)->around_other(this, first, last)) {
okflag = false;
}
}
return okflag;
}
/**
*
*/
void BoundingVolume::
write(ostream &out, int indent_level) const {
indent(out, indent_level) << *this << "\n";
}
/**
* 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.
*/
GeometricBoundingVolume *BoundingVolume::
as_geometric_bounding_volume() {
return nullptr;
}
/**
* 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 GeometricBoundingVolume *BoundingVolume::
as_geometric_bounding_volume() const {
return nullptr;
}
/**
* 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 FiniteBoundingVolume *BoundingVolume::
as_finite_bounding_volume() const {
return nullptr;
}
/**
* 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 BoundingSphere *BoundingVolume::
as_bounding_sphere() const {
return nullptr;
}
/**
* 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 BoundingBox *BoundingVolume::
as_bounding_box() const {
return nullptr;
}
/**
* 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 BoundingHexahedron *BoundingVolume::
as_bounding_hexahedron() const {
return nullptr;
}
/**
* 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 BoundingLine *BoundingVolume::
as_bounding_line() const {
return nullptr;
}
/**
* 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 *BoundingVolume::
as_bounding_plane() const {
return nullptr;
}
/**
* Returns the BoundsType corresponding to the indicated string.
*/
BoundingVolume::BoundsType BoundingVolume::
string_bounds_type(const string &str) {
if (strcmp(str.c_str(), "default") == 0) {
return BT_default;
} else if (strcmp(str.c_str(), "best") == 0) {
return BT_best;
} else if (strcmp(str.c_str(), "fastest") == 0) {
return BT_fastest;
} else if (strcmp(str.c_str(), "sphere") == 0) {
return BT_sphere;
} else if (strcmp(str.c_str(), "box") == 0) {
return BT_box;
}
return BT_default;
}
/**
* Double-dispatch support: called by extend_other() when the type we're
* extending by is known to be a sphere.
*/
bool BoundingVolume::
extend_by_sphere(const BoundingSphere *sphere) {
return extend_by_finite(sphere);
}
/**
* Double-dispatch support: called by extend_other() when the type we're
* extending by is known to be a box.
*/
bool BoundingVolume::
extend_by_box(const BoundingBox *box) {
return extend_by_finite(box);
}
/**
* Double-dispatch support: called by extend_other() when the type we're
* extending by is known to be a hexahedron.
*/
bool BoundingVolume::
extend_by_hexahedron(const BoundingHexahedron *hexahedron) {
return extend_by_finite(hexahedron);
}
/**
* Double-dispatch support: called by extend_other() when the type we're
* extending by is known to be a line.
*/
bool BoundingVolume::
extend_by_line(const BoundingLine *line) {
return extend_by_geometric(line);
}
/**
* Double-dispatch support: called by extend_other() when the type we're
* extending by is known to be a plane.
*/
bool BoundingVolume::
extend_by_plane(const BoundingPlane *plane) {
return extend_by_geometric(plane);
}
/**
* Double-dispatch support: called by extend_other() when the type we're
* extending by is known to be a union.
*/
bool BoundingVolume::
extend_by_union(const UnionBoundingVolume *unionv) {
return extend_by_geometric(unionv);
}
/**
* Double-dispatch support: called by extend_other() when the type we're
* extending by is known to be a intersection.
*/
bool BoundingVolume::
extend_by_intersection(const IntersectionBoundingVolume *intersection) {
return extend_by_geometric(intersection);
}
/**
* Generic handler for a FiniteBoundingVolume.
*/
bool BoundingVolume::
extend_by_finite(const FiniteBoundingVolume *volume) {
return extend_by_geometric(volume);
}
/**
* Generic handler for a GeometricBoundingVolume.
*/
bool BoundingVolume::
extend_by_geometric(const GeometricBoundingVolume *volume) {
mathutil_cat.warning()
<< get_type() << "::extend_by_geometric() called with " << volume->get_type() << "\n";
_flags = F_infinite;
return false;
}
/**
* Double-dispatch support: called by around_other() when the type of the
* first element in the list is known to be a nonempty sphere.
*/
bool BoundingVolume::
around_spheres(const BoundingVolume **first, const BoundingVolume **last) {
return around_finite(first, last);
}
/**
* Double-dispatch support: called by around_other() when the type of the
* first element in the list is known to be a nonempty box.
*/
bool BoundingVolume::
around_boxes(const BoundingVolume **first, const BoundingVolume **last) {
return around_finite(first, last);
}
/**
* Double-dispatch support: called by around_other() when the type of the
* first element in the list is known to be a nonempty hexahedron.
*/
bool BoundingVolume::
around_hexahedrons(const BoundingVolume **first, const BoundingVolume **last) {
return around_finite(first, last);
}
/**
* Double-dispatch support: called by around_other() when the type of the
* first element in the list is known to be a nonempty line.
*/
bool BoundingVolume::
around_lines(const BoundingVolume **first, const BoundingVolume **last) {
return around_geometric(first, last);
}
/**
* Double-dispatch support: called by around_other() when the type of the
* first element in the list is known to be a nonempty plane.
*/
bool BoundingVolume::
around_planes(const BoundingVolume **first, const BoundingVolume **last) {
return around_geometric(first, last);
}
/**
* Double-dispatch support: called by around_other() when the type of the
* first element in the list is known to be a union object.
*/
bool BoundingVolume::
around_unions(const BoundingVolume **first, const BoundingVolume **last) {
return around_geometric(first, last);
}
/**
* Double-dispatch support: called by around_other() when the type of the
* first element in the list is known to be an intersection object.
*/
bool BoundingVolume::
around_intersections(const BoundingVolume **first, const BoundingVolume **last) {
return around_geometric(first, last);
}
/**
* Generic handler for a FiniteBoundingVolume.
*/
bool BoundingVolume::
around_finite(const BoundingVolume **first, const BoundingVolume **last) {
return around_geometric(first, last);
}
/**
* Generic handler for a GeometricBoundingVolume.
*/
bool BoundingVolume::
around_geometric(const BoundingVolume **first, const BoundingVolume **last) {
mathutil_cat.warning()
<< get_type() << "::extend_by_geometric() called with " << first[0]->get_type() << "\n";
_flags = F_infinite;
return false;
}
/**
* Double-dispatch support: called by contains_other() when the type we're
* testing for intersection is known to be a sphere.
*/
int BoundingVolume::
contains_sphere(const BoundingSphere *sphere) const {
return contains_finite(sphere);
}
/**
* Double-dispatch support: called by contains_other() when the type we're
* testing for intersection is known to be a box.
*/
int BoundingVolume::
contains_box(const BoundingBox *box) const {
return contains_finite(box);
}
/**
* Double-dispatch support: called by contains_other() when the type we're
* testing for intersection is known to be a hexahedron.
*/
int BoundingVolume::
contains_hexahedron(const BoundingHexahedron *hexahedron) const {
return contains_finite(hexahedron);
}
/**
* Double-dispatch support: called by contains_other() when the type we're
* testing for intersection is known to be a line.
*/
int BoundingVolume::
contains_line(const BoundingLine *line) const {
return contains_geometric(line);
}
/**
* Double-dispatch support: called by contains_other() when the type we're
* testing for intersection is known to be a plane.
*/
int BoundingVolume::
contains_plane(const BoundingPlane *plane) const {
return contains_geometric(plane);
}
/**
* Double-dispatch support: called by contains_other() when the type we're
* testing for intersection is known to be a union object.
*/
int BoundingVolume::
contains_union(const UnionBoundingVolume *unionv) const {
return unionv->other_contains_union(this);
}
/**
* Double-dispatch support: called by contains_other() when the type we're
* testing for intersection is known to be an intersection object.
*/
int BoundingVolume::
contains_intersection(const IntersectionBoundingVolume *intersection) const {
return intersection->other_contains_intersection(this);
}
/**
* Generic handler for a FiniteBoundingVolume.
*/
int BoundingVolume::
contains_finite(const FiniteBoundingVolume *volume) const {
return contains_geometric(volume);
}
/**
* Generic handler for a GeometricBoundingVolume.
*/
int BoundingVolume::
contains_geometric(const GeometricBoundingVolume *volume) const {
mathutil_cat.warning()
<< get_type() << "::contains_geometric() called with " << volume->get_type() << "\n";
return IF_dont_understand;
}
ostream &
operator << (ostream &out, BoundingVolume::BoundsType type) {
switch (type) {
case BoundingVolume::BT_default:
return out << "default";
case BoundingVolume::BT_best:
return out << "best";
case BoundingVolume::BT_fastest:
return out << "fastest";
case BoundingVolume::BT_sphere:
return out << "sphere";
case BoundingVolume::BT_box:
return out << "box";
}
mathutil_cat.error()
<< "Invalid BoundingVolume::BoundsType value: " << (int)type << "\n";
nassertr(false, out);
return out;
}
istream &
operator >> (istream &in, BoundingVolume::BoundsType &type) {
string word;
in >> word;
type = BoundingVolume::string_bounds_type(word);
if (type == BoundingVolume::BT_default) {
mathutil_cat->error()
<< "Invalid BoundingVolume::BoundsType string: " << word << "\n";
}
return in;
}