Add Character control to btDiscreteDynamicsWorld (moved btCharacterControllerInterface/btKinematicCharacterController functionality from demo)

Remove ibmsdk from CcdPhysicsDemo and CollisionDemo
This commit is contained in:
erwin.coumans
2008-11-08 21:01:20 +00:00
parent ce0bdd891d
commit f9aa7f3b53
13 changed files with 289 additions and 353 deletions

View File

@@ -1,73 +0,0 @@
# ---------------------------------------------------------------
# PLEASE DO NOT MODIFY THIS SECTION
# This prolog section is automatically generated.
#
# (C) Copyright 2001,2006,
# International Business Machines Corporation,
#
# All Rights Reserved.
# ---------------------------------------------------------------
# --------------------------------------------------------------
# PROLOG END TAG zYx
########################################################################
# Source Code
########################################################################
VPATH = ../
########################################################################
# Target
########################################################################
ROOT = ../../..
HOSTINC = /usr/include
PROGRAM_ppu := CcdPhysicsDemo
#######################################################################
# Objs
######################################################################
OBJS = CcdPhysicsDemo.o main.o
########################################################################
# Libraries, Include paths, Defines
########################################################################
INCLUDE = -DUSE_LIBSPE2 \
-I$(CELL_SYSROOT)/usr/include \
-I../ \
-I$(ROOT)/src \
-I$(ROOT)/Demos/OpenGL \
-I$(HOSTINC)
SYS_LIBS := -lspe2 -lglut -lGLU -lGL -lm -lXext -lXmu -lX11
IMPORTS = $(ROOT)/lib/ibmsdk/bulletmultithreaded.a \
$(ROOT)/lib/ibmsdk/bulletopenglsupport.a \
$(ROOT)/lib/ibmsdk/bulletdynamics.a \
$(ROOT)/lib/ibmsdk/bulletconvexhull.a \
$(ROOT)/lib/ibmsdk/bulletcollision.a \
$(ROOT)/lib/ibmsdk/bulletmath.a
#######################################################################
# Install files/dirs
#######################################################################
INSTALL_DIR = $(ROOT)/ibmsdk
INSTALL_FILES = $(PROGRAM_ppu)
########################################################################
# make.footer
########################################################################
IBM_CELLSDK_VERSION := $(shell if [ -d /opt/cell ]; then echo "3.0"; fi)
ifeq ("$(IBM_CELLSDK_VERSION)","3.0")
CELL_TOP ?= /opt/cell/sdk
# CELL_SYSROOT = $(CELL_TOP);
include $(CELL_TOP)/buildutils/make.footer
else
CELL_TOP ?= /opt/ibm/cell-sdk/prototype
CELL_SYSROOT = $(CELL_TOP)/sysroot
include $(CELL_TOP)/make.footer
endif
$(PPMS):
cp textures/$@ .
cleanlocal:
rm -f $(PPMS)

View File

@@ -1,32 +0,0 @@
#ifndef CHARACTER_CONTROLLER_INTERFACE_H
#define CHARACTER_CONTROLLER_INTERFACE_H
#include "LinearMath/btVector3.h"
class btCollisionShape;
class btRigidBody;
class btCollisionWorld;
class CharacterControllerInterface
{
public:
CharacterControllerInterface () {};
virtual ~CharacterControllerInterface () {};
virtual void reset () = 0;
virtual void warp (const btVector3& origin) = 0;
virtual void preStep ( btCollisionWorld* collisionWorld) = 0;
virtual void playerStep (btCollisionWorld* collisionWorld, btScalar dt,
int forward,
int backward,
int left,
int right,
int jump) = 0;
virtual bool canJump () const = 0;
virtual void jump () = 0;
virtual bool onGround () const = 0;
};
#endif

View File

