open_toontown_panda3d/panda/src/physx/physxController.cxx

393 lines
12 KiB
C++

// Filename: physxController.cxx
// Created by: enn0x (24Sep09)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) Carnegie Mellon University. All rights reserved.
//
// All use of this software is subject to the terms of the revised BSD
// license. You should have received a copy of this license along
// with this source code in a file named "LICENSE."
//
////////////////////////////////////////////////////////////////////
#include "event.h"
#include "eventQueue.h"
#include "eventParameter.h"
#include "physxController.h"
#include "physxManager.h"
#include "physxActor.h"
#include "physxBoxController.h"
#include "physxCapsuleController.h"
TypeHandle PhysxController::_type_handle;
////////////////////////////////////////////////////////////////////
// Function: PhysxController::release
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
void PhysxController::
release() {
nassertv(_error_type == ET_ok);
NxControllerManager *cm = get_actor()->get_scene()->cm();
unlink();
cm->releaseController(*ptr());
}
////////////////////////////////////////////////////////////////////
// Function: PhysxController::factory
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
PhysxController *PhysxController::
factory(NxControllerType controllerType) {
switch (controllerType) {
case NX_CONTROLLER_BOX:
return new PhysxBoxController();
case NX_CONTROLLER_CAPSULE:
return new PhysxCapsuleController();
default:
break;
}
physx_cat.error() << "Unknown controller type.\n";
return NULL;
}
////////////////////////////////////////////////////////////////////
// Function: PhysxController::get_actor
// Access: Published
// Description: Retrieves the actor which this controller is
// associated with.
////////////////////////////////////////////////////////////////////
PhysxActor *PhysxController::
get_actor() const {
nassertr(_error_type == ET_ok, NULL);
return (PhysxActor *)(ptr()->getActor()->userData);
}
////////////////////////////////////////////////////////////////////
// Function: PhysxController::set_pos
// Access: Published
// Description: Sets the position of the controller is global
// space. This can be used for initial placement or
// for teleporting the character.
////////////////////////////////////////////////////////////////////
void PhysxController::
set_pos(const LPoint3f &pos) {
nassertv(_error_type == ET_ok);
ptr()->setPosition(PhysxManager::point3_to_nxExtVec3(pos));
}
////////////////////////////////////////////////////////////////////
// Function: PhysxController::get_pos
// Access: Published
// Description: Retruns the position of the controller is global
// space.
////////////////////////////////////////////////////////////////////
LPoint3f PhysxController::
get_pos() const {
nassertr(_error_type == ET_ok, LPoint3f::zero());
return PhysxManager::nxExtVec3_to_point3(ptr()->getPosition());
}
////////////////////////////////////////////////////////////////////
// Function: PhysxController::set_sharpness
// Access: Published
// Description: Sharpness is used to smooth motion with a feedback
// filter, having a value between 0 (so smooth it
// doesn't move) and 1 (no smoothing = unfiltered
// motion). Sharpness can ease the motion curve when
// the auto-step feature is used with boxes.
// Default value is 1.0.
////////////////////////////////////////////////////////////////////
void PhysxController::
set_sharpness(float sharpness) {
nassertv(_error_type == ET_ok);
nassertv(sharpness > 0.0f);
nassertv(sharpness <= 1.0f);
_sharpness = sharpness;
}
////////////////////////////////////////////////////////////////////
// Function: PhysxController::get_sharpness
// Access: Published
// Description: Returns the sharpness used to ease the motion curve
// when the auto-step feature is used.
// Default value is 1.0.
////////////////////////////////////////////////////////////////////
float PhysxController::
get_sharpness() const {
nassertr(_error_type == ET_ok, 0.0f);
return _sharpness;
}
////////////////////////////////////////////////////////////////////
// Function: PhysxController::set_collision
// Access: Published
// Description: Enable/Disable collisions for this controller and
// actor.
////////////////////////////////////////////////////////////////////
void PhysxController::
set_collision(bool enable) {
nassertv(_error_type == ET_ok);
ptr()->setCollision(enable);
}
////////////////////////////////////////////////////////////////////
// Function: PhysxController::set_min_distance
// Access: Published
// Description: Sets the the minimum travelled distance to consider
// when moving the controller. If travelled distance
// is smaller, the character doesn't move. This is
// used to stop the recursive motion algorithm when
// remaining distance to travel is small.
// The default value is 0.0001.
////////////////////////////////////////////////////////////////////
void PhysxController::
set_min_distance(float min_dist) {
nassertv(_error_type == ET_ok);
nassertv(min_dist > 0.0f);
_min_dist = min_dist;
}
////////////////////////////////////////////////////////////////////
// Function: PhysxController::set_step_offset
// Access: Published
// Description: Sets the step height/offset for the controller.
////////////////////////////////////////////////////////////////////
void PhysxController::
set_step_offset(float offset) {
nassertv(_error_type == ET_ok);
nassertv(offset > 0.0f);
ptr()->setStepOffset(offset);
}
////////////////////////////////////////////////////////////////////
// Function: PhysxController::set_global_speed
// Access: Published
// Description: Sets the linear speed of the controller in global
// space.
////////////////////////////////////////////////////////////////////
void PhysxController::
set_global_speed(const LVector3f &speed) {
nassertv(_error_type == ET_ok);
nassertv_always(!speed.is_nan());
_speed = NxVec3(speed.get_x(), speed.get_y(), speed.get_z());
}
////////////////////////////////////////////////////////////////////
// Function: PhysxController::set_local_speed
// Access: Published
// Description: Sets the linear speed of the controller in local
// coordinates.
////////////////////////////////////////////////////////////////////
void PhysxController::
set_local_speed(const LVector3f &speed) {
nassertv(_error_type == ET_ok);
nassertv_always(!speed.is_nan());
NodePath np = get_actor()->get_node_path();
nassertv(!np.is_empty());
NxQuat q = ptr()->getActor()->getGlobalOrientationQuat();
NxVec3 s = NxVec3(speed.get_x(), speed.get_y(), speed.get_z());
_speed = (q * _up_quat_inv).rot(s);
}
////////////////////////////////////////////////////////////////////
// Function: PhysxController::set_omega
// Access: Published
// Description: Sets the angular velocity (degrees per second)
// of the controller. The angular velocity is used to
// compute the new heading when updating the
// controller.
////////////////////////////////////////////////////////////////////
void PhysxController::
set_omega(float omega) {
nassertv(_error_type == ET_ok);
_omega = omega;
}
////////////////////////////////////////////////////////////////////
// Function: PhysxController::set_h
// Access: Published
// Description: Sets the heading of the controller is global
// space. Note: only heading is supported. Pitch and
// roll are constrained by PhysX in order to alyways
// keep the character upright.
////////////////////////////////////////////////////////////////////
void PhysxController::
set_h(float heading) {
nassertv(_error_type == ET_ok);
_heading = heading;
NxQuat q(_heading, _up_vector);
ptr()->getActor()->moveGlobalOrientationQuat(_up_quat * q);
}
////////////////////////////////////////////////////////////////////
// Function: PhysxController::get_h
// Access: Published
// Description: Returns the heading of the controller in global
// space.
////////////////////////////////////////////////////////////////////
float PhysxController::
get_h() const {
nassertr(_error_type == ET_ok, 0.0f);
return _heading;
}
////////////////////////////////////////////////////////////////////
// Function: PhysxController::report_scene_changed
// Access: Published
// Description: The character controller uses caching in order to
// speed up collision testing, this caching can not
// detect when static objects have changed in the
// scene. You need to call this method when such
// changes have been made.
////////////////////////////////////////////////////////////////////
void PhysxController::
report_scene_changed() {
nassertv(_error_type == ET_ok);
ptr()->reportSceneChanged();
}
////////////////////////////////////////////////////////////////////
// Function: PhysxController::update_controller
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
void PhysxController::
update_controller(float dt) {
nassertv(_error_type == ET_ok);
// Speed
NxU32 mask = 0xFFFFFFFF;
NxU32 collision_flags;
NxVec3 gravity;
ptr()->getActor()->getScene().getGravity(gravity);
NxVec3 d = (_speed + gravity) * dt;
NxReal heightDelta = get_jump_height(dt, gravity);
if (heightDelta != 0.0f) {
((_up_axis == NX_Z) ? d.z : d.y) += heightDelta;
}
ptr()->move(d, mask, _min_dist, collision_flags, _sharpness);
if (collision_flags & NXCC_COLLISION_DOWN) {
stop_jump();
}
// Omega
if (_omega != 0.0f) {
NxReal delta = _omega * dt;
_heading += delta;
NxQuat q(_heading, _up_vector);
ptr()->getActor()->moveGlobalOrientationQuat(_up_quat * q);
}
// Reset speed and omega
_speed.zero();
_omega = 0.0f;
}
////////////////////////////////////////////////////////////////////
// Function: PhysxController::get_jump_height
// Access: Private
// Description:
////////////////////////////////////////////////////////////////////
NxReal PhysxController::
get_jump_height(float dt, NxVec3 &gravity) {
if (_jumping == false) {
return 0.0f;
}
_jump_time += dt;
float G = (_up_axis == NX_Z) ? gravity.z : gravity.y;
float h = 2.0f * G * _jump_time * _jump_time + _jump_v0 * _jump_time;
return (h - G) * dt;
}
////////////////////////////////////////////////////////////////////
// Function: PhysxController::start_jump
// Access: Published
// Description: Enters the jump mode. The parameter is the intial
// upward velocity of the character.
////////////////////////////////////////////////////////////////////
void PhysxController::
start_jump(float v0) {
nassertv(_error_type == ET_ok);
if (_jumping == true) {
return;
}
_jumping = true;
_jump_time = 0.0f;
_jump_v0 = v0;
}
////////////////////////////////////////////////////////////////////
// Function: PhysxController::stop_jump
// Access: Published
// Description: Leaves the jump mode. This method is automatically
// called if a ground collision is detected. Usually
// users need not call this method.
////////////////////////////////////////////////////////////////////
void PhysxController::
stop_jump() {
nassertv(_error_type == ET_ok);
if (_jumping == false) {
return;
}
_jumping = false;
//NxVec3 v = ptr()->getActor()->getLinearVelocity();
//double velocity = (_up_axis == NX_Z) ? v.z : v.y;
Event *event = new Event("physx-controller-down");
event->add_parameter(EventParameter(this));
//event->add_parameter(EventParameter(velocity));
EventQueue::get_global_event_queue()->queue_event(event);
}