| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202 |
- // Filename: collisionLevelState.cxx
- // Created by: drose (16Mar02)
- //
- ////////////////////////////////////////////////////////////////////
- //
- // PANDA 3D SOFTWARE
- // Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
- //
- // All use of this software is subject to the terms of the Panda 3d
- // Software license. You should have received a copy of this license
- // along with this source code; you will also find a current copy of
- // the license at http://www.panda3d.org/license.txt .
- //
- // To contact the maintainers of this program write to
- // [email protected] .
- //
- ////////////////////////////////////////////////////////////////////
- #include "collisionLevelState.h"
- #include "collisionSolid.h"
- #include "dcast.h"
- ////////////////////////////////////////////////////////////////////
- // Function: CollisionLevelState::clear
- // Access: Public
- // Description:
- ////////////////////////////////////////////////////////////////////
- void CollisionLevelState::
- clear() {
- _colliders.clear();
- _local_bounds.clear();
- _parent_bounds.clear();
- _current = 0;
- _colliders_with_geom = 0;
- }
- ////////////////////////////////////////////////////////////////////
- // Function: CollisionLevelState::reserve
- // Access: Public
- // Description:
- ////////////////////////////////////////////////////////////////////
- void CollisionLevelState::
- reserve(int max_colliders) {
- _colliders.reserve(max_colliders);
- _local_bounds.reserve(max_colliders);
- }
- ////////////////////////////////////////////////////////////////////
- // Function: CollisionLevelState::prepare_collider
- // Access: Public
- // Description: Adds the indicated Collider to the set of Colliders
- // in the current level state.
- ////////////////////////////////////////////////////////////////////
- void CollisionLevelState::
- prepare_collider(const ColliderDef &def) {
- int index = (int)_colliders.size();
- _colliders.push_back(def);
- CollisionSolid *collider = def._collider;
- const BoundingVolume &bv = collider->get_bound();
- if (!bv.is_of_type(GeometricBoundingVolume::get_class_type())) {
- _local_bounds.push_back((GeometricBoundingVolume *)NULL);
- } else {
- GeometricBoundingVolume *gbv;
- DCAST_INTO_V(gbv, bv.make_copy());
- gbv->xform(def._space);
- _local_bounds.push_back(gbv);
- }
- _current |= get_mask(index);
- if (def._node->get_collide_geom()) {
- _colliders_with_geom |= get_mask(index);
- }
- _parent_bounds = _local_bounds;
- }
- ////////////////////////////////////////////////////////////////////
- // Function: CollisionLevelState::any_in_bounds
- // Access: Public
- // Description: Checks the bounding volume of the current node
- // against each of our colliders. Eliminates from the
- // current collider list any that are outside of the
- // bounding volume. Returns true if any colliders
- // remain, false if all of them fall outside this node's
- // bounding volume.
- ////////////////////////////////////////////////////////////////////
- bool CollisionLevelState::
- 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;
- DCAST_INTO_R(node_gbv, &node_bv, false);
- int num_colliders = get_num_colliders();
- for (int c = 0; c < num_colliders; c++) {
- if (has_collider(c)) {
- CollisionNode *collider = get_node(c);
- bool is_in = false;
- // Don't even bother testing the bounding volume if there are
- // no collide bits in common between our collider and this
- // node.
- CollideMask from_mask = collider->get_from_collide_mask();
- if (collider->get_collide_geom() ||
- (from_mask & node()->get_net_collide_mask()) != 0) {
- // There are bits in common, so go ahead and try the
- // bounding volume.
- const GeometricBoundingVolume *col_gbv =
- 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
- }
- }
- if (!is_in) {
- // This collider cannot intersect with any geometry at
- // this node or below.
- omit_collider(c);
- }
- }
- }
- }
- #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();
- }
- ////////////////////////////////////////////////////////////////////
- // Function: CollisionLevelState::apply_transform
- // Access: Public
- // Description: Applies the inverse transform from the current node,
- // if any, onto all the colliders in the level state.
- ////////////////////////////////////////////////////////////////////
- void CollisionLevelState::
- 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 =
- node_transform->invert_compose(TransformState::make_identity());
- const LMatrix4f &mat = inv_transform->get_mat();
- // Now build the new bounding volumes list.
- BoundingVolumes new_bounds;
- int num_colliders = get_num_colliders();
- new_bounds.reserve(num_colliders);
- for (int c = 0; c < num_colliders; c++) {
- if (!has_collider(c) ||
- get_local_bound(c) == (GeometricBoundingVolume *)NULL) {
- new_bounds.push_back((GeometricBoundingVolume *)NULL);
- } else {
- const GeometricBoundingVolume *old_bound = get_local_bound(c);
- GeometricBoundingVolume *new_bound =
- DCAST(GeometricBoundingVolume, old_bound->make_copy());
- new_bound->xform(mat);
- new_bounds.push_back(new_bound);
- }
- }
-
- _local_bounds = new_bounds;
- }
- }
|