543 lines
21 KiB
C++
543 lines
21 KiB
C++
// Filename: boundingVolume.cxx
|
|
// Created by: drose (01Oct99)
|
|
//
|
|
////////////////////////////////////////////////////////////////////
|
|
//
|
|
// 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 "boundingVolume.h"
|
|
#include "finiteBoundingVolume.h"
|
|
#include "unionBoundingVolume.h"
|
|
#include "intersectionBoundingVolume.h"
|
|
|
|
#include "indent.h"
|
|
|
|
TypeHandle BoundingVolume::_type_handle;
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: BoundingVolume::around
|
|
// Access: Published
|
|
// Description: 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;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: BoundingVolume::write
|
|
// Access: Published
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
void BoundingVolume::
|
|
write(ostream &out, int indent_level) const {
|
|
indent(out, indent_level) << *this << "\n";
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: BoundingVolume::as_geometric_bounding_volume
|
|
// 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 GeometricBoundingVolume *BoundingVolume::
|
|
as_geometric_bounding_volume() const {
|
|
return NULL;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: BoundingVolume::as_finite_bounding_volume
|
|
// 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 FiniteBoundingVolume *BoundingVolume::
|
|
as_finite_bounding_volume() const {
|
|
return NULL;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: BoundingVolume::as_bounding_sphere
|
|
// 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 BoundingSphere *BoundingVolume::
|
|
as_bounding_sphere() const {
|
|
return NULL;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: BoundingVolume::as_bounding_box
|
|
// 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 BoundingBox *BoundingVolume::
|
|
as_bounding_box() const {
|
|
return NULL;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: BoundingVolume::as_bounding_hexahedron
|
|
// 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 BoundingHexahedron *BoundingVolume::
|
|
as_bounding_hexahedron() const {
|
|
return NULL;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: BoundingVolume::as_bounding_line
|
|
// 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 BoundingLine *BoundingVolume::
|
|
as_bounding_line() const {
|
|
return NULL;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: BoundingVolume::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 *BoundingVolume::
|
|
as_bounding_plane() const {
|
|
return NULL;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: BoundingVolume::string_bounds_type
|
|
// Access: Public, Static
|
|
// Description: 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(), "sphere") == 0) {
|
|
return BT_sphere;
|
|
|
|
} else if (strcmp(str.c_str(), "box") == 0) {
|
|
return BT_box;
|
|
}
|
|
|
|
return BT_default;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: BoundingVolume::extend_by_sphere
|
|
// Access: Protected, Virtual
|
|
// Description: 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);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: BoundingVolume::extend_by_box
|
|
// Access: Protected, Virtual
|
|
// Description: 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);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: BoundingVolume::extend_by_hexahedron
|
|
// Access: Protected, Virtual
|
|
// Description: 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);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: BoundingVolume::extend_by_line
|
|
// Access: Protected, Virtual
|
|
// Description: 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);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: BoundingVolume::extend_by_plane
|
|
// Access: Protected, Virtual
|
|
// Description: 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);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: BoundingVolume::extend_by_union
|
|
// Access: Protected, Virtual
|
|
// Description: 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);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: BoundingVolume::extend_by_intersection
|
|
// Access: Protected, Virtual
|
|
// Description: 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);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: BoundingVolume::extend_by_finite
|
|
// Access: Protected, Virtual
|
|
// Description: Generic handler for a FiniteBoundingVolume.
|
|
////////////////////////////////////////////////////////////////////
|
|
bool BoundingVolume::
|
|
extend_by_finite(const FiniteBoundingVolume *volume) {
|
|
return extend_by_geometric(volume);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: BoundingVolume::extend_by_geometric
|
|
// Access: Protected, Virtual
|
|
// Description: 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;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: BoundingVolume::around_spheres
|
|
// Access: Protected, Virtual
|
|
// Description: 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);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: BoundingVolume::around_boxes
|
|
// Access: Protected, Virtual
|
|
// Description: 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);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: BoundingVolume::around_hexahedrons
|
|
// Access: Protected, Virtual
|
|
// Description: 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);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: BoundingVolume::around_lines
|
|
// Access: Protected, Virtual
|
|
// Description: 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);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: BoundingVolume::around_planes
|
|
// Access: Protected, Virtual
|
|
// Description: 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);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: BoundingVolume::around_unions
|
|
// Access: Protected, Virtual
|
|
// Description: 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);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: BoundingVolume::around_intersections
|
|
// Access: Protected, Virtual
|
|
// Description: 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);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: BoundingVolume::around_finite
|
|
// Access: Protected, Virtual
|
|
// Description: Generic handler for a FiniteBoundingVolume.
|
|
////////////////////////////////////////////////////////////////////
|
|
bool BoundingVolume::
|
|
around_finite(const BoundingVolume **first, const BoundingVolume **last) {
|
|
return around_geometric(first, last);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: BoundingVolume::around_geometric
|
|
// Access: Protected, Virtual
|
|
// Description: 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;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: BoundingVolume::contains_sphere
|
|
// Access: Protected, Virtual
|
|
// Description: 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);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: BoundingVolume::contains_box
|
|
// Access: Protected, Virtual
|
|
// Description: 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);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: BoundingVolume::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 BoundingVolume::
|
|
contains_hexahedron(const BoundingHexahedron *hexahedron) const {
|
|
return contains_finite(hexahedron);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: BoundingVolume::contains_line
|
|
// Access: Protected, Virtual
|
|
// Description: 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);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: BoundingVolume::contains_plane
|
|
// Access: Protected, Virtual
|
|
// Description: 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);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: BoundingVolume::contains_union
|
|
// Access: Protected, Virtual
|
|
// Description: 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);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: BoundingVolume::contains_intersection
|
|
// Access: Protected, Virtual
|
|
// Description: 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);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: BoundingVolume::contains_finite
|
|
// Access: Protected, Virtual
|
|
// Description: Generic handler for a FiniteBoundingVolume.
|
|
////////////////////////////////////////////////////////////////////
|
|
int BoundingVolume::
|
|
contains_finite(const FiniteBoundingVolume *volume) const {
|
|
return contains_geometric(volume);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: BoundingVolume::contains_geometric
|
|
// Access: Protected, Virtual
|
|
// Description: 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_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;
|
|
}
|
|
|