fix translated GeomNode problem

This commit is contained in:
David Rose 2002-04-09 22:28:40 +00:00
parent c598485e8e
commit 63f4a07801
5 changed files with 97 additions and 14 deletions

View File

@ -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

View File

@ -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 =

View File

@ -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"

View File

@ -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) {

View File

@ -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,