Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

panda/src/collide/collisionLevelState.cxx

Go to the documentation of this file.
00001 // Filename: collisionLevelState.cxx
00002 // Created by:  drose (16Mar02)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
00008 //
00009 // All use of this software is subject to the terms of the Panda 3d
00010 // Software license.  You should have received a copy of this license
00011 // along with this source code; you will also find a current copy of
00012 // the license at http://www.panda3d.org/license.txt .
00013 //
00014 // To contact the maintainers of this program write to
00015 // panda3d@yahoogroups.com .
00016 //
00017 ////////////////////////////////////////////////////////////////////
00018 
00019 #include "collisionLevelState.h"
00020 #include "collisionSolid.h"
00021 #include "dcast.h"
00022 
00023 ////////////////////////////////////////////////////////////////////
00024 //     Function: CollisionLevelState::clear
00025 //       Access: Public
00026 //  Description:
00027 ////////////////////////////////////////////////////////////////////
00028 void CollisionLevelState::
00029 clear() {
00030   _colliders.clear();
00031   _local_bounds.clear();
00032   _parent_bounds.clear();
00033   _current = 0;
00034   _colliders_with_geom = 0;
00035 }
00036 
00037 ////////////////////////////////////////////////////////////////////
00038 //     Function: CollisionLevelState::reserve
00039 //       Access: Public
00040 //  Description:
00041 ////////////////////////////////////////////////////////////////////
00042 void CollisionLevelState::
00043 reserve(int max_colliders) {
00044   _colliders.reserve(max_colliders);
00045   _local_bounds.reserve(max_colliders);
00046 }
00047 
00048 ////////////////////////////////////////////////////////////////////
00049 //     Function: CollisionLevelState::prepare_collider
00050 //       Access: Public
00051 //  Description: Adds the indicated Collider to the set of Colliders
00052 //               in the current level state.
00053 ////////////////////////////////////////////////////////////////////
00054 void CollisionLevelState::
00055 prepare_collider(const ColliderDef &def) {
00056   int index = (int)_colliders.size();
00057   _colliders.push_back(def);
00058 
00059   CollisionSolid *collider = def._collider;
00060   const BoundingVolume &bv = collider->get_bound();
00061   if (!bv.is_of_type(GeometricBoundingVolume::get_class_type())) {
00062     _local_bounds.push_back((GeometricBoundingVolume *)NULL);
00063   } else {
00064     GeometricBoundingVolume *gbv;
00065     DCAST_INTO_V(gbv, bv.make_copy());
00066 
00067     if (def._node->has_velocity()) {
00068       // If the node has a velocity, we have to include the starting
00069       // point in the volume as well.
00070 
00071       // Strictly speaking, we should actually transform gbv backward
00072       // by get_velocity(), and extend by *that* volume, instead of
00073       // just extending by the single point at -get_velocity().
00074       // However, assuming the solids within a moving CollisionNode
00075       // tend to be near the origin, this will generally produce the
00076       // same results, and is much easier to compute.
00077       gbv->extend_by(LPoint3f(-def._node->get_velocity()));
00078     }
00079 
00080     gbv->xform(def._space);
00081     _local_bounds.push_back(gbv);
00082   }
00083 
00084   _current |= get_mask(index);
00085 
00086   if (def._node->get_collide_geom()) {
00087     _colliders_with_geom |= get_mask(index);
00088   }
00089   _parent_bounds = _local_bounds;
00090 }
00091 
00092 ////////////////////////////////////////////////////////////////////
00093 //     Function: CollisionLevelState::any_in_bounds
00094 //       Access: Public
00095 //  Description: Checks the bounding volume of the current node
00096 //               against each of our colliders.  Eliminates from the
00097 //               current collider list any that are outside of the
00098 //               bounding volume.  Returns true if any colliders
00099 //               remain, false if all of them fall outside this node's
00100 //               bounding volume.
00101 ////////////////////////////////////////////////////////////////////
00102 bool CollisionLevelState::
00103 any_in_bounds() {
00104 #ifndef NDEBUG
00105   int indent_level = 0;
00106   if (collide_cat.is_spam()) {
00107     indent_level = _node_path.get_num_nodes() * 2;
00108     collide_cat.spam();
00109     indent(collide_cat.spam(false), indent_level)
00110       << "Considering " << _node_path.get_node_path() << "\n";
00111   }
00112 #endif  // NDEBUG
00113 
00114   const BoundingVolume &node_bv = node()->get_bound();
00115   if (node_bv.is_of_type(GeometricBoundingVolume::get_class_type())) {
00116     const GeometricBoundingVolume *node_gbv;
00117     DCAST_INTO_R(node_gbv, &node_bv, false);
00118 
00119     int num_colliders = get_num_colliders();
00120     for (int c = 0; c < num_colliders; c++) {
00121       if (has_collider(c)) {
00122         CollisionNode *collider = get_node(c);
00123         bool is_in = false;
00124 
00125         // Don't even bother testing the bounding volume if there are
00126         // no collide bits in common between our collider and this
00127         // node.
00128         CollideMask from_mask = collider->get_from_collide_mask();
00129         if (collider->get_collide_geom() ||
00130             (from_mask & node()->get_net_collide_mask()) != 0) {
00131           // There are bits in common, so go ahead and try the
00132           // bounding volume.
00133           const GeometricBoundingVolume *col_gbv =
00134             get_local_bound(c);
00135           if (col_gbv != (GeometricBoundingVolume *)NULL) {
00136             is_in = (node_gbv->contains(col_gbv) != 0);
00137 
00138 #ifndef NDEBUG
00139             if (collide_cat.is_spam()) {
00140               collide_cat.spam();
00141               indent(collide_cat.spam(false), indent_level)
00142                 << "Comparing " << c << ": " << *col_gbv
00143                 << " to " << *node_gbv << ", is_in = " << is_in << "\n";
00144             }
00145 #endif  // NDEBUG
00146           }
00147         }
00148 
00149         if (!is_in) {
00150           // This collider cannot intersect with any geometry at
00151           // this node or below.
00152           omit_collider(c);
00153         }
00154       }
00155     }
00156   }
00157 
00158 #ifndef NDEBUG
00159   if (collide_cat.is_spam()) {
00160     int num_active_colliders = 0;
00161     int num_colliders = get_num_colliders();
00162     for (int c = 0; c < num_colliders; c++) {
00163       if (has_collider(c)) {
00164         num_active_colliders++;
00165       }
00166     }
00167 
00168     collide_cat.spam();
00169     indent(collide_cat.spam(false), indent_level)
00170       << _node_path.get_node_path() << " has " << num_active_colliders
00171       << " interested colliders.\n";
00172   }
00173 #endif  // NDEBUG
00174   return has_any_collider();
00175 }
00176 
00177 ////////////////////////////////////////////////////////////////////
00178 //     Function: CollisionLevelState::apply_transform
00179 //       Access: Public
00180 //  Description: Applies the inverse transform from the current node,
00181 //               if any, onto all the colliders in the level state.
00182 ////////////////////////////////////////////////////////////////////
00183 void CollisionLevelState::
00184 apply_transform() {
00185   // The "parent" bounds list remembers the bounds list of the
00186   // previous node.
00187   _parent_bounds = _local_bounds;
00188 
00189   // Recompute the bounds list of this node (if we have a transform).
00190   const TransformState *node_transform = node()->get_transform();
00191   if (!node_transform->is_identity()) {
00192     CPT(TransformState) inv_transform = 
00193       node_transform->invert_compose(TransformState::make_identity());
00194     const LMatrix4f &mat = inv_transform->get_mat();
00195 
00196     // Now build the new bounding volumes list.
00197     BoundingVolumes new_bounds;
00198 
00199     int num_colliders = get_num_colliders();
00200     new_bounds.reserve(num_colliders);
00201     for (int c = 0; c < num_colliders; c++) {
00202       if (!has_collider(c) ||
00203           get_local_bound(c) == (GeometricBoundingVolume *)NULL) {
00204         new_bounds.push_back((GeometricBoundingVolume *)NULL);
00205       } else {
00206         const GeometricBoundingVolume *old_bound = get_local_bound(c);
00207         GeometricBoundingVolume *new_bound = 
00208           DCAST(GeometricBoundingVolume, old_bound->make_copy());
00209         new_bound->xform(mat);
00210         new_bounds.push_back(new_bound);
00211       }
00212     }
00213     
00214     _local_bounds = new_bounds;
00215   }    
00216 }

Generated on Fri May 2 00:35:35 2003 for Panda by doxygen1.3