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

panda/src/collide/collisionTraverser.cxx

Go to the documentation of this file.
00001 // Filename: collisionTraverser.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 "collisionTraverser.h"
00020 #include "collisionNode.h"
00021 #include "collisionEntry.h"
00022 #include "collisionPolygon.h"
00023 #include "collisionRecorder.h"
00024 #include "config_collide.h"
00025 
00026 #include "transformState.h"
00027 #include "geomNode.h"
00028 #include "geom.h"
00029 #include "nodePath.h"
00030 #include "pStatTimer.h"
00031 #include "indent.h"
00032 
00033 #ifndef CPPPARSER
00034 PStatCollector CollisionTraverser::_collisions_pcollector("App:Collisions");
00035 #endif
00036 
00037 ////////////////////////////////////////////////////////////////////
00038 //     Function: CollisionTraverser::Constructor
00039 //       Access: Public
00040 //  Description:
00041 ////////////////////////////////////////////////////////////////////
00042 CollisionTraverser::
00043 CollisionTraverser() {
00044 #ifdef DO_COLLISION_RECORDING
00045   _recorder = (CollisionRecorder *)NULL;
00046 #endif
00047 }
00048 
00049 ////////////////////////////////////////////////////////////////////
00050 //     Function: CollisionTraverser::Destructor
00051 //       Access: Public
00052 //  Description:
00053 ////////////////////////////////////////////////////////////////////
00054 CollisionTraverser::
00055 ~CollisionTraverser() {
00056 #ifdef DO_COLLISION_RECORDING
00057   clear_recorder();
00058 #endif
00059 }
00060 
00061 ////////////////////////////////////////////////////////////////////
00062 //     Function: CollisionTraverser::add_collider
00063 //       Access: Public
00064 //  Description: Adds a new CollisionNode, representing an object that
00065 //               will be tested for collisions into other objects,
00066 //               along with the handler that will serve each detected
00067 //               collision.  Each CollisionNode may be served by only
00068 //               one handler at a time, but a given handler may serve
00069 //               many CollisionNodes.
00070 //
00071 //               The handler that serves a particular node may be
00072 //               changed from time to time by calling add_collider()
00073 //               again on the same node.
00074 ////////////////////////////////////////////////////////////////////
00075 void CollisionTraverser::
00076 add_collider(CollisionNode *node, CollisionHandler *handler) {
00077   nassertv(_ordered_colliders.size() == _colliders.size());
00078   nassertv(node != (CollisionNode *)NULL);
00079   nassertv(handler != (CollisionHandler *)NULL);
00080 
00081   Colliders::iterator ci = _colliders.find(node);
00082   if (ci != _colliders.end()) {
00083     // We already knew about this collider.
00084     if ((*ci).second != handler) {
00085       // Change the handler.
00086       PT(CollisionHandler) old_handler = (*ci).second;
00087       (*ci).second = handler;
00088 
00089       // Now update our own reference counts within our handler set.
00090       Handlers::iterator hi = _handlers.find(old_handler);
00091       nassertv(hi != _handlers.end());
00092       (*hi).second--;
00093       nassertv((*hi).second >= 0);
00094       if ((*hi).second == 0) {
00095         _handlers.erase(hi);
00096       }
00097 
00098       hi = _handlers.find(handler);
00099       if (hi == _handlers.end()) {
00100         _handlers.insert(Handlers::value_type(handler, 1));
00101       } else {
00102         (*hi).second++;
00103       }
00104     }
00105 
00106   } else {
00107     // We hadn't already known about this collider.
00108     _colliders.insert(Colliders::value_type(node, handler));
00109     _ordered_colliders.push_back(node);
00110 
00111     Handlers::iterator hi = _handlers.find(handler);
00112     if (hi == _handlers.end()) {
00113       _handlers.insert(Handlers::value_type(handler, 1));
00114     } else {
00115       (*hi).second++;
00116     }
00117   }
00118 
00119   nassertv(_ordered_colliders.size() == _colliders.size());
00120 }
00121 
00122 ////////////////////////////////////////////////////////////////////
00123 //     Function: CollisionTraverser::remove_collider
00124 //       Access: Public
00125 //  Description: Removes the collider (and its associated handler)
00126 //               from the set of CollisionNodes that will be tested
00127 //               each frame for collisions into other objects.
00128 //               Returns true if the definition was found and removed,
00129 //               false if it wasn't present to begin with.
00130 ////////////////////////////////////////////////////////////////////
00131 bool CollisionTraverser::
00132 remove_collider(CollisionNode *node) {
00133   nassertr(_ordered_colliders.size() == _colliders.size(), false);
00134 
00135   Colliders::iterator ci = _colliders.find(node);
00136   if (ci == _colliders.end()) {
00137     // We didn't know about this node.
00138     return false;
00139   }
00140 
00141   CollisionHandler *handler = (*ci).second;
00142 
00143   // Update the set of handlers.
00144   Handlers::iterator hi = _handlers.find(handler);
00145   nassertr(hi != _handlers.end(), false);
00146   (*hi).second--;
00147   nassertr((*hi).second >= 0, false);
00148   if ((*hi).second == 0) {
00149     _handlers.erase(hi);
00150   }
00151 
00152   _colliders.erase(ci);
00153 
00154   OrderedColliders::iterator oci =
00155     find(_ordered_colliders.begin(), _ordered_colliders.end(), node);
00156   nassertr(oci != _ordered_colliders.end(), false);
00157   _ordered_colliders.erase(oci);
00158 
00159   nassertr(_ordered_colliders.size() == _colliders.size(), false);
00160   return true;
00161 }
00162 
00163 ////////////////////////////////////////////////////////////////////
00164 //     Function: CollisionTraverser::has_collider
00165 //       Access: Public
00166 //  Description: Returns true if the indicated node is current in the
00167 //               set of nodes that will be tested each frame for
00168 //               collisions into other objects.
00169 ////////////////////////////////////////////////////////////////////
00170 bool CollisionTraverser::
00171 has_collider(CollisionNode *node) const {
00172   Colliders::const_iterator ci = _colliders.find(node);
00173   return (ci != _colliders.end());
00174 }
00175 
00176 ////////////////////////////////////////////////////////////////////
00177 //     Function: CollisionTraverser::get_num_colliders
00178 //       Access: Public
00179 //  Description: Returns the number of CollisionNodes that have been
00180 //               added to the traverser via add_collider().
00181 ////////////////////////////////////////////////////////////////////
00182 int CollisionTraverser::
00183 get_num_colliders() const {
00184   nassertr(_ordered_colliders.size() == _colliders.size(), 0);
00185   return _ordered_colliders.size();
00186 }
00187 
00188 ////////////////////////////////////////////////////////////////////
00189 //     Function: CollisionTraverser::get_collider
00190 //       Access: Public
00191 //  Description: Returns the nth CollisionNode that has been
00192 //               added to the traverser via add_collider().
00193 ////////////////////////////////////////////////////////////////////
00194 CollisionNode *CollisionTraverser::
00195 get_collider(int n) const {
00196   nassertr(_ordered_colliders.size() == _colliders.size(), NULL);
00197   nassertr(n >= 0 && n < (int)_ordered_colliders.size(), NULL);
00198   return _ordered_colliders[n];
00199 }
00200 
00201 ////////////////////////////////////////////////////////////////////
00202 //     Function: CollisionTraverser::get_handler
00203 //       Access: Public
00204 //  Description: Returns the handler that is currently assigned to
00205 //               serve the indicated collision node, or NULL if the
00206 //               node is not on the traverser's set of active nodes.
00207 ////////////////////////////////////////////////////////////////////
00208 CollisionHandler *CollisionTraverser::
00209 get_handler(CollisionNode *node) const {
00210   Colliders::const_iterator ci = _colliders.find(node);
00211   if (ci != _colliders.end()) {
00212     return (*ci).second;
00213   };
00214   return NULL;
00215 }
00216 
00217 ////////////////////////////////////////////////////////////////////
00218 //     Function: CollisionTraverser::clear_colliders
00219 //       Access: Public
00220 //  Description: Completely empties the set of collision nodes and
00221 //               their associated handlers.
00222 ////////////////////////////////////////////////////////////////////
00223 void CollisionTraverser::
00224 clear_colliders() {
00225   _colliders.clear();
00226   _ordered_colliders.clear();
00227 }
00228 
00229 
00230 ////////////////////////////////////////////////////////////////////
00231 //     Function: CollisionTraverser::traverse
00232 //       Access: Public
00233 //  Description:
00234 ////////////////////////////////////////////////////////////////////
00235 void CollisionTraverser::
00236 traverse(const NodePath &root) {
00237   PStatTimer timer(_collisions_pcollector);
00238 
00239 #ifdef DO_COLLISION_RECORDING
00240   if (has_recorder()) {
00241     get_recorder()->begin_traversal();
00242   }
00243 #endif  // DO_COLLISION_RECORDING
00244 
00245   CollisionLevelState level_state(root);
00246   prepare_colliders(level_state);
00247 
00248   Handlers::iterator hi;
00249   for (hi = _handlers.begin(); hi != _handlers.end(); ++hi) {
00250     (*hi).first->begin_group();
00251   }
00252 
00253   r_traverse(level_state);
00254 
00255   hi = _handlers.begin();
00256   while (hi != _handlers.end()) {
00257     if (!(*hi).first->end_group()) {
00258       // This handler wants to remove itself from the traversal list.
00259       Handlers::iterator hnext = hi;
00260       ++hnext;
00261       _handlers.erase(hi);
00262       hi = hnext;
00263     } else {
00264       ++hi;
00265     }
00266   }
00267 
00268   if (auto_clear_velocity) {
00269     // Clear all the velocities for next time.
00270     OrderedColliders::iterator ci;
00271     for (ci = _ordered_colliders.begin(); 
00272          ci != _ordered_colliders.end(); 
00273          ++ci) {
00274       CollisionNode *node = (*ci);
00275       node->clear_velocity();
00276     }
00277   }
00278 
00279 #ifdef DO_COLLISION_RECORDING
00280   if (has_recorder()) {
00281     get_recorder()->end_traversal();
00282   }
00283 #endif  // DO_COLLISION_RECORDING
00284 }
00285 
00286 #ifdef DO_COLLISION_RECORDING
00287 ////////////////////////////////////////////////////////////////////
00288 //     Function: CollisionTraverser::set_recorder
00289 //       Access: Public
00290 //  Description: Uses the indicated CollisionRecorder object to start
00291 //               recording the intersection tests made by each
00292 //               subsequent call to traverse() on this object.  A
00293 //               particular CollisionRecorder object can only record
00294 //               one traverser at a time; if this object has already
00295 //               been assigned to another traverser, that assignment
00296 //               is broken.
00297 //
00298 //               This is intended to be used in a debugging mode to
00299 //               try to determine what work is being performed by the
00300 //               collision traversal.  Usually, attaching a recorder
00301 //               will impose significant runtime overhead.
00302 //
00303 //               This does not transfer ownership of the
00304 //               CollisionRecorder pointer; maintenance of that
00305 //               remains the caller's responsibility.  If the
00306 //               CollisionRecorder is destructed, it will cleanly
00307 //               remove itself from the traverser.
00308 ////////////////////////////////////////////////////////////////////
00309 void CollisionTraverser::
00310 set_recorder(CollisionRecorder *recorder) {
00311   if (recorder != _recorder) {
00312     // Remove the old recorder, if any.
00313     if (_recorder != (CollisionRecorder *)NULL) {
00314       nassertv(_recorder->_trav == this);
00315       _recorder->_trav = (CollisionTraverser *)NULL;
00316     }
00317     
00318     _recorder = recorder;
00319     
00320     // Tell the new recorder about his new owner.
00321     if (_recorder != (CollisionRecorder *)NULL) {
00322       nassertv(_recorder->_trav != this);
00323       if (_recorder->_trav != (CollisionTraverser *)NULL) {
00324         _recorder->_trav->clear_recorder();
00325       }
00326       nassertv(_recorder->_trav == (CollisionTraverser *)NULL);
00327       _recorder->_trav = this;
00328     }
00329   }
00330 }
00331 #endif  // DO_COLLISION_RECORDING
00332 
00333 ////////////////////////////////////////////////////////////////////
00334 //     Function: CollisionTraverser::output
00335 //       Access: Public
00336 //  Description:
00337 ////////////////////////////////////////////////////////////////////
00338 void CollisionTraverser::
00339 output(ostream &out) const {
00340   out << "CollisionTraverser, " << _colliders.size()
00341       << " colliders and " << _handlers.size() << " handlers.\n";
00342 }
00343 
00344 ////////////////////////////////////////////////////////////////////
00345 //     Function: CollisionTraverser::write
00346 //       Access: Public
00347 //  Description:
00348 ////////////////////////////////////////////////////////////////////
00349 void CollisionTraverser::
00350 write(ostream &out, int indent_level) const {
00351   indent(out, indent_level)
00352     << "CollisionTraverser, " << _colliders.size()
00353     << " colliders and " << _handlers.size() << " handlers:\n";
00354   Colliders::const_iterator ci;
00355   for (ci = _colliders.begin(); ci != _colliders.end(); ++ci) {
00356     CollisionNode *cnode = (*ci).first;
00357     CollisionHandler *handler = (*ci).second;
00358     nassertv(cnode != (CollisionNode *)NULL);
00359     nassertv(handler != (CollisionHandler *)NULL);
00360 
00361     indent(out, indent_level + 2)
00362       << *cnode << " handled by " << handler->get_type() << "\n";
00363     int num_solids = cnode->get_num_solids();
00364     for (int i = 0; i < num_solids; i++) {
00365       cnode->get_solid(i)->write(out, indent_level + 4);
00366     }
00367   }
00368 }
00369 
00370 
00371 ////////////////////////////////////////////////////////////////////
00372 //     Function: CollisionTraverser::prepare_colliders
00373 //       Access: Private
00374 //  Description:
00375 ////////////////////////////////////////////////////////////////////
00376 void CollisionTraverser::
00377 prepare_colliders(CollisionLevelState &level_state) {
00378   level_state.clear();
00379   level_state.reserve(_colliders.size());
00380 
00381   int i = 0;
00382   while (i < (int)_ordered_colliders.size()) {
00383     CollisionNode *cnode = _ordered_colliders[i];
00384 
00385     CollisionLevelState::ColliderDef def;
00386     def._node = cnode;
00387     NodePath root;
00388     NodePath cnode_path(cnode);
00389     def._space = cnode_path.get_mat(root);
00390     def._inv_space = root.get_mat(cnode_path);
00391 
00392 #ifndef NDEBUG
00393     if (def._space.is_nan()) {
00394       collide_cat.error()
00395         << "Collider " << *cnode
00396         << " has become NaN.  Dropping from traverser.\n";
00397       // This is safe to do while traversing the list of colliders,
00398       // because we do not increment i in this case.
00399       remove_collider(cnode);
00400     } else
00401 #endif
00402       {
00403         int num_solids = cnode->get_num_solids();
00404         for (int s = 0; s < num_solids; s++) {
00405           CollisionSolid *collider = cnode->get_solid(s);
00406           def._collider = collider;
00407           level_state.prepare_collider(def);
00408         }
00409         i++;
00410       }
00411   }
00412 }
00413 
00414 ////////////////////////////////////////////////////////////////////
00415 //     Function: CollisionTraverser::r_traverse
00416 //       Access: Private
00417 //  Description:
00418 ////////////////////////////////////////////////////////////////////
00419 void CollisionTraverser::
00420 r_traverse(CollisionLevelState &level_state) {
00421   if (!level_state.any_in_bounds()) {
00422     return;
00423   }
00424   level_state.apply_transform();
00425 
00426   PandaNode *node = level_state.node();
00427   if (node->is_exact_type(CollisionNode::get_class_type())) {
00428     level_state.reached_collision_node();
00429 
00430     CollisionNode *cnode;
00431     DCAST_INTO_V(cnode, node);
00432     const BoundingVolume &node_bv = cnode->get_bound();
00433     const GeometricBoundingVolume *node_gbv = NULL;
00434     if (node_bv.is_of_type(GeometricBoundingVolume::get_class_type())) {
00435       DCAST_INTO_V(node_gbv, &node_bv);
00436     }
00437 
00438     CollisionEntry entry;
00439     entry._into_node = cnode;
00440     entry._into_node_path = level_state.get_node_path();
00441     entry._into_space = entry._into_node_path.get_mat(NodePath());
00442 
00443     int num_colliders = level_state.get_num_colliders();
00444     for (int c = 0; c < num_colliders; c++) {
00445       if (level_state.has_collider(c)) {
00446         entry._from_node = level_state.get_node(c);
00447 
00448         if ((entry._from_node->get_from_collide_mask() &
00449              cnode->get_into_collide_mask()) != 0) {
00450           entry._from = level_state.get_collider(c);
00451           entry._from_space = level_state.get_space(c);
00452 
00453           if (entry._from_node->has_velocity()) {
00454             entry.set_from_velocity(entry._from_node->get_velocity());
00455           }
00456 
00457           NodePath root;
00458           const LMatrix4f &into_space_inv = 
00459             root.get_mat(entry._into_node_path);
00460           entry._wrt_space = entry._from_space * into_space_inv;
00461           entry._inv_wrt_space =
00462             entry._into_space * level_state.get_inv_space(c);
00463 
00464           compare_collider_to_node(entry, 
00465                                    level_state.get_parent_bound(c),
00466                                    level_state.get_local_bound(c),
00467                                    node_gbv);
00468         }
00469       }
00470     }
00471 
00472   } else if (node->is_geom_node() && level_state.has_any_collide_geom()) {
00473 #ifndef NDEBUG
00474     if (collide_cat.is_spam()) {
00475       collide_cat.spam()
00476         << "Reached " << *node << "\n";
00477     }
00478 #endif
00479     
00480     GeomNode *gnode;
00481     DCAST_INTO_V(gnode, node);
00482     const BoundingVolume &node_bv = gnode->get_bound();
00483     const GeometricBoundingVolume *node_gbv = NULL;
00484     if (node_bv.is_of_type(GeometricBoundingVolume::get_class_type())) {
00485       DCAST_INTO_V(node_gbv, &node_bv);
00486     }
00487 
00488     CollisionEntry entry;
00489     entry._into_node = gnode;
00490     entry._into_node_path = level_state.get_node_path();
00491     entry._into_space = entry._into_node_path.get_mat(NodePath());
00492 
00493     int num_colliders = level_state.get_num_colliders();
00494     for (int c = 0; c < num_colliders; c++) {
00495       if (level_state.has_collider_with_geom(c)) {
00496         entry._from_node = level_state.get_node(c);
00497 
00498         entry._from = level_state.get_collider(c);
00499         entry._from_space = level_state.get_space(c);
00500 
00501         NodePath root;
00502         const LMatrix4f &into_space_inv = 
00503           root.get_mat(entry._into_node_path);
00504         entry._wrt_space = entry._from_space * into_space_inv;
00505         entry._inv_wrt_space =
00506           entry._into_space * level_state.get_inv_space(c);
00507 
00508         compare_collider_to_geom_node(entry, 
00509                                       level_state.get_parent_bound(c),
00510                                       level_state.get_local_bound(c),
00511                                       node_gbv);
00512       }
00513     }
00514   }
00515 
00516   if (node->has_single_child_visibility()) {
00517     // If it's a switch node or sequence node, visit just the one
00518     // visible child.
00519     int index = node->get_visible_child();
00520     if (index >= 0 && index < node->get_num_children()) {
00521       CollisionLevelState next_state(level_state, node->get_child(index));
00522       r_traverse(next_state);
00523     }
00524 
00525   } else {
00526     // Otherwise, visit all the children.
00527     int num_children = node->get_num_children();
00528     for (int i = 0; i < num_children; i++) {
00529       CollisionLevelState next_state(level_state, node->get_child(i));
00530       r_traverse(next_state);
00531     }
00532   }
00533 }
00534 
00535 ////////////////////////////////////////////////////////////////////
00536 //     Function: CollisionTraverser::compare_collider_to_node
00537 //       Access: Private
00538 //  Description:
00539 ////////////////////////////////////////////////////////////////////
00540 void CollisionTraverser::
00541 compare_collider_to_node(CollisionEntry &entry,
00542                          const GeometricBoundingVolume *from_parent_gbv,
00543                          const GeometricBoundingVolume *from_node_gbv,
00544                          const GeometricBoundingVolume *into_node_gbv) {
00545   bool within_node_bounds = true;
00546   if (from_parent_gbv != (GeometricBoundingVolume *)NULL &&
00547       into_node_gbv != (GeometricBoundingVolume *)NULL) {
00548     within_node_bounds = (into_node_gbv->contains(from_parent_gbv) != 0);
00549   }
00550 
00551   if (within_node_bounds) {
00552     CollisionNode *cnode;
00553     DCAST_INTO_V(cnode, entry._into_node);
00554     int num_solids = cnode->get_num_solids();
00555     for (int s = 0; s < num_solids; s++) {
00556       entry._into = cnode->get_solid(s);
00557       if (entry._from != entry._into) {
00558         const BoundingVolume &solid_bv = entry._into->get_bound();
00559         const GeometricBoundingVolume *solid_gbv = NULL;
00560         if (num_solids > 1 &&
00561             solid_bv.is_of_type(GeometricBoundingVolume::get_class_type())) {
00562           // Only bother to test against each solid's bounding
00563           // volume if we have more than one solid in the node, as a
00564           // slight optimization.  (If the node contains just one
00565           // solid, then the node's bounding volume, which we just
00566           // tested, is the same as the solid's bounding volume.)
00567           DCAST_INTO_V(solid_gbv, &solid_bv);
00568         }
00569 
00570         compare_collider_to_solid(entry, from_node_gbv, solid_gbv);
00571       }
00572     }
00573   }
00574 }
00575 
00576 ////////////////////////////////////////////////////////////////////
00577 //     Function: CollisionTraverser::compare_collider_to_geom_node
00578 //       Access: Private
00579 //  Description:
00580 ////////////////////////////////////////////////////////////////////
00581 void CollisionTraverser::
00582 compare_collider_to_geom_node(CollisionEntry &entry,
00583                               const GeometricBoundingVolume *from_parent_gbv,
00584                               const GeometricBoundingVolume *from_node_gbv,
00585                               const GeometricBoundingVolume *into_node_gbv) {
00586   bool within_node_bounds = true;
00587   if (from_parent_gbv != (GeometricBoundingVolume *)NULL &&
00588       into_node_gbv != (GeometricBoundingVolume *)NULL) {
00589     within_node_bounds = (into_node_gbv->contains(from_parent_gbv) != 0);
00590   }
00591 
00592   if (within_node_bounds) {
00593     GeomNode *gnode;
00594     DCAST_INTO_V(gnode, entry._into_node);
00595     int num_geoms = gnode->get_num_geoms();
00596     for (int s = 0; s < num_geoms; s++) {
00597       entry._into = (CollisionSolid *)NULL;
00598       Geom *geom = DCAST(Geom, gnode->get_geom(s));
00599       if (geom != (Geom *)NULL) {
00600         const BoundingVolume &geom_bv = geom->get_bound();
00601         const GeometricBoundingVolume *geom_gbv = NULL;
00602         if (num_geoms > 1 &&
00603             geom_bv.is_of_type(GeometricBoundingVolume::get_class_type())) {
00604           // Only bother to test against each geom's bounding
00605           // volume if we have more than one geom in the node, as a
00606           // slight optimization.  (If the node contains just one
00607           // geom, then the node's bounding volume, which we just
00608           // tested, is the same as the geom's bounding volume.)
00609           DCAST_INTO_V(geom_gbv, &geom_bv);
00610         }
00611 
00612         compare_collider_to_geom(entry, geom, from_node_gbv, geom_gbv);
00613       }
00614     }
00615   }
00616 }
00617 
00618 ////////////////////////////////////////////////////////////////////
00619 //     Function: CollisionTraverser::compare_collider_to_solid
00620 //       Access: Private
00621 //  Description:
00622 ////////////////////////////////////////////////////////////////////
00623 void CollisionTraverser::
00624 compare_collider_to_solid(CollisionEntry &entry,
00625                           const GeometricBoundingVolume *from_node_gbv,
00626                           const GeometricBoundingVolume *solid_gbv) {
00627   bool within_solid_bounds = true;
00628   if (from_node_gbv != (GeometricBoundingVolume *)NULL &&
00629       solid_gbv != (GeometricBoundingVolume *)NULL) {
00630     within_solid_bounds = (solid_gbv->contains(from_node_gbv) != 0);
00631   }
00632   if (within_solid_bounds) {
00633     Colliders::const_iterator ci;
00634     ci = _colliders.find(entry.get_from_node());
00635     nassertv(ci != _colliders.end());
00636     entry.test_intersection((*ci).second, this);
00637   }
00638 }
00639 
00640 ////////////////////////////////////////////////////////////////////
00641 //     Function: CollisionTraverser::compare_collider_to_geom
00642 //       Access: Private
00643 //  Description:
00644 ////////////////////////////////////////////////////////////////////
00645 void CollisionTraverser::
00646 compare_collider_to_geom(CollisionEntry &entry, Geom *geom,
00647                          const GeometricBoundingVolume *from_node_gbv,
00648                          const GeometricBoundingVolume *geom_gbv) {
00649   bool within_geom_bounds = true;
00650   if (from_node_gbv != (GeometricBoundingVolume *)NULL &&
00651       geom_gbv != (GeometricBoundingVolume *)NULL) {
00652     within_geom_bounds = (geom_gbv->contains(from_node_gbv) != 0);
00653   }
00654   if (within_geom_bounds) {
00655     Colliders::const_iterator ci;
00656     ci = _colliders.find(entry.get_from_node());
00657     nassertv(ci != _colliders.end());
00658 
00659     PTA_Vertexf coords;
00660     PTA_ushort vindex;
00661     geom->get_coords(coords, vindex);
00662     PTA_ushort tris = geom->get_tris();
00663 
00664     for (int i = 0; i < (int)tris.size(); i += 3) {
00665       if (CollisionPolygon::verify_points(coords[tris[i]],
00666                                           coords[tris[i + 1]],
00667                                           coords[tris[i + 2]])) {
00668         // Generate a temporary CollisionPolygon on the fly for each
00669         // triangle in the Geom.
00670         entry._into =
00671           new CollisionPolygon(coords[tris[i]], coords[tris[i + 1]],
00672                                coords[tris[i + 2]]);
00673         entry.test_intersection((*ci).second, this);
00674       }
00675     }
00676   }
00677 }

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