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