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