Panda3D
|
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