Panda3D
 All Classes Functions Variables Enumerations
collisionHandlerFloor.cxx
1 // Filename: collisionHandlerFloor.cxx
2 // Created by: drose (16Mar02)
3 //
4 ////////////////////////////////////////////////////////////////////
5 //
6 // PANDA 3D SOFTWARE
7 // Copyright (c) Carnegie Mellon University. All rights reserved.
8 //
9 // All use of this software is subject to the terms of the revised BSD
10 // license. You should have received a copy of this license along
11 // with this source code in a file named "LICENSE."
12 //
13 ////////////////////////////////////////////////////////////////////
14 
15 #include "collisionHandlerFloor.h"
16 #include "collisionNode.h"
17 #include "collisionEntry.h"
18 #include "config_collide.h"
19 
20 #include "clockObject.h"
21 
22 TypeHandle CollisionHandlerFloor::_type_handle;
23 
24 ////////////////////////////////////////////////////////////////////
25 // Function: CollisionHandlerFloor::Constructor
26 // Access: Public
27 // Description:
28 ////////////////////////////////////////////////////////////////////
29 CollisionHandlerFloor::
30 CollisionHandlerFloor() {
31  _offset = 0.0f;
32  _reach = 1.0f;
33  _max_velocity = 0.0f;
34 }
35 
36 ////////////////////////////////////////////////////////////////////
37 // Function: CollisionHandlerFloor::Destructor
38 // Access: Public, Virtual
39 // Description:
40 ////////////////////////////////////////////////////////////////////
41 CollisionHandlerFloor::
42 ~CollisionHandlerFloor() {
43 }
44 
45 ////////////////////////////////////////////////////////////////////
46 // Function: CollisionHandlerGravity::set_highest_collision
47 // Access: Protected
48 // Description:
49 //
50 //
51 //
52 //
53 //
54 //
55 ////////////////////////////////////////////////////////////////////
56 PN_stdfloat CollisionHandlerFloor::
57 set_highest_collision(const NodePath &target_node_path, const NodePath &from_node_path, const Entries &entries) {
58  // Get the maximum height for all collisions with this node.
59  // This is really the distance to-the-ground, so it will
60  // be negative when the avatar is above the ground.
61  // Larger values (less negative) are higher elevation (assuming
62  // the avatar is right-side-up (or the ray is plumb)).
63  bool got_max = false;
64  bool got_min = false;
65  PN_stdfloat max_height = 0.0f;
66  PN_stdfloat min_height = 0.0f;
67  CollisionEntry *highest = NULL;
68  CollisionEntry *lowest = NULL;
69 
70  Entries::const_iterator ei;
71  for (ei = entries.begin(); ei != entries.end(); ++ei) {
72  CollisionEntry *entry = (*ei);
73  nassertr(entry != (CollisionEntry *)NULL, 0.0f);
74  nassertr(from_node_path == entry->get_from_node_path(), 0.0f);
75 
76  if (entry->has_surface_point()) {
77  LPoint3 point = entry->get_surface_point(target_node_path);
78  if (collide_cat.is_debug()) {
79  collide_cat.debug()
80  << "Intersection point detected at " << point << "\n";
81  }
82 
83  PN_stdfloat height = point[2];
84  if (height < _offset + _reach &&
85  (!got_max || height > max_height)) {
86  got_max = true;
87  max_height = height;
88  highest = entry;
89  }
90  if (!got_min || height < min_height) {
91  got_min = true;
92  min_height = height;
93  lowest = entry;
94  }
95  }
96  }
97  if (!got_max && got_min) {
98  // We've fallen through the world, but we're also under some walkable
99  // geometry.
100  // Move us up to the lowest surface:
101  got_max = true;
102  max_height = min_height;
103  highest = lowest;
104  }
105  //#*#_has_contact = got_max;
106 
107  #if 0
108  cout<<"\ncolliding with:\n";
109  for (Colliding::const_iterator i = _current_colliding.begin(); i != _current_colliding.end(); ++i) {
110  (**i).write(cout, 2);
111  }
112  cout<<"\nhighest:\n";
113  highest->write(cout, 2);
114  cout<<endl;
115  #endif
116  #if 1
117  // We only collide with things we are impacting with.
118  // Remove the collisions:
119  _current_colliding.clear();
120  // Add only the one that we're impacting with:
121  add_entry(highest);
122  #endif
123 
124  return max_height;
125 }
126 
127 ////////////////////////////////////////////////////////////////////
128 // Function: CollisionHandlerFloor::handle_entries
129 // Access: Protected, Virtual
130 // Description: Called by the parent class after all collisions have
131 // been detected, this manages the various collisions
132 // and moves around the nodes as necessary.
133 //
134 // The return value is normally true, but it may be
135 // false to indicate the CollisionTraverser should
136 // disable this handler from being called in the future.
137 ////////////////////////////////////////////////////////////////////
138 bool CollisionHandlerFloor::
139 handle_entries() {
140  bool okflag = true;
141 
142  // Reset the set of things our parent class CollisionHandlerEvent
143  // recorded a collision with. We'll only consider ourselves
144  // collided with the topmost object for each from_entry.
145  _current_colliding.clear();
146 
147  FromEntries::const_iterator fi;
148  for (fi = _from_entries.begin(); fi != _from_entries.end(); ++fi) {
149  const NodePath &from_node_path = (*fi).first;
150  const Entries &entries = (*fi).second;
151 
152  Colliders::iterator ci;
153  ci = _colliders.find(from_node_path);
154  if (ci == _colliders.end()) {
155  // Hmm, someone added a CollisionNode to a traverser and gave
156  // it this CollisionHandler pointer--but they didn't tell us
157  // about the node.
158  collide_cat.error()
159  << get_type() << " doesn't know about "
160  << from_node_path << ", disabling.\n";
161  okflag = false;
162  } else {
163  ColliderDef &def = (*ci).second;
164  {
165  #if 0
166  // Get the maximum height for all collisions with this node.
167  bool got_max = false;
168  PN_stdfloat max_height = 0.0f;
169  CollisionEntry *max_entry = NULL;
170 
171  Entries::const_iterator ei;
172  for (ei = entries.begin(); ei != entries.end(); ++ei) {
173  CollisionEntry *entry = (*ei);
174  nassertr(entry != (CollisionEntry *)NULL, false);
175  nassertr(from_node_path == entry->get_from_node_path(), false);
176 
177  if (entry->has_surface_point()) {
178  LPoint3 point = entry->get_surface_point(def._target);
179  if (collide_cat.is_debug()) {
180  collide_cat.debug()
181  << "Intersection point detected at " << point << "\n";
182  }
183 
184  PN_stdfloat height = point[2];
185  if (!got_max || height > max_height) {
186  got_max = true;
187  max_height = height;
188  max_entry = entry;
189  }
190  }
191  }
192 
193  // Record a collision with the topmost element for the
194  // CollisionHandlerEvent base class.
195  _current_colliding.insert(max_entry);
196 
197  // Now set our height accordingly.
198  PN_stdfloat adjust = max_height + _offset;
199  #else
200  PN_stdfloat max_height = set_highest_collision(def._target, from_node_path, entries);
201 
202  // Now set our height accordingly.
203  PN_stdfloat adjust = max_height + _offset;
204  #endif
205  if (!IS_THRESHOLD_ZERO(adjust, 0.001)) {
206  if (collide_cat.is_debug()) {
207  collide_cat.debug()
208  << "Adjusting height by " << adjust << "\n";
209  }
210 
211  if (adjust < 0.0f && _max_velocity != 0.0f) {
212  PN_stdfloat max_adjust =
213  _max_velocity * ClockObject::get_global_clock()->get_dt();
214  adjust = max(adjust, -max_adjust);
215  }
216 
217  CPT(TransformState) trans = def._target.get_transform();
218  LVecBase3 pos = trans->get_pos();
219  pos[2] += adjust;
220  def._target.set_transform(trans->set_pos(pos));
221  def.updated_transform();
222 
223  apply_linear_force(def, LVector3(0.0f, 0.0f, adjust));
224  } else {
225  if (collide_cat.is_spam()) {
226  collide_cat.spam()
227  << "Leaving height unchanged.\n";
228  }
229  }
230  }
231  }
232  }
233 
234  return okflag;
235 }
236 
237 ////////////////////////////////////////////////////////////////////
238 // Function: CollisionHandlerFloor::apply_linear_force
239 // Access: Protected, Virtual
240 // Description:
241 ////////////////////////////////////////////////////////////////////
242 void CollisionHandlerFloor::
243 apply_linear_force(ColliderDef &def, const LVector3 &force) {
244 }
static ClockObject * get_global_clock()
Returns a pointer to the global ClockObject.
Definition: clockObject.I:271
This is the base class for all three-component vectors and points.
Definition: lvecBase3.h:105
This is a three-component vector distance (as opposed to a three-component point, which represents a ...
Definition: lvector3.h:100
This is a three-component point in space (as opposed to a three-component vector, which represents a ...
Definition: lpoint3.h:99
double get_dt(Thread *current_thread=Thread::get_current_thread()) const
Returns the elapsed time for the previous frame: the number of seconds elapsed between the last two c...
Definition: clockObject.I:141
LPoint3 get_surface_point(const NodePath &space) const
Returns the point, on the surface of the &quot;into&quot; object, at which a collision is detected.
Defines a single collision event.
bool has_surface_point() const
Returns true if the surface point has been specified, false otherwise.
virtual void add_entry(CollisionEntry *entry)
Called between a begin_group() .
NodePath get_from_node_path() const
Returns the NodePath that represents the CollisionNode that contains the CollisionSolid that triggere...
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:85
NodePath is the fundamental system for disambiguating instances, and also provides a higher-level int...
Definition: nodePath.h:165