Panda3D

collisionHandlerFloor.cxx

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 }
 All Classes Functions Variables Enumerations