Panda3D

collisionLevelState.I

00001 // Filename: collisionLevelState.I
00002 // Created by:  drose (05Apr07)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) Carnegie Mellon University.  All rights reserved.
00008 //
00009 // All use of this software is subject to the terms of the revised BSD
00010 // license.  You should have received a copy of this license along
00011 // with this source code in a file named "LICENSE."
00012 //
00013 ////////////////////////////////////////////////////////////////////
00014 
00015 #ifndef CPPPARSER
00016 ////////////////////////////////////////////////////////////////////
00017 //     Function: CollisionLevelState::Constructor
00018 //       Access: Public
00019 //  Description:
00020 ////////////////////////////////////////////////////////////////////
00021 template<class MaskType>
00022 INLINE CollisionLevelState<MaskType>::
00023 CollisionLevelState(const NodePath &node_path) :
00024   CollisionLevelStateBase(node_path),
00025   _current(CurrentMask::all_off())
00026 {
00027 }
00028 #endif  // CPPPARSER
00029 
00030 #ifndef CPPPARSER
00031 ////////////////////////////////////////////////////////////////////
00032 //     Function: CollisionLevelState::Constructor
00033 //       Access: Public
00034 //  Description: This constructor goes to the next child node in the
00035 //               traversal.
00036 ////////////////////////////////////////////////////////////////////
00037 template<class MaskType>
00038 INLINE CollisionLevelState<MaskType>::
00039 CollisionLevelState(const CollisionLevelState<MaskType> &parent, PandaNode *child) :
00040   CollisionLevelStateBase(parent, child),
00041   _current(parent._current)
00042 {
00043 }
00044 #endif  // CPPPARSER
00045 
00046 #ifndef CPPPARSER
00047 ////////////////////////////////////////////////////////////////////
00048 //     Function: CollisionLevelState::Copy Constructor
00049 //       Access: Public
00050 //  Description: 
00051 ////////////////////////////////////////////////////////////////////
00052 template<class MaskType>
00053 INLINE CollisionLevelState<MaskType>::
00054 CollisionLevelState(const CollisionLevelState<MaskType> &copy) :
00055   CollisionLevelStateBase(copy),
00056   _current(copy._current)
00057 {
00058 }
00059 #endif  // CPPPARSER
00060 
00061 #ifndef CPPPARSER
00062 ////////////////////////////////////////////////////////////////////
00063 //     Function: CollisionLevelState::Copy Assignment Operator
00064 //       Access: Public
00065 //  Description: 
00066 ////////////////////////////////////////////////////////////////////
00067 template<class MaskType>
00068 INLINE void CollisionLevelState<MaskType>::
00069 operator = (const CollisionLevelState<MaskType> &copy) {
00070   CollisionLevelStateBase::operator = (copy);
00071   _current = copy._current;
00072 }
00073 #endif  // CPPPARSER
00074 
00075 #ifndef CPPPARSER
00076 ////////////////////////////////////////////////////////////////////
00077 //     Function: CollisionLevelState::clear
00078 //       Access: Public
00079 //  Description:
00080 ////////////////////////////////////////////////////////////////////
00081 template<class MaskType>
00082 INLINE void CollisionLevelState<MaskType>::
00083 clear() {
00084   CollisionLevelStateBase::clear();
00085   _current.clear();
00086 }
00087 #endif  // CPPPARSER
00088 
00089 #ifndef CPPPARSER
00090 ////////////////////////////////////////////////////////////////////
00091 //     Function: CollisionLevelState::prepare_collider
00092 //       Access: Public
00093 //  Description: Adds the indicated Collider to the set of Colliders
00094 //               in the current level state.
00095 ////////////////////////////////////////////////////////////////////
00096 template<class MaskType>
00097 INLINE void CollisionLevelState<MaskType>::
00098 prepare_collider(const ColliderDef &def, const NodePath &root) {
00099   int index = (int)_colliders.size();
00100   nassertv(!CurrentMask::has_max_num_bits() ||
00101            index <= CurrentMask::get_max_num_bits());
00102 
00103   CollisionLevelStateBase::prepare_collider(def, root);
00104   _current.set_bit(index);
00105 }
00106 #endif  // CPPPARSER
00107 
00108 #ifndef CPPPARSER
00109 ////////////////////////////////////////////////////////////////////
00110 //     Function: CollisionLevelState::any_in_bounds
00111 //       Access: Public
00112 //  Description: Checks the bounding volume of the current node
00113 //               against each of our colliders.  Eliminates from the
00114 //               current collider list any that are outside of the
00115 //               bounding volume.  Returns true if any colliders
00116 //               remain, false if all of them fall outside this node's
00117 //               bounding volume.
00118 ////////////////////////////////////////////////////////////////////
00119 template<class MaskType>
00120 bool CollisionLevelState<MaskType>::
00121 any_in_bounds() {
00122 #ifndef NDEBUG
00123   int indent_level = 0;
00124   if (collide_cat.is_spam()) {
00125     indent_level = _node_path.get_num_nodes() * 2;
00126     collide_cat.spam();
00127     indent(collide_cat.spam(false), indent_level)
00128       << "Considering " << _node_path.get_node_path() << "\n";
00129   }
00130 #endif  // NDEBUG
00131 
00132   CPT(BoundingVolume) node_bv = node()->get_bounds();
00133   if (node_bv->is_of_type(GeometricBoundingVolume::get_class_type())) {
00134     const GeometricBoundingVolume *node_gbv;
00135     DCAST_INTO_R(node_gbv, node_bv, false);
00136 
00137     int num_colliders = get_num_colliders();
00138     for (int c = 0; c < num_colliders; c++) {
00139       if (has_collider(c)) {
00140         CollisionNode *cnode = get_collider_node(c);
00141         bool is_in = false;
00142 
00143         // Don't even bother testing the bounding volume if there are
00144         // no collide bits in common between our collider and this
00145         // node.
00146         CollideMask from_mask = cnode->get_from_collide_mask() & _include_mask;
00147         if (!(from_mask & node()->get_net_collide_mask()).is_zero()) {
00148           // Also don't test a node with itself, or with any of its
00149           // descendants.
00150           if (node() == cnode) {
00151 #ifndef NDEBUG
00152             if (collide_cat.is_spam()) {
00153               indent(collide_cat.spam(false), indent_level)
00154                 << "Not comparing " << c << " to " << _node_path
00155                 << " (same node)\n";
00156             }
00157 #endif  // NDEBUG
00158 
00159           } else {
00160             // There are bits in common, and it's not the same
00161             // instance, so go ahead and try the bounding volume.
00162             const GeometricBoundingVolume *col_gbv =
00163               get_local_bound(c);
00164 
00165             is_in = true;  // If there's no bounding volume, we're implicitly in.
00166           
00167             if (col_gbv != (GeometricBoundingVolume *)NULL) {
00168               is_in = (node_gbv->contains(col_gbv) != 0);
00169               _node_volume_pcollector.add_level(1);
00170               
00171 #ifndef NDEBUG
00172               if (collide_cat.is_spam()) {
00173                 indent(collide_cat.spam(false), indent_level)
00174                   << "Comparing " << c << ": " << *col_gbv
00175                   << " to " << *node_gbv << ", is_in = " << is_in << "\n";
00176               }
00177 #endif  // NDEBUG
00178             }
00179           }
00180         }
00181 
00182         if (!is_in) {
00183           // This collider cannot intersect with any geometry at
00184           // this node or below.
00185           omit_collider(c);
00186         }
00187       }
00188     }
00189   }
00190 
00191 #ifndef NDEBUG
00192   if (collide_cat.is_spam()) {
00193     int num_active_colliders = 0;
00194     int num_colliders = get_num_colliders();
00195     for (int c = 0; c < num_colliders; c++) {
00196       if (has_collider(c)) {
00197         num_active_colliders++;
00198       }
00199     }
00200 
00201     collide_cat.spam();
00202     indent(collide_cat.spam(false), indent_level)
00203       << _node_path.get_node_path() << " has " << num_active_colliders
00204       << " interested colliders";
00205     if (num_colliders != 0) {
00206       collide_cat.spam(false)
00207         << " (";
00208       for (int c = 0; c < num_colliders; c++) {
00209         if (has_collider(c)) {
00210           CollisionNode *cnode = get_collider_node(c);
00211           collide_cat.spam(false)
00212             << " " << c << ". " << cnode->get_name();
00213         }
00214       }
00215       collide_cat.spam(false)
00216         << " )";
00217     }
00218     collide_cat.spam(false)
00219       << "\n";
00220   }
00221 #endif  // NDEBUG
00222   return has_any_collider();
00223 }
00224 #endif  // CPPPARSER
00225 
00226 #ifndef CPPPARSER
00227 ////////////////////////////////////////////////////////////////////
00228 //     Function: CollisionLevelStateBase::apply_transform
00229 //       Access: Public
00230 //  Description: Applies the inverse transform from the current node,
00231 //               if any, onto all the colliders in the level state.
00232 //
00233 //               Returns true if the inverse transform is valid, or
00234 //               false if it is not valid (e.g. the transform has a
00235 //               scale to zero).  If the inverse transform is not
00236 //               valid, the caller should not visit this node.
00237 ////////////////////////////////////////////////////////////////////
00238 template<class MaskType>
00239 bool CollisionLevelState<MaskType>::
00240 apply_transform() {
00241   // The "parent" bounds list remembers the bounds list of the
00242   // previous node.
00243   _parent_bounds = _local_bounds;
00244 
00245   if (node()->is_final()) {
00246     // If this node has a "final" bounds, we blank out all of the from
00247     // bounding volumes, since we've already tested against this
00248     // node's into bounds, and there's no need to test any further
00249     // bounding volumes at this node level or below.
00250     BoundingVolumes new_bounds;
00251 
00252     int num_colliders = get_num_colliders();
00253     new_bounds.reserve(num_colliders);
00254     for (int c = 0; c < num_colliders; c++) {
00255       new_bounds.push_back((GeometricBoundingVolume *)NULL);
00256     }
00257     
00258     _local_bounds = new_bounds;
00259 
00260   } else {
00261     // Otherwise, in the usual case, the bounds tests will continue.
00262     // Recompute the bounds list of this node (if we have a
00263     // transform).
00264     const TransformState *node_transform = node()->get_transform();
00265     if (!node_transform->is_identity()) {
00266       CPT(TransformState) inv_transform = 
00267         node_transform->invert_compose(TransformState::make_identity());
00268       if (!inv_transform->has_mat()) {
00269         // No inverse.
00270         return false;
00271       }
00272 
00273       const LMatrix4 &mat = inv_transform->get_mat();
00274       
00275       // Now build the new bounding volumes list.
00276       BoundingVolumes new_bounds;
00277       
00278       int num_colliders = get_num_colliders();
00279       new_bounds.reserve(num_colliders);
00280       for (int c = 0; c < num_colliders; c++) {
00281         if (!has_collider(c) ||
00282             get_local_bound(c) == (GeometricBoundingVolume *)NULL) {
00283           new_bounds.push_back((GeometricBoundingVolume *)NULL);
00284         } else {
00285           const GeometricBoundingVolume *old_bound = get_local_bound(c);
00286           GeometricBoundingVolume *new_bound = 
00287             DCAST(GeometricBoundingVolume, old_bound->make_copy());
00288           new_bound->xform(mat);
00289           new_bounds.push_back(new_bound);
00290         }
00291       }
00292       
00293       _local_bounds = new_bounds;
00294     }    
00295   }
00296 
00297   return true;
00298 }
00299 #endif  // CPPPARSER
00300 
00301 #ifndef CPPPARSER
00302 ////////////////////////////////////////////////////////////////////
00303 //     Function: CollisionLevelState::has_max_colliders
00304 //       Access: Public, Static
00305 //  Description: Returns true if there is any the maximum number of
00306 //               colliders that may be added to the
00307 //               CollisionLevelStateBase at any one time.
00308 ////////////////////////////////////////////////////////////////////
00309 template<class MaskType>
00310 INLINE bool CollisionLevelState<MaskType>::
00311 has_max_colliders() {
00312   return CurrentMask::has_max_num_bits();
00313 }
00314 #endif  // CPPPARSER
00315 
00316 #ifndef CPPPARSER
00317 ////////////////////////////////////////////////////////////////////
00318 //     Function: CollisionLevelState::get_max_colliders
00319 //       Access: Public, Static
00320 //  Description: Returns the maximum number of colliders that may be
00321 //               added to the CollisionLevelStateBase at any one time.
00322 ////////////////////////////////////////////////////////////////////
00323 template<class MaskType>
00324 INLINE int CollisionLevelState<MaskType>::
00325 get_max_colliders() {
00326   return CurrentMask::get_max_num_bits();
00327 }
00328 #endif  // CPPPARSER
00329 
00330 #ifndef CPPPARSER
00331 ////////////////////////////////////////////////////////////////////
00332 //     Function: CollisionLevelState::has_collider
00333 //       Access: Public
00334 //  Description: Returns true if the nth collider in the LevelState is
00335 //               still part of the level.
00336 ////////////////////////////////////////////////////////////////////
00337 template<class MaskType>
00338 INLINE bool CollisionLevelState<MaskType>::
00339 has_collider(int n) const {
00340   nassertr(n >= 0 && n < (int)_colliders.size(), false);
00341   return (_current.get_bit(n));
00342 }
00343 #endif  // CPPPARSER
00344 
00345 #ifndef CPPPARSER
00346 ////////////////////////////////////////////////////////////////////
00347 //     Function: CollisionLevelState::has_any_collider
00348 //       Access: Public
00349 //  Description:
00350 ////////////////////////////////////////////////////////////////////
00351 template<class MaskType>
00352 INLINE bool CollisionLevelState<MaskType>::
00353 has_any_collider() const {
00354   return !_current.is_zero();
00355 }
00356 #endif  // CPPPARSER
00357 
00358 #ifndef CPPPARSER
00359 ////////////////////////////////////////////////////////////////////
00360 //     Function: CollisionLevelState::omit_collider
00361 //       Access: Public
00362 //  Description:
00363 ////////////////////////////////////////////////////////////////////
00364 template<class MaskType>
00365 INLINE void CollisionLevelState<MaskType>::
00366 omit_collider(int n) {
00367   nassertv(n >= 0 && n < (int)_colliders.size());
00368   nassertv(has_collider(n));
00369 
00370   _current.clear_bit(n);
00371 }
00372 #endif  // CPPPARSER
 All Classes Functions Variables Enumerations