@@ -27,7 +27,7 @@ subject to the following restrictions:
#ifdef DYNAMIC_CHARACTER_CONTROLLER #ifdef DYNAMIC_CHARACTER_CONTROLLER
#include "DynamicCharacterController.h" #include "DynamicCharacterController.h"
#else #else
#include "KinematicCharacterController.h" #include "BulletDynamics/Character/btKinematicCharacterController.h"
#endif #endif
const int maxProxies = 32766; const int maxProxies = 32766;
@@ -39,15 +39,7 @@ static int gLeft = 0;
static int gRight = 0; static int gRight = 0;
static int gJump = 0; static int gJump = 0;
///playerStepCallback is the main function that is updating the character.
///Register this callback using: m_dynamicsWorld->setInternalTickCallback(playerStepCallback,m_character);
///This function will be called at the end of each internal simulation time step
void playerStepCallback(btDynamicsWorld* dynamicsWorld, btScalar timeStep)
{
CharacterControllerInterface* characterInterface= (CharacterControllerInterface*) dynamicsWorld->getWorldUserInfo();
characterInterface->preStep (dynamicsWorld);
characterInterface->playerStep (dynamicsWorld, timeStep, gForward, gBackward, gLeft, gRight, gJump);
}
CharacterDemo::CharacterDemo() CharacterDemo::CharacterDemo()
@@ -95,16 +87,14 @@ void CharacterDemo::initPhysics()
m_ghostObject->setCollisionFlags (btCollisionObject::CF_CHARACTER_OBJECT); m_ghostObject->setCollisionFlags (btCollisionObject::CF_CHARACTER_OBJECT);
btScalar stepHeight = btScalar(0.35); btScalar stepHeight = btScalar(0.35);
m_character = new KinematicCharacterController (m_ghostObject,capsule,stepHeight); m_character = new btKinematicCharacterController (m_ghostObject,capsule,stepHeight);
#endif #endif
m_dynamicsWorld->setInternalTickCallback(playerStepCallback,m_character);
///only collide with static for now (no interaction with dynamic objects) ///only collide with static for now (no interaction with dynamic objects)
m_dynamicsWorld->addCollisionObject(m_ghostObject,btBroadphaseProxy::CharacterFilter, btBroadphaseProxy::StaticFilter|btBroadphaseProxy::DefaultFilter); m_dynamicsWorld->addCollisionObject(m_ghostObject,btBroadphaseProxy::CharacterFilter, btBroadphaseProxy::StaticFilter|btBroadphaseProxy::DefaultFilter);
m_dynamicsWorld->addCharacter(m_character);
//////////////// ////////////////
@@ -231,6 +221,38 @@ void CharacterDemo::clientMoveAndDisplay()
if (m_idle) if (m_idle)
dt = 1.0/420.f; dt = 1.0/420.f;
///set walkDirection for our character
btTransform xform;
xform = m_ghostObject->getWorldTransform ();
btVector3 forwardDir = xform.getBasis()[2];
// printf("forwardDir=%f,%f,%f\n",forwardDir[0],forwardDir[1],forwardDir[2]);
btVector3 upDir = xform.getBasis()[1];
btVector3 strafeDir = xform.getBasis()[0];
forwardDir.normalize ();
upDir.normalize ();
strafeDir.normalize ();
btVector3 walkDirection = btVector3(0.0, 0.0, 0.0);
btScalar walkVelocity = btScalar(1.1) * 4.0; // 4 km/h -> 1.1 m/s
btScalar walkSpeed = walkVelocity * dt;
if (gLeft)
walkDirection += strafeDir;
if (gRight)
walkDirection -= strafeDir;
if (gForward)
walkDirection += forwardDir;
if (gBackward)
walkDirection -= forwardDir;
m_character->setWalkDirection(walkDirection*walkSpeed);
int numSimSteps = m_dynamicsWorld->stepSimulation(dt,maxSimSubSteps); int numSimSteps = m_dynamicsWorld->stepSimulation(dt,maxSimSubSteps);
//optional but useful: debug drawing //optional but useful: debug drawing

View File

@@ -16,14 +16,14 @@ subject to the following restrictions:
#define CHARACTER_DEMO_H #define CHARACTER_DEMO_H
///DYNAMIC_CHARACTER_CONTROLLER is not at the moment ///DYNAMIC_CHARACTER_CONTROLLER is not fully implemented yet at the moment
//#define DYNAMIC_CHARACTER_CONTROLLER 1 //#define DYNAMIC_CHARACTER_CONTROLLER 1
#include "BulletCollision/CollisionShapes/btConvexHullShape.h" #include "BulletCollision/CollisionShapes/btConvexHullShape.h"
class CharacterControllerInterface; class btCharacterControllerInterface;
class DynamicCharacterController; class btDynamicCharacterController;
class KinematicCharacterController; class btKinematicCharacterController;
class btCollisionShape; class btCollisionShape;
@@ -36,12 +36,13 @@ class CharacterDemo : public DemoApplication
public: public:
#ifdef DYNAMIC_CHARACTER_CONTROLLER #ifdef DYNAMIC_CHARACTER_CONTROLLER
CharacterControllerInterface* m_character; btCharacterControllerInterface* m_character;
#else #else
KinematicCharacterController* m_character; btKinematicCharacterController* m_character;
class btPairCachingGhostObject* m_ghostObject; class btPairCachingGhostObject* m_ghostObject;
#endif #endif
btAlignedObjectArray<btCollisionShape*> m_collisionShapes; btAlignedObjectArray<btCollisionShape*> m_collisionShapes;
class btBroadphaseInterface* m_overlappingPairCache; class btBroadphaseInterface* m_overlappingPairCache;

View File

