From 63f4a07801dc03c3a11b6a919b7565cf7cd9e809 Mon Sep 17 00:00:00 2001 From: David Rose Date: Tue, 9 Apr 2002 22:28:40 +0000 Subject: [PATCH] fix translated GeomNode problem --- panda/src/collide/qpcollisionLevelState.I | 25 +++++++++++- panda/src/collide/qpcollisionLevelState.cxx | 42 +++++++++++++++++++++ panda/src/collide/qpcollisionLevelState.h | 9 ++++- panda/src/collide/qpcollisionTraverser.cxx | 33 ++++++++++------ panda/src/collide/qpcollisionTraverser.h | 2 + 5 files changed, 97 insertions(+), 14 deletions(-) diff --git a/panda/src/collide/qpcollisionLevelState.I b/panda/src/collide/qpcollisionLevelState.I index c3a8259aa4..a8a3e47f7f 100644 --- a/panda/src/collide/qpcollisionLevelState.I +++ b/panda/src/collide/qpcollisionLevelState.I @@ -191,7 +191,9 @@ get_inv_space(int n) const { //////////////////////////////////////////////////////////////////// // Function: qpCollisionLevelState::get_local_bound // Access: Public -// Description: +// Description: Returns the bounding volume of the indicated +// collider, transformed into the current node's +// transform space. //////////////////////////////////////////////////////////////////// INLINE const GeometricBoundingVolume *qpCollisionLevelState:: get_local_bound(int n) const { @@ -207,6 +209,27 @@ get_local_bound(int n) const { return *(_local_bounds + n); } +//////////////////////////////////////////////////////////////////// +// Function: qpCollisionLevelState::get_parent_bound +// Access: Public +// Description: Returns the bounding volume of the indicated +// collider, transformed into the previous node's +// transform space, but not transformed by the current +// node's transform. This is appropriate for testing +// against the bounding volume of the current node +// (which does not have its own transform applied to +// it). +//////////////////////////////////////////////////////////////////// +INLINE const GeometricBoundingVolume *qpCollisionLevelState:: +get_parent_bound(int n) const { + nassertr(n >= 0 && n < (int)_colliders.size(), NULL); + nassertr(has_collider(n), NULL); + nassertr(n >= 0 && n < (int)_parent_bounds.size(), NULL); + + // But it can figure out this equivalent line. + return *(_parent_bounds + n); +} + //////////////////////////////////////////////////////////////////// // Function: qpCollisionLevelState::omit_collider // Access: Public diff --git a/panda/src/collide/qpcollisionLevelState.cxx b/panda/src/collide/qpcollisionLevelState.cxx index f2a5b14bd7..4a116e72b1 100644 --- a/panda/src/collide/qpcollisionLevelState.cxx +++ b/panda/src/collide/qpcollisionLevelState.cxx @@ -29,6 +29,7 @@ void qpCollisionLevelState:: clear() { _colliders.clear(); _local_bounds.clear(); + _parent_bounds.clear(); _current = 0; _colliders_with_geom = 0; } @@ -71,6 +72,7 @@ prepare_collider(const ColliderDef &def) { if (def._node->get_collide_geom()) { _colliders_with_geom |= get_mask(index); } + _parent_bounds = _local_bounds; } //////////////////////////////////////////////////////////////////// @@ -85,6 +87,16 @@ prepare_collider(const ColliderDef &def) { //////////////////////////////////////////////////////////////////// bool qpCollisionLevelState:: any_in_bounds() { +#ifndef NDEBUG + int indent_level = 0; + if (collide_cat.is_spam()) { + indent_level = _node_path.get_num_nodes() * 2; + collide_cat.spam(); + indent(collide_cat.spam(false), indent_level) + << "Considering " << _node_path.get_node_path() << "\n"; + } +#endif // NDEBUG + const BoundingVolume &node_bv = node()->get_bound(); if (node_bv.is_of_type(GeometricBoundingVolume::get_class_type())) { const GeometricBoundingVolume *node_gbv; @@ -108,6 +120,15 @@ any_in_bounds() { get_local_bound(c); if (col_gbv != (GeometricBoundingVolume *)NULL) { is_in = (node_gbv->contains(col_gbv) != 0); + +#ifndef NDEBUG + if (collide_cat.is_spam()) { + collide_cat.spam(); + indent(collide_cat.spam(false), indent_level) + << "Comparing " << c << ": " << *col_gbv + << " to " << *node_gbv << ", is_in = " << is_in << "\n"; + } +#endif // NDEBUG } } @@ -120,6 +141,22 @@ any_in_bounds() { } } +#ifndef NDEBUG + if (collide_cat.is_spam()) { + int num_active_colliders = 0; + int num_colliders = get_num_colliders(); + for (int c = 0; c < num_colliders; c++) { + if (has_collider(c)) { + num_active_colliders++; + } + } + + collide_cat.spam(); + indent(collide_cat.spam(false), indent_level) + << _node_path.get_node_path() << " has " << num_active_colliders + << " interested colliders.\n"; + } +#endif // NDEBUG return has_any_collider(); } @@ -131,6 +168,11 @@ any_in_bounds() { //////////////////////////////////////////////////////////////////// void qpCollisionLevelState:: apply_transform() { + // The "parent" bounds list remembers the bounds list of the + // previous node. + _parent_bounds = _local_bounds; + + // Recompute the bounds list of this node (if we have a transform). const TransformState *node_transform = node()->get_transform(); if (!node_transform->is_identity()) { CPT(TransformState) inv_transform = diff --git a/panda/src/collide/qpcollisionLevelState.h b/panda/src/collide/qpcollisionLevelState.h index 4a714cc13d..8a1244c7c7 100644 --- a/panda/src/collide/qpcollisionLevelState.h +++ b/panda/src/collide/qpcollisionLevelState.h @@ -75,10 +75,16 @@ public: INLINE const LMatrix4f &get_space(int n) const; INLINE const LMatrix4f &get_inv_space(int n) const; INLINE const GeometricBoundingVolume *get_local_bound(int n) const; + INLINE const GeometricBoundingVolume *get_parent_bound(int n) const; INLINE void omit_collider(int n); - //private: +private: + // ColliderMask here is a locally-defined value that simply serves + // to keep track of the colliders that are still interested in the + // current node. Don't confuse it with CollideMask, which is a set + // of user-defined bits that specify which CollisionSolids may + // possibly intersect with each other. typedef int ColliderMask; INLINE ColliderMask get_mask(int n) const; @@ -92,6 +98,7 @@ public: typedef PTA(CPT(GeometricBoundingVolume)) BoundingVolumes; BoundingVolumes _local_bounds; + BoundingVolumes _parent_bounds; }; #include "qpcollisionLevelState.I" diff --git a/panda/src/collide/qpcollisionTraverser.cxx b/panda/src/collide/qpcollisionTraverser.cxx index e389441bcc..ba288bc9ef 100644 --- a/panda/src/collide/qpcollisionTraverser.cxx +++ b/panda/src/collide/qpcollisionTraverser.cxx @@ -380,15 +380,22 @@ r_traverse(qpCollisionLevelState &level_state) { entry._inv_wrt_space = entry._into_space * level_state.get_inv_space(c); - const GeometricBoundingVolume *col_gbv = - level_state.get_local_bound(c); - - compare_collider_to_node(entry, col_gbv, node_gbv); + compare_collider_to_node(entry, + level_state.get_parent_bound(c), + level_state.get_local_bound(c), + node_gbv); } } } } else if (node->is_geom_node() && level_state.has_any_collide_geom()) { +#ifndef NDEBUG + if (collide_cat.is_spam()) { + collide_cat.spam() + << "Reached " << *node << "\n"; + } +#endif + qpGeomNode *gnode; DCAST_INTO_V(gnode, node); const BoundingVolume &node_bv = gnode->get_bound(); @@ -417,10 +424,10 @@ r_traverse(qpCollisionLevelState &level_state) { entry._inv_wrt_space = entry._into_space * level_state.get_inv_space(c); - const GeometricBoundingVolume *col_gbv = - level_state.get_local_bound(c); - - compare_collider_to_geom_node(entry, col_gbv, node_gbv); + compare_collider_to_geom_node(entry, + level_state.get_parent_bound(c), + level_state.get_local_bound(c), + node_gbv); } } } @@ -439,12 +446,13 @@ r_traverse(qpCollisionLevelState &level_state) { //////////////////////////////////////////////////////////////////// void qpCollisionTraverser:: compare_collider_to_node(qpCollisionEntry &entry, + const GeometricBoundingVolume *from_parent_gbv, const GeometricBoundingVolume *from_node_gbv, const GeometricBoundingVolume *into_node_gbv) { bool within_node_bounds = true; - if (from_node_gbv != (GeometricBoundingVolume *)NULL && + if (from_parent_gbv != (GeometricBoundingVolume *)NULL && into_node_gbv != (GeometricBoundingVolume *)NULL) { - within_node_bounds = (into_node_gbv->contains(from_node_gbv) != 0); + within_node_bounds = (into_node_gbv->contains(from_parent_gbv) != 0); } if (within_node_bounds) { @@ -479,12 +487,13 @@ compare_collider_to_node(qpCollisionEntry &entry, //////////////////////////////////////////////////////////////////// void qpCollisionTraverser:: compare_collider_to_geom_node(qpCollisionEntry &entry, + const GeometricBoundingVolume *from_parent_gbv, const GeometricBoundingVolume *from_node_gbv, const GeometricBoundingVolume *into_node_gbv) { bool within_node_bounds = true; - if (from_node_gbv != (GeometricBoundingVolume *)NULL && + if (from_parent_gbv != (GeometricBoundingVolume *)NULL && into_node_gbv != (GeometricBoundingVolume *)NULL) { - within_node_bounds = (into_node_gbv->contains(from_node_gbv) != 0); + within_node_bounds = (into_node_gbv->contains(from_parent_gbv) != 0); } if (within_node_bounds) { diff --git a/panda/src/collide/qpcollisionTraverser.h b/panda/src/collide/qpcollisionTraverser.h index 213a62fa31..1800d97856 100644 --- a/panda/src/collide/qpcollisionTraverser.h +++ b/panda/src/collide/qpcollisionTraverser.h @@ -62,9 +62,11 @@ private: void r_traverse(qpCollisionLevelState &level_state); void compare_collider_to_node(qpCollisionEntry &entry, + const GeometricBoundingVolume *from_parent_gbv, const GeometricBoundingVolume *from_node_gbv, const GeometricBoundingVolume *into_node_gbv); void compare_collider_to_geom_node(qpCollisionEntry &entry, + const GeometricBoundingVolume *from_parent_gbv, const GeometricBoundingVolume *from_node_gbv, const GeometricBoundingVolume *into_node_gbv); void compare_collider_to_solid(qpCollisionEntry &entry,