Panda3D

physxController.cxx

00001 // Filename: physxController.cxx
00002 // Created by:  enn0x (24Sep09)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) Carnegie Mellon University.  All rights reserved.
00008 //
00009 // All use of this software is subject to the terms of the revised BSD
00010 // license.  You should have received a copy of this license along
00011 // with this source code in a file named "LICENSE."
00012 //
00013 ////////////////////////////////////////////////////////////////////
00014 
00015 #include "event.h"
00016 #include "eventQueue.h"
00017 #include "eventParameter.h"
00018 
00019 #include "physxController.h"
00020 #include "physxManager.h"
00021 #include "physxActor.h"
00022 #include "physxBoxController.h"
00023 #include "physxCapsuleController.h"
00024 
00025 TypeHandle PhysxController::_type_handle;
00026 
00027 ////////////////////////////////////////////////////////////////////
00028 //     Function: PhysxController::release
00029 //       Access: Published
00030 //  Description: 
00031 ////////////////////////////////////////////////////////////////////
00032 void PhysxController::
00033 release() {
00034 
00035   nassertv(_error_type == ET_ok);
00036 
00037   NxControllerManager *cm = get_actor()->get_scene()->cm();
00038   unlink();
00039   cm->releaseController(*ptr());
00040 }
00041 
00042 ////////////////////////////////////////////////////////////////////
00043 //     Function: PhysxController::factory
00044 //       Access: Public
00045 //  Description: 
00046 ////////////////////////////////////////////////////////////////////
00047 PhysxController *PhysxController::
00048 factory(NxControllerType controllerType) {
00049 
00050   switch (controllerType) {
00051 
00052   case NX_CONTROLLER_BOX:
00053     return new PhysxBoxController();
00054 
00055   case NX_CONTROLLER_CAPSULE:
00056     return new PhysxCapsuleController();
00057 
00058   }
00059 
00060   physx_cat.error() << "Unknown controller type.\n";
00061   return NULL;
00062 }
00063 
00064 
00065 ////////////////////////////////////////////////////////////////////
00066 //     Function: PhysxController::get_actor
00067 //       Access: Published
00068 //  Description: Retrieves the actor which this controller is
00069 //               associated with.
00070 ////////////////////////////////////////////////////////////////////
00071 PhysxActor *PhysxController::
00072 get_actor() const {
00073 
00074   nassertr(_error_type == ET_ok, NULL);
00075   return (PhysxActor *)(ptr()->getActor()->userData);
00076 }
00077 
00078 ////////////////////////////////////////////////////////////////////
00079 //     Function: PhysxController::set_pos
00080 //       Access: Published
00081 //  Description: Sets the position of the controller is global
00082 //               space. This can be used for initial placement or
00083 //               for teleporting the character.
00084 ////////////////////////////////////////////////////////////////////
00085 void PhysxController::
00086 set_pos(const LPoint3f &pos) {
00087 
00088   nassertv(_error_type == ET_ok);
00089   ptr()->setPosition(PhysxManager::point3_to_nxExtVec3(pos));
00090 }
00091 
00092 ////////////////////////////////////////////////////////////////////
00093 //     Function: PhysxController::get_pos
00094 //       Access: Published
00095 //  Description: Retruns the position of the controller is global
00096 //               space.
00097 ////////////////////////////////////////////////////////////////////
00098 LPoint3f PhysxController::
00099 get_pos() const {
00100 
00101   nassertr(_error_type == ET_ok, LPoint3f::zero());
00102   return PhysxManager::nxExtVec3_to_point3(ptr()->getPosition());
00103 }
00104 
00105 ////////////////////////////////////////////////////////////////////
00106 //     Function: PhysxController::set_sharpness
00107 //       Access: Published
00108 //  Description: Sharpness is used to smooth motion with a feedback
00109 //               filter, having a value between 0 (so smooth it
00110 //               doesn't move) and 1 (no smoothing = unfiltered
00111 //               motion). Sharpness can ease the motion curve when
00112 //               the auto-step feature is used with boxes.
00113 //               Default value is 1.0.
00114 ////////////////////////////////////////////////////////////////////
00115 void PhysxController::
00116 set_sharpness(float sharpness) {
00117 
00118   nassertv(_error_type == ET_ok);
00119   nassertv(sharpness > 0.0f);
00120   nassertv(sharpness <= 1.0f);
00121 
00122   _sharpness = sharpness;
00123 }
00124 
00125 ////////////////////////////////////////////////////////////////////
00126 //     Function: PhysxController::get_sharpness
00127 //       Access: Published
00128 //  Description: Returns the sharpness used to ease the motion curve
00129 //               when the auto-step feature is used.
00130 //               Default value is 1.0.
00131 ////////////////////////////////////////////////////////////////////
00132 float PhysxController::
00133 get_sharpness() const {
00134 
00135   nassertr(_error_type == ET_ok, 0.0f);
00136   return _sharpness;
00137 }
00138 
00139 ////////////////////////////////////////////////////////////////////
00140 //     Function: PhysxController::set_collision
00141 //       Access: Published
00142 //  Description: Enable/Disable collisions for this controller and
00143 //               actor.
00144 ////////////////////////////////////////////////////////////////////
00145 void PhysxController::
00146 set_collision(bool enable) {
00147 
00148   nassertv(_error_type == ET_ok);
00149   ptr()->setCollision(enable);
00150 }
00151 
00152 ////////////////////////////////////////////////////////////////////
00153 //     Function: PhysxController::set_min_distance
00154 //       Access: Published
00155 //  Description: Sets the the minimum travelled distance to consider
00156 //               when moving the controller. If travelled distance
00157 //               is smaller, the character doesn't move. This is
00158 //               used to stop the recursive motion algorithm when
00159 //               remaining distance to travel is small. 
00160 //               The default value is 0.0001.
00161 ////////////////////////////////////////////////////////////////////
00162 void PhysxController::
00163 set_min_distance(float min_dist) {
00164 
00165   nassertv(_error_type == ET_ok);
00166   nassertv(min_dist > 0.0f);
00167 
00168   _min_dist = min_dist;
00169 }
00170 
00171 ////////////////////////////////////////////////////////////////////
00172 //     Function: PhysxController::set_step_offset
00173 //       Access: Published
00174 //  Description: Sets the step height/offset for the controller.
00175 ////////////////////////////////////////////////////////////////////
00176 void PhysxController::
00177 set_step_offset(float offset) {
00178 
00179   nassertv(_error_type == ET_ok);
00180   nassertv(offset > 0.0f);
00181 
00182   ptr()->setStepOffset(offset);
00183 }
00184 
00185 ////////////////////////////////////////////////////////////////////
00186 //     Function: PhysxController::set_global_speed
00187 //       Access: Published
00188 //  Description: Sets the linear speed of the controller in global
00189 //               space.
00190 ////////////////////////////////////////////////////////////////////
00191 void PhysxController::
00192 set_global_speed(const LVector3f &speed) {
00193 
00194   nassertv(_error_type == ET_ok);
00195   nassertv_always(!speed.is_nan());
00196 
00197   _speed = NxVec3(speed.get_x(), speed.get_y(), speed.get_z());
00198 }
00199 
00200 ////////////////////////////////////////////////////////////////////
00201 //     Function: PhysxController::set_local_speed
00202 //       Access: Published
00203 //  Description: Sets the linear speed of the controller in local
00204 //               coordinates.
00205 ////////////////////////////////////////////////////////////////////
00206 void PhysxController::
00207 set_local_speed(const LVector3f &speed) {
00208 
00209   nassertv(_error_type == ET_ok);
00210   nassertv_always(!speed.is_nan());
00211 
00212   NodePath np = get_actor()->get_node_path();
00213   nassertv(!np.is_empty());
00214 
00215   NxQuat q = ptr()->getActor()->getGlobalOrientationQuat();
00216   NxVec3 s = NxVec3(speed.get_x(), speed.get_y(), speed.get_z());
00217   _speed = (q * _up_quat_inv).rot(s);
00218 }
00219 
00220 ////////////////////////////////////////////////////////////////////
00221 //     Function: PhysxController::set_omega
00222 //       Access: Published
00223 //  Description: Sets the angular velocity (degrees per second)
00224 //               of the controller. The angular velocity is used to
00225 //               compute the new heading when updating the
00226 //               controller.
00227 ////////////////////////////////////////////////////////////////////
00228 void PhysxController::
00229 set_omega(float omega) {
00230 
00231   nassertv(_error_type == ET_ok);
00232   _omega = omega;
00233 }
00234 
00235 ////////////////////////////////////////////////////////////////////
00236 //     Function: PhysxController::set_h
00237 //       Access: Published
00238 //  Description: Sets the heading of the controller is global
00239 //               space. Note: only heading is supported. Pitch and
00240 //               roll are constrained by PhysX in order to alyways
00241 //               keep the character upright.
00242 ////////////////////////////////////////////////////////////////////
00243 void PhysxController::
00244 set_h(float heading) {
00245 
00246   nassertv(_error_type == ET_ok);
00247 
00248   _heading = heading;
00249   NxQuat q(_heading, _up_vector);
00250   ptr()->getActor()->moveGlobalOrientationQuat(_up_quat * q);
00251 }
00252 
00253 ////////////////////////////////////////////////////////////////////
00254 //     Function: PhysxController::get_h
00255 //       Access: Published
00256 //  Description: Returns the heading of the controller in global
00257 //               space.
00258 ////////////////////////////////////////////////////////////////////
00259 float PhysxController::
00260 get_h() const {
00261 
00262   nassertr(_error_type == ET_ok, 0.0f);
00263   return _heading;
00264 }
00265 
00266 ////////////////////////////////////////////////////////////////////
00267 //     Function: PhysxController::report_scene_changed
00268 //       Access: Published
00269 //  Description: The character controller uses caching in order to
00270 //               speed up collision testing, this caching can not
00271 //               detect when static objects have changed in the
00272 //               scene. You need to call this method when such
00273 //               changes have been made.
00274 ////////////////////////////////////////////////////////////////////
00275 void PhysxController::
00276 report_scene_changed() {
00277 
00278   nassertv(_error_type == ET_ok);
00279   ptr()->reportSceneChanged();
00280 }
00281 
00282 ////////////////////////////////////////////////////////////////////
00283 //     Function: PhysxController::update_controller
00284 //       Access: Public
00285 //  Description: 
00286 ////////////////////////////////////////////////////////////////////
00287 void PhysxController::
00288 update_controller(float dt) {
00289 
00290   nassertv(_error_type == ET_ok);
00291 
00292   // Speed
00293   NxU32 mask = 0xFFFFFFFF;
00294   NxU32 collision_flags;
00295   NxVec3 gravity;
00296 
00297   ptr()->getActor()->getScene().getGravity(gravity);
00298 
00299   NxVec3 d = (_speed + gravity) * dt;
00300 
00301   NxReal heightDelta = get_jump_height(dt, gravity);
00302   if (heightDelta != 0.0f) {
00303     ((_up_axis == NX_Z) ? d.z : d.y) += heightDelta;
00304   }
00305 
00306   ptr()->move(d, mask, _min_dist, collision_flags, _sharpness);
00307 
00308   if (collision_flags & NXCC_COLLISION_DOWN) {
00309     stop_jump();
00310   }
00311 
00312   // Omega
00313   if (_omega != 0.0f) {
00314     NxReal delta = _omega * dt;
00315     _heading += delta;
00316     NxQuat q(_heading, _up_vector);
00317     ptr()->getActor()->moveGlobalOrientationQuat(_up_quat * q);
00318   }
00319 
00320   // Reset speed and omega
00321   _speed.zero();
00322   _omega = 0.0f;
00323 }
00324 
00325 ////////////////////////////////////////////////////////////////////
00326 //     Function: PhysxController::get_jump_height
00327 //       Access: Private
00328 //  Description: 
00329 ////////////////////////////////////////////////////////////////////
00330 NxReal PhysxController::
00331 get_jump_height(float dt, NxVec3 &gravity) {
00332 
00333   if (_jumping == false) {
00334     return 0.0f;
00335   }
00336 
00337   _jump_time += dt;
00338 
00339   float G = (_up_axis == NX_Z) ? gravity.z : gravity.y;
00340   float h = 2.0f * G * _jump_time * _jump_time + _jump_v0 * _jump_time;
00341   return (h - G) * dt;
00342 }
00343 
00344 ////////////////////////////////////////////////////////////////////
00345 //     Function: PhysxController::start_jump
00346 //       Access: Published
00347 //  Description: Enters the jump mode. The parameter is the intial
00348 //               upward velocity of the character.
00349 ////////////////////////////////////////////////////////////////////
00350 void PhysxController::
00351 start_jump(float v0) {
00352 
00353   nassertv(_error_type == ET_ok);
00354 
00355   if (_jumping == true) {
00356      return;
00357   }
00358 
00359   _jumping = true;
00360   _jump_time = 0.0f;
00361   _jump_v0 = v0;
00362 }
00363 
00364 ////////////////////////////////////////////////////////////////////
00365 //     Function: PhysxController::stop_jump
00366 //       Access: Published
00367 //  Description: Leaves the jump mode. This method is automatically
00368 //               called if a ground collision is detected. Usually
00369 //               users need not call this method.
00370 ////////////////////////////////////////////////////////////////////
00371 void PhysxController::
00372 stop_jump() {
00373 
00374   nassertv(_error_type == ET_ok);
00375 
00376   if (_jumping == false) {
00377     return;
00378   }
00379 
00380   _jumping = false;
00381 
00382   //NxVec3 v = ptr()->getActor()->getLinearVelocity();
00383   //double velocity = (_up_axis == NX_Z) ? v.z : v.y;
00384 
00385   Event *event = new Event("physx-controller-down");
00386   event->add_parameter(EventParameter(this));
00387   //event->add_parameter(EventParameter(velocity));
00388   EventQueue::get_global_event_queue()->queue_event(event);
00389 }
00390 
 All Classes Functions Variables Enumerations