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