diff --git a/panda/src/display/graphicsEngine.cxx b/panda/src/display/graphicsEngine.cxx index f9ca6efdbf..ee701a4032 100644 --- a/panda/src/display/graphicsEngine.cxx +++ b/panda/src/display/graphicsEngine.cxx @@ -1153,7 +1153,7 @@ do_cull(CullHandler *cull_handler, SceneSetup *scene_setup, // First, we have to get the current viewing frustum, which comes // from the lens. - PT(BoundingVolume) bv = scene_setup->get_lens()->make_bounds(); + PT(BoundingVolume) bv = scene_setup->get_cull_bounds(); if (bv != (BoundingVolume *)NULL && bv->is_of_type(GeometricBoundingVolume::get_class_type())) { diff --git a/panda/src/mathutil/Sources.pp b/panda/src/mathutil/Sources.pp index e13ec4bcaf..0ccafac9cb 100644 --- a/panda/src/mathutil/Sources.pp +++ b/panda/src/mathutil/Sources.pp @@ -20,6 +20,7 @@ fftCompressor.h finiteBoundingVolume.h frustum.h \ frustum_src.I frustum_src.h geometricBoundingVolume.I \ geometricBoundingVolume.h \ + intersectionBoundingVolume.h intersectionBoundingVolume.I \ linmath_events.h \ look_at.h look_at_src.I \ look_at_src.cxx look_at_src.h \ @@ -38,7 +39,8 @@ rotate_to.h rotate_to_src.cxx \ stackedPerlinNoise2.h stackedPerlinNoise2.I \ stackedPerlinNoise3.h stackedPerlinNoise3.I \ - triangulator.h triangulator.I + triangulator.h triangulator.I \ + unionBoundingVolume.h unionBoundingVolume.I #define INCLUDED_SOURCES \ boundingHexahedron.cxx boundingLine.cxx \ @@ -47,6 +49,7 @@ boundingSphere.cxx \ boundingVolume.cxx config_mathutil.cxx fftCompressor.cxx \ finiteBoundingVolume.cxx geometricBoundingVolume.cxx \ + intersectionBoundingVolume.cxx \ look_at.cxx \ linmath_events.cxx \ mersenne.cxx \ @@ -62,7 +65,8 @@ rotate_to.cxx \ stackedPerlinNoise2.cxx \ stackedPerlinNoise3.cxx \ - triangulator.cxx + triangulator.cxx \ + unionBoundingVolume.cxx #define INSTALL_HEADERS \ boundingHexahedron.I boundingHexahedron.h boundingLine.I \ @@ -75,6 +79,7 @@ pta_LVecBase4.h pta_LVecBase2.h \ finiteBoundingVolume.h frustum.h frustum_src.I frustum_src.h \ geometricBoundingVolume.I geometricBoundingVolume.h look_at.h \ + intersectionBoundingVolume.h intersectionBoundingVolume.I \ look_at_src.I look_at_src.h \ linmath_events.h \ mersenne.h \ @@ -88,7 +93,8 @@ rotate_to.h rotate_to_src.cxx \ stackedPerlinNoise2.h stackedPerlinNoise2.I \ stackedPerlinNoise3.h stackedPerlinNoise3.I \ - triangulator.h triangulator.I + triangulator.h triangulator.I \ + unionBoundingVolume.h unionBoundingVolume.I diff --git a/panda/src/mathutil/boundingBox.cxx b/panda/src/mathutil/boundingBox.cxx index ceb3ef6756..7f1ceba25f 100644 --- a/panda/src/mathutil/boundingBox.cxx +++ b/panda/src/mathutil/boundingBox.cxx @@ -203,16 +203,6 @@ extend_by_point(const LPoint3 &point) { return true; } -//////////////////////////////////////////////////////////////////// -// Function: BoundingBox::extend_by_sphere -// Access: Protected, Virtual -// Description: -//////////////////////////////////////////////////////////////////// -bool BoundingBox:: -extend_by_sphere(const BoundingSphere *sphere) { - return extend_by_finite(sphere); -} - //////////////////////////////////////////////////////////////////// // Function: BoundingBox::extend_by_box // Access: Protected, Virtual @@ -240,23 +230,13 @@ extend_by_box(const BoundingBox *box) { } //////////////////////////////////////////////////////////////////// -// Function: BoundingBox::extend_by_hexahedron +// Function: BoundingBox::extend_by_finite // Access: Protected, Virtual // Description: //////////////////////////////////////////////////////////////////// bool BoundingBox:: -extend_by_hexahedron(const BoundingHexahedron *hexahedron) { - return extend_by_finite(hexahedron); -} - -//////////////////////////////////////////////////////////////////// -// Function: BoundingBox::extend_by_finite -// Access: Protected -// Description: -//////////////////////////////////////////////////////////////////// -bool BoundingBox:: extend_by_finite(const FiniteBoundingVolume *volume) { - nassertr(!volume->is_empty(), false); + nassertr(!volume->is_empty() && !volume->is_infinite(), false); LVector3 min1 = volume->get_min(); LVector3 max1 = volume->get_max(); @@ -347,47 +327,14 @@ around_points(const LPoint3 *first, const LPoint3 *last) { return true; } -//////////////////////////////////////////////////////////////////// -// Function: BoundingBox::around_spheres -// Access: Protected, Virtual -// Description: -//////////////////////////////////////////////////////////////////// -bool BoundingBox:: -around_spheres(const BoundingVolume **first, - const BoundingVolume **last) { - return around_finite(first, last); -} - -//////////////////////////////////////////////////////////////////// -// Function: BoundingBox::around_boxes -// Access: Protected, Virtual -// Description: -//////////////////////////////////////////////////////////////////// -bool BoundingBox:: -around_boxes(const BoundingVolume **first, - const BoundingVolume **last) { - return around_finite(first, last); -} - -//////////////////////////////////////////////////////////////////// -// Function: BoundingBox::around_hexahedrons -// Access: Protected, Virtual -// Description: -//////////////////////////////////////////////////////////////////// -bool BoundingBox:: -around_hexahedrons(const BoundingVolume **first, - const BoundingVolume **last) { - return around_finite(first, last); -} - //////////////////////////////////////////////////////////////////// // Function: BoundingBox::around_finite -// Access: Protected +// Access: Protected, Virtual // Description: //////////////////////////////////////////////////////////////////// bool BoundingBox:: around_finite(const BoundingVolume **first, - const BoundingVolume **last) { + const BoundingVolume **last) { nassertr(first != last, false); // We're given a set of bounding volumes, at least the first one of @@ -538,18 +485,6 @@ contains_lineseg(const LPoint3 &a, const LPoint3 &b) const { } } -//////////////////////////////////////////////////////////////////// -// Function: BoundingBox::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 BoundingBox:: -contains_sphere(const BoundingSphere *sphere) const { - return contains_finite(sphere); -} - //////////////////////////////////////////////////////////////////// // Function: BoundingBox::contains_box // Access: Protected, Virtual @@ -630,7 +565,7 @@ contains_plane(const BoundingPlane *plane) const { //////////////////////////////////////////////////////////////////// // Function: BoundingBox::contains_finite -// Access: Protected +// Access: Protected, Virtual // Description: //////////////////////////////////////////////////////////////////// int BoundingBox:: diff --git a/panda/src/mathutil/boundingBox.h b/panda/src/mathutil/boundingBox.h index f166de283c..d816e69a58 100644 --- a/panda/src/mathutil/boundingBox.h +++ b/panda/src/mathutil/boundingBox.h @@ -71,30 +71,21 @@ protected: virtual bool extend_by_point(const LPoint3 &point); - virtual bool extend_by_sphere(const BoundingSphere *sphere); virtual bool extend_by_box(const BoundingBox *box); - virtual bool extend_by_hexahedron(const BoundingHexahedron *hexahedron); - bool extend_by_finite(const FiniteBoundingVolume *volume); + virtual bool extend_by_finite(const FiniteBoundingVolume *volume); virtual bool around_points(const LPoint3 *first, const LPoint3 *last); - virtual bool around_spheres(const BoundingVolume **first, - const BoundingVolume **last); - virtual bool around_boxes(const BoundingVolume **first, - const BoundingVolume **last); - virtual bool around_hexahedrons(const BoundingVolume **first, - const BoundingVolume **last); - bool around_finite(const BoundingVolume **first, - const BoundingVolume **last); + virtual bool around_finite(const BoundingVolume **first, + const BoundingVolume **last); virtual int contains_point(const LPoint3 &point) const; virtual int contains_lineseg(const LPoint3 &a, const LPoint3 &b) const; virtual int contains_hexahedron(const BoundingHexahedron *hexahedron) const; - virtual int contains_sphere(const BoundingSphere *sphere) const; virtual int contains_box(const BoundingBox *box) const; virtual int contains_line(const BoundingLine *line) const; virtual int contains_plane(const BoundingPlane *plane) const; - int contains_finite(const FiniteBoundingVolume *volume) const; + virtual int contains_finite(const FiniteBoundingVolume *volume) const; private: LPoint3 _min; diff --git a/panda/src/mathutil/boundingSphere.cxx b/panda/src/mathutil/boundingSphere.cxx index abd4b13c0e..9373c8a21b 100644 --- a/panda/src/mathutil/boundingSphere.cxx +++ b/panda/src/mathutil/boundingSphere.cxx @@ -42,8 +42,8 @@ make_copy() const { //////////////////////////////////////////////////////////////////// LPoint3 BoundingSphere:: get_min() const { - nassertr(!is_empty(), LPoint3(0.0f, 0.0f, 0.0f)); - nassertr(!is_infinite(), LPoint3(0.0f, 0.0f, 0.0f)); + nassertr(!is_empty(), LPoint3::zero()); + nassertr(!is_infinite(), LPoint3::zero()); return LPoint3(_center[0] - _radius, _center[1] - _radius, _center[2] - _radius); @@ -56,8 +56,8 @@ get_min() const { //////////////////////////////////////////////////////////////////// LPoint3 BoundingSphere:: get_max() const { - nassertr(!is_empty(), LPoint3(0.0f, 0.0f, 0.0f)); - nassertr(!is_infinite(), LPoint3(0.0f, 0.0f, 0.0f)); + nassertr(!is_empty(), LPoint3::zero()); + nassertr(!is_infinite(), LPoint3::zero()); return LPoint3(_center[0] + _radius, _center[1] + _radius, _center[2] + _radius); @@ -86,8 +86,8 @@ get_volume() const { //////////////////////////////////////////////////////////////////// LPoint3 BoundingSphere:: get_approx_center() const { - nassertr(!is_empty(), LPoint3(0.0f, 0.0f, 0.0f)); - nassertr(!is_infinite(), LPoint3(0.0f, 0.0f, 0.0f)); + nassertr(!is_empty(), LPoint3::zero()); + nassertr(!is_infinite(), LPoint3::zero()); return get_center(); } @@ -384,39 +384,6 @@ around_points(const LPoint3 *first, const LPoint3 *last) { return true; } -//////////////////////////////////////////////////////////////////// -// Function: BoundingSphere::around_spheres -// Access: Protected, Virtual -// Description: -//////////////////////////////////////////////////////////////////// -bool BoundingSphere:: -around_spheres(const BoundingVolume **first, - const BoundingVolume **last) { - return around_finite(first, last); -} - -//////////////////////////////////////////////////////////////////// -// Function: BoundingSphere::around_boxes -// Access: Protected, Virtual -// Description: -//////////////////////////////////////////////////////////////////// -bool BoundingSphere:: -around_boxes(const BoundingVolume **first, - const BoundingVolume **last) { - return around_finite(first, last); -} - -//////////////////////////////////////////////////////////////////// -// Function: BoundingSphere::around_hexahedrons -// Access: Protected, Virtual -// Description: -//////////////////////////////////////////////////////////////////// -bool BoundingSphere:: -around_hexahedrons(const BoundingVolume **first, - const BoundingVolume **last) { - return around_finite(first, last); -} - //////////////////////////////////////////////////////////////////// // Function: BoundingSphere::around_finite // Access: Protected diff --git a/panda/src/mathutil/boundingSphere.h b/panda/src/mathutil/boundingSphere.h index c75c156944..d5b8854763 100644 --- a/panda/src/mathutil/boundingSphere.h +++ b/panda/src/mathutil/boundingSphere.h @@ -62,18 +62,12 @@ protected: virtual bool extend_by_sphere(const BoundingSphere *sphere); virtual bool extend_by_box(const BoundingBox *box); virtual bool extend_by_hexahedron(const BoundingHexahedron *hexahedron); - bool extend_by_finite(const FiniteBoundingVolume *volume); + virtual bool extend_by_finite(const FiniteBoundingVolume *volume); virtual bool around_points(const LPoint3 *first, const LPoint3 *last); - virtual bool around_spheres(const BoundingVolume **first, - const BoundingVolume **last); - virtual bool around_boxes(const BoundingVolume **first, - const BoundingVolume **last); - virtual bool around_hexahedrons(const BoundingVolume **first, - const BoundingVolume **last); - bool around_finite(const BoundingVolume **first, - const BoundingVolume **last); + virtual bool around_finite(const BoundingVolume **first, + const BoundingVolume **last); virtual int contains_point(const LPoint3 &point) const; virtual int contains_lineseg(const LPoint3 &a, const LPoint3 &b) const; diff --git a/panda/src/mathutil/boundingVolume.cxx b/panda/src/mathutil/boundingVolume.cxx index 5baf349e0b..39d086dbe6 100644 --- a/panda/src/mathutil/boundingVolume.cxx +++ b/panda/src/mathutil/boundingVolume.cxx @@ -14,6 +14,8 @@ #include "boundingVolume.h" #include "finiteBoundingVolume.h" +#include "unionBoundingVolume.h" +#include "intersectionBoundingVolume.h" #include "indent.h" @@ -192,11 +194,8 @@ string_bounds_type(const string &str) { // sphere. //////////////////////////////////////////////////////////////////// bool BoundingVolume:: -extend_by_sphere(const BoundingSphere *) { - mathutil_cat.warning() - << get_type() << "::extend_by_sphere() called\n"; - _flags = F_infinite; - return false; +extend_by_sphere(const BoundingSphere *sphere) { + return extend_by_finite(sphere); } //////////////////////////////////////////////////////////////////// @@ -207,11 +206,8 @@ extend_by_sphere(const BoundingSphere *) { // box. //////////////////////////////////////////////////////////////////// bool BoundingVolume:: -extend_by_box(const BoundingBox *) { - mathutil_cat.warning() - << get_type() << "::extend_by_box() called\n"; - _flags = F_infinite; - return false; +extend_by_box(const BoundingBox *box) { + return extend_by_finite(box); } //////////////////////////////////////////////////////////////////// @@ -222,11 +218,8 @@ extend_by_box(const BoundingBox *) { // hexahedron. //////////////////////////////////////////////////////////////////// bool BoundingVolume:: -extend_by_hexahedron(const BoundingHexahedron *) { - mathutil_cat.warning() - << get_type() << "::extend_by_hexahedron() called\n"; - _flags = F_infinite; - return false; +extend_by_hexahedron(const BoundingHexahedron *hexahedron) { + return extend_by_finite(hexahedron); } //////////////////////////////////////////////////////////////////// @@ -237,11 +230,8 @@ extend_by_hexahedron(const BoundingHexahedron *) { // line. //////////////////////////////////////////////////////////////////// bool BoundingVolume:: -extend_by_line(const BoundingLine *) { - mathutil_cat.warning() - << get_type() << "::extend_by_line() called\n"; - _flags = F_infinite; - return false; +extend_by_line(const BoundingLine *line) { + return extend_by_geometric(line); } //////////////////////////////////////////////////////////////////// @@ -252,9 +242,53 @@ extend_by_line(const BoundingLine *) { // plane. //////////////////////////////////////////////////////////////////// bool BoundingVolume:: -extend_by_plane(const BoundingPlane *) { +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_plane() called\n"; + << get_type() << "::extend_by_geometric() called with " << volume->get_type() << "\n"; _flags = F_infinite; return false; } @@ -267,11 +301,8 @@ extend_by_plane(const BoundingPlane *) { // known to be a nonempty sphere. //////////////////////////////////////////////////////////////////// bool BoundingVolume:: -around_spheres(const BoundingVolume **, const BoundingVolume **) { - mathutil_cat.warning() - << get_type() << "::around_spheres() called\n"; - _flags = F_infinite; - return false; +around_spheres(const BoundingVolume **first, const BoundingVolume **last) { + return around_finite(first, last); } //////////////////////////////////////////////////////////////////// @@ -282,11 +313,8 @@ around_spheres(const BoundingVolume **, const BoundingVolume **) { // known to be a nonempty box. //////////////////////////////////////////////////////////////////// bool BoundingVolume:: -around_boxes(const BoundingVolume **, const BoundingVolume **) { - mathutil_cat.warning() - << get_type() << "::around_boxes() called\n"; - _flags = F_infinite; - return false; +around_boxes(const BoundingVolume **first, const BoundingVolume **last) { + return around_finite(first, last); } //////////////////////////////////////////////////////////////////// @@ -297,11 +325,8 @@ around_boxes(const BoundingVolume **, const BoundingVolume **) { // known to be a nonempty hexahedron. //////////////////////////////////////////////////////////////////// bool BoundingVolume:: -around_hexahedrons(const BoundingVolume **, const BoundingVolume **) { - mathutil_cat.warning() - << get_type() << "::around_hexahedrons() called\n"; - _flags = F_infinite; - return false; +around_hexahedrons(const BoundingVolume **first, const BoundingVolume **last) { + return around_finite(first, last); } //////////////////////////////////////////////////////////////////// @@ -312,15 +337,8 @@ around_hexahedrons(const BoundingVolume **, const BoundingVolume **) { // known to be a nonempty line. //////////////////////////////////////////////////////////////////// bool BoundingVolume:: -around_lines(const BoundingVolume **, const BoundingVolume **) { - _flags = F_infinite; - - mathutil_cat.warning() - << get_type() << "::around_lines() called\n"; - - // If we get here, the function isn't defined by a subclass, so we - // return false to indicate this. - return false; +around_lines(const BoundingVolume **first, const BoundingVolume **last) { + return around_geometric(first, last); } //////////////////////////////////////////////////////////////////// @@ -331,14 +349,54 @@ around_lines(const BoundingVolume **, const BoundingVolume **) { // known to be a nonempty plane. //////////////////////////////////////////////////////////////////// bool BoundingVolume:: -around_planes(const BoundingVolume **, const BoundingVolume **) { - _flags = F_infinite; +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() << "::around_planes() called\n"; - - // If we get here, the function isn't defined by a subclass, so we - // return false to indicate this. + << get_type() << "::extend_by_geometric() called with " << first[0]->get_type() << "\n"; + _flags = F_infinite; return false; } @@ -350,10 +408,8 @@ around_planes(const BoundingVolume **, const BoundingVolume **) { // to be a sphere. //////////////////////////////////////////////////////////////////// int BoundingVolume:: -contains_sphere(const BoundingSphere *) const { - mathutil_cat.warning() - << get_type() << "::contains_sphere() called\n"; - return IF_dont_understand; +contains_sphere(const BoundingSphere *sphere) const { + return contains_finite(sphere); } //////////////////////////////////////////////////////////////////// @@ -364,10 +420,8 @@ contains_sphere(const BoundingSphere *) const { // to be a box. //////////////////////////////////////////////////////////////////// int BoundingVolume:: -contains_box(const BoundingBox *) const { - mathutil_cat.warning() - << get_type() << "::contains_box() called\n"; - return IF_dont_understand; +contains_box(const BoundingBox *box) const { + return contains_finite(box); } //////////////////////////////////////////////////////////////////// @@ -378,10 +432,8 @@ contains_box(const BoundingBox *) const { // to be a hexahedron. //////////////////////////////////////////////////////////////////// int BoundingVolume:: -contains_hexahedron(const BoundingHexahedron *) const { - mathutil_cat.warning() - << get_type() << "::contains_hexahedron() called\n"; - return IF_dont_understand; +contains_hexahedron(const BoundingHexahedron *hexahedron) const { + return contains_finite(hexahedron); } //////////////////////////////////////////////////////////////////// @@ -392,10 +444,8 @@ contains_hexahedron(const BoundingHexahedron *) const { // to be a line. //////////////////////////////////////////////////////////////////// int BoundingVolume:: -contains_line(const BoundingLine *) const { - mathutil_cat.warning() - << get_type() << "::contains_line() called\n"; - return IF_dont_understand; +contains_line(const BoundingLine *line) const { + return contains_geometric(line); } //////////////////////////////////////////////////////////////////// @@ -406,9 +456,53 @@ contains_line(const BoundingLine *) const { // to be a plane. //////////////////////////////////////////////////////////////////// int BoundingVolume:: -contains_plane(const BoundingPlane *) const { +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_plane() called\n"; + << get_type() << "::contains_geometric() called with " << volume->get_type() << "\n"; return IF_dont_understand; } diff --git a/panda/src/mathutil/boundingVolume.h b/panda/src/mathutil/boundingVolume.h index d731e259c7..bf15e4d908 100644 --- a/panda/src/mathutil/boundingVolume.h +++ b/panda/src/mathutil/boundingVolume.h @@ -28,6 +28,8 @@ class BoundingBox; class BoundingHexahedron; class BoundingLine; class BoundingPlane; +class UnionBoundingVolume; +class IntersectionBoundingVolume; //////////////////////////////////////////////////////////////////// @@ -143,6 +145,10 @@ protected: virtual bool extend_by_hexahedron(const BoundingHexahedron *hexahedron); virtual bool extend_by_line(const BoundingLine *line); virtual bool extend_by_plane(const BoundingPlane *plane); + virtual bool extend_by_union(const UnionBoundingVolume *unionv); + virtual bool extend_by_intersection(const IntersectionBoundingVolume *intersection); + virtual bool extend_by_finite(const FiniteBoundingVolume *volume); + virtual bool extend_by_geometric(const GeometricBoundingVolume *volume); virtual bool around_spheres(const BoundingVolume **first, const BoundingVolume **last); @@ -153,13 +159,25 @@ protected: virtual bool around_lines(const BoundingVolume **first, const BoundingVolume **last); virtual bool around_planes(const BoundingVolume **first, - const BoundingVolume **last); + const BoundingVolume **last); + virtual bool around_unions(const BoundingVolume **first, + const BoundingVolume **last); + virtual bool around_intersections(const BoundingVolume **first, + const BoundingVolume **last); + virtual bool around_finite(const BoundingVolume **first, + const BoundingVolume **last); + virtual bool around_geometric(const BoundingVolume **first, + const BoundingVolume **last); virtual int contains_sphere(const BoundingSphere *sphere) const; virtual int contains_box(const BoundingBox *box) const; virtual int contains_hexahedron(const BoundingHexahedron *hexahedron) const; virtual int contains_line(const BoundingLine *line) const; virtual int contains_plane(const BoundingPlane *plane) const; + virtual int contains_union(const UnionBoundingVolume *unionv) const; + virtual int contains_intersection(const IntersectionBoundingVolume *intersection) const; + virtual int contains_finite(const FiniteBoundingVolume *volume) const; + virtual int contains_geometric(const GeometricBoundingVolume *volume) const; public: @@ -184,6 +202,8 @@ private: friend class BoundingHexahedron; friend class BoundingLine; friend class BoundingPlane; + friend class UnionBoundingVolume; + friend class IntersectionBoundingVolume; }; INLINE_MATHUTIL ostream &operator << (ostream &out, const BoundingVolume &bound); diff --git a/panda/src/mathutil/config_mathutil.cxx b/panda/src/mathutil/config_mathutil.cxx index e56a68aa7f..7b912f13d3 100644 --- a/panda/src/mathutil/config_mathutil.cxx +++ b/panda/src/mathutil/config_mathutil.cxx @@ -22,6 +22,8 @@ #include "boundingHexahedron.h" #include "boundingLine.h" #include "boundingPlane.h" +#include "unionBoundingVolume.h" +#include "intersectionBoundingVolume.h" #include "linmath_events.h" #include "dconfig.h" #include "pandaSystem.h" @@ -29,6 +31,10 @@ Configure(config_mathutil); NotifyCategoryDef(mathutil, ""); +ConfigureFn(config_mathutil) { + init_libmathutil(); +} + ConfigVariableDouble fft_offset ("fft-offset", 0.001); @@ -47,7 +53,22 @@ ConfigVariableEnum bounds_type "by Panda to enclose geometry. Use 'sphere' or 'box', or use " "'best' to let Panda decide which is most appropriate.")); -ConfigureFn(config_mathutil) { +//////////////////////////////////////////////////////////////////// +// Function: init_libmathutil +// Description: Initializes the library. This must be called at +// least once before any of the functions or classes in +// this library can be used. Normally it will be +// called by the static initializers and need not be +// called explicitly, but special cases exist. +//////////////////////////////////////////////////////////////////// +void +init_libmathutil() { + static bool initialized = false; + if (initialized) { + return; + } + initialized = true; + BoundingHexahedron::init_type(); BoundingSphere::init_type(); BoundingBox::init_type(); @@ -55,6 +76,8 @@ ConfigureFn(config_mathutil) { FiniteBoundingVolume::init_type(); GeometricBoundingVolume::init_type(); OmniBoundingVolume::init_type(); + UnionBoundingVolume::init_type(); + IntersectionBoundingVolume::init_type(); BoundingLine::init_type(); BoundingPlane::init_type(); EventStoreVec2::init_type("EventStoreVec2"); diff --git a/panda/src/mathutil/config_mathutil.h b/panda/src/mathutil/config_mathutil.h index 683fd56915..9bbc35cc9a 100644 --- a/panda/src/mathutil/config_mathutil.h +++ b/panda/src/mathutil/config_mathutil.h @@ -29,6 +29,8 @@ extern ConfigVariableDouble fft_exponent; extern ConfigVariableDouble fft_error_threshold; extern EXPCL_PANDA_MATHUTIL ConfigVariableEnum bounds_type; +extern EXPCL_PANDA_MATHUTIL void init_libmathutil(); + #endif diff --git a/panda/src/mathutil/intersectionBoundingVolume.I b/panda/src/mathutil/intersectionBoundingVolume.I new file mode 100644 index 0000000000..a7c2c138da --- /dev/null +++ b/panda/src/mathutil/intersectionBoundingVolume.I @@ -0,0 +1,46 @@ +// Filename: intersectionBoundingVolume.I +// 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." +// +//////////////////////////////////////////////////////////////////// + + + +//////////////////////////////////////////////////////////////////// +// Function: IntersectionBoundingVolume::Constructor +// Access: Published +// Description: Constructs an empty intersection. +//////////////////////////////////////////////////////////////////// +INLINE_MATHUTIL IntersectionBoundingVolume:: +IntersectionBoundingVolume() { + _flags = F_infinite; +} + +//////////////////////////////////////////////////////////////////// +// Function: IntersectionBoundingVolume::get_num_components +// Access: Published +// Description: Returns the number of components in the intersection. +//////////////////////////////////////////////////////////////////// +INLINE_MATHUTIL int IntersectionBoundingVolume:: +get_num_components() const { + return (int)_components.size(); +} + +//////////////////////////////////////////////////////////////////// +// Function: IntersectionBoundingVolume::get_component +// Access: Published +// Description: Returns the nth component in the intersection. +//////////////////////////////////////////////////////////////////// +INLINE_MATHUTIL const GeometricBoundingVolume *IntersectionBoundingVolume:: +get_component(int n) const { + nassertr(n >= 0 && n < (int)_components.size(), NULL); + return _components[n]; +} diff --git a/panda/src/mathutil/intersectionBoundingVolume.cxx b/panda/src/mathutil/intersectionBoundingVolume.cxx new file mode 100644 index 0000000000..c1a5e2dc35 --- /dev/null +++ b/panda/src/mathutil/intersectionBoundingVolume.cxx @@ -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; +} + diff --git a/panda/src/mathutil/intersectionBoundingVolume.h b/panda/src/mathutil/intersectionBoundingVolume.h new file mode 100644 index 0000000000..3d43494d33 --- /dev/null +++ b/panda/src/mathutil/intersectionBoundingVolume.h @@ -0,0 +1,104 @@ +// Filename: intersectionBoundingVolume.h +// 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." +// +//////////////////////////////////////////////////////////////////// + +#ifndef INTERSECTIONBOUNDINGVOLUME_H +#define INTERSECTIONBOUNDINGVOLUME_H + +#include "pandabase.h" + +#include "geometricBoundingVolume.h" +#include "pvector.h" + +//////////////////////////////////////////////////////////////////// +// Class : IntersectionBoundingVolume +// Description : This special bounding volume is the intersection of all of +// its constituent bounding volumes. +// +// A point is defined to be within an +// IntersectionBoundingVolume if it is within all of its +// component bounding volumes. +//////////////////////////////////////////////////////////////////// +class EXPCL_PANDA_MATHUTIL IntersectionBoundingVolume : public GeometricBoundingVolume { +PUBLISHED: + INLINE_MATHUTIL IntersectionBoundingVolume(); + ALLOC_DELETED_CHAIN(IntersectionBoundingVolume); + +public: + IntersectionBoundingVolume(const IntersectionBoundingVolume ©); + +public: + virtual BoundingVolume *make_copy() const; + + virtual LPoint3 get_approx_center() const; + virtual void xform(const LMatrix4 &mat); + + virtual void output(ostream &out) const; + virtual void write(ostream &out, int indent_level) const; + +PUBLISHED: + INLINE_MATHUTIL int get_num_components() const; + INLINE_MATHUTIL const GeometricBoundingVolume *get_component(int n) const; + MAKE_SEQ(get_components, get_num_components, get_component); + + void clear_components(); + void add_component(const GeometricBoundingVolume *component); + +protected: + virtual bool extend_other(BoundingVolume *other) const; + virtual bool around_other(BoundingVolume *other, + const BoundingVolume **first, + const BoundingVolume **last) const; + virtual int contains_other(const BoundingVolume *other) const; + + virtual int contains_point(const LPoint3 &point) const; + virtual int contains_lineseg(const LPoint3 &a, const LPoint3 &b) const; + virtual int contains_sphere(const BoundingSphere *sphere) const; + virtual int contains_box(const BoundingBox *box) const; + virtual int contains_hexahedron(const BoundingHexahedron *hexahedron) const; + virtual int contains_line(const BoundingLine *line) const; + virtual int contains_plane(const BoundingPlane *plane) const; + virtual int contains_union(const UnionBoundingVolume *unionv) const; + virtual int contains_intersection(const IntersectionBoundingVolume *intersection) const; + virtual int contains_finite(const FiniteBoundingVolume *volume) const; + virtual int contains_geometric(const GeometricBoundingVolume *volume) const; + int other_contains_intersection(const BoundingVolume *other) const; + +private: + typedef pvector Components; + Components _components; + +public: + static TypeHandle get_class_type() { + return _type_handle; + } + static void init_type() { + GeometricBoundingVolume::init_type(); + register_type(_type_handle, "IntersectionBoundingVolume", + GeometricBoundingVolume::get_class_type()); + } + virtual TypeHandle get_type() const { + return get_class_type(); + } + virtual TypeHandle force_init_type() {init_type(); return get_class_type();} + +private: + static TypeHandle _type_handle; + + friend class BoundingVolume; +}; + +#include "intersectionBoundingVolume.I" + +#endif + diff --git a/panda/src/mathutil/p3mathutil_composite1.cxx b/panda/src/mathutil/p3mathutil_composite1.cxx index d315b5901b..021e8281ac 100644 --- a/panda/src/mathutil/p3mathutil_composite1.cxx +++ b/panda/src/mathutil/p3mathutil_composite1.cxx @@ -6,6 +6,8 @@ #include "boundingVolume.cxx" #include "finiteBoundingVolume.cxx" #include "geometricBoundingVolume.cxx" +#include "intersectionBoundingVolume.cxx" #include "omniBoundingVolume.cxx" +#include "unionBoundingVolume.cxx" #include "parabola.cxx" #include "config_mathutil.cxx" diff --git a/panda/src/mathutil/unionBoundingVolume.I b/panda/src/mathutil/unionBoundingVolume.I new file mode 100644 index 0000000000..634e1ed2a4 --- /dev/null +++ b/panda/src/mathutil/unionBoundingVolume.I @@ -0,0 +1,44 @@ +// Filename: unionBoundingVolume.I +// 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." +// +//////////////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////// +// Function: UnionBoundingVolume::Constructor +// Access: Published +// Description: Constructs an empty union. +//////////////////////////////////////////////////////////////////// +INLINE_MATHUTIL UnionBoundingVolume:: +UnionBoundingVolume() { +} + +//////////////////////////////////////////////////////////////////// +// Function: UnionBoundingVolume::get_num_components +// Access: Published +// Description: Returns the number of components in the union. +//////////////////////////////////////////////////////////////////// +INLINE_MATHUTIL int UnionBoundingVolume:: +get_num_components() const { + return (int)_components.size(); +} + +//////////////////////////////////////////////////////////////////// +// Function: UnionBoundingVolume::get_component +// Access: Published +// Description: Returns the nth component in the union. +//////////////////////////////////////////////////////////////////// +INLINE_MATHUTIL const GeometricBoundingVolume *UnionBoundingVolume:: +get_component(int n) const { + nassertr(n >= 0 && n < (int)_components.size(), NULL); + return _components[n]; +} diff --git a/panda/src/mathutil/unionBoundingVolume.cxx b/panda/src/mathutil/unionBoundingVolume.cxx new file mode 100644 index 0000000000..acfe9e1807 --- /dev/null +++ b/panda/src/mathutil/unionBoundingVolume.cxx @@ -0,0 +1,559 @@ +// Filename: unionBoundingVolume.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 "unionBoundingVolume.h" +#include "config_mathutil.h" +#include "dcast.h" +#include "indent.h" + +TypeHandle UnionBoundingVolume::_type_handle; + +//////////////////////////////////////////////////////////////////// +// Function: UnionBoundingVolume::Copy Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +UnionBoundingVolume:: +UnionBoundingVolume(const UnionBoundingVolume ©) : + GeometricBoundingVolume(copy), + _components(copy._components) +{ +} + +//////////////////////////////////////////////////////////////////// +// Function: UnionBoundingVolume::make_copy +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +BoundingVolume *UnionBoundingVolume:: +make_copy() const { + return new UnionBoundingVolume(*this); +} + +//////////////////////////////////////////////////////////////////// +// Function: UnionBoundingVolume::get_approx_center +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +LPoint3 UnionBoundingVolume:: +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: UnionBoundingVolume::xform +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +void UnionBoundingVolume:: +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: UnionBoundingVolume::output +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +void UnionBoundingVolume:: +output(ostream &out) const { + if (is_empty()) { + out << "union, empty"; + } else if (is_infinite()) { + out << "union, infinite"; + } else { + out << "union ["; + for (Components::const_iterator ci = _components.begin(); + ci != _components.end(); + ++ci) { + out << " " << *(*ci); + } + out << " ]"; + } +} + +//////////////////////////////////////////////////////////////////// +// Function: UnionBoundingVolume::write +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +void UnionBoundingVolume:: +write(ostream &out, int indent_level) const { + if (is_empty()) { + indent(out, indent_level) << "union, empty\n"; + } else if (is_infinite()) { + indent(out, indent_level) << "union, infinite\n"; + } else { + indent(out, indent_level) << "union {\n"; + for (Components::const_iterator ci = _components.begin(); + ci != _components.end(); + ++ci) { + (*ci)->write(out, indent_level + 2); + } + indent(out, indent_level) << "}\n"; + } +} + +//////////////////////////////////////////////////////////////////// +// Function: UnionBoundingVolume::clear_components +// Access: Published +// Description: Removes all components from the volume. +//////////////////////////////////////////////////////////////////// +void UnionBoundingVolume:: +clear_components() { + _components.clear(); + _flags = F_empty; +} + +//////////////////////////////////////////////////////////////////// +// Function: UnionBoundingVolume::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 UnionBoundingVolume:: +add_component(const GeometricBoundingVolume *component) { + if (component->is_infinite()) { + _flags = F_infinite; + _components.clear(); + + } else if (component->is_empty() || is_infinite()) { + // No-op. + + } else { + size_t i = 0; + while (i < _components.size()) { + const GeometricBoundingVolume *existing = _components[i]; + ++i; + + int result = existing->contains(component); + if ((result & IF_all) != 0) { + // This new component is entirely within an existing + // component; no need to do anything with it. + return; + } + + result = component->contains(existing); + if ((result & IF_all) != 0) { + // The existing component is entirely within this one; no need + // to keep the existing one. + --i; + _components.erase(_components.begin() + i); + } + } + + _flags &= ~F_empty; + _components.push_back(component); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: UnionBoundingVolume::filter_intersection +// Access: Published +// Description: Removes from the union any components that have no +// intersection with the indicated volume. +//////////////////////////////////////////////////////////////////// +void UnionBoundingVolume:: +filter_intersection(const BoundingVolume *volume) { + size_t i = 0; + while (i < _components.size()) { + const GeometricBoundingVolume *existing = _components[i]; + ++i; + + int result = volume->contains(existing); + if ((result & IF_possible) == 0) { + // There is no intersection. Remove this component. + --i; + _components.erase(_components.begin() + i); + } + } + + if (_components.empty()) { + _flags |= F_empty; + } +} + +//////////////////////////////////////////////////////////////////// +// Function: UnionBoundingVolume::extend_other +// Access: Protected, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +bool UnionBoundingVolume:: +extend_other(BoundingVolume *other) const { + return other->extend_by_union(this); +} + +//////////////////////////////////////////////////////////////////// +// Function: UnionBoundingVolume::around_other +// Access: Protected, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +bool UnionBoundingVolume:: +around_other(BoundingVolume *other, + const BoundingVolume **first, + const BoundingVolume **last) const { + return other->around_unions(first, last); +} + +//////////////////////////////////////////////////////////////////// +// Function: UnionBoundingVolume::contains_other +// Access: Protected, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +int UnionBoundingVolume:: +contains_other(const BoundingVolume *other) const { + return other->contains_union(this); +} + +//////////////////////////////////////////////////////////////////// +// Function: UnionBoundingVolume::extend_by_geometric +// Access: Protected +// Description: +//////////////////////////////////////////////////////////////////// +bool UnionBoundingVolume:: +extend_by_geometric(const GeometricBoundingVolume *volume) { + add_component(volume); + return true; +} + +//////////////////////////////////////////////////////////////////// +// Function: UnionBoundingVolume::around_geometric +// Access: Protected +// Description: +//////////////////////////////////////////////////////////////////// +bool UnionBoundingVolume:: +around_geometric(const BoundingVolume **first, + const BoundingVolume **last) { + nassertr(first != last, false); + + clear_components(); + + const BoundingVolume **p = first; + while (p != last) { + nassertr(!(*p)->is_infinite(), false); + if (!(*p)->is_empty()) { + const GeometricBoundingVolume *volume = (*p)->as_geometric_bounding_volume(); + if (volume != (GeometricBoundingVolume *)NULL) { + add_component(volume); + } else { + set_infinite(); + _components.clear(); + return false; + } + } + } + + return true; +} + +//////////////////////////////////////////////////////////////////// +// Function: UnionBoundingVolume::contains_point +// Access: Protected, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +int UnionBoundingVolume:: +contains_point(const LPoint3 &point) const { + nassertr(!point.is_nan(), IF_no_intersection); + + int result = 0; + for (Components::const_iterator ci = _components.begin(); + ci != _components.end(); + ++ci) { + result |= (*ci)->contains(point); + if ((result & (IF_all | IF_dont_understand)) != 0) { + // No point in looking further. + break; + } + } + + return result; +} + +//////////////////////////////////////////////////////////////////// +// Function: UnionBoundingVolume::contains_lineseg +// Access: Protected, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +int UnionBoundingVolume:: +contains_lineseg(const LPoint3 &a, const LPoint3 &b) const { + nassertr(!a.is_nan() && !b.is_nan(), IF_no_intersection); + + int result = 0; + for (Components::const_iterator ci = _components.begin(); + ci != _components.end(); + ++ci) { + result |= (*ci)->contains(a, b); + if ((result & (IF_all | IF_dont_understand)) != 0) { + // No point in looking further. + break; + } + } + + return result; +} + +//////////////////////////////////////////////////////////////////// +// Function: UnionBoundingVolume::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 UnionBoundingVolume:: +contains_sphere(const BoundingSphere *sphere) const { + int result = 0; + for (Components::const_iterator ci = _components.begin(); + ci != _components.end(); + ++ci) { + result |= (*ci)->contains_sphere(sphere); + if ((result & (IF_all | IF_dont_understand)) != 0) { + // No point in looking further. + break; + } + } + + return result; +} + +//////////////////////////////////////////////////////////////////// +// Function: UnionBoundingVolume::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 UnionBoundingVolume:: +contains_box(const BoundingBox *box) const { + int result = 0; + for (Components::const_iterator ci = _components.begin(); + ci != _components.end(); + ++ci) { + result |= (*ci)->contains_box(box); + if ((result & (IF_all | IF_dont_understand)) != 0) { + // No point in looking further. + break; + } + } + + return result; +} + +//////////////////////////////////////////////////////////////////// +// Function: UnionBoundingVolume::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 UnionBoundingVolume:: +contains_hexahedron(const BoundingHexahedron *hexahedron) const { + int result = 0; + for (Components::const_iterator ci = _components.begin(); + ci != _components.end(); + ++ci) { + result |= (*ci)->contains_hexahedron(hexahedron); + if ((result & (IF_all | IF_dont_understand)) != 0) { + // No point in looking further. + break; + } + } + + return result; +} + +//////////////////////////////////////////////////////////////////// +// Function: UnionBoundingVolume::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 UnionBoundingVolume:: +contains_line(const BoundingLine *line) const { + int result = 0; + for (Components::const_iterator ci = _components.begin(); + ci != _components.end(); + ++ci) { + result |= (*ci)->contains_line(line); + if ((result & (IF_all | IF_dont_understand)) != 0) { + // No point in looking further. + break; + } + } + + return result; +} + +//////////////////////////////////////////////////////////////////// +// Function: UnionBoundingVolume::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 UnionBoundingVolume:: +contains_plane(const BoundingPlane *plane) const { + int result = 0; + for (Components::const_iterator ci = _components.begin(); + ci != _components.end(); + ++ci) { + result |= (*ci)->contains_plane(plane); + if ((result & (IF_all | IF_dont_understand)) != 0) { + // No point in looking further. + break; + } + } + + return result; +} + +//////////////////////////////////////////////////////////////////// +// Function: UnionBoundingVolume::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 UnionBoundingVolume:: +contains_union(const UnionBoundingVolume *unionv) const { + int result = 0; + for (Components::const_iterator ci = _components.begin(); + ci != _components.end(); + ++ci) { + result |= (*ci)->contains_union(unionv); + if ((result & (IF_all | IF_dont_understand)) != 0) { + // No point in looking further. + break; + } + } + + return result; +} + +//////////////////////////////////////////////////////////////////// +// Function: UnionBoundingVolume::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 UnionBoundingVolume:: +contains_intersection(const IntersectionBoundingVolume *intersection) const { + int result = 0; + for (Components::const_iterator ci = _components.begin(); + ci != _components.end(); + ++ci) { + result |= (*ci)->contains_intersection(intersection); + if ((result & (IF_all | IF_dont_understand)) != 0) { + // No point in looking further. + break; + } + } + + return result; +} + +//////////////////////////////////////////////////////////////////// +// Function: UnionBoundingVolume::contains_finite +// Access: Protected, Virtual +// Description: Generic handler for a FiniteBoundingVolume. +//////////////////////////////////////////////////////////////////// +int UnionBoundingVolume:: +contains_finite(const FiniteBoundingVolume *volume) const { + int result = 0; + for (Components::const_iterator ci = _components.begin(); + ci != _components.end(); + ++ci) { + result |= (*ci)->contains_finite(volume); + if ((result & (IF_all | IF_dont_understand)) != 0) { + // No point in looking further. + break; + } + } + + return result; +} + +//////////////////////////////////////////////////////////////////// +// Function: UnionBoundingVolume::contains_geometric +// Access: Protected, Virtual +// Description: Generic handler for a GeometricBoundingVolume. +//////////////////////////////////////////////////////////////////// +int UnionBoundingVolume:: +contains_geometric(const GeometricBoundingVolume *volume) const { + int result = 0; + for (Components::const_iterator ci = _components.begin(); + ci != _components.end(); + ++ci) { + result |= (*ci)->contains_geometric(volume); + if ((result & (IF_all | IF_dont_understand)) != 0) { + // No point in looking further. + break; + } + } + + return result; +} + +//////////////////////////////////////////////////////////////////// +// Function: UnionBoundingVolume::other_contains_union +// Access: Protected, Virtual +// Description: Generic reverse-direction comparison. Called by +// BoundingVolumes that do not implement +// contains_union() explicitly. This returns the test +// of whether the other volume contains this volume. +//////////////////////////////////////////////////////////////////// +int UnionBoundingVolume:: +other_contains_union(const BoundingVolume *volume) const { + int all_result = IF_possible | IF_some | IF_all; + int some_result = 0; + for (Components::const_iterator ci = _components.begin(); + ci != _components.end(); + ++ci) { + int this_result = volume->contains(*ci); + if ((this_result & IF_dont_understand) != 0) { + some_result |= IF_dont_understand; + break; + } + all_result &= this_result; + some_result |= this_result; + } + + some_result &= ~IF_all; + return some_result | all_result; +} + diff --git a/panda/src/mathutil/unionBoundingVolume.h b/panda/src/mathutil/unionBoundingVolume.h new file mode 100644 index 0000000000..e3996b1b73 --- /dev/null +++ b/panda/src/mathutil/unionBoundingVolume.h @@ -0,0 +1,108 @@ +// Filename: unionBoundingVolume.h +// 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." +// +//////////////////////////////////////////////////////////////////// + +#ifndef UNIONBOUNDINGVOLUME_H +#define UNIONBOUNDINGVOLUME_H + +#include "pandabase.h" + +#include "geometricBoundingVolume.h" +#include "pvector.h" + +//////////////////////////////////////////////////////////////////// +// Class : UnionBoundingVolume +// Description : This special bounding volume is the union of all of +// its constituent bounding volumes. +// +// A point is defined to be within a UnionBoundingVolume +// if it is within any one or more of its component +// bounding volumes. +//////////////////////////////////////////////////////////////////// +class EXPCL_PANDA_MATHUTIL UnionBoundingVolume : public GeometricBoundingVolume { +PUBLISHED: + INLINE_MATHUTIL UnionBoundingVolume(); + ALLOC_DELETED_CHAIN(UnionBoundingVolume); + +public: + UnionBoundingVolume(const UnionBoundingVolume ©); + + virtual BoundingVolume *make_copy() const; + + virtual LPoint3 get_approx_center() const; + virtual void xform(const LMatrix4 &mat); + + virtual void output(ostream &out) const; + virtual void write(ostream &out, int indent_level) const; + +PUBLISHED: + INLINE_MATHUTIL int get_num_components() const; + INLINE_MATHUTIL const GeometricBoundingVolume *get_component(int n) const; + MAKE_SEQ(get_components, get_num_components, get_component); + + void clear_components(); + void add_component(const GeometricBoundingVolume *component); + + void filter_intersection(const BoundingVolume *volume); + +protected: + virtual bool extend_other(BoundingVolume *other) const; + virtual bool around_other(BoundingVolume *other, + const BoundingVolume **first, + const BoundingVolume **last) const; + virtual int contains_other(const BoundingVolume *other) const; + + virtual bool extend_by_geometric(const GeometricBoundingVolume *volume); + virtual bool around_geometric(const BoundingVolume **first, + const BoundingVolume **last); + + virtual int contains_point(const LPoint3 &point) const; + virtual int contains_lineseg(const LPoint3 &a, const LPoint3 &b) const; + virtual int contains_sphere(const BoundingSphere *sphere) const; + virtual int contains_box(const BoundingBox *box) const; + virtual int contains_hexahedron(const BoundingHexahedron *hexahedron) const; + virtual int contains_line(const BoundingLine *line) const; + virtual int contains_plane(const BoundingPlane *plane) const; + virtual int contains_union(const UnionBoundingVolume *unionv) const; + virtual int contains_intersection(const IntersectionBoundingVolume *intersection) const; + virtual int contains_finite(const FiniteBoundingVolume *volume) const; + virtual int contains_geometric(const GeometricBoundingVolume *volume) const; + int other_contains_union(const BoundingVolume *other) const; + +private: + typedef pvector Components; + Components _components; + +public: + static TypeHandle get_class_type() { + return _type_handle; + } + static void init_type() { + GeometricBoundingVolume::init_type(); + register_type(_type_handle, "UnionBoundingVolume", + GeometricBoundingVolume::get_class_type()); + } + virtual TypeHandle get_type() const { + return get_class_type(); + } + virtual TypeHandle force_init_type() {init_type(); return get_class_type();} + +private: + static TypeHandle _type_handle; + + friend class BoundingVolume; +}; + +#include "unionBoundingVolume.I" + +#endif diff --git a/panda/src/pgraph/camera.I b/panda/src/pgraph/camera.I index 5c33ea6fc7..bdebaaa440 100644 --- a/panda/src/pgraph/camera.I +++ b/panda/src/pgraph/camera.I @@ -148,6 +148,34 @@ get_cull_center() const { return _cull_center; } +//////////////////////////////////////////////////////////////////// +// Function: Camera::set_cull_bounds +// Access: Published +// Description: Specifies the bounding volume that should be used to +// perform culling from this camera. Normally, this is +// the bounding volume returned from the active lens' +// make_bounds() call, but you may override this to +// specify a custom volume if you require. The +// specified bounding volume will be understood to be in +// the coordinate space of the get_cull_center() node. +//////////////////////////////////////////////////////////////////// +INLINE void Camera:: +set_cull_bounds(BoundingVolume *cull_bounds) { + _cull_bounds = cull_bounds; +} + +//////////////////////////////////////////////////////////////////// +// Function: Camera::get_cull_bounds +// Access: Published +// Description: Returns the custom cull volume that was set by +// set_cull_bounds(), if any, or NULL if no custom cull +// volume was set. +//////////////////////////////////////////////////////////////////// +INLINE BoundingVolume *Camera:: +get_cull_bounds() const { + return _cull_bounds; +} + //////////////////////////////////////////////////////////////////// // Function: Camera::set_lod_center // Access: Published diff --git a/panda/src/pgraph/camera.h b/panda/src/pgraph/camera.h index 4573584550..c7fb73f732 100644 --- a/panda/src/pgraph/camera.h +++ b/panda/src/pgraph/camera.h @@ -63,6 +63,9 @@ PUBLISHED: INLINE void set_cull_center(const NodePath &cull_center); INLINE const NodePath &get_cull_center() const; + INLINE void set_cull_bounds(BoundingVolume *cull_bounds); + INLINE BoundingVolume *get_cull_bounds() const; + INLINE void set_lod_center(const NodePath &lod_center); INLINE const NodePath &get_lod_center() const; @@ -90,6 +93,7 @@ private: bool _active; NodePath _scene; NodePath _cull_center; + PT(BoundingVolume) _cull_bounds; NodePath _lod_center; DrawMask _camera_mask; diff --git a/panda/src/pgraph/sceneSetup.I b/panda/src/pgraph/sceneSetup.I index c43364e1dc..17a81c58ca 100644 --- a/panda/src/pgraph/sceneSetup.I +++ b/panda/src/pgraph/sceneSetup.I @@ -206,6 +206,25 @@ get_cull_center() const { } } +//////////////////////////////////////////////////////////////////// +// Function: SceneSetup::get_cull_bounds +// Access: Published +// Description: Returns the bounding volume that should be used to +// perform view-frustum culling (in the space of +// get_cull_center()). This is normally the current +// lens' bounding volume, but it may be overridden with +// Camera::set_cull_bounds(). +//////////////////////////////////////////////////////////////////// +INLINE PT(BoundingVolume) SceneSetup:: +get_cull_bounds() const { + PT(BoundingVolume) bounds = _camera_node->get_cull_bounds(); + if (bounds != (BoundingVolume *)NULL) { + return bounds; + } + + return _lens->make_bounds(); +} + //////////////////////////////////////////////////////////////////// // Function: SceneSetup::set_initial_state // Access: Published diff --git a/panda/src/pgraph/sceneSetup.h b/panda/src/pgraph/sceneSetup.h index 982936b5df..e3f2d39065 100644 --- a/panda/src/pgraph/sceneSetup.h +++ b/panda/src/pgraph/sceneSetup.h @@ -60,6 +60,7 @@ PUBLISHED: INLINE bool get_inverted() const; INLINE const NodePath &get_cull_center() const; + INLINE PT(BoundingVolume) get_cull_bounds() const; INLINE void set_initial_state(const RenderState *initial_state); INLINE const RenderState *get_initial_state() const;