diff --git a/panda/src/mathutil/boundingBox.cxx b/panda/src/mathutil/boundingBox.cxx index d00e32067c..3287569c6c 100644 --- a/panda/src/mathutil/boundingBox.cxx +++ b/panda/src/mathutil/boundingBox.cxx @@ -140,6 +140,18 @@ output(ostream &out) const { } } +//////////////////////////////////////////////////////////////////// +// Function: BoundingBox::as_bounding_box +// Access: Public, Virtual +// Description: Virtual downcast method. Returns this object as a +// pointer of the indicated type, if it is in fact that +// type. Returns NULL if it is not that type. +//////////////////////////////////////////////////////////////////// +const BoundingBox *BoundingBox:: +as_bounding_box() const { + return this; +} + //////////////////////////////////////////////////////////////////// // Function: BoundingBox::extend_other // Access: Protected, Virtual diff --git a/panda/src/mathutil/boundingBox.h b/panda/src/mathutil/boundingBox.h index 70bc61961d..11860f3517 100644 --- a/panda/src/mathutil/boundingBox.h +++ b/panda/src/mathutil/boundingBox.h @@ -61,6 +61,9 @@ public: INLINE_MATHUTIL const LPoint3f &get_minq() const; INLINE_MATHUTIL const LPoint3f &get_maxq() const; +public: + virtual const BoundingBox *as_bounding_box() const; + protected: virtual bool extend_other(BoundingVolume *other) const; virtual bool around_other(BoundingVolume *other, diff --git a/panda/src/mathutil/boundingHexahedron.cxx b/panda/src/mathutil/boundingHexahedron.cxx index 2c2484585f..8d31d3063c 100644 --- a/panda/src/mathutil/boundingHexahedron.cxx +++ b/panda/src/mathutil/boundingHexahedron.cxx @@ -204,6 +204,18 @@ write(ostream &out, int indent_level) const { } } +//////////////////////////////////////////////////////////////////// +// Function: BoundingHexahedron::as_bounding_hexahedron +// Access: Public, Virtual +// Description: Virtual downcast method. Returns this object as a +// pointer of the indicated type, if it is in fact that +// type. Returns NULL if it is not that type. +//////////////////////////////////////////////////////////////////// +const BoundingHexahedron *BoundingHexahedron:: +as_bounding_hexahedron() const { + return this; +} + //////////////////////////////////////////////////////////////////// // Function: BoundingHexahedron::extend_other // Access: Protected, Virtual diff --git a/panda/src/mathutil/boundingHexahedron.h b/panda/src/mathutil/boundingHexahedron.h index c0ed9f155c..5efa4c7faa 100644 --- a/panda/src/mathutil/boundingHexahedron.h +++ b/panda/src/mathutil/boundingHexahedron.h @@ -68,6 +68,9 @@ PUBLISHED: INLINE_MATHUTIL int get_num_planes() const; INLINE_MATHUTIL Planef get_plane(int n) const; +public: + virtual const BoundingHexahedron *as_bounding_hexahedron() const; + protected: virtual bool extend_other(BoundingVolume *other) const; virtual bool around_other(BoundingVolume *other, diff --git a/panda/src/mathutil/boundingLine.cxx b/panda/src/mathutil/boundingLine.cxx index bfb5dacee4..6a7b0832dd 100644 --- a/panda/src/mathutil/boundingLine.cxx +++ b/panda/src/mathutil/boundingLine.cxx @@ -82,6 +82,18 @@ output(ostream &out) const { } } +//////////////////////////////////////////////////////////////////// +// Function: BoundingLine::as_bounding_line +// Access: Public, Virtual +// Description: Virtual downcast method. Returns this object as a +// pointer of the indicated type, if it is in fact that +// type. Returns NULL if it is not that type. +//////////////////////////////////////////////////////////////////// +const BoundingLine *BoundingLine:: +as_bounding_line() const { + return this; +} + //////////////////////////////////////////////////////////////////// // Function: BoundingLine::extend_other // Access: Protected, Virtual diff --git a/panda/src/mathutil/boundingLine.h b/panda/src/mathutil/boundingLine.h index 0de9a0953d..ce8f48006c 100644 --- a/panda/src/mathutil/boundingLine.h +++ b/panda/src/mathutil/boundingLine.h @@ -54,6 +54,9 @@ PUBLISHED: INLINE_MATHUTIL const LPoint3f &get_point_a() const; INLINE_MATHUTIL LPoint3f get_point_b() const; +public: + virtual const BoundingLine *as_bounding_line() const; + protected: virtual bool extend_other(BoundingVolume *other) const; virtual bool around_other(BoundingVolume *other, diff --git a/panda/src/mathutil/boundingPlane.cxx b/panda/src/mathutil/boundingPlane.cxx index 08f36090d9..b06a7b882c 100644 --- a/panda/src/mathutil/boundingPlane.cxx +++ b/panda/src/mathutil/boundingPlane.cxx @@ -74,6 +74,18 @@ output(ostream &out) const { } } +//////////////////////////////////////////////////////////////////// +// Function: BoundingPlane::as_bounding_plane +// Access: Public, Virtual +// Description: Virtual downcast method. Returns this object as a +// pointer of the indicated type, if it is in fact that +// type. Returns NULL if it is not that type. +//////////////////////////////////////////////////////////////////// +const BoundingPlane *BoundingPlane:: +as_bounding_plane() const { + return this; +} + //////////////////////////////////////////////////////////////////// // Function: BoundingPlane::extend_other // Access: Public, Virtual diff --git a/panda/src/mathutil/boundingPlane.h b/panda/src/mathutil/boundingPlane.h index 9fcaae2a68..0f8984b723 100644 --- a/panda/src/mathutil/boundingPlane.h +++ b/panda/src/mathutil/boundingPlane.h @@ -49,6 +49,9 @@ public: PUBLISHED: INLINE_MATHUTIL const Planef &get_plane() const; +public: + virtual const BoundingPlane *as_bounding_plane() const; + protected: virtual bool extend_other(BoundingVolume *other) const; virtual bool around_other(BoundingVolume *other, diff --git a/panda/src/mathutil/boundingSphere.cxx b/panda/src/mathutil/boundingSphere.cxx index 98ce4b6925..8049f3699a 100644 --- a/panda/src/mathutil/boundingSphere.cxx +++ b/panda/src/mathutil/boundingSphere.cxx @@ -157,6 +157,18 @@ output(ostream &out) const { } } +//////////////////////////////////////////////////////////////////// +// Function: BoundingSphere::as_bounding_sphere +// Access: Public, Virtual +// Description: Virtual downcast method. Returns this object as a +// pointer of the indicated type, if it is in fact that +// type. Returns NULL if it is not that type. +//////////////////////////////////////////////////////////////////// +const BoundingSphere *BoundingSphere:: +as_bounding_sphere() const { + return this; +} + //////////////////////////////////////////////////////////////////// // Function: BoundingSphere::extend_other // Access: Protected, Virtual @@ -439,20 +451,21 @@ around_finite(const BoundingVolume **first, // box. const BoundingVolume **p = first; nassertr(!(*p)->is_empty() && !(*p)->is_infinite(), false); - const FiniteBoundingVolume *vol = DCAST(FiniteBoundingVolume, *p); + const FiniteBoundingVolume *vol = (*p)->as_finite_bounding_volume(); + nassertr(vol != (FiniteBoundingVolume *)NULL, false); LPoint3f min_box = vol->get_min(); LPoint3f max_box = vol->get_max(); - bool any_spheres = vol->is_exact_type(BoundingSphere::get_class_type()); + bool any_spheres = (vol->as_bounding_sphere() != NULL); for (++p; p != last; ++p) { nassertr(!(*p)->is_infinite(), false); if (!(*p)->is_empty()) { - if (!(*p)->is_of_type(FiniteBoundingVolume::get_class_type())) { + vol = (*p)->as_finite_bounding_volume(); + if (vol == (FiniteBoundingVolume *)NULL) { set_infinite(); return true; } - const FiniteBoundingVolume *vol = DCAST(FiniteBoundingVolume, *p); LPoint3f min1 = vol->get_min(); LPoint3f max1 = vol->get_max(); min_box.set(min(min_box[0], min1[0]), @@ -462,7 +475,7 @@ around_finite(const BoundingVolume **first, max(max_box[1], max1[1]), max(max_box[2], max1[2])); - if (vol->is_exact_type(BoundingSphere::get_class_type())) { + if (vol->as_bounding_sphere() != NULL) { any_spheres = true; } } @@ -482,15 +495,16 @@ around_finite(const BoundingVolume **first, _radius = 0.0f; for (p = first; p != last; ++p) { if (!(*p)->is_empty()) { - if ((*p)->is_exact_type(BoundingSphere::get_class_type())) { + const BoundingSphere *sphere = (*p)->as_bounding_sphere(); + if (sphere != (BoundingSphere *)NULL) { // This is a sphere; consider its corner. - const BoundingSphere *sphere = DCAST(BoundingSphere, *p); float dist = length(sphere->_center - _center); _radius = max(_radius, dist + sphere->_radius); } else { // This is a nonsphere. We fit around it. - const FiniteBoundingVolume *vol = DCAST(FiniteBoundingVolume, *p); + const FiniteBoundingVolume *vol = (*p)->as_finite_bounding_volume(); + nassertr(vol != (FiniteBoundingVolume *)NULL, false); BoundingBox box(vol->get_min(), vol->get_max()); box.local_object(); diff --git a/panda/src/mathutil/boundingSphere.h b/panda/src/mathutil/boundingSphere.h index f785066ebb..e7ea6482ca 100644 --- a/panda/src/mathutil/boundingSphere.h +++ b/panda/src/mathutil/boundingSphere.h @@ -51,6 +51,9 @@ PUBLISHED: INLINE_MATHUTIL const LPoint3f &get_center() const; INLINE_MATHUTIL float get_radius() const; +public: + virtual const BoundingSphere *as_bounding_sphere() const; + protected: virtual bool extend_other(BoundingVolume *other) const; virtual bool around_other(BoundingVolume *other, diff --git a/panda/src/mathutil/boundingVolume.cxx b/panda/src/mathutil/boundingVolume.cxx index e96c8069f1..5355dca86c 100644 --- a/panda/src/mathutil/boundingVolume.cxx +++ b/panda/src/mathutil/boundingVolume.cxx @@ -80,6 +80,90 @@ write(ostream &out, int indent_level) const { indent(out, indent_level) << *this << "\n"; } +//////////////////////////////////////////////////////////////////// +// Function: BoundingVolume::as_geometric_bounding_volume +// Access: Public, Virtual +// Description: Virtual downcast method. Returns this object as a +// pointer of the indicated type, if it is in fact that +// type. Returns NULL if it is not that type. +//////////////////////////////////////////////////////////////////// +const GeometricBoundingVolume *BoundingVolume:: +as_geometric_bounding_volume() const { + return NULL; +} + +//////////////////////////////////////////////////////////////////// +// Function: BoundingVolume::as_finite_bounding_volume +// Access: Public, Virtual +// Description: Virtual downcast method. Returns this object as a +// pointer of the indicated type, if it is in fact that +// type. Returns NULL if it is not that type. +//////////////////////////////////////////////////////////////////// +const FiniteBoundingVolume *BoundingVolume:: +as_finite_bounding_volume() const { + return NULL; +} + +//////////////////////////////////////////////////////////////////// +// Function: BoundingVolume::as_bounding_sphere +// Access: Public, Virtual +// Description: Virtual downcast method. Returns this object as a +// pointer of the indicated type, if it is in fact that +// type. Returns NULL if it is not that type. +//////////////////////////////////////////////////////////////////// +const BoundingSphere *BoundingVolume:: +as_bounding_sphere() const { + return NULL; +} + +//////////////////////////////////////////////////////////////////// +// Function: BoundingVolume::as_bounding_box +// Access: Public, Virtual +// Description: Virtual downcast method. Returns this object as a +// pointer of the indicated type, if it is in fact that +// type. Returns NULL if it is not that type. +//////////////////////////////////////////////////////////////////// +const BoundingBox *BoundingVolume:: +as_bounding_box() const { + return NULL; +} + +//////////////////////////////////////////////////////////////////// +// Function: BoundingVolume::as_bounding_hexahedron +// Access: Public, Virtual +// Description: Virtual downcast method. Returns this object as a +// pointer of the indicated type, if it is in fact that +// type. Returns NULL if it is not that type. +//////////////////////////////////////////////////////////////////// +const BoundingHexahedron *BoundingVolume:: +as_bounding_hexahedron() const { + return NULL; +} + +//////////////////////////////////////////////////////////////////// +// Function: BoundingVolume::as_bounding_line +// Access: Public, Virtual +// Description: Virtual downcast method. Returns this object as a +// pointer of the indicated type, if it is in fact that +// type. Returns NULL if it is not that type. +//////////////////////////////////////////////////////////////////// +const BoundingLine *BoundingVolume:: +as_bounding_line() const { + return NULL; +} + +//////////////////////////////////////////////////////////////////// +// Function: BoundingVolume::as_bounding_plane +// Access: Public, Virtual +// Description: Virtual downcast method. Returns this object as a +// pointer of the indicated type, if it is in fact that +// type. Returns NULL if it is not that type. +//////////////////////////////////////////////////////////////////// +const BoundingPlane *BoundingVolume:: +as_bounding_plane() const { + return NULL; +} + //////////////////////////////////////////////////////////////////// // Function: BoundingVolume::string_bounds_type // Access: Public, Static @@ -231,18 +315,12 @@ around_hexahedrons(const BoundingVolume **, const BoundingVolume **) { bool BoundingVolume:: around_lines(const BoundingVolume **, const BoundingVolume **) { _flags = F_infinite; - if (is_of_type(FiniteBoundingVolume::get_class_type())) { - // If it's a FiniteBoundingVolume, we can't do any better than - // making it infinite. So we return true. - return true; - } mathutil_cat.warning() << get_type() << "::around_lines() called\n"; - // Otherwise, we might do better, and we require each class to - // define a function. If we get here, the function isn't defined, - // so we return false to indicate this. + // If we get here, the function isn't defined by a subclass, so we + // return false to indicate this. return false; } @@ -256,18 +334,12 @@ around_lines(const BoundingVolume **, const BoundingVolume **) { bool BoundingVolume:: around_planes(const BoundingVolume **, const BoundingVolume **) { _flags = F_infinite; - if (is_of_type(FiniteBoundingVolume::get_class_type())) { - // If it's a FiniteBoundingVolume, we can't do any better than - // making it infinite. So we return true. - return true; - } mathutil_cat.warning() << get_type() << "::around_planes() called\n"; - // Otherwise, we might do better, and we require each class to - // define a function. If we get here, the function isn't defined, - // so we return false to indicate this. + // If we get here, the function isn't defined by a subclass, so we + // return false to indicate this. return false; } diff --git a/panda/src/mathutil/boundingVolume.h b/panda/src/mathutil/boundingVolume.h index b3bb932405..ee1adf3155 100644 --- a/panda/src/mathutil/boundingVolume.h +++ b/panda/src/mathutil/boundingVolume.h @@ -25,6 +25,8 @@ #include "typedReferenceCount.h" #include "deletedChain.h" +class GeometricBoundingVolume; +class FiniteBoundingVolume; class BoundingSphere; class BoundingBox; class BoundingHexahedron; @@ -110,6 +112,14 @@ PUBLISHED: }; public: + virtual const GeometricBoundingVolume *as_geometric_bounding_volume() const; + virtual const FiniteBoundingVolume *as_finite_bounding_volume() const; + virtual const BoundingSphere *as_bounding_sphere() const; + virtual const BoundingBox *as_bounding_box() const; + virtual const BoundingHexahedron *as_bounding_hexahedron() const; + virtual const BoundingLine *as_bounding_line() const; + virtual const BoundingPlane *as_bounding_plane() const; + static BoundsType string_bounds_type(const string &str); protected: diff --git a/panda/src/mathutil/finiteBoundingVolume.cxx b/panda/src/mathutil/finiteBoundingVolume.cxx index 24265bf935..b1d704932f 100644 --- a/panda/src/mathutil/finiteBoundingVolume.cxx +++ b/panda/src/mathutil/finiteBoundingVolume.cxx @@ -42,3 +42,47 @@ get_volume() const { box.local_object(); return box.get_volume(); } + +//////////////////////////////////////////////////////////////////// +// Function: FiniteBoundingVolume::as_finite_bounding_volume +// Access: Public, Virtual +// Description: Virtual downcast method. Returns this object as a +// pointer of the indicated type, if it is in fact that +// type. Returns NULL if it is not that type. +//////////////////////////////////////////////////////////////////// +const FiniteBoundingVolume *FiniteBoundingVolume:: +as_finite_bounding_volume() const { + return this; +} + +//////////////////////////////////////////////////////////////////// +// Function: FiniteBoundingVolume::around_lines +// Access: Protected, Virtual +// Description: Double-dispatch support: called by around_other() +// when the type of the first element in the list is +// known to be a nonempty line. +//////////////////////////////////////////////////////////////////// +bool FiniteBoundingVolume:: +around_lines(const BoundingVolume **, const BoundingVolume **) { + _flags = F_infinite; + + // Since it's a FiniteBoundingVolume, we can't do any better than + // making it infinite. So we return true. + return true; +} + +//////////////////////////////////////////////////////////////////// +// Function: FiniteBoundingVolume::around_planes +// Access: Protected, Virtual +// Description: Double-dispatch support: called by around_other() +// when the type of the first element in the list is +// known to be a nonempty plane. +//////////////////////////////////////////////////////////////////// +bool FiniteBoundingVolume:: +around_planes(const BoundingVolume **, const BoundingVolume **) { + _flags = F_infinite; + + // Since it's a FiniteBoundingVolume, we can't do any better than + // making it infinite. So we return true. + return true; +} diff --git a/panda/src/mathutil/finiteBoundingVolume.h b/panda/src/mathutil/finiteBoundingVolume.h index b81374512a..33c0031044 100644 --- a/panda/src/mathutil/finiteBoundingVolume.h +++ b/panda/src/mathutil/finiteBoundingVolume.h @@ -36,6 +36,15 @@ PUBLISHED: virtual LPoint3f get_max() const=0; virtual float get_volume() const; +public: + virtual const FiniteBoundingVolume *as_finite_bounding_volume() const; + +protected: + virtual bool around_lines(const BoundingVolume **first, + const BoundingVolume **last); + virtual bool around_planes(const BoundingVolume **first, + const BoundingVolume **last); + public: static TypeHandle get_class_type() { return _type_handle; diff --git a/panda/src/mathutil/geometricBoundingVolume.cxx b/panda/src/mathutil/geometricBoundingVolume.cxx index 4144b3e50e..f9503570a4 100644 --- a/panda/src/mathutil/geometricBoundingVolume.cxx +++ b/panda/src/mathutil/geometricBoundingVolume.cxx @@ -21,22 +21,58 @@ TypeHandle GeometricBoundingVolume::_type_handle; +//////////////////////////////////////////////////////////////////// +// Function: GeometricBoundingVolume::as_geometric_bounding_volume +// Access: Public, Virtual +// Description: Virtual downcast method. Returns this object as a +// pointer of the indicated type, if it is in fact that +// type. Returns NULL if it is not that type. +//////////////////////////////////////////////////////////////////// +const GeometricBoundingVolume *GeometricBoundingVolume:: +as_geometric_bounding_volume() const { + return this; +} + +//////////////////////////////////////////////////////////////////// +// Function: GeometricBoundingVolume::extend_by_point +// Access: Protected, Virtual +// Description: Extends the volume to include the indicated point. +// Returns true if possible, false if not. +//////////////////////////////////////////////////////////////////// bool GeometricBoundingVolume:: extend_by_point(const LPoint3f &) { return false; } +//////////////////////////////////////////////////////////////////// +// Function: GeometricBoundingVolume::around_points +// Access: Protected, Virtual +// Description: Puts the volume around the indicated list of points, +// identified by an STL-style begin/end list. +//////////////////////////////////////////////////////////////////// bool GeometricBoundingVolume:: around_points(const LPoint3f *, const LPoint3f *) { _flags = F_empty; return false; } +//////////////////////////////////////////////////////////////////// +// Function: GeometricBoundingVolume::contains_point +// Access: Protected, Virtual +// Description: Tests whether the volume contains the indicated +// point. +//////////////////////////////////////////////////////////////////// int GeometricBoundingVolume:: contains_point(const LPoint3f &) const { return IF_dont_understand; } +//////////////////////////////////////////////////////////////////// +// Function: GeometricBoundingVolume::contains_lineseg +// Access: Protected, Virtual +// Description: Tests whether the volume contains the indicated line +// segment. +//////////////////////////////////////////////////////////////////// int GeometricBoundingVolume:: contains_lineseg(const LPoint3f &, const LPoint3f &) const { return IF_dont_understand; diff --git a/panda/src/mathutil/geometricBoundingVolume.h b/panda/src/mathutil/geometricBoundingVolume.h index ad5292369e..25ff6db6de 100644 --- a/panda/src/mathutil/geometricBoundingVolume.h +++ b/panda/src/mathutil/geometricBoundingVolume.h @@ -55,6 +55,9 @@ PUBLISHED: virtual LPoint3f get_approx_center() const=0; virtual void xform(const LMatrix4f &mat)=0; +public: + virtual const GeometricBoundingVolume *as_geometric_bounding_volume() const; + protected: // Some virtual functions to implement fundamental bounding // operations on points in 3-d space. diff --git a/panda/src/pgraph/pandaNode.cxx b/panda/src/pgraph/pandaNode.cxx index 19281e8506..5cdd093c7f 100644 --- a/panda/src/pgraph/pandaNode.cxx +++ b/panda/src/pgraph/pandaNode.cxx @@ -3439,7 +3439,7 @@ update_bounds(int pipeline_stage, PandaNode::CDLockedStageReader &cdata) { #endif nassertr(child_volumes_i < num_children + 1, CDStageWriter(_cycler, pipeline_stage, cdata)); child_volumes[child_volumes_i++] = internal_bounds; - if (!internal_bounds->is_exact_type(BoundingBox::get_class_type())) { + if (internal_bounds->as_bounding_box() == NULL) { all_box = false; } } @@ -3497,7 +3497,7 @@ update_bounds(int pipeline_stage, PandaNode::CDLockedStageReader &cdata) { #endif nassertr(child_volumes_i < num_children + 1, CDStageWriter(_cycler, pipeline_stage, cdata)); child_volumes[child_volumes_i++] = child_cdataw->_external_bounds; - if (!child_cdataw->_external_bounds->is_exact_type(BoundingBox::get_class_type())) { + if (child_cdataw->_external_bounds->as_bounding_box() == NULL) { all_box = false; } } @@ -3537,7 +3537,7 @@ update_bounds(int pipeline_stage, PandaNode::CDLockedStageReader &cdata) { #endif nassertr(child_volumes_i < num_children + 1, CDStageWriter(_cycler, pipeline_stage, cdata)); child_volumes[child_volumes_i++] = child_cdata->_external_bounds; - if (!child_cdata->_external_bounds->is_exact_type(BoundingBox::get_class_type())) { + if (child_cdata->_external_bounds->as_bounding_box() == NULL) { all_box = false; } }