Panda3D
|
00001 // Filename: collisionHandlerFloor.cxx 00002 // Created by: drose (16Mar02) 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 #include "collisionHandlerFloor.h" 00016 #include "collisionNode.h" 00017 #include "collisionEntry.h" 00018 #include "config_collide.h" 00019 00020 #include "clockObject.h" 00021 00022 TypeHandle CollisionHandlerFloor::_type_handle; 00023 00024 //////////////////////////////////////////////////////////////////// 00025 // Function: CollisionHandlerFloor::Constructor 00026 // Access: Public 00027 // Description: 00028 //////////////////////////////////////////////////////////////////// 00029 CollisionHandlerFloor:: 00030 CollisionHandlerFloor() { 00031 _offset = 0.0f; 00032 _reach = 1.0f; 00033 _max_velocity = 0.0f; 00034 } 00035 00036 //////////////////////////////////////////////////////////////////// 00037 // Function: CollisionHandlerFloor::Destructor 00038 // Access: Public, Virtual 00039 // Description: 00040 //////////////////////////////////////////////////////////////////// 00041 CollisionHandlerFloor:: 00042 ~CollisionHandlerFloor() { 00043 } 00044 00045 //////////////////////////////////////////////////////////////////// 00046 // Function: CollisionHandlerGravity::set_highest_collision 00047 // Access: Protected 00048 // Description: 00049 // 00050 // 00051 // 00052 // 00053 // 00054 // 00055 //////////////////////////////////////////////////////////////////// 00056 PN_stdfloat CollisionHandlerFloor:: 00057 set_highest_collision(const NodePath &target_node_path, const NodePath &from_node_path, const Entries &entries) { 00058 // Get the maximum height for all collisions with this node. 00059 // This is really the distance to-the-ground, so it will 00060 // be negative when the avatar is above the ground. 00061 // Larger values (less negative) are higher elevation (assuming 00062 // the avatar is right-side-up (or the ray is plumb)). 00063 bool got_max = false; 00064 bool got_min = false; 00065 PN_stdfloat max_height = 0.0f; 00066 PN_stdfloat min_height = 0.0f; 00067 CollisionEntry *highest = NULL; 00068 CollisionEntry *lowest = NULL; 00069 00070 Entries::const_iterator ei; 00071 for (ei = entries.begin(); ei != entries.end(); ++ei) { 00072 CollisionEntry *entry = (*ei); 00073 nassertr(entry != (CollisionEntry *)NULL, 0.0f); 00074 nassertr(from_node_path == entry->get_from_node_path(), 0.0f); 00075 00076 if (entry->has_surface_point()) { 00077 LPoint3 point = entry->get_surface_point(target_node_path); 00078 if (collide_cat.is_debug()) { 00079 collide_cat.debug() 00080 << "Intersection point detected at " << point << "\n"; 00081 } 00082 00083 PN_stdfloat height = point[2]; 00084 if (height < _offset + _reach && 00085 (!got_max || height > max_height)) { 00086 got_max = true; 00087 max_height = height; 00088 highest = entry; 00089 } 00090 if (!got_min || height < min_height) { 00091 got_min = true; 00092 min_height = height; 00093 lowest = entry; 00094 } 00095 } 00096 } 00097 if (!got_max && got_min) { 00098 // We've fallen through the world, but we're also under some walkable 00099 // geometry. 00100 // Move us up to the lowest surface: 00101 got_max = true; 00102 max_height = min_height; 00103 highest = lowest; 00104 } 00105 //#*#_has_contact = got_max; 00106 00107 #if 0 00108 cout<<"\ncolliding with:\n"; 00109 for (Colliding::const_iterator i = _current_colliding.begin(); i != _current_colliding.end(); ++i) { 00110 (**i).write(cout, 2); 00111 } 00112 cout<<"\nhighest:\n"; 00113 highest->write(cout, 2); 00114 cout<<endl; 00115 #endif 00116 #if 1 00117 // We only collide with things we are impacting with. 00118 // Remove the collisions: 00119 _current_colliding.clear(); 00120 // Add only the one that we're impacting with: 00121 add_entry(highest); 00122 #endif 00123 00124 return max_height; 00125 } 00126 00127 //////////////////////////////////////////////////////////////////// 00128 // Function: CollisionHandlerFloor::handle_entries 00129 // Access: Protected, Virtual 00130 // Description: Called by the parent class after all collisions have 00131 // been detected, this manages the various collisions 00132 // and moves around the nodes as necessary. 00133 // 00134 // The return value is normally true, but it may be 00135 // false to indicate the CollisionTraverser should 00136 // disable this handler from being called in the future. 00137 //////////////////////////////////////////////////////////////////// 00138 bool CollisionHandlerFloor:: 00139 handle_entries() { 00140 bool okflag = true; 00141 00142 // Reset the set of things our parent class CollisionHandlerEvent 00143 // recorded a collision with. We'll only consider ourselves 00144 // collided with the topmost object for each from_entry. 00145 _current_colliding.clear(); 00146 00147 FromEntries::const_iterator fi; 00148 for (fi = _from_entries.begin(); fi != _from_entries.end(); ++fi) { 00149 const NodePath &from_node_path = (*fi).first; 00150 const Entries &entries = (*fi).second; 00151 00152 Colliders::iterator ci; 00153 ci = _colliders.find(from_node_path); 00154 if (ci == _colliders.end()) { 00155 // Hmm, someone added a CollisionNode to a traverser and gave 00156 // it this CollisionHandler pointer--but they didn't tell us 00157 // about the node. 00158 collide_cat.error() 00159 << get_type() << " doesn't know about " 00160 << from_node_path << ", disabling.\n"; 00161 okflag = false; 00162 } else { 00163 ColliderDef &def = (*ci).second; 00164 { 00165 #if 0 00166 // Get the maximum height for all collisions with this node. 00167 bool got_max = false; 00168 PN_stdfloat max_height = 0.0f; 00169 CollisionEntry *max_entry = NULL; 00170 00171 Entries::const_iterator ei; 00172 for (ei = entries.begin(); ei != entries.end(); ++ei) { 00173 CollisionEntry *entry = (*ei); 00174 nassertr(entry != (CollisionEntry *)NULL, false); 00175 nassertr(from_node_path == entry->get_from_node_path(), false); 00176 00177 if (entry->has_surface_point()) { 00178 LPoint3 point = entry->get_surface_point(def._target); 00179 if (collide_cat.is_debug()) { 00180 collide_cat.debug() 00181 << "Intersection point detected at " << point << "\n"; 00182 } 00183 00184 PN_stdfloat height = point[2]; 00185 if (!got_max || height > max_height) { 00186 got_max = true; 00187 max_height = height; 00188 max_entry = entry; 00189 } 00190 } 00191 } 00192 00193 // Record a collision with the topmost element for the 00194 // CollisionHandlerEvent base class. 00195 _current_colliding.insert(max_entry); 00196 00197 // Now set our height accordingly. 00198 PN_stdfloat adjust = max_height + _offset; 00199 #else 00200 PN_stdfloat max_height = set_highest_collision(def._target, from_node_path, entries); 00201 00202 // Now set our height accordingly. 00203 PN_stdfloat adjust = max_height + _offset; 00204 #endif 00205 if (!IS_THRESHOLD_ZERO(adjust, 0.001)) { 00206 if (collide_cat.is_debug()) { 00207 collide_cat.debug() 00208 << "Adjusting height by " << adjust << "\n"; 00209 } 00210 00211 if (adjust < 0.0f && _max_velocity != 0.0f) { 00212 PN_stdfloat max_adjust = 00213 _max_velocity * ClockObject::get_global_clock()->get_dt(); 00214 adjust = max(adjust, -max_adjust); 00215 } 00216 00217 CPT(TransformState) trans = def._target.get_transform(); 00218 LVecBase3 pos = trans->get_pos(); 00219 pos[2] += adjust; 00220 def._target.set_transform(trans->set_pos(pos)); 00221 def.updated_transform(); 00222 00223 apply_linear_force(def, LVector3(0.0f, 0.0f, adjust)); 00224 } else { 00225 if (collide_cat.is_spam()) { 00226 collide_cat.spam() 00227 << "Leaving height unchanged.\n"; 00228 } 00229 } 00230 } 00231 } 00232 } 00233 00234 return okflag; 00235 } 00236 00237 //////////////////////////////////////////////////////////////////// 00238 // Function: CollisionHandlerFloor::apply_linear_force 00239 // Access: Protected, Virtual 00240 // Description: 00241 //////////////////////////////////////////////////////////////////// 00242 void CollisionHandlerFloor:: 00243 apply_linear_force(ColliderDef &def, const LVector3 &force) { 00244 }