|
@@ -0,0 +1,592 @@
|
|
|
|
|
+// Filename: intersectionBoundingVolume.cxx
|
|
|
|
|
+// Created by: drose (08Feb12)
|
|
|
|
|
+//
|
|
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
|
|
+//
|
|
|
|
|
+// 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 "intersectionBoundingVolume.h"
|
|
|
|
|
+#include "unionBoundingVolume.h"
|
|
|
|
|
+#include "config_mathutil.h"
|
|
|
|
|
+#include "dcast.h"
|
|
|
|
|
+
|
|
|
|
|
+TypeHandle IntersectionBoundingVolume::_type_handle;
|
|
|
|
|
+
|
|
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
|
|
+// Function: IntersectionBoundingVolume::Copy Constructor
|
|
|
|
|
+// Access: Public
|
|
|
|
|
+// Description:
|
|
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
|
|
+IntersectionBoundingVolume::
|
|
|
|
|
+IntersectionBoundingVolume(const IntersectionBoundingVolume ©) :
|
|
|
|
|
+ GeometricBoundingVolume(copy),
|
|
|
|
|
+ _components(copy._components)
|
|
|
|
|
+{
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
|
|
+// Function: IntersectionBoundingVolume::make_copy
|
|
|
|
|
+// Access: Public, Virtual
|
|
|
|
|
+// Description:
|
|
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
|
|
+BoundingVolume *IntersectionBoundingVolume::
|
|
|
|
|
+make_copy() const {
|
|
|
|
|
+ return new IntersectionBoundingVolume(*this);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
|
|
+// Function: IntersectionBoundingVolume::get_approx_center
|
|
|
|
|
+// Access: Public, Virtual
|
|
|
|
|
+// Description:
|
|
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
|
|
+LPoint3 IntersectionBoundingVolume::
|
|
|
|
|
+get_approx_center() const {
|
|
|
|
|
+ nassertr(!is_empty(), LPoint3::zero());
|
|
|
|
|
+ nassertr(!is_infinite(), LPoint3::zero());
|
|
|
|
|
+
|
|
|
|
|
+ LPoint3 center = LPoint3::zero();
|
|
|
|
|
+ for (Components::const_iterator ci = _components.begin();
|
|
|
|
|
+ ci != _components.end();
|
|
|
|
|
+ ++ci) {
|
|
|
|
|
+ center += (*ci)->get_approx_center();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return center / (PN_stdfloat)_components.size();
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
|
|
+// Function: IntersectionBoundingVolume::xform
|
|
|
|
|
+// Access: Public, Virtual
|
|
|
|
|
+// Description:
|
|
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
|
|
+void IntersectionBoundingVolume::
|
|
|
|
|
+xform(const LMatrix4 &mat) {
|
|
|
|
|
+ nassertv(!mat.is_nan());
|
|
|
|
|
+
|
|
|
|
|
+ for (Components::iterator ci = _components.begin();
|
|
|
|
|
+ ci != _components.end();
|
|
|
|
|
+ ++ci) {
|
|
|
|
|
+ PT(GeometricBoundingVolume) copy = DCAST(GeometricBoundingVolume, (*ci)->make_copy());
|
|
|
|
|
+ copy->xform(mat);
|
|
|
|
|
+ (*ci) = copy;
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
|
|
+// Function: IntersectionBoundingVolume::output
|
|
|
|
|
+// Access: Public, Virtual
|
|
|
|
|
+// Description:
|
|
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
|
|
+void IntersectionBoundingVolume::
|
|
|
|
|
+output(ostream &out) const {
|
|
|
|
|
+ if (is_empty()) {
|
|
|
|
|
+ out << "intersection, empty";
|
|
|
|
|
+ } else if (is_infinite()) {
|
|
|
|
|
+ out << "intersection, infinite";
|
|
|
|
|
+ } else {
|
|
|
|
|
+ out << "intersection [";
|
|
|
|
|
+ for (Components::const_iterator ci = _components.begin();
|
|
|
|
|
+ ci != _components.end();
|
|
|
|
|
+ ++ci) {
|
|
|
|
|
+ out << " " << *(*ci);
|
|
|
|
|
+ }
|
|
|
|
|
+ out << " ]";
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
|
|
+// Function: IntersectionBoundingVolume::write
|
|
|
|
|
+// Access: Public, Virtual
|
|
|
|
|
+// Description:
|
|
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
|
|
+void IntersectionBoundingVolume::
|
|
|
|
|
+write(ostream &out, int indent_level) const {
|
|
|
|
|
+ if (is_empty()) {
|
|
|
|
|
+ indent(out, indent_level) << "intersection, empty\n";
|
|
|
|
|
+ } else if (is_infinite()) {
|
|
|
|
|
+ indent(out, indent_level) << "intersection, infinite\n";
|
|
|
|
|
+ } else {
|
|
|
|
|
+ indent(out, indent_level) << "intersection {\n";
|
|
|
|
|
+ for (Components::const_iterator ci = _components.begin();
|
|
|
|
|
+ ci != _components.end();
|
|
|
|
|
+ ++ci) {
|
|
|
|
|
+ (*ci)->write(out, indent_level + 2);
|
|
|
|
|
+ }
|
|
|
|
|
+ indent(out, indent_level) << "}\n";
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
|
|
+// Function: IntersectionBoundingVolume::clear_components
|
|
|
|
|
+// Access: Published
|
|
|
|
|
+// Description: Removes all components from the volume.
|
|
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
|
|
+void IntersectionBoundingVolume::
|
|
|
|
|
+clear_components() {
|
|
|
|
|
+ _components.clear();
|
|
|
|
|
+ _flags = F_infinite;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
|
|
+// Function: IntersectionBoundingVolume::add_component
|
|
|
|
|
+// Access: Published
|
|
|
|
|
+// Description: Adds a new component to the volume. This does not
|
|
|
|
|
+// necessarily increase the total number of components
|
|
|
|
|
+// by one, and you may or may not be able to find this
|
|
|
|
|
+// component in the volume by a subsequent call to
|
|
|
|
|
+// get_component(); certain optimizations may prevent
|
|
|
|
|
+// the component from being added, or have other
|
|
|
|
|
+// unexpected effects on the total set of components.
|
|
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
|
|
+void IntersectionBoundingVolume::
|
|
|
|
|
+add_component(const GeometricBoundingVolume *component) {
|
|
|
|
|
+ CPT(GeometricBoundingVolume) gbv;
|
|
|
|
|
+
|
|
|
|
|
+ if (component->is_exact_type(UnionBoundingVolume::get_class_type())) {
|
|
|
|
|
+ // Here's a special case. We'll construct a new union that
|
|
|
|
|
+ // includes only those components that have some intersection with
|
|
|
|
|
+ // our existing components. (No need to include the components
|
|
|
|
|
+ // that have no intersection.)
|
|
|
|
|
+ PT(UnionBoundingVolume) unionv = DCAST(UnionBoundingVolume, component->make_copy());
|
|
|
|
|
+ unionv->filter_intersection(this);
|
|
|
|
|
+
|
|
|
|
|
+ // Save the modified union in a PT() so it won't be destructed.
|
|
|
|
|
+ gbv = unionv.p();
|
|
|
|
|
+
|
|
|
|
|
+ if (unionv->get_num_components() == 1) {
|
|
|
|
|
+ // If there's only one component left, use just that one.
|
|
|
|
|
+ gbv = unionv->get_component(0);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ component = gbv;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (component->is_empty()) {
|
|
|
|
|
+ _flags = F_empty;
|
|
|
|
|
+ _components.clear();
|
|
|
|
|
+
|
|
|
|
|
+ } else if (component->is_infinite() || is_empty()) {
|
|
|
|
|
+ // No-op.
|
|
|
|
|
+
|
|
|
|
|
+ } else if (component->is_exact_type(IntersectionBoundingVolume::get_class_type())) {
|
|
|
|
|
+ // Another special case. Just more components.
|
|
|
|
|
+ const IntersectionBoundingVolume *other = DCAST(IntersectionBoundingVolume, component);
|
|
|
|
|
+ for (Components::const_iterator ci = other->_components.begin();
|
|
|
|
|
+ ci != other->_components.end();
|
|
|
|
|
+ ++ci) {
|
|
|
|
|
+ add_component(*ci);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ } else {
|
|
|
|
|
+ // The general case.
|
|
|
|
|
+ size_t i = 0;
|
|
|
|
|
+ while (i < _components.size()) {
|
|
|
|
|
+ const GeometricBoundingVolume *existing = _components[i];
|
|
|
|
|
+ ++i;
|
|
|
|
|
+
|
|
|
|
|
+ int result = component->contains(existing);
|
|
|
|
|
+ if ((result & IF_all) != 0) {
|
|
|
|
|
+ // The existing component is entirely within this one; no need
|
|
|
|
|
+ // to do anything with it.
|
|
|
|
|
+ return;
|
|
|
|
|
+
|
|
|
|
|
+ } else if (result == 0) {
|
|
|
|
|
+ // No intersection between these components; we're now empty.
|
|
|
|
|
+ _flags = F_empty;
|
|
|
|
|
+ _components.clear();
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ result = existing->contains(component);
|
|
|
|
|
+ if ((result & IF_all) != 0) {
|
|
|
|
|
+ // This new component is entirely within an existing
|
|
|
|
|
+ // component; no need to keep the existing one.
|
|
|
|
|
+ --i;
|
|
|
|
|
+ _components.erase(_components.begin() + i);
|
|
|
|
|
+
|
|
|
|
|
+ } else if (result == 0) {
|
|
|
|
|
+ // No intersection between these components; we're now empty.
|
|
|
|
|
+ _flags = F_empty;
|
|
|
|
|
+ _components.clear();
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ _flags &= ~F_infinite;
|
|
|
|
|
+ _components.push_back(component);
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
|
|
+// Function: IntersectionBoundingVolume::extend_other
|
|
|
|
|
+// Access: Protected, Virtual
|
|
|
|
|
+// Description:
|
|
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
|
|
+bool IntersectionBoundingVolume::
|
|
|
|
|
+extend_other(BoundingVolume *other) const {
|
|
|
|
|
+ return other->extend_by_intersection(this);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
|
|
+// Function: IntersectionBoundingVolume::around_other
|
|
|
|
|
+// Access: Protected, Virtual
|
|
|
|
|
+// Description:
|
|
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
|
|
+bool IntersectionBoundingVolume::
|
|
|
|
|
+around_other(BoundingVolume *other,
|
|
|
|
|
+ const BoundingVolume **first,
|
|
|
|
|
+ const BoundingVolume **last) const {
|
|
|
|
|
+ return other->around_intersections(first, last);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
|
|
+// Function: IntersectionBoundingVolume::contains_other
|
|
|
|
|
+// Access: Protected, Virtual
|
|
|
|
|
+// Description:
|
|
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
|
|
+int IntersectionBoundingVolume::
|
|
|
|
|
+contains_other(const BoundingVolume *other) const {
|
|
|
|
|
+ return other->contains_intersection(this);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
|
|
+// Function: IntersectionBoundingVolume::contains_point
|
|
|
|
|
+// Access: Protected, Virtual
|
|
|
|
|
+// Description:
|
|
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
|
|
+int IntersectionBoundingVolume::
|
|
|
|
|
+contains_point(const LPoint3 &point) const {
|
|
|
|
|
+ nassertr(!point.is_nan(), IF_no_intersection);
|
|
|
|
|
+
|
|
|
|
|
+ int result = IF_possible | IF_some | IF_all;
|
|
|
|
|
+ for (Components::const_iterator ci = _components.begin();
|
|
|
|
|
+ ci != _components.end();
|
|
|
|
|
+ ++ci) {
|
|
|
|
|
+ int this_result = (*ci)->contains(point);
|
|
|
|
|
+ if ((this_result & IF_dont_understand) != 0) {
|
|
|
|
|
+ result |= IF_dont_understand;
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ result &= this_result;
|
|
|
|
|
+ if ((result & IF_possible) == 0) {
|
|
|
|
|
+ // No point in looking further.
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return result;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
|
|
+// Function: IntersectionBoundingVolume::contains_lineseg
|
|
|
|
|
+// Access: Protected, Virtual
|
|
|
|
|
+// Description:
|
|
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
|
|
+int IntersectionBoundingVolume::
|
|
|
|
|
+contains_lineseg(const LPoint3 &a, const LPoint3 &b) const {
|
|
|
|
|
+ nassertr(!a.is_nan() && !b.is_nan(), IF_no_intersection);
|
|
|
|
|
+
|
|
|
|
|
+ int result = IF_possible | IF_some | IF_all;
|
|
|
|
|
+ for (Components::const_iterator ci = _components.begin();
|
|
|
|
|
+ ci != _components.end();
|
|
|
|
|
+ ++ci) {
|
|
|
|
|
+ int this_result = (*ci)->contains(a, b);
|
|
|
|
|
+ if ((this_result & IF_dont_understand) != 0) {
|
|
|
|
|
+ result |= IF_dont_understand;
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ result &= this_result;
|
|
|
|
|
+ if ((result & IF_possible) == 0) {
|
|
|
|
|
+ // No point in looking further.
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return result;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
|
|
+// Function: IntersectionBoundingVolume::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 IntersectionBoundingVolume::
|
|
|
|
|
+contains_sphere(const BoundingSphere *sphere) const {
|
|
|
|
|
+ int result = IF_possible | IF_some | IF_all;
|
|
|
|
|
+ for (Components::const_iterator ci = _components.begin();
|
|
|
|
|
+ ci != _components.end();
|
|
|
|
|
+ ++ci) {
|
|
|
|
|
+ int this_result = (*ci)->contains_sphere(sphere);
|
|
|
|
|
+ if ((this_result & IF_dont_understand) != 0) {
|
|
|
|
|
+ result |= IF_dont_understand;
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ result &= this_result;
|
|
|
|
|
+ if ((result & IF_possible) == 0) {
|
|
|
|
|
+ // No point in looking further.
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return result;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
|
|
+// Function: IntersectionBoundingVolume::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 IntersectionBoundingVolume::
|
|
|
|
|
+contains_box(const BoundingBox *box) const {
|
|
|
|
|
+ int result = IF_possible | IF_some | IF_all;
|
|
|
|
|
+ for (Components::const_iterator ci = _components.begin();
|
|
|
|
|
+ ci != _components.end();
|
|
|
|
|
+ ++ci) {
|
|
|
|
|
+ int this_result = (*ci)->contains_box(box);
|
|
|
|
|
+ if ((this_result & IF_dont_understand) != 0) {
|
|
|
|
|
+ result |= IF_dont_understand;
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ result &= this_result;
|
|
|
|
|
+ if ((result & IF_possible) == 0) {
|
|
|
|
|
+ // No point in looking further.
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return result;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
|
|
+// Function: IntersectionBoundingVolume::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 IntersectionBoundingVolume::
|
|
|
|
|
+contains_hexahedron(const BoundingHexahedron *hexahedron) const {
|
|
|
|
|
+ int result = IF_possible | IF_some | IF_all;
|
|
|
|
|
+ for (Components::const_iterator ci = _components.begin();
|
|
|
|
|
+ ci != _components.end();
|
|
|
|
|
+ ++ci) {
|
|
|
|
|
+ int this_result = (*ci)->contains_hexahedron(hexahedron);
|
|
|
|
|
+ if ((this_result & IF_dont_understand) != 0) {
|
|
|
|
|
+ result |= IF_dont_understand;
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ result &= this_result;
|
|
|
|
|
+ if ((result & IF_possible) == 0) {
|
|
|
|
|
+ // No point in looking further.
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return result;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
|
|
+// Function: IntersectionBoundingVolume::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 IntersectionBoundingVolume::
|
|
|
|
|
+contains_line(const BoundingLine *line) const {
|
|
|
|
|
+ int result = IF_possible | IF_some | IF_all;
|
|
|
|
|
+ for (Components::const_iterator ci = _components.begin();
|
|
|
|
|
+ ci != _components.end();
|
|
|
|
|
+ ++ci) {
|
|
|
|
|
+ int this_result = (*ci)->contains_line(line);
|
|
|
|
|
+ if ((this_result & IF_dont_understand) != 0) {
|
|
|
|
|
+ result |= IF_dont_understand;
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ result &= this_result;
|
|
|
|
|
+ if ((result & IF_possible) == 0) {
|
|
|
|
|
+ // No point in looking further.
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return result;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
|
|
+// Function: IntersectionBoundingVolume::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 IntersectionBoundingVolume::
|
|
|
|
|
+contains_plane(const BoundingPlane *plane) const {
|
|
|
|
|
+ int result = IF_possible | IF_some | IF_all;
|
|
|
|
|
+ for (Components::const_iterator ci = _components.begin();
|
|
|
|
|
+ ci != _components.end();
|
|
|
|
|
+ ++ci) {
|
|
|
|
|
+ int this_result = (*ci)->contains_plane(plane);
|
|
|
|
|
+ if ((this_result & IF_dont_understand) != 0) {
|
|
|
|
|
+ result |= IF_dont_understand;
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ result &= this_result;
|
|
|
|
|
+ if ((result & IF_possible) == 0) {
|
|
|
|
|
+ // No point in looking further.
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return result;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
|
|
+// Function: IntersectionBoundingVolume::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 IntersectionBoundingVolume::
|
|
|
|
|
+contains_union(const UnionBoundingVolume *unionv) const {
|
|
|
|
|
+ int result = IF_possible | IF_some | IF_all;
|
|
|
|
|
+ for (Components::const_iterator ci = _components.begin();
|
|
|
|
|
+ ci != _components.end();
|
|
|
|
|
+ ++ci) {
|
|
|
|
|
+ int this_result = (*ci)->contains_union(unionv);
|
|
|
|
|
+ if ((this_result & IF_dont_understand) != 0) {
|
|
|
|
|
+ result |= IF_dont_understand;
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ result &= this_result;
|
|
|
|
|
+ if ((result & IF_possible) == 0) {
|
|
|
|
|
+ // No point in looking further.
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return result;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
|
|
+// Function: IntersectionBoundingVolume::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 IntersectionBoundingVolume::
|
|
|
|
|
+contains_intersection(const IntersectionBoundingVolume *intersection) const {
|
|
|
|
|
+ int result = IF_possible | IF_some | IF_all;
|
|
|
|
|
+ for (Components::const_iterator ci = _components.begin();
|
|
|
|
|
+ ci != _components.end();
|
|
|
|
|
+ ++ci) {
|
|
|
|
|
+ int this_result = (*ci)->contains_intersection(intersection);
|
|
|
|
|
+ if ((this_result & IF_dont_understand) != 0) {
|
|
|
|
|
+ result |= IF_dont_understand;
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ result &= this_result;
|
|
|
|
|
+ if ((result & IF_possible) == 0) {
|
|
|
|
|
+ // No point in looking further.
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return result;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
|
|
+// Function: IntersectionBoundingVolume::contains_finite
|
|
|
|
|
+// Access: Protected, Virtual
|
|
|
|
|
+// Description: Generic handler for a FiniteBoundingVolume.
|
|
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
|
|
+int IntersectionBoundingVolume::
|
|
|
|
|
+contains_finite(const FiniteBoundingVolume *volume) const {
|
|
|
|
|
+ int result = IF_possible | IF_some | IF_all;
|
|
|
|
|
+ for (Components::const_iterator ci = _components.begin();
|
|
|
|
|
+ ci != _components.end();
|
|
|
|
|
+ ++ci) {
|
|
|
|
|
+ int this_result = (*ci)->contains_finite(volume);
|
|
|
|
|
+ if ((this_result & IF_dont_understand) != 0) {
|
|
|
|
|
+ result |= IF_dont_understand;
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ result &= this_result;
|
|
|
|
|
+ if ((result & IF_possible) == 0) {
|
|
|
|
|
+ // No point in looking further.
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return result;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
|
|
+// Function: IntersectionBoundingVolume::contains_geometric
|
|
|
|
|
+// Access: Protected, Virtual
|
|
|
|
|
+// Description: Generic handler for a GeometricBoundingVolume.
|
|
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
|
|
+int IntersectionBoundingVolume::
|
|
|
|
|
+contains_geometric(const GeometricBoundingVolume *volume) const {
|
|
|
|
|
+ int result = IF_possible | IF_some | IF_all;
|
|
|
|
|
+ for (Components::const_iterator ci = _components.begin();
|
|
|
|
|
+ ci != _components.end();
|
|
|
|
|
+ ++ci) {
|
|
|
|
|
+ int this_result = (*ci)->contains_geometric(volume);
|
|
|
|
|
+ if ((this_result & IF_dont_understand) != 0) {
|
|
|
|
|
+ result |= IF_dont_understand;
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ result &= this_result;
|
|
|
|
|
+ if ((result & IF_possible) == 0) {
|
|
|
|
|
+ // No point in looking further.
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return result;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
|
|
+// Function: IntersectionBoundingVolume::other_contains_intersection
|
|
|
|
|
+// Access: Protected, Virtual
|
|
|
|
|
+// Description: Generic reverse-direction comparison. Called by
|
|
|
|
|
+// BoundingVolumes that do not implement
|
|
|
|
|
+// contains_intersection() explicitly. This returns the test
|
|
|
|
|
+// of whether the other volume contains this volume.
|
|
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
|
|
+int IntersectionBoundingVolume::
|
|
|
|
|
+other_contains_intersection(const BoundingVolume *volume) const {
|
|
|
|
|
+ int result = IF_possible | IF_some | IF_all;
|
|
|
|
|
+ for (Components::const_iterator ci = _components.begin();
|
|
|
|
|
+ ci != _components.end();
|
|
|
|
|
+ ++ci) {
|
|
|
|
|
+ int this_result = volume->contains(*ci);
|
|
|
|
|
+ if ((this_result & IF_dont_understand) != 0) {
|
|
|
|
|
+ result |= IF_dont_understand;
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ result &= this_result;
|
|
|
|
|
+ if ((result & IF_possible) == 0) {
|
|
|
|
|
+ // No point in looking further.
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return result;
|
|
|
|
|
+}
|
|
|
|
|
+
|