@@ -3,14 +3,14 @@
#include "LinearMath/btVector3.h" #include "LinearMath/btVector3.h"
#include "CharacterControllerInterface.h" #include "BulletDynamics/Character/btCharacterControllerInterface.h"
class btCollisionShape; class btCollisionShape;
class btRigidBody; class btRigidBody;
class btCollisionWorld; class btCollisionWorld;
///DynamicCharacterController is obsolete/unsupported at the moment ///DynamicCharacterController is obsolete/unsupported at the moment
class DynamicCharacterController : public CharacterControllerInterface class DynamicCharacterController : public btCharacterControllerInterface
{ {
protected: protected:
btScalar m_halfHeight; btScalar m_halfHeight;

View File

@@ -1,85 +0,0 @@
#ifndef KINEMATIC_CHARACTER_CONTROLLER_H
#define KINEMATIC_CHARACTER_CONTROLLER_H
#include "LinearMath/btVector3.h"
#include "CharacterControllerInterface.h"
class btCollisionShape;
class btRigidBody;
class btCollisionWorld;
class btCollisionDispatcher;
class btPairCachingGhostObject;
///KinematicCharacterController is a collision object with support for sliding motion in a world.
///It uses the convex sweep test to test for upcoming collisions. This is combined with discrete collision detection to recover from penetrations.
///Interaction between KinematicCharacterController and dynamic rigid bodies needs to be explicity implemented by the user.
class KinematicCharacterController : public CharacterControllerInterface
{
protected:
btScalar m_halfHeight;
btPairCachingGhostObject* m_ghostObject;
btConvexShape* m_convexShape;//is also in m_ghostObject, but it needs to be convex, so we store it here to avoid upcast
btScalar m_fallSpeed;
btScalar m_jumpSpeed;
btScalar m_maxJumpHeight;
btScalar m_turnAngle;
btScalar m_walkVelocity;
btScalar m_stepHeight;
btVector3 m_upDirection;
btVector3 m_forwardDirection;
btVector3 m_strafeDirection;
btVector3 m_currentPosition;
btScalar m_currentStepOffset;
btVector3 m_targetPosition;
btManifoldArray m_manifoldArray;
bool m_touchingContact;
btVector3 m_touchingNormal;
bool m_useGhostObjectSweepTest;
bool recoverFromPenetration (btCollisionWorld* collisionWorld);
void stepUp (btCollisionWorld* collisionWorld);
void updateTargetPositionBasedOnCollision (const btVector3& hit_normal, btScalar tangentMag = btScalar(0.0), btScalar normalMag = btScalar(1.0));
void stepForwardAndStrafe (btCollisionWorld* collisionWorld, const btVector3& walkMove);
void stepDown (btCollisionWorld* collisionWorld, btScalar dt);
public:
KinematicCharacterController (btPairCachingGhostObject* ghostObject,btConvexShape* convexShape,btScalar stepHeight);
~KinematicCharacterController ();
btPairCachingGhostObject* getGhostObject();
void reset ();
void warp (const btVector3& origin);
void preStep ( btCollisionWorld* collisionWorld);
void playerStep (btCollisionWorld* collisionWorld, btScalar dt,
int forward,
int backward,
int left,
int right,
int jump);
void setFallSpeed (btScalar fallSpeed);
void setJumpSpeed (btScalar jumpSpeed);
void setMaxJumpHeight (btScalar maxJumpHeight);
bool canJump () const;
void jump ();
void setUseGhostSweepTest(bool useGhostObjectSweepTest)
{
m_useGhostObjectSweepTest = useGhostObjectSweepTest;
}
bool onGround () const;
};
#endif // KINEMATIC_CHARACTER_CONTROLLER_H

View File

@@ -1,68 +0,0 @@
# ---------------------------------------------------------------
# PLEASE DO NOT MODIFY THIS SECTION
# This prolog section is automatically generated.
#
# (C) Copyright 2001,2006,
# International Business Machines Corporation,
#
# All Rights Reserved.
# ---------------------------------------------------------------
# --------------------------------------------------------------
# PROLOG END TAG zYx
########################################################################
# Source Code
########################################################################
VPATH = ../
########################################################################
# Target
########################################################################
ROOT = ../../..
HOSTINC = /usr/include
PROGRAM_ppu := CollisionDemo
#######################################################################
# Objs
######################################################################
OBJS = CollisionDemo.o
########################################################################
# Libraries, Include paths, Defines
########################################################################
INCLUDE = \
-I../ \
-I$(ROOT)/src \
-I$(ROOT)/Demos/OpenGL \
-I$(HOSTINC)
SYS_LIBS := -lglut -lGLU -lGL -lm -lXext -lXmu -lX11
IMPORTS = $(ROOT)/lib/ibmsdk/bulletopenglsupport.a \
$(ROOT)/lib/ibmsdk/bulletdynamics.a \
$(ROOT)/lib/ibmsdk/bulletconvexhull.a \
$(ROOT)/lib/ibmsdk/bulletcollision.a \
$(ROOT)/lib/ibmsdk/bulletmath.a
#######################################################################
# Install files/dirs
#######################################################################
INSTALL_DIR = $(ROOT)/ibmsdk
INSTALL_FILES = $(PROGRAM_ppu)
########################################################################
# make.footer
########################################################################
IBM_CELLSDK_VERSION := $(shell if [ -d /opt/cell ]; then echo "3.0"; fi)
ifeq ("$(IBM_CELLSDK_VERSION)","3.0")
CELL_TOP ?= /opt/cell/sdk
include $(CELL_TOP)/buildutils/make.footer
else
CELL_TOP ?= /opt/ibm/cell-sdk/prototype
include $(CELL_TOP)/make.footer
endif
$(PPMS):
cp textures/$@ .
cleanlocal:
rm -f $(PPMS)

View File

@@ -0,0 +1,43 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2008 Erwin Coumans http://bulletphysics.com
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef CHARACTER_CONTROLLER_INTERFACE_H
#define CHARACTER_CONTROLLER_INTERFACE_H
#include "LinearMath/btVector3.h"
class btCollisionShape;
class btRigidBody;
class btCollisionWorld;
class btCharacterControllerInterface
{
public:
btCharacterControllerInterface () {};
virtual ~btCharacterControllerInterface () {};
virtual void setWalkDirection(const btVector3& walkDirection) = 0;
virtual void reset () = 0;
virtual void warp (const btVector3& origin) = 0;
virtual void preStep ( btCollisionWorld* collisionWorld) = 0;
virtual void playerStep (btCollisionWorld* collisionWorld, btScalar dt) = 0;
virtual bool canJump () const = 0;
virtual void jump () = 0;
virtual bool onGround () const = 0;
};
#endif

View File

@@ -1,12 +1,26 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2008 Erwin Coumans http://bulletphysics.com
#include "GLDebugDrawer.h" This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "LinearMath/btIDebugDraw.h"
#include "BulletCollision/CollisionDispatch/btGhostObject.h" #include "BulletCollision/CollisionDispatch/btGhostObject.h"
#include "BulletCollision/CollisionShapes/btMultiSphereShape.h" #include "BulletCollision/CollisionShapes/btMultiSphereShape.h"
#include "BulletCollision/BroadphaseCollision/btOverlappingPairCache.h" #include "BulletCollision/BroadphaseCollision/btOverlappingPairCache.h"
#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h" #include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
#include "BulletCollision/CollisionDispatch/btCollisionWorld.h" #include "BulletCollision/CollisionDispatch/btCollisionWorld.h"
#include "LinearMath/btDefaultMotionState.h" #include "LinearMath/btDefaultMotionState.h"
#include "KinematicCharacterController.h" #include "btKinematicCharacterController.h"
///@todo Interact with dynamic objects, ///@todo Interact with dynamic objects,
///Ride kinematicly animated platforms properly ///Ride kinematicly animated platforms properly
@@ -14,10 +28,10 @@
/// -> Should integrate falling velocity manually and use that in stepDown() /// -> Should integrate falling velocity manually and use that in stepDown()
///Support jumping ///Support jumping
///Support ducking ///Support ducking
class ClosestNotMeRayResultCallback : public btCollisionWorld::ClosestRayResultCallback class btClosestNotMeRayResultCallback : public btCollisionWorld::ClosestRayResultCallback
{ {
public: public:
ClosestNotMeRayResultCallback (btCollisionObject* me) : btCollisionWorld::ClosestRayResultCallback(btVector3(0.0, 0.0, 0.0), btVector3(0.0, 0.0, 0.0)) btClosestNotMeRayResultCallback (btCollisionObject* me) : btCollisionWorld::ClosestRayResultCallback(btVector3(0.0, 0.0, 0.0), btVector3(0.0, 0.0, 0.0))
{ {
m_me = me; m_me = me;
} }
@@ -33,10 +47,10 @@ protected:
btCollisionObject* m_me; btCollisionObject* m_me;
}; };
class ClosestNotMeConvexResultCallback : public btCollisionWorld::ClosestConvexResultCallback class btClosestNotMeConvexResultCallback : public btCollisionWorld::ClosestConvexResultCallback
{ {
public: public:
ClosestNotMeConvexResultCallback (btCollisionObject* me) : btCollisionWorld::ClosestConvexResultCallback(btVector3(0.0, 0.0, 0.0), btVector3(0.0, 0.0, 0.0)) btClosestNotMeConvexResultCallback (btCollisionObject* me) : btCollisionWorld::ClosestConvexResultCallback(btVector3(0.0, 0.0, 0.0), btVector3(0.0, 0.0, 0.0))
{ {
m_me = me; m_me = me;
} }
@@ -57,7 +71,7 @@ protected:
* *
* from: http://www-cs-students.stanford.edu/~adityagp/final/node3.html * from: http://www-cs-students.stanford.edu/~adityagp/final/node3.html
*/ */
btVector3 computeReflectionDirection (const btVector3& direction, const btVector3& normal) btVector3 btKinematicCharacterController::computeReflectionDirection (const btVector3& direction, const btVector3& normal)
{ {
return direction - (btScalar(2.0) * direction.dot(normal)) * normal; return direction - (btScalar(2.0) * direction.dot(normal)) * normal;
} }
@@ -65,7 +79,7 @@ btVector3 computeReflectionDirection (const btVector3& direction, const btVector
/* /*
* Returns the portion of 'direction' that is parallel to 'normal' * Returns the portion of 'direction' that is parallel to 'normal'
*/ */
btVector3 parallelComponent (const btVector3& direction, const btVector3& normal) btVector3 btKinematicCharacterController::parallelComponent (const btVector3& direction, const btVector3& normal)
{ {
btScalar magnitude = direction.dot(normal); btScalar magnitude = direction.dot(normal);
return normal * magnitude; return normal * magnitude;
@@ -74,33 +88,33 @@ btVector3 parallelComponent (const btVector3& direction, const btVector3& normal
/* /*
* Returns the portion of 'direction' that is perpindicular to 'normal' * Returns the portion of 'direction' that is perpindicular to 'normal'
*/ */
btVector3 perpindicularComponent (const btVector3& direction, const btVector3& normal) btVector3 btKinematicCharacterController::perpindicularComponent (const btVector3& direction, const btVector3& normal)
{ {
return direction - parallelComponent(direction, normal); return direction - parallelComponent(direction, normal);
} }
KinematicCharacterController::KinematicCharacterController (btPairCachingGhostObject* ghostObject,btConvexShape* convexShape,btScalar stepHeight) btKinematicCharacterController::btKinematicCharacterController (btPairCachingGhostObject* ghostObject,btConvexShape* convexShape,btScalar stepHeight)
{ {
m_walkDirection.setValue(0,0,0);
m_useGhostObjectSweepTest = true; m_useGhostObjectSweepTest = true;
m_ghostObject = ghostObject; m_ghostObject = ghostObject;
m_stepHeight = stepHeight; m_stepHeight = stepHeight;
m_turnAngle = btScalar(0.0); m_turnAngle = btScalar(0.0);
m_walkVelocity = btScalar(1.1) * 4.0; // 4 km/h -> 1.1 m/s
m_convexShape=convexShape; m_convexShape=convexShape;
} }
KinematicCharacterController::~KinematicCharacterController () btKinematicCharacterController::~btKinematicCharacterController ()
{ {
} }
btPairCachingGhostObject* KinematicCharacterController::getGhostObject() btPairCachingGhostObject* btKinematicCharacterController::getGhostObject()
{ {
return m_ghostObject; return m_ghostObject;
} }
bool KinematicCharacterController::recoverFromPenetration (btCollisionWorld* collisionWorld) bool btKinematicCharacterController::recoverFromPenetration (btCollisionWorld* collisionWorld)
{ {
bool penetration = false; bool penetration = false;
@@ -153,7 +167,7 @@ bool KinematicCharacterController::recoverFromPenetration (btCollisionWorld* col
return penetration; return penetration;
} }
void KinematicCharacterController::stepUp ( btCollisionWorld* world) void btKinematicCharacterController::stepUp ( btCollisionWorld* world)
{ {
// phase 1: up // phase 1: up
btTransform start, end; btTransform start, end;
@@ -166,7 +180,7 @@ void KinematicCharacterController::stepUp ( btCollisionWorld* world)
start.setOrigin (m_currentPosition + btVector3(btScalar(0.0), btScalar(0.1), btScalar(0.0))); start.setOrigin (m_currentPosition + btVector3(btScalar(0.0), btScalar(0.1), btScalar(0.0)));
end.setOrigin (m_targetPosition); end.setOrigin (m_targetPosition);
ClosestNotMeConvexResultCallback callback (m_ghostObject); btClosestNotMeConvexResultCallback callback (m_ghostObject);
callback.m_collisionFilterGroup = getGhostObject()->getBroadphaseHandle()->m_collisionFilterGroup; callback.m_collisionFilterGroup = getGhostObject()->getBroadphaseHandle()->m_collisionFilterGroup;
callback.m_collisionFilterMask = getGhostObject()->getBroadphaseHandle()->m_collisionFilterMask; callback.m_collisionFilterMask = getGhostObject()->getBroadphaseHandle()->m_collisionFilterMask;
@@ -190,7 +204,7 @@ void KinematicCharacterController::stepUp ( btCollisionWorld* world)
} }
} }
void KinematicCharacterController::updateTargetPositionBasedOnCollision (const btVector3& hitNormal, btScalar tangentMag, btScalar normalMag) void btKinematicCharacterController::updateTargetPositionBasedOnCollision (const btVector3& hitNormal, btScalar tangentMag, btScalar normalMag)
{ {
btVector3 movementDirection = m_targetPosition - m_currentPosition; btVector3 movementDirection = m_targetPosition - m_currentPosition;
btScalar movementLength = movementDirection.length(); btScalar movementLength = movementDirection.length();
@@ -226,7 +240,7 @@ void KinematicCharacterController::updateTargetPositionBasedOnCollision (const b
} }
} }
void KinematicCharacterController::stepForwardAndStrafe ( btCollisionWorld* collisionWorld, const btVector3& walkMove) void btKinematicCharacterController::stepForwardAndStrafe ( btCollisionWorld* collisionWorld, const btVector3& walkMove)
{ {
btVector3 originalDir = walkMove.normalized(); btVector3 originalDir = walkMove.normalized();
@@ -258,7 +272,7 @@ void KinematicCharacterController::stepForwardAndStrafe ( btCollisionWorld* coll
start.setOrigin (m_currentPosition); start.setOrigin (m_currentPosition);
end.setOrigin (m_targetPosition); end.setOrigin (m_targetPosition);
ClosestNotMeConvexResultCallback callback (m_ghostObject); btClosestNotMeConvexResultCallback callback (m_ghostObject);
callback.m_collisionFilterGroup = getGhostObject()->getBroadphaseHandle()->m_collisionFilterGroup; callback.m_collisionFilterGroup = getGhostObject()->getBroadphaseHandle()->m_collisionFilterGroup;
callback.m_collisionFilterMask = getGhostObject()->getBroadphaseHandle()->m_collisionFilterMask; callback.m_collisionFilterMask = getGhostObject()->getBroadphaseHandle()->m_collisionFilterMask;
@@ -322,7 +336,7 @@ void KinematicCharacterController::stepForwardAndStrafe ( btCollisionWorld* coll
} }
} }
void KinematicCharacterController::stepDown ( btCollisionWorld* collisionWorld, btScalar dt) void btKinematicCharacterController::stepDown ( btCollisionWorld* collisionWorld, btScalar dt)
{ {
btTransform start, end; btTransform start, end;
@@ -337,7 +351,7 @@ void KinematicCharacterController::stepDown ( btCollisionWorld* collisionWorld,
start.setOrigin (m_currentPosition); start.setOrigin (m_currentPosition);
end.setOrigin (m_targetPosition); end.setOrigin (m_targetPosition);
ClosestNotMeConvexResultCallback callback (m_ghostObject); btClosestNotMeConvexResultCallback callback (m_ghostObject);
callback.m_collisionFilterGroup = getGhostObject()->getBroadphaseHandle()->m_collisionFilterGroup; callback.m_collisionFilterGroup = getGhostObject()->getBroadphaseHandle()->m_collisionFilterGroup;
callback.m_collisionFilterMask = getGhostObject()->getBroadphaseHandle()->m_collisionFilterMask; callback.m_collisionFilterMask = getGhostObject()->getBroadphaseHandle()->m_collisionFilterMask;
@@ -360,11 +374,11 @@ void KinematicCharacterController::stepDown ( btCollisionWorld* collisionWorld,
} }
} }
void KinematicCharacterController::reset () void btKinematicCharacterController::reset ()
{ {
} }
void KinematicCharacterController::warp (const btVector3& origin) void btKinematicCharacterController::warp (const btVector3& origin)
{ {
btTransform xform; btTransform xform;
xform.setIdentity(); xform.setIdentity();
@@ -373,7 +387,7 @@ void KinematicCharacterController::warp (const btVector3& origin)
} }
void KinematicCharacterController::preStep ( btCollisionWorld* collisionWorld) void btKinematicCharacterController::preStep ( btCollisionWorld* collisionWorld)
{ {
int numPenetrationLoops = 0; int numPenetrationLoops = 0;
@@ -388,51 +402,16 @@ void KinematicCharacterController::preStep ( btCollisionWorld* collisionWorld)
break; break;
} }
} }
btTransform xform;
xform = m_ghostObject->getWorldTransform ();
btVector3 forwardDir = xform.getBasis()[2]; m_currentPosition = m_ghostObject->getWorldTransform().getOrigin();
// printf("forwardDir=%f,%f,%f\n",forwardDir[0],forwardDir[1],forwardDir[2]);
btVector3 upDir = xform.getBasis()[1];
btVector3 strafeDir = xform.getBasis()[0];
forwardDir.normalize ();
upDir.normalize ();
strafeDir.normalize ();
m_upDirection = upDir;
m_forwardDirection = forwardDir;
m_strafeDirection = strafeDir;
m_currentPosition = xform.getOrigin();
m_targetPosition = m_currentPosition; m_targetPosition = m_currentPosition;
// printf("m_targetPosition=%f,%f,%f\n",m_targetPosition[0],m_targetPosition[1],m_targetPosition[2]); // printf("m_targetPosition=%f,%f,%f\n",m_targetPosition[0],m_targetPosition[1],m_targetPosition[2]);
} }
void KinematicCharacterController::playerStep ( btCollisionWorld* collisionWorld, void btKinematicCharacterController::playerStep ( btCollisionWorld* collisionWorld, btScalar dt)
btScalar dt,
int forward,
int backward,
int left,
int right,
int jump)
{ {
btVector3 walkDirection = btVector3(0.0, 0.0, 0.0);
btScalar walkSpeed = m_walkVelocity * dt;
if (left)
walkDirection += m_strafeDirection;
if (right)
walkDirection -= m_strafeDirection;
if (forward)
walkDirection += m_forwardDirection;
if (backward)
walkDirection -= m_forwardDirection;
btTransform xform; btTransform xform;
xform = m_ghostObject->getWorldTransform (); xform = m_ghostObject->getWorldTransform ();
@@ -440,34 +419,34 @@ void KinematicCharacterController::playerStep ( btCollisionWorld* collisionWorld
// printf("walkSpeed=%f\n",walkSpeed); // printf("walkSpeed=%f\n",walkSpeed);
stepUp (collisionWorld); stepUp (collisionWorld);
stepForwardAndStrafe (collisionWorld, walkDirection * walkSpeed); stepForwardAndStrafe (collisionWorld, m_walkDirection);
stepDown (collisionWorld, dt); stepDown (collisionWorld, dt);
xform.setOrigin (m_currentPosition); xform.setOrigin (m_currentPosition);
m_ghostObject->setWorldTransform (xform); m_ghostObject->setWorldTransform (xform);
} }
void KinematicCharacterController::setFallSpeed (btScalar fallSpeed) void btKinematicCharacterController::setFallSpeed (btScalar fallSpeed)
{ {
m_fallSpeed = fallSpeed; m_fallSpeed = fallSpeed;
} }
void KinematicCharacterController::setJumpSpeed (btScalar jumpSpeed) void btKinematicCharacterController::setJumpSpeed (btScalar jumpSpeed)
{ {
m_jumpSpeed = jumpSpeed; m_jumpSpeed = jumpSpeed;
} }
void KinematicCharacterController::setMaxJumpHeight (btScalar maxJumpHeight) void btKinematicCharacterController::setMaxJumpHeight (btScalar maxJumpHeight)
{ {
m_maxJumpHeight = maxJumpHeight; m_maxJumpHeight = maxJumpHeight;
} }
bool KinematicCharacterController::canJump () const bool btKinematicCharacterController::canJump () const
{ {
return onGround(); return onGround();
} }
void KinematicCharacterController::jump () void btKinematicCharacterController::jump ()
{ {
if (!canJump()) if (!canJump())
return; return;
@@ -483,7 +462,7 @@ void KinematicCharacterController::jump ()
#endif #endif
} }
bool KinematicCharacterController::onGround () const bool btKinematicCharacterController::onGround () const
{ {
return true; return true;
} }

View File

@@ -0,0 +1,103 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2008 Erwin Coumans http://bulletphysics.com
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef KINEMATIC_CHARACTER_CONTROLLER_H
#define KINEMATIC_CHARACTER_CONTROLLER_H
#include "LinearMath/btVector3.h"
#include "btCharacterControllerInterface.h"
class btCollisionShape;
class btRigidBody;
class btCollisionWorld;
class btCollisionDispatcher;
class btPairCachingGhostObject;
///btKinematicCharacterController is an object that supports a sliding motion in a world.
///It uses a ghost object and convex sweep test to test for upcoming collisions. This is combined with discrete collision detection to recover from penetrations.
///Interaction between btKinematicCharacterController and dynamic rigid bodies needs to be explicity implemented by the user.
class btKinematicCharacterController : public btCharacterControllerInterface
{
protected:
btScalar m_halfHeight;
btPairCachingGhostObject* m_ghostObject;
btConvexShape* m_convexShape;//is also in m_ghostObject, but it needs to be convex, so we store it here to avoid upcast
btScalar m_fallSpeed;
btScalar m_jumpSpeed;
btScalar m_maxJumpHeight;
btScalar m_turnAngle;
btScalar m_stepHeight;
///this is the desired walk direction, set by the user
btVector3 m_walkDirection;
//some internal variables
btVector3 m_currentPosition;
btScalar m_currentStepOffset;
btVector3 m_targetPosition;
///keep track of the contact manifolds
btManifoldArray m_manifoldArray;
bool m_touchingContact;
btVector3 m_touchingNormal;
bool m_useGhostObjectSweepTest;
btVector3 computeReflectionDirection (const btVector3& direction, const btVector3& normal);
btVector3 parallelComponent (const btVector3& direction, const btVector3& normal);
btVector3 perpindicularComponent (const btVector3& direction, const btVector3& normal);
bool recoverFromPenetration (btCollisionWorld* collisionWorld);
void stepUp (btCollisionWorld* collisionWorld);
void updateTargetPositionBasedOnCollision (const btVector3& hit_normal, btScalar tangentMag = btScalar(0.0), btScalar normalMag = btScalar(1.0));
void stepForwardAndStrafe (btCollisionWorld* collisionWorld, const btVector3& walkMove);
void stepDown (btCollisionWorld* collisionWorld, btScalar dt);
public:
btKinematicCharacterController (btPairCachingGhostObject* ghostObject,btConvexShape* convexShape,btScalar stepHeight);
~btKinematicCharacterController ();
virtual void setWalkDirection(const btVector3& walkDirection)
{
m_walkDirection = walkDirection;
}
void reset ();
void warp (const btVector3& origin);
void preStep ( btCollisionWorld* collisionWorld);
void playerStep (btCollisionWorld* collisionWorld, btScalar dt);
void setFallSpeed (btScalar fallSpeed);
void setJumpSpeed (btScalar jumpSpeed);
void setMaxJumpHeight (btScalar maxJumpHeight);
bool canJump () const;
void jump ();
btPairCachingGhostObject* getGhostObject();
void setUseGhostSweepTest(bool useGhostObjectSweepTest)
{
m_useGhostObjectSweepTest = useGhostObjectSweepTest;
}
bool onGround () const;
};
#endif // KINEMATIC_CHARACTER_CONTROLLER_H

View File

@@ -51,6 +51,9 @@ subject to the following restrictions:
#include "BulletDynamics/Vehicle/btRaycastVehicle.h" #include "BulletDynamics/Vehicle/btRaycastVehicle.h"
#include "BulletDynamics/Vehicle/btVehicleRaycaster.h" #include "BulletDynamics/Vehicle/btVehicleRaycaster.h"
#include "BulletDynamics/Vehicle/btWheelInfo.h" #include "BulletDynamics/Vehicle/btWheelInfo.h"
//character
#include "BulletDynamics/Character/btCharacterControllerInterface.h"
#include "LinearMath/btIDebugDraw.h" #include "LinearMath/btIDebugDraw.h"
#include "LinearMath/btQuickprof.h" #include "LinearMath/btQuickprof.h"
#include "LinearMath/btMotionState.h" #include "LinearMath/btMotionState.h"
@@ -404,6 +407,7 @@ void btDiscreteDynamicsWorld::internalSingleStepSimulation(btScalar timeStep)
///update vehicle simulation ///update vehicle simulation
updateVehicles(timeStep); updateVehicles(timeStep);
updateCharacters(timeStep);
updateActivationState( timeStep ); updateActivationState( timeStep );
@@ -479,6 +483,20 @@ void btDiscreteDynamicsWorld::updateVehicles(btScalar timeStep)
} }
} }
void btDiscreteDynamicsWorld::updateCharacters(btScalar timeStep)
{
BT_PROFILE("updateCharacters");
for ( int i=0;i<m_characters.size();i++)
{
btCharacterControllerInterface* character = m_characters[i];
character->preStep (this);
character->playerStep (this,timeStep);
}
}
void btDiscreteDynamicsWorld::updateActivationState(btScalar timeStep) void btDiscreteDynamicsWorld::updateActivationState(btScalar timeStep)
{ {
BT_PROFILE("updateActivationState"); BT_PROFILE("updateActivationState");
@@ -543,6 +561,17 @@ void btDiscreteDynamicsWorld::removeVehicle(btRaycastVehicle* vehicle)
m_vehicles.remove(vehicle); m_vehicles.remove(vehicle);
} }
void btDiscreteDynamicsWorld::addCharacter(btCharacterControllerInterface* character)
{
m_characters.push_back(character);
}
void btDiscreteDynamicsWorld::removeCharacter(btCharacterControllerInterface* character)
{
m_characters.remove(character);
}
SIMD_FORCE_INLINE int btGetConstraintIslandId(const btTypedConstraint* lhs) SIMD_FORCE_INLINE int btGetConstraintIslandId(const btTypedConstraint* lhs)
{ {
int islandId; int islandId;

View File

@@ -26,6 +26,7 @@ class btTypedConstraint;
class btRaycastVehicle; class btRaycastVehicle;
class btCharacterControllerInterface;
class btIDebugDraw; class btIDebugDraw;
#include "LinearMath/btAlignedObjectArray.h" #include "LinearMath/btAlignedObjectArray.h"
@@ -54,6 +55,9 @@ protected:
btAlignedObjectArray<btRaycastVehicle*> m_vehicles; btAlignedObjectArray<btRaycastVehicle*> m_vehicles;
btAlignedObjectArray<btCharacterControllerInterface*> m_characters;
int m_profileTimings; int m_profileTimings;
virtual void predictUnconstraintMotion(btScalar timeStep); virtual void predictUnconstraintMotion(btScalar timeStep);
@@ -68,6 +72,8 @@ protected:
void updateVehicles(btScalar timeStep); void updateVehicles(btScalar timeStep);
void updateCharacters(btScalar timeStep);
void startProfiling(btScalar timeStep); void startProfiling(btScalar timeStep);
virtual void internalSingleStepSimulation( btScalar timeStep); virtual void internalSingleStepSimulation( btScalar timeStep);
@@ -95,13 +101,18 @@ public:
///this can be useful to synchronize a single rigid body -> graphics object ///this can be useful to synchronize a single rigid body -> graphics object
void synchronizeSingleMotionState(btRigidBody* body); void synchronizeSingleMotionState(btRigidBody* body);
void addConstraint(btTypedConstraint* constraint, bool disableCollisionsBetweenLinkedBodies=false); virtual void addConstraint(btTypedConstraint* constraint, bool disableCollisionsBetweenLinkedBodies=false);
void removeConstraint(btTypedConstraint* constraint); virtual void removeConstraint(btTypedConstraint* constraint);
void addVehicle(btRaycastVehicle* vehicle); virtual void addVehicle(btRaycastVehicle* vehicle);
virtual void removeVehicle(btRaycastVehicle* vehicle);
virtual void addCharacter(btCharacterControllerInterface* character);
virtual void removeCharacter(btCharacterControllerInterface* character);
void removeVehicle(btRaycastVehicle* vehicle);
btSimulationIslandManager* getSimulationIslandManager() btSimulationIslandManager* getSimulationIslandManager()
{ {

View File

@@ -23,6 +23,7 @@ class btTypedConstraint;
class btRaycastVehicle; class btRaycastVehicle;
class btConstraintSolver; class btConstraintSolver;
class btDynamicsWorld; class btDynamicsWorld;
class btCharacterControllerInterface;
/// Type for the callback for each tick /// Type for the callback for each tick
typedef void (*btInternalTickCallback)(btDynamicsWorld *world, btScalar timeStep); typedef void (*btInternalTickCallback)(btDynamicsWorld *world, btScalar timeStep);
@@ -75,6 +76,11 @@ public:
virtual void removeVehicle(btRaycastVehicle* vehicle) {(void)vehicle;} virtual void removeVehicle(btRaycastVehicle* vehicle) {(void)vehicle;}
virtual void addCharacter(btCharacterControllerInterface* character) {(void)character;}
virtual void removeCharacter(btCharacterControllerInterface* character) {(void)character;}
//once a rigidbody is added to the dynamics world, it will get this gravity assigned //once a rigidbody is added to the dynamics world, it will get this gravity assigned
//existing rigidbodies in the world get gravity assigned too, during this method //existing rigidbodies in the world get gravity assigned too, during this method
virtual void setGravity(const btVector3& gravity) = 0; virtual void setGravity(const btVector3& gravity) = 0;