Panda3D
physxController.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 physxController.cxx
10  * @author enn0x
11  * @date 2009-09-24
12  */
13 
14 #include "event.h"
15 #include "eventQueue.h"
16 #include "eventParameter.h"
17 
18 #include "physxController.h"
19 #include "physxManager.h"
20 #include "physxActor.h"
21 #include "physxBoxController.h"
22 #include "physxCapsuleController.h"
23 
24 TypeHandle PhysxController::_type_handle;
25 
26 /**
27  *
28  */
29 void PhysxController::
30 release() {
31 
32  nassertv(_error_type == ET_ok);
33 
34  NxControllerManager *cm = get_actor()->get_scene()->cm();
35  unlink();
36  cm->releaseController(*ptr());
37 }
38 
39 /**
40  *
41  */
42 PhysxController *PhysxController::
43 factory(NxControllerType controllerType) {
44 
45  switch (controllerType) {
46 
47  case NX_CONTROLLER_BOX:
48  return new PhysxBoxController();
49 
50  case NX_CONTROLLER_CAPSULE:
51  return new PhysxCapsuleController();
52 
53  default:
54  break;
55  }
56 
57  physx_cat.error() << "Unknown controller type.\n";
58  return nullptr;
59 }
60 
61 
62 /**
63  * Retrieves the actor which this controller is associated with.
64  */
66 get_actor() const {
67 
68  nassertr(_error_type == ET_ok, nullptr);
69  return (PhysxActor *)(ptr()->getActor()->userData);
70 }
71 
72 /**
73  * Sets the position of the controller is global space. This can be used for
74  * initial placement or for teleporting the character.
75  */
77 set_pos(const LPoint3f &pos) {
78 
79  nassertv(_error_type == ET_ok);
80  ptr()->setPosition(PhysxManager::point3_to_nxExtVec3(pos));
81 }
82 
83 /**
84  * Retruns the position of the controller is global space.
85  */
87 get_pos() const {
88 
89  nassertr(_error_type == ET_ok, LPoint3f::zero());
90  return PhysxManager::nxExtVec3_to_point3(ptr()->getPosition());
91 }
92 
93 /**
94  * Sharpness is used to smooth motion with a feedback filter, having a value
95  * between 0 (so smooth it doesn't move) and 1 (no smoothing = unfiltered
96  * motion). Sharpness can ease the motion curve when the auto-step feature is
97  * used with boxes. Default value is 1.0.
98  */
100 set_sharpness(float sharpness) {
101 
102  nassertv(_error_type == ET_ok);
103  nassertv(sharpness > 0.0f);
104  nassertv(sharpness <= 1.0f);
105 
106  _sharpness = sharpness;
107 }
108 
109 /**
110  * Returns the sharpness used to ease the motion curve when the auto-step
111  * feature is used. Default value is 1.0.
112  */
114 get_sharpness() const {
115 
116  nassertr(_error_type == ET_ok, 0.0f);
117  return _sharpness;
118 }
119 
120 /**
121  * Enable/Disable collisions for this controller and actor.
122  */
124 set_collision(bool enable) {
125 
126  nassertv(_error_type == ET_ok);
127  ptr()->setCollision(enable);
128 }
129 
130 /**
131  * Sets the the minimum travelled distance to consider when moving the
132  * controller. If travelled distance is smaller, the character doesn't move.
133  * This is used to stop the recursive motion algorithm when remaining distance
134  * to travel is small. The default value is 0.0001.
135  */
137 set_min_distance(float min_dist) {
138 
139  nassertv(_error_type == ET_ok);
140  nassertv(min_dist > 0.0f);
141 
142  _min_dist = min_dist;
143 }
144 
145 /**
146  * Sets the step height/offset for the controller.
147  */
149 set_step_offset(float offset) {
150 
151  nassertv(_error_type == ET_ok);
152  nassertv(offset > 0.0f);
153 
154  ptr()->setStepOffset(offset);
155 }
156 
157 /**
158  * Sets the linear speed of the controller in global space.
159  */
161 set_global_speed(const LVector3f &speed) {
162 
163  nassertv(_error_type == ET_ok);
164  nassertv_always(!speed.is_nan());
165 
166  _speed = NxVec3(speed.get_x(), speed.get_y(), speed.get_z());
167 }
168 
169 /**
170  * Sets the linear speed of the controller in local coordinates.
171  */
173 set_local_speed(const LVector3f &speed) {
174 
175  nassertv(_error_type == ET_ok);
176  nassertv_always(!speed.is_nan());
177 
178  NodePath np = get_actor()->get_node_path();
179  nassertv(!np.is_empty());
180 
181  NxQuat q = ptr()->getActor()->getGlobalOrientationQuat();
182  NxVec3 s = NxVec3(speed.get_x(), speed.get_y(), speed.get_z());
183  _speed = (q * _up_quat_inv).rot(s);
184 }
185 
186 /**
187  * Sets the angular velocity (degrees per second) of the controller. The
188  * angular velocity is used to compute the new heading when updating the
189  * controller.
190  */
192 set_omega(float omega) {
193 
194  nassertv(_error_type == ET_ok);
195  _omega = omega;
196 }
197 
198 /**
199  * Sets the heading of the controller is global space. Note: only heading is
200  * supported. Pitch and roll are constrained by PhysX in order to alyways
201  * keep the character upright.
202  */
204 set_h(float heading) {
205 
206  nassertv(_error_type == ET_ok);
207 
208  _heading = heading;
209  NxQuat q(_heading, _up_vector);
210  ptr()->getActor()->moveGlobalOrientationQuat(_up_quat * q);
211 }
212 
213 /**
214  * Returns the heading of the controller in global space.
215  */
217 get_h() const {
218 
219  nassertr(_error_type == ET_ok, 0.0f);
220  return _heading;
221 }
222 
223 /**
224  * The character controller uses caching in order to speed up collision
225  * testing, this caching can not detect when static objects have changed in
226  * the scene. You need to call this method when such changes have been made.
227  */
230 
231  nassertv(_error_type == ET_ok);
232  ptr()->reportSceneChanged();
233 }
234 
235 /**
236  *
237  */
238 void PhysxController::
239 update_controller(float dt) {
240 
241  nassertv(_error_type == ET_ok);
242 
243  // Speed
244  NxU32 mask = 0xFFFFFFFF;
245  NxU32 collision_flags;
246  NxVec3 gravity;
247 
248  ptr()->getActor()->getScene().getGravity(gravity);
249 
250  NxVec3 d = (_speed + gravity) * dt;
251 
252  NxReal heightDelta = get_jump_height(dt, gravity);
253  if (heightDelta != 0.0f) {
254  ((_up_axis == NX_Z) ? d.z : d.y) += heightDelta;
255  }
256 
257  ptr()->move(d, mask, _min_dist, collision_flags, _sharpness);
258 
259  if (collision_flags & NXCC_COLLISION_DOWN) {
260  stop_jump();
261  }
262 
263  // Omega
264  if (_omega != 0.0f) {
265  NxReal delta = _omega * dt;
266  _heading += delta;
267  NxQuat q(_heading, _up_vector);
268  ptr()->getActor()->moveGlobalOrientationQuat(_up_quat * q);
269  }
270 
271  // Reset speed and omega
272  _speed.zero();
273  _omega = 0.0f;
274 }
275 
276 /**
277  *
278  */
279 NxReal PhysxController::
280 get_jump_height(float dt, NxVec3 &gravity) {
281 
282  if (_jumping == false) {
283  return 0.0f;
284  }
285 
286  _jump_time += dt;
287 
288  float G = (_up_axis == NX_Z) ? gravity.z : gravity.y;
289  float h = 2.0f * G * _jump_time * _jump_time + _jump_v0 * _jump_time;
290  return (h - G) * dt;
291 }
292 
293 /**
294  * Enters the jump mode. The parameter is the intial upward velocity of the
295  * character.
296  */
298 start_jump(float v0) {
299 
300  nassertv(_error_type == ET_ok);
301 
302  if (_jumping == true) {
303  return;
304  }
305 
306  _jumping = true;
307  _jump_time = 0.0f;
308  _jump_v0 = v0;
309 }
310 
311 /**
312  * Leaves the jump mode. This method is automatically called if a ground
313  * collision is detected. Usually users need not call this method.
314  */
316 stop_jump() {
317 
318  nassertv(_error_type == ET_ok);
319 
320  if (_jumping == false) {
321  return;
322  }
323 
324  _jumping = false;
325 
326  // NxVec3 v = ptr()->getActor()->getLinearVelocity(); double velocity =
327  // (_up_axis == NX_Z) ? v.z : v.y;
328 
329  Event *event = new Event("physx-controller-down");
330  event->add_parameter(EventParameter(this));
331  // event->add_parameter(EventParameter(velocity));
332  EventQueue::get_global_event_queue()->queue_event(event);
333 }
An optional parameter associated with an event.
static EventQueue * get_global_event_queue()
Returns a pointer to the one global EventQueue object.
Definition: eventQueue.I:19
A named event, possibly with parameters.
Definition: event.h:33
NodePath is the fundamental system for disambiguating instances, and also provides a higher-level int...
Definition: nodePath.h:159
bool is_empty() const
Returns true if the NodePath contains no nodes.
Definition: nodePath.I:188
Actors are the main simulation objects.
Definition: physxActor.h:44
NodePath get_node_path() const
Retrieves a previously attached NodePath.
Definition: physxActor.cxx:348
PhysxScene * get_scene() const
Retrieves the scene which this actor belongs to.
Definition: physxActor.cxx:359
Box character controller.
A capsule character controller.
Abstract base class for character controllers.
void set_sharpness(float sharpness)
Sharpness is used to smooth motion with a feedback filter, having a value between 0 (so smooth it doe...
float get_h() const
Returns the heading of the controller in global space.
PhysxActor * get_actor() const
Retrieves the actor which this controller is associated with.
float get_sharpness() const
Returns the sharpness used to ease the motion curve when the auto-step feature is used.
void set_min_distance(float min_dist)
Sets the the minimum travelled distance to consider when moving the controller.
void stop_jump()
Leaves the jump mode.
void set_global_speed(const LVector3f &speed)
Sets the linear speed of the controller in global space.
void set_h(float heading)
Sets the heading of the controller is global space.
void set_step_offset(float offset)
Sets the step height/offset for the controller.
void start_jump(float v0)
Enters the jump mode.
void report_scene_changed()
The character controller uses caching in order to speed up collision testing, this caching can not de...
void set_omega(float omega)
Sets the angular velocity (degrees per second) of the controller.
LPoint3f get_pos() const
Retruns the position of the controller is global space.
void set_local_speed(const LVector3f &speed)
Sets the linear speed of the controller in local coordinates.
void set_collision(bool enable)
Enable/Disable collisions for this controller and actor.
void set_pos(const LPoint3f &pos)
Sets the position of the controller is global space.
static NxExtendedVec3 point3_to_nxExtVec3(const LPoint3f &p)
Converts from LPoint3f to NxExtendedVec3.
Definition: physxManager.I:81
static LPoint3f nxExtVec3_to_point3(const NxExtendedVec3 &p)
Converts from NxExtendedVec3 to LPoint3f.
Definition: physxManager.I:90
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.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.