Panda3D
|
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> ©) : 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> ©) { 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