+ improved KinematicCharacterController

+ improved btSubsimplexConvexCast, btContinuousConvexCollision and btGjkConvexCast to support configuration that start in touching/penetration, required for 'sliding'.
+ added files to CMakeLists.txt for CharacterController
+ bump up version to 2.70 (preparation for beta)
This commit is contained in:
erwin.coumans
2008-07-09 00:08:49 +00:00
parent 76bac83937
commit dcd57f333b
23 changed files with 431 additions and 243 deletions

View File

@@ -8,7 +8,9 @@
# You shouldn't have to modify anything below this line # You shouldn't have to modify anything below this line
######################################################## ########################################################
LINK_DIRECTORIES(
"C:/MinGW/lib"
)
INCLUDE_DIRECTORIES( INCLUDE_DIRECTORIES(
${BULLET_PHYSICS_SOURCE_DIR}/Extras/BulletColladaConverter ${BULLET_PHYSICS_SOURCE_DIR}/Extras ${BULLET_PHYSICS_SOURCE_DIR}/Extras/GIMPACT/include ${BULLET_PHYSICS_SOURCE_DIR}/Extras/GIMPACTUtils ${BULLET_PHYSICS_SOURCE_DIR}/Extras/ConvexDecomposition ${BULLET_PHYSICS_SOURCE_DIR}/Extras/LibXML ${BULLET_PHYSICS_SOURCE_DIR}/Extras/LibXML/include ${BULLET_PHYSICS_SOURCE_DIR}/Extras/COLLADA_DOM/include/1.4 ${BULLET_PHYSICS_SOURCE_DIR}/Extras/COLLADA_DOM/include ${BULLET_PHYSICS_SOURCE_DIR}/src ${BULLET_PHYSICS_SOURCE_DIR}/Demos/OpenGL } ${BULLET_PHYSICS_SOURCE_DIR}/Extras/BulletColladaConverter ${BULLET_PHYSICS_SOURCE_DIR}/Extras ${BULLET_PHYSICS_SOURCE_DIR}/Extras/GIMPACT/include ${BULLET_PHYSICS_SOURCE_DIR}/Extras/GIMPACTUtils ${BULLET_PHYSICS_SOURCE_DIR}/Extras/ConvexDecomposition ${BULLET_PHYSICS_SOURCE_DIR}/Extras/LibXML ${BULLET_PHYSICS_SOURCE_DIR}/Extras/LibXML/include ${BULLET_PHYSICS_SOURCE_DIR}/Extras/COLLADA_DOM/include/1.4 ${BULLET_PHYSICS_SOURCE_DIR}/Extras/COLLADA_DOM/include ${BULLET_PHYSICS_SOURCE_DIR}/src ${BULLET_PHYSICS_SOURCE_DIR}/Demos/OpenGL }
@@ -24,23 +26,23 @@ ADD_EXECUTABLE(AllBulletDemos
Main.cpp Main.cpp
DemoEntries.cpp DemoEntries.cpp
../CcdPhysicsDemo/CcdPhysicsDemo.cpp ../CcdPhysicsDemo/CcdPhysicsDemo.cpp
../BasicDemo/BasicDemo.cpp ../BasicDemo/BasicDemo.cpp
../Benchmarks/BenchmarkDemo.cpp ../Benchmarks/BenchmarkDemo.cpp
../BspDemo/BspDemo.cpp ../BspDemo/BspDemo.cpp
../BspDemo/BspConverter.cpp ../BspDemo/BspConverter.cpp
../BspDemo/BspLoader.cpp ../BspDemo/BspLoader.cpp
../DynamicControlDemo/MotorDemo.cpp ../DynamicControlDemo/MotorDemo.cpp
../ConcaveDemo/ConcavePhysicsDemo.cpp ../ConcaveDemo/ConcavePhysicsDemo.cpp
../ConcaveRaycastDemo/ConcaveRaycastDemo.cpp ../ConcaveRaycastDemo/ConcaveRaycastDemo.cpp
../ConcaveConvexcastDemo/ConcaveConvexcastDemo.cpp ../ConcaveConvexcastDemo/ConcaveConvexcastDemo.cpp
../ConvexDecompositionDemo/ConvexDecompositionDemo.cpp ../ConvexDecompositionDemo/ConvexDecompositionDemo.cpp
../SliderConstraintDemo/SliderConstraintDemo.cpp ../SliderConstraintDemo/SliderConstraintDemo.cpp
../RagdollDemo/RagdollDemo.cpp ../RagdollDemo/RagdollDemo.cpp
../GimpactTestDemo/GimpactTestDemo.cpp ../GimpactTestDemo/GimpactTestDemo.cpp
../Raytracer/Raytracer.cpp ../Raytracer/Raytracer.cpp
../GjkConvexCastDemo/LinearConvexCastDemo.cpp ../GjkConvexCastDemo/LinearConvexCastDemo.cpp
../VehicleDemo/VehicleDemo.cpp ../VehicleDemo/VehicleDemo.cpp
../SoftDemo/SoftDemo.cpp ../SoftDemo/SoftDemo.cpp
../ConstraintDemo/ConstraintDemo.cpp ../ConstraintDemo/ConstraintDemo.cpp
) )

View File

@@ -4,8 +4,8 @@ Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
This software is provided 'as-is', without any express or implied warranty. 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. 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, Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely, including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions: 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. 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.
@@ -124,13 +124,13 @@ void CcdPhysicsDemo::createStack( btCollisionShape* boxShape, float halfCubeSize
-rowSize * halfCubeSize + halfCubeSize + j * 2.0f * halfCubeSize, -rowSize * halfCubeSize + halfCubeSize + j * 2.0f * halfCubeSize,
halfCubeSize + i * halfCubeSize * 2.0f, halfCubeSize + i * halfCubeSize * 2.0f,
zPos); zPos);
trans.setOrigin(pos); trans.setOrigin(pos);
btScalar mass = 1.f; btScalar mass = 1.f;
btRigidBody* body = 0; btRigidBody* body = 0;
body = localCreateRigidBody(mass,trans,boxShape); body = localCreateRigidBody(mass,trans,boxShape);
#ifdef USER_DEFINED_FRICTION_MODEL #ifdef USER_DEFINED_FRICTION_MODEL
///Advanced use: override the friction solver ///Advanced use: override the friction solver
body->m_frictionSolverType = USER_CONTACT_SOLVER_TYPE1; body->m_frictionSolverType = USER_CONTACT_SOLVER_TYPE1;
#endif //USER_DEFINED_FRICTION_MODEL #endif //USER_DEFINED_FRICTION_MODEL
@@ -145,7 +145,7 @@ void CcdPhysicsDemo::createStack( btCollisionShape* boxShape, float halfCubeSize
//by default, Bullet will use its own nearcallback, but you can override it using dispatcher->setNearCallback() //by default, Bullet will use its own nearcallback, but you can override it using dispatcher->setNearCallback()
void customNearCallback(btBroadphasePair& collisionPair, btCollisionDispatcher& dispatcher, btDispatcherInfo& dispatchInfo) void customNearCallback(btBroadphasePair& collisionPair, btCollisionDispatcher& dispatcher, const btDispatcherInfo& dispatchInfo)
{ {
btCollisionObject* colObj0 = (btCollisionObject*)collisionPair.m_pProxy0->m_clientObject; btCollisionObject* colObj0 = (btCollisionObject*)collisionPair.m_pProxy0->m_clientObject;
btCollisionObject* colObj1 = (btCollisionObject*)collisionPair.m_pProxy1->m_clientObject; btCollisionObject* colObj1 = (btCollisionObject*)collisionPair.m_pProxy1->m_clientObject;
@@ -161,7 +161,7 @@ void customNearCallback(btBroadphasePair& collisionPair, btCollisionDispatcher&
if (collisionPair.m_algorithm) if (collisionPair.m_algorithm)
{ {
btManifoldResult contactPointResult(colObj0,colObj1); btManifoldResult contactPointResult(colObj0,colObj1);
if (dispatchInfo.m_dispatchFunc == btDispatcherInfo::DISPATCH_DISCRETE) if (dispatchInfo.m_dispatchFunc == btDispatcherInfo::DISPATCH_DISCRETE)
{ {
//discrete collision detection query //discrete collision detection query
@@ -196,7 +196,7 @@ extern int gTotalContactPoints;
void CcdPhysicsDemo::clientMoveAndDisplay() void CcdPhysicsDemo::clientMoveAndDisplay()
{ {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
#ifdef USE_KINEMATIC_GROUND #ifdef USE_KINEMATIC_GROUND
@@ -220,16 +220,16 @@ void CcdPhysicsDemo::clientMoveAndDisplay()
float dt = getDeltaTimeMicroseconds() * 0.000001f; float dt = getDeltaTimeMicroseconds() * 0.000001f;
// printf("dt = %f: ",dt); // printf("dt = %f: ",dt);
if (m_dynamicsWorld) if (m_dynamicsWorld)
{ {
//#define FIXED_STEP 1 //#define FIXED_STEP 1
#ifdef FIXED_STEP #ifdef FIXED_STEP
m_dynamicsWorld->stepSimulation(1.0f/60.f,0); m_dynamicsWorld->stepSimulation(1.0f/60.f,0);
#else #else
//during idle mode, just run 1 simulation step maximum //during idle mode, just run 1 simulation step maximum
int maxSimSubSteps = m_idle ? 1 : 1; int maxSimSubSteps = m_idle ? 1 : 1;
@@ -238,10 +238,10 @@ void CcdPhysicsDemo::clientMoveAndDisplay()
int numSimSteps = 0; int numSimSteps = 0;
numSimSteps = m_dynamicsWorld->stepSimulation(dt,maxSimSubSteps); numSimSteps = m_dynamicsWorld->stepSimulation(dt,maxSimSubSteps);
//optional but useful: debug drawing //optional but useful: debug drawing
m_dynamicsWorld->debugDrawWorld(); m_dynamicsWorld->debugDrawWorld();
#ifdef VERBOSE_TIMESTEPPING_CONSOLEOUTPUT #ifdef VERBOSE_TIMESTEPPING_CONSOLEOUTPUT
if (!numSimSteps) if (!numSimSteps)
printf("Interpolated transforms\n"); printf("Interpolated transforms\n");
@@ -260,12 +260,12 @@ void CcdPhysicsDemo::clientMoveAndDisplay()
#endif #endif
} }
#ifdef USE_QUICKPROF #ifdef USE_QUICKPROF
btProfiler::beginBlock("render"); btProfiler::beginBlock("render");
#endif //USE_QUICKPROF #endif //USE_QUICKPROF
renderme(); renderme();
//render the graphics objects, with center of mass shift //render the graphics objects, with center of mass shift
@@ -274,9 +274,9 @@ void CcdPhysicsDemo::clientMoveAndDisplay()
#ifdef USE_QUICKPROF #ifdef USE_QUICKPROF
btProfiler::endBlock("render"); btProfiler::endBlock("render");
#endif #endif
glFlush(); glFlush();
//some additional debugging info //some additional debugging info
#ifdef PRINT_CONTACT_STATISTICS #ifdef PRINT_CONTACT_STATISTICS
@@ -294,7 +294,7 @@ void CcdPhysicsDemo::clientMoveAndDisplay()
void CcdPhysicsDemo::displayCallback(void) { void CcdPhysicsDemo::displayCallback(void) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
renderme(); renderme();
@@ -342,7 +342,7 @@ void CcdPhysicsDemo::initPhysics()
// m_collisionShapes.push_back(new btBoxShape (btVector3(CUBE_HALF_EXTENTS,CUBE_HALF_EXTENTS,CUBE_HALF_EXTENTS))); // m_collisionShapes.push_back(new btBoxShape (btVector3(CUBE_HALF_EXTENTS,CUBE_HALF_EXTENTS,CUBE_HALF_EXTENTS)));
m_collisionShapes.push_back(new btCylinderShape (btVector3(CUBE_HALF_EXTENTS,CUBE_HALF_EXTENTS,CUBE_HALF_EXTENTS))); m_collisionShapes.push_back(new btCylinderShape (btVector3(CUBE_HALF_EXTENTS,CUBE_HALF_EXTENTS,CUBE_HALF_EXTENTS)));
#endif #endif
#ifdef DO_BENCHMARK_PYRAMIDS #ifdef DO_BENCHMARK_PYRAMIDS
@@ -355,7 +355,7 @@ void CcdPhysicsDemo::initPhysics()
m_dispatcher=0; m_dispatcher=0;
m_collisionConfiguration = new btDefaultCollisionConfiguration(); m_collisionConfiguration = new btDefaultCollisionConfiguration();
#ifdef USE_PARALLEL_DISPATCHER #ifdef USE_PARALLEL_DISPATCHER
int maxNumOutstandingTasks = 4; int maxNumOutstandingTasks = 4;
@@ -397,7 +397,7 @@ int maxNumOutstandingTasks = 4;
m_dispatcher = new SpuGatheringCollisionDispatcher(m_threadSupportCollision,maxNumOutstandingTasks,m_collisionConfiguration); m_dispatcher = new SpuGatheringCollisionDispatcher(m_threadSupportCollision,maxNumOutstandingTasks,m_collisionConfiguration);
// m_dispatcher = new btCollisionDispatcher(m_collisionConfiguration); // m_dispatcher = new btCollisionDispatcher(m_collisionConfiguration);
#else #else
m_dispatcher = new btCollisionDispatcher(m_collisionConfiguration); m_dispatcher = new btCollisionDispatcher(m_collisionConfiguration);
#endif //USE_PARALLEL_DISPATCHER #endif //USE_PARALLEL_DISPATCHER
@@ -414,14 +414,14 @@ int maxNumOutstandingTasks = 4;
// m_broadphase = new bt32BitAxisSweep3(worldAabbMin,worldAabbMax,maxProxies); // m_broadphase = new bt32BitAxisSweep3(worldAabbMin,worldAabbMax,maxProxies);
/// When trying to debug broadphase issues, try to use the btSimpleBroadphase /// When trying to debug broadphase issues, try to use the btSimpleBroadphase
// m_broadphase = new btSimpleBroadphase; // m_broadphase = new btSimpleBroadphase;
//box-box is in Extras/AlternativeCollisionAlgorithms:it requires inclusion of those files //box-box is in Extras/AlternativeCollisionAlgorithms:it requires inclusion of those files
#ifdef COMPARE_WITH_QUICKSTEP #ifdef COMPARE_WITH_QUICKSTEP
m_solver = new btOdeQuickstepConstraintSolver(); m_solver = new btOdeQuickstepConstraintSolver();
#else #else
#ifdef USE_PARALLEL_SOLVER #ifdef USE_PARALLEL_SOLVER
m_threadSupportSolver = new Win32ThreadSupport(Win32ThreadSupport::Win32ThreadConstructionInfo( m_threadSupportSolver = new Win32ThreadSupport(Win32ThreadSupport::Win32ThreadConstructionInfo(
@@ -435,11 +435,11 @@ int maxNumOutstandingTasks = 4;
btSequentialImpulseConstraintSolver* solver = new btSequentialImpulseConstraintSolver(); btSequentialImpulseConstraintSolver* solver = new btSequentialImpulseConstraintSolver();
m_solver = solver;//new btOdeQuickstepConstraintSolver(); m_solver = solver;//new btOdeQuickstepConstraintSolver();
#endif //USE_PARALLEL_SOLVER #endif //USE_PARALLEL_SOLVER
#endif #endif
btDiscreteDynamicsWorld* world = new btDiscreteDynamicsWorld(m_dispatcher,m_broadphase,m_solver,m_collisionConfiguration); btDiscreteDynamicsWorld* world = new btDiscreteDynamicsWorld(m_dispatcher,m_broadphase,m_solver,m_collisionConfiguration);
@@ -459,7 +459,7 @@ int maxNumOutstandingTasks = 4;
m_dynamicsWorld->getDispatchInfo().m_enableSPU = true; m_dynamicsWorld->getDispatchInfo().m_enableSPU = true;
m_dynamicsWorld->setGravity(btVector3(0,-10,0)); m_dynamicsWorld->setGravity(btVector3(0,-10,0));
#ifdef USER_DEFINED_FRICTION_MODEL #ifdef USER_DEFINED_FRICTION_MODEL
{ {
@@ -478,7 +478,7 @@ int maxNumOutstandingTasks = 4;
btTransform tr; btTransform tr;
tr.setIdentity(); tr.setIdentity();
for (i=0;i<gNumObjects;i++) for (i=0;i<gNumObjects;i++)
{ {
if (i>0) if (i>0)
@@ -520,7 +520,7 @@ int maxNumOutstandingTasks = 4;
btTransform trans; btTransform trans;
trans.setIdentity(); trans.setIdentity();
if (i>0) if (i>0)
{ {
//stack them //stack them
@@ -549,7 +549,7 @@ int maxNumOutstandingTasks = 4;
if (!isDyna) if (!isDyna)
mass = 0.f; mass = 0.f;
btRigidBody* body = localCreateRigidBody(mass,trans,shape); btRigidBody* body = localCreateRigidBody(mass,trans,shape);
#ifdef USE_KINEMATIC_GROUND #ifdef USE_KINEMATIC_GROUND
if (mass == 0.f) if (mass == 0.f)
@@ -558,15 +558,15 @@ int maxNumOutstandingTasks = 4;
body->setActivationState(DISABLE_DEACTIVATION); body->setActivationState(DISABLE_DEACTIVATION);
} }
#endif //USE_KINEMATIC_GROUND #endif //USE_KINEMATIC_GROUND
// Only do CCD if motion in one timestep (1.f/60.f) exceeds CUBE_HALF_EXTENTS // Only do CCD if motion in one timestep (1.f/60.f) exceeds CUBE_HALF_EXTENTS
body->setCcdSquareMotionThreshold( CUBE_HALF_EXTENTS ); body->setCcdSquareMotionThreshold( CUBE_HALF_EXTENTS );
//Experimental: better estimation of CCD Time of Impact: //Experimental: better estimation of CCD Time of Impact:
body->setCcdSweptSphereRadius( 0.2*CUBE_HALF_EXTENTS ); body->setCcdSweptSphereRadius( 0.2*CUBE_HALF_EXTENTS );
#ifdef USER_DEFINED_FRICTION_MODEL #ifdef USER_DEFINED_FRICTION_MODEL
///Advanced use: override the friction solver ///Advanced use: override the friction solver
body->m_frictionSolverType = USER_CONTACT_SOLVER_TYPE1; body->m_frictionSolverType = USER_CONTACT_SOLVER_TYPE1;
#endif //USER_DEFINED_FRICTION_MODEL #endif //USER_DEFINED_FRICTION_MODEL
@@ -578,7 +578,7 @@ int maxNumOutstandingTasks = 4;
#ifdef DO_BENCHMARK_PYRAMIDS #ifdef DO_BENCHMARK_PYRAMIDS
btTransform trans; btTransform trans;
trans.setIdentity(); trans.setIdentity();
btScalar halfExtents = CUBE_HALF_EXTENTS; btScalar halfExtents = CUBE_HALF_EXTENTS;
trans.setOrigin(btVector3(0,-halfExtents,0)); trans.setOrigin(btVector3(0,-halfExtents,0));
@@ -609,13 +609,13 @@ int maxNumOutstandingTasks = 4;
m_collisionShapes.push_back(ball); m_collisionShapes.push_back(ball);
btRigidBody* ballBody = localCreateRigidBody(10000.f,sphereTrans,ball); btRigidBody* ballBody = localCreateRigidBody(10000.f,sphereTrans,ball);
ballBody->setLinearVelocity(btVector3(0,0,-10)); ballBody->setLinearVelocity(btVector3(0,0,-10));
#endif #endif
#endif //DO_BENCHMARK_PYRAMIDS #endif //DO_BENCHMARK_PYRAMIDS
// clientResetScene(); // clientResetScene();
} }
@@ -680,7 +680,7 @@ void CcdPhysicsDemo::exitPhysics()
delete m_collisionConfiguration; delete m_collisionConfiguration;
} }

View File

@@ -12,16 +12,16 @@ class CharacterControllerInterface
public: public:
CharacterControllerInterface () {}; CharacterControllerInterface () {};
virtual ~CharacterControllerInterface () {}; virtual ~CharacterControllerInterface () {};
virtual void setup (btDynamicsWorld* dynamicsWorld, btScalar height = 2.0, btScalar width = 0.25, btScalar stepHeight = 0.25) = 0; virtual void setup (btScalar height = 2.0, btScalar width = 0.25, btScalar stepHeight = 0.25) = 0;
virtual void destroy (btDynamicsWorld* dynamicsWorld) = 0; virtual void destroy () = 0;
virtual btCollisionObject* getCollisionObject () = 0; virtual btCollisionObject* getCollisionObject () = 0;
virtual void reset () = 0; virtual void reset () = 0;
virtual void warp (const btVector3& origin) = 0; virtual void warp (const btVector3& origin) = 0;
virtual void registerPairCacheAndDispatcher (btOverlappingPairCache* pairCache, btCollisionDispatcher* dispatcher)=0;
virtual void preStep (btDynamicsWorld* dynamicsWorld) = 0; virtual void preStep (const btDynamicsWorld* dynamicsWorld) = 0;
virtual void playerStep (btDynamicsWorld* dynamicsWorld, btScalar dt, virtual void playerStep (const btDynamicsWorld* dynamicsWorld, btScalar dt,
int forward, int forward,
int backward, int backward,
int left, int left,

View File

@@ -43,14 +43,25 @@ static int gLeft = 0;
static int gRight = 0; static int gRight = 0;
static int gJump = 0; static int gJump = 0;
#define QUAKE_BSP_IMPORTING 1 ///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(const btDynamicsWorld* dynamicsWorld, btScalar timeStep)
{
CharacterControllerInterface* characterInterface= (CharacterControllerInterface*) dynamicsWorld->getWorldUserInfo();
characterInterface->preStep (dynamicsWorld);
characterInterface->playerStep (dynamicsWorld, timeStep, gForward, gBackward, gLeft, gRight, gJump);
}
#define QUAKE_BSP_IMPORTING 1
#ifdef QUAKE_BSP_IMPORTING #ifdef QUAKE_BSP_IMPORTING
#include "../BspDemo/BspLoader.h" #include "../BspDemo/BspLoader.h"
#include "../BspDemo/BspConverter.h" #include "../BspDemo/BspConverter.h"
class BspToBulletConverter : public BspConverter class BspToBulletConverter : public BspConverter
{ {
CharacterDemo* m_demoApp; CharacterDemo* m_demoApp;
@@ -108,7 +119,10 @@ CharacterDemo::~CharacterDemo()
{ {
//cleanup in the reverse order of creation/initialization //cleanup in the reverse order of creation/initialization
if (m_character) if (m_character)
m_character->destroy (m_dynamicsWorld); {
m_dynamicsWorld->removeCollisionObject(m_character->getCollisionObject());
m_character->destroy ();
}
//remove the rigidbodies from the dynamics world and delete them //remove the rigidbodies from the dynamics world and delete them
@@ -163,8 +177,10 @@ class MyCustomOverlappingPairCallback : public btOverlappingPairCallback
{ {
bool needBroadphaseCollision(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) const bool needBroadphaseCollision(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) const
{ {
// we already know that the character proxy is either proxy0 or proxy1 bool collides = (proxy0->m_collisionFilterGroup & proxy1->m_collisionFilterMask) != 0;
return true; collides = collides && (proxy1->m_collisionFilterGroup & proxy0->m_collisionFilterMask);
return collides;
} }
} myCustomOverlapFilterCallback; } myCustomOverlapFilterCallback;
@@ -237,12 +253,12 @@ void CharacterDemo::initPhysics()
m_constraintSolver = new btSequentialImpulseConstraintSolver(); m_constraintSolver = new btSequentialImpulseConstraintSolver();
m_dynamicsWorld = new btDiscreteDynamicsWorld(m_dispatcher,m_overlappingPairCache,m_constraintSolver,m_collisionConfiguration); m_dynamicsWorld = new btDiscreteDynamicsWorld(m_dispatcher,m_overlappingPairCache,m_constraintSolver,m_collisionConfiguration);
//m_dynamicsWorld->setGravity(btVector3(0,0,0)); //m_dynamicsWorld->setGravity(btVector3(0,0,0));
btTransform tr; btTransform tr;
tr.setIdentity(); tr.setIdentity();
#define USE_BSP_STAGE
#ifdef USE_BSP_STAGE
#ifdef QUAKE_BSP_IMPORTING #ifdef QUAKE_BSP_IMPORTING
char* bspfilename = "BspDemo.bsp"; char* bspfilename = "BspDemo.bsp";
void* memoryBuffer = 0; void* memoryBuffer = 0;
@@ -286,7 +302,6 @@ void CharacterDemo::initPhysics()
fclose(file); fclose(file);
} }
#endif
#else #else
#define USE_TRIMESH_GROUND 1 #define USE_TRIMESH_GROUND 1
#ifdef USE_TRIMESH_GROUND #ifdef USE_TRIMESH_GROUND
@@ -477,12 +492,19 @@ const float TRIANGLE_SIZE=20.f;
#else #else
m_character = new KinematicCharacterController (); m_character = new KinematicCharacterController ();
#endif #endif
m_character->setup (m_dynamicsWorld); m_character->setup ();
m_dynamicsWorld->setInternalTickCallback(playerStepCallback,m_character);
//some custom callback sample //some custom callback sample
m_customPairCallback = new MyCustomOverlappingPairCallback(this,m_character->getCollisionObject()); m_customPairCallback = new MyCustomOverlappingPairCallback(this,m_character->getCollisionObject());
sweepBP->setOverlappingPairUserCallback(m_customPairCallback); sweepBP->setOverlappingPairUserCallback(m_customPairCallback);
m_character->registerPairCache (m_customPairCallback->getOverlappingPairCache()); m_character->registerPairCacheAndDispatcher (m_customPairCallback->getOverlappingPairCache(), m_dispatcher);
m_dynamicsWorld->addCollisionObject(m_character->getCollisionObject(),btBroadphaseProxy::DebrisFilter, btBroadphaseProxy::StaticFilter);//AllFilter);
clientResetScene(); clientResetScene();
setCameraDistance(26.f); setCameraDistance(26.f);
@@ -498,22 +520,11 @@ void CharacterDemo::renderme()
DemoApplication::renderme(); DemoApplication::renderme();
} }
void CharacterDemo::clientMoveAndDisplay()
void CharacterDemo::debugDrawContacts()
{ {
// printf("numPairs = %d\n",m_customPairCallback->getOverlappingPairArray().size());
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
float dt = getDeltaTimeMicroseconds() * 0.000001f;
/* Character stuff &*/
if (m_character)
{
m_character->preStep (m_dynamicsWorld);
m_character->playerStep (m_dynamicsWorld, dt, gForward, gBackward, gLeft, gRight, gJump);
}
#if 0
printf("numPairs = %d\n",m_customPairCallback->getOverlappingPairArray().size());
{ {
btManifoldArray manifoldArray; btManifoldArray manifoldArray;
for (int i=0;i<m_customPairCallback->getOverlappingPairArray().size();i++) for (int i=0;i<m_customPairCallback->getOverlappingPairArray().size();i++)
@@ -541,8 +552,23 @@ void CharacterDemo::clientMoveAndDisplay()
} }
} }
} }
#endif
}
void CharacterDemo::clientMoveAndDisplay()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
float dt = getDeltaTimeMicroseconds() * 0.000001f;
/* Character stuff &*/
if (m_character)
{
}
debugDrawContacts();
if (m_dynamicsWorld) if (m_dynamicsWorld)
@@ -612,6 +638,7 @@ void CharacterDemo::displayCallback(void)
if (m_dynamicsWorld) if (m_dynamicsWorld)
m_dynamicsWorld->debugDrawWorld(); m_dynamicsWorld->debugDrawWorld();
debugDrawContacts();
glFlush(); glFlush();
glutSwapBuffers(); glutSwapBuffers();
@@ -622,7 +649,8 @@ void CharacterDemo::clientResetScene()
m_dynamicsWorld->getBroadphase()->getOverlappingPairCache()->cleanProxyFromPairs(m_character->getCollisionObject()->getBroadphaseHandle(),getDynamicsWorld()->getDispatcher()); m_dynamicsWorld->getBroadphase()->getOverlappingPairCache()->cleanProxyFromPairs(m_character->getCollisionObject()->getBroadphaseHandle(),getDynamicsWorld()->getDispatcher());
m_character->reset (); m_character->reset ();
m_character->warp (btVector3(0.0, 1.75, 0.0)); ///WTF
m_character->warp (btVector3(0, -2.0, 0.));
} }
void CharacterDemo::specialKeyboardUp(int key, int x, int y) void CharacterDemo::specialKeyboardUp(int key, int x, int y)

View File

@@ -15,7 +15,12 @@ subject to the following restrictions:
#ifndef CHARACTER_DEMO_H #ifndef CHARACTER_DEMO_H
#define CHARACTER_DEMO_H #define CHARACTER_DEMO_H
class CharacterController;
///DYNAMIC_CHARACTER_CONTROLLER is not supported/obsolete at the moment
//#define DYNAMIC_CHARACTER_CONTROLLER 1
class CharacterControllerInterface;
class DynamicCharacterController;
class KinematicCharacterController; class KinematicCharacterController;
class btCollisionShape; class btCollisionShape;
@@ -29,7 +34,7 @@ class CharacterDemo : public DemoApplication
public: public:
#ifdef DYNAMIC_CHARACTER_CONTROLLER #ifdef DYNAMIC_CHARACTER_CONTROLLER
CharacterController* m_character; CharacterControllerInterface* m_character;
#else #else
KinematicCharacterController* m_character; KinematicCharacterController* m_character;
#endif #endif
@@ -50,6 +55,7 @@ class CharacterDemo : public DemoApplication
btVector3* m_vertices; btVector3* m_vertices;
void debugDrawContacts();
float m_cameraHeight; float m_cameraHeight;
@@ -67,7 +73,7 @@ class CharacterDemo : public DemoApplication
virtual void displayCallback(); virtual void displayCallback();
///a very basic camera following the vehicle ///a very basic camera following the character
virtual void updateCamera(); virtual void updateCamera();
virtual void specialKeyboard(int key, int x, int y); virtual void specialKeyboard(int key, int x, int y);

View File

@@ -21,7 +21,7 @@ DynamicCharacterController::~DynamicCharacterController ()
{ {
} }
void DynamicCharacterController::setup (btDynamicsWorld* dynamicsWorld, btScalar height, btScalar width, btScalar stepHeight) void DynamicCharacterController::setup (btScalar height, btScalar width, btScalar stepHeight)
{ {
btVector3 spherePositions[2]; btVector3 spherePositions[2];
btScalar sphereRadii[2]; btScalar sphereRadii[2];
@@ -45,10 +45,10 @@ void DynamicCharacterController::setup (btDynamicsWorld* dynamicsWorld, btScalar
//m_rigidBody->setCollisionFlags( m_rigidBody->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT); //m_rigidBody->setCollisionFlags( m_rigidBody->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT);
m_rigidBody->setSleepingThresholds (0.0, 0.0); m_rigidBody->setSleepingThresholds (0.0, 0.0);
m_rigidBody->setAngularFactor (0.0); m_rigidBody->setAngularFactor (0.0);
dynamicsWorld->addRigidBody (m_rigidBody);
} }
void DynamicCharacterController::destroy (btDynamicsWorld* dynamicsWorld) void DynamicCharacterController::destroy ()
{ {
if (m_shape) if (m_shape)
{ {
@@ -57,8 +57,8 @@ void DynamicCharacterController::destroy (btDynamicsWorld* dynamicsWorld)
if (m_rigidBody) if (m_rigidBody)
{ {
dynamicsWorld->removeRigidBody (m_rigidBody);
delete m_rigidBody; delete m_rigidBody;
m_rigidBody = 0;
} }
} }
@@ -67,7 +67,7 @@ btCollisionObject* DynamicCharacterController::getCollisionObject ()
return m_rigidBody; return m_rigidBody;
} }
void DynamicCharacterController::preStep (btDynamicsWorld* dynamicsWorld) void DynamicCharacterController::preStep (const btDynamicsWorld* dynamicsWorld)
{ {
btTransform xform; btTransform xform;
m_rigidBody->getMotionState()->getWorldTransform (xform); m_rigidBody->getMotionState()->getWorldTransform (xform);
@@ -118,7 +118,7 @@ void DynamicCharacterController::preStep (btDynamicsWorld* dynamicsWorld)
} }
} }
void DynamicCharacterController::playerStep (btScalar dt, void DynamicCharacterController::playerStep (const btDynamicsWorld* dynaWorld,btScalar dt,
int forward, int forward,
int backward, int backward,
int left, int left,
@@ -190,3 +190,15 @@ bool DynamicCharacterController::onGround () const
{ {
return m_rayLambda[0] < btScalar(1.0); return m_rayLambda[0] < btScalar(1.0);
} }
void DynamicCharacterController::reset ()
{
}
void DynamicCharacterController::warp (const btVector3& origin)
{
}
void DynamicCharacterController::registerPairCacheAndDispatcher (btOverlappingPairCache* pairCache, btCollisionDispatcher* dispatcher)
{
}

View File

@@ -9,6 +9,7 @@ class btCollisionShape;
class btRigidBody; class btRigidBody;
class btDynamicsWorld; class btDynamicsWorld;
///DynamicCharacterController is obsolete/unsupported at the moment
class DynamicCharacterController : public CharacterControllerInterface class DynamicCharacterController : public CharacterControllerInterface
{ {
protected: protected:
@@ -29,13 +30,17 @@ protected:
public: public:
DynamicCharacterController (); DynamicCharacterController ();
~DynamicCharacterController (); ~DynamicCharacterController ();
void setup (btDynamicsWorld* dynamicsWorld, btScalar height = 2.0, btScalar width = 0.25, btScalar stepHeight = 0.25); void setup (btScalar height = 2.0, btScalar width = 0.25, btScalar stepHeight = 0.25);
void destroy (btDynamicsWorld* dynamicsWorld); void destroy ();
virtual void reset ();
virtual void warp (const btVector3& origin);
virtual void registerPairCacheAndDispatcher (btOverlappingPairCache* pairCache, btCollisionDispatcher* dispatcher);
btCollisionObject* getCollisionObject (); btCollisionObject* getCollisionObject ();
void preStep (btDynamicsWorld* dynamicsWorld); void preStep (const btDynamicsWorld* dynamicsWorld);
void playerStep (btScalar dt, void playerStep (const btDynamicsWorld* dynaWorld,btScalar dt,
int forward, int forward,
int backward, int backward,
int left, int left,

View File

@@ -87,7 +87,7 @@ btVector3 perpindicularComponent (const btVector3& direction, const btVector3& n
KinematicCharacterController::KinematicCharacterController () KinematicCharacterController::KinematicCharacterController ()
{ {
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_walkVelocity = btScalar(1.1) * 14.0; // 4 km/h -> 1.1 m/s
m_shape = NULL; m_shape = NULL;
m_pairCache = NULL; m_pairCache = NULL;
m_collisionObject = NULL; m_collisionObject = NULL;
@@ -97,15 +97,15 @@ KinematicCharacterController::~KinematicCharacterController ()
{ {
} }
void KinematicCharacterController::setup (btDynamicsWorld* dynamicsWorld, btScalar height, btScalar width, btScalar stepHeight) void KinematicCharacterController::setup (btScalar height, btScalar width, btScalar stepHeight)
{ {
btVector3 spherePositions[2]; btVector3 spherePositions[2];
btScalar sphereRadii[2]; btScalar sphereRadii[2];
sphereRadii[0] = width; sphereRadii[0] = width;
sphereRadii[1] = width; sphereRadii[1] = width;
spherePositions[0] = btVector3 (0.0, (height/btScalar(2.0) - width), 0.0); spherePositions[0] = btVector3 (0.0, (height/btScalar(2.0) ), 0.0);
spherePositions[1] = btVector3 (0.0, (-height/btScalar(2.0) + width), 0.0); spherePositions[1] = btVector3 (0.0, (-height/btScalar(2.0)), 0.0);
m_halfHeight = height/btScalar(2.0); m_halfHeight = height/btScalar(2.0);
@@ -116,19 +116,20 @@ void KinematicCharacterController::setup (btDynamicsWorld* dynamicsWorld, btScal
btTransform startTransform; btTransform startTransform;
startTransform.setIdentity (); startTransform.setIdentity ();
startTransform.setOrigin (btVector3(0.0, 4.0, 0.0)); startTransform.setOrigin (btVector3(0.0, 4.0, 0.0));
btDefaultMotionState* myMotionState = new btDefaultMotionState(startTransform); //btDefaultMotionState* myMotionState = new btDefaultMotionState(startTransform);
btRigidBody::btRigidBodyConstructionInfo cInfo(1.0, myMotionState, m_shape); //btRigidBody::btRigidBodyConstructionInfo cInfo(1.0, myMotionState, m_shape);
m_collisionObject = new btCollisionObject (); m_collisionObject = new btCollisionObject ();
m_collisionObject->setWorldTransform(startTransform);
m_collisionObject->setCollisionShape (m_shape); m_collisionObject->setCollisionShape (m_shape);
m_collisionObject->setCollisionFlags (btCollisionObject::CF_KINEMATIC_OBJECT); m_collisionObject->setCollisionFlags (btCollisionObject::CF_NO_CONTACT_RESPONSE);
dynamicsWorld->addCollisionObject (m_collisionObject);
} }
void KinematicCharacterController::destroy (btDynamicsWorld* dynamicsWorld) void KinematicCharacterController::destroy ()
{ {
if (m_collisionObject) if (m_collisionObject)
{ {
dynamicsWorld->removeCollisionObject (m_collisionObject);
delete m_collisionObject; delete m_collisionObject;
} }
@@ -143,29 +144,33 @@ btCollisionObject* KinematicCharacterController::getCollisionObject ()
return m_collisionObject; return m_collisionObject;
} }
bool KinematicCharacterController::recoverFromPenetration (btDynamicsWorld* dynamicsWorld) bool KinematicCharacterController::recoverFromPenetration (const btDynamicsWorld* dynamicsWorld)
{ {
if (m_pairCache == NULL) if (m_pairCache == NULL)
return false; return false;
bool penetration = false; bool penetration = false;
dynamicsWorld->getDispatcher()->dispatchAllCollisionPairs (m_pairCache, dynamicsWorld->getDispatchInfo(), dynamicsWorld->getDispatcher());
m_dispatcher->dispatchAllCollisionPairs (m_pairCache, dynamicsWorld->getDispatchInfo(), m_dispatcher);
btManifoldArray manifoldArray; m_currentPosition = m_collisionObject->getWorldTransform().getOrigin();
btScalar maxPen = btScalar(0.0); btScalar maxPen = btScalar(0.0);
for (int i = 0; i < m_pairCache->getNumOverlappingPairs(); i++) for (int i = 0; i < m_pairCache->getNumOverlappingPairs(); i++)
{ {
manifoldArray.clear(); m_manifoldArray.resize(0);
btBroadphasePair* collisionPair = &m_pairCache->getOverlappingPairArray()[i]; btBroadphasePair* collisionPair = &m_pairCache->getOverlappingPairArray()[i];
if (collisionPair->m_algorithm) if (collisionPair->m_algorithm)
collisionPair->m_algorithm->getAllContactManifolds(manifoldArray); collisionPair->m_algorithm->getAllContactManifolds(m_manifoldArray);
for (int j=0;j<manifoldArray.size();j++)
for (int j=0;j<m_manifoldArray.size();j++)
{ {
btPersistentManifold* manifold = manifoldArray[j]; btPersistentManifold* manifold = m_manifoldArray[j];
btScalar directionSign = manifold->getBody0() == m_collisionObject ? btScalar(-1.0) : btScalar(1.0); btScalar directionSign = manifold->getBody0() == m_collisionObject ? btScalar(-1.0) : btScalar(1.0);
for (int p=0;p<manifold->getNumContacts();p++) for (int p=0;p<manifold->getNumContacts();p++)
{ {
@@ -176,7 +181,8 @@ bool KinematicCharacterController::recoverFromPenetration (btDynamicsWorld* dyna
if (pt.getDistance() < maxPen) if (pt.getDistance() < maxPen)
{ {
maxPen = pt.getDistance(); maxPen = pt.getDistance();
m_touchingNormal = pt.m_normalWorldOnB * directionSign; m_touchingNormal = pt.m_normalWorldOnB * directionSign;//??
} }
m_currentPosition += pt.m_normalWorldOnB * directionSign * pt.getDistance() * btScalar(0.2); m_currentPosition += pt.m_normalWorldOnB * directionSign * pt.getDistance() * btScalar(0.2);
penetration = true; penetration = true;
@@ -184,13 +190,18 @@ bool KinematicCharacterController::recoverFromPenetration (btDynamicsWorld* dyna
//printf("touching %f\n", pt.getDistance()); //printf("touching %f\n", pt.getDistance());
} }
} }
manifold->clearManifold();
//manifold->clearManifold();
} }
} }
btTransform newTrans = m_collisionObject->getWorldTransform();
newTrans.setOrigin(m_currentPosition);
m_collisionObject->setWorldTransform(newTrans);
// printf("m_touchingNormal = %f,%f,%f\n",m_touchingNormal[0],m_touchingNormal[1],m_touchingNormal[2]);
return penetration; return penetration;
} }
void KinematicCharacterController::stepUp (btDynamicsWorld* dynamicsWorld) void KinematicCharacterController::stepUp (const btDynamicsWorld* dynamicsWorld)
{ {
// phase 1: up // phase 1: up
btTransform start, end; btTransform start, end;
@@ -222,31 +233,47 @@ void KinematicCharacterController::updateTargetPositionBasedOnCollision (const b
{ {
btVector3 movementDirection = m_targetPosition - m_currentPosition; btVector3 movementDirection = m_targetPosition - m_currentPosition;
btScalar movementLength = movementDirection.length(); btScalar movementLength = movementDirection.length();
movementDirection.normalize(); if (movementLength>SIMD_EPSILON)
btVector3 reflectDir = computeReflectionDirection (movementDirection, hitNormal);
reflectDir.normalize();
btVector3 parallelDir, perpindicularDir;
parallelDir = parallelComponent (reflectDir, hitNormal);
perpindicularDir = perpindicularComponent (reflectDir, hitNormal);
m_targetPosition = m_currentPosition;
if (tangentMag != 0.0)
{ {
m_targetPosition += parallelDir * btScalar (tangentMag*movementLength); movementDirection.normalize();
}
if (normalMag != 0.0) btVector3 reflectDir = computeReflectionDirection (movementDirection, hitNormal);
reflectDir.normalize();
btVector3 parallelDir, perpindicularDir;
parallelDir = parallelComponent (reflectDir, hitNormal);
perpindicularDir = perpindicularComponent (reflectDir, hitNormal);
m_targetPosition = m_currentPosition;
if (0)//tangentMag != 0.0)
{
btVector3 parComponent = parallelDir * btScalar (tangentMag*movementLength);
// printf("parComponent=%f,%f,%f\n",parComponent[0],parComponent[1],parComponent[2]);
m_targetPosition += parComponent;
}
if (normalMag != 0.0)
{
btVector3 perpComponent = perpindicularDir * btScalar (normalMag*movementLength);
// printf("perpComponent=%f,%f,%f\n",perpComponent[0],perpComponent[1],perpComponent[2]);
m_targetPosition += perpComponent;
}
} else
{ {
m_targetPosition += perpindicularDir * btScalar (normalMag*movementLength); // printf("movementLength don't normalize a zero vector\n");
} }
} }
void KinematicCharacterController::stepForwardAndStrafe (btDynamicsWorld* dynamicsWorld, const btVector3& walkMove) void KinematicCharacterController::stepForwardAndStrafe (const btDynamicsWorld* dynamicsWorld, const btVector3& walkMove)
{ {
btVector3 originalDir = walkMove.normalized(); btVector3 originalDir = walkMove.normalized();
if (walkMove.length() < SIMD_EPSILON)
{
originalDir.setValue(0.f,0.f,0.f);
}
// printf("originalDir=%f,%f,%f\n",originalDir[0],originalDir[1],originalDir[2]);
// phase 2: forward and strafe // phase 2: forward and strafe
btTransform start, end; btTransform start, end;
m_targetPosition = m_currentPosition + walkMove; m_targetPosition = m_currentPosition + walkMove;
@@ -255,6 +282,7 @@ void KinematicCharacterController::stepForwardAndStrafe (btDynamicsWorld* dynami
btScalar fraction = 1.0; btScalar fraction = 1.0;
btScalar distance2 = (m_currentPosition-m_targetPosition).length2(); btScalar distance2 = (m_currentPosition-m_targetPosition).length2();
// printf("distance2=%f\n",distance2);
if (m_touchingContact) if (m_touchingContact)
{ {
@@ -262,44 +290,67 @@ void KinematicCharacterController::stepForwardAndStrafe (btDynamicsWorld* dynami
updateTargetPositionBasedOnCollision (m_touchingNormal); updateTargetPositionBasedOnCollision (m_touchingNormal);
} }
while (fraction > btScalar(0.01)) int maxIter = 10;
while (fraction > btScalar(0.01) && maxIter-- > 0)
{ {
start.setOrigin (m_currentPosition); start.setOrigin (m_currentPosition);
end.setOrigin (m_targetPosition); end.setOrigin (m_targetPosition);
ClosestNotMeConvexResultCallback callback (m_collisionObject); ClosestNotMeConvexResultCallback callback (m_collisionObject);
dynamicsWorld->convexSweepTest (m_shape, start, end, callback);
//btScalar margin = m_shape->getMargin();
//m_shape->setMargin(margin - 0.06f);
dynamicsWorld->convexSweepTest (m_shape, start, end, callback);
//m_shape->setMargin(margin);
fraction -= callback.m_closestHitFraction; fraction -= callback.m_closestHitFraction;
if (callback.HasHit()) if (callback.HasHit())
{ {
// we moved only a fraction // we moved only a fraction
btScalar hitDistance = (callback.m_hitPointWorld - m_currentPosition).length(); btScalar hitDistance = (callback.m_hitPointWorld - m_currentPosition).length();
if (hitDistance<0.f)
{
// printf("neg dist?\n");
}
/* If the distance is farther than the collision margin, move */ /* If the distance is farther than the collision margin, move */
if (hitDistance > 0.05) if (hitDistance > 0.05)
{ {
// printf("callback.m_closestHitFraction=%f\n",callback.m_closestHitFraction);
m_currentPosition.setInterpolate3 (m_currentPosition, m_targetPosition, callback.m_closestHitFraction); m_currentPosition.setInterpolate3 (m_currentPosition, m_targetPosition, callback.m_closestHitFraction);
} }
updateTargetPositionBasedOnCollision (callback.m_hitNormalWorld); updateTargetPositionBasedOnCollision (callback.m_hitNormalWorld);
btVector3 currentDir = m_targetPosition - m_currentPosition; btVector3 currentDir = m_targetPosition - m_currentPosition;
distance2 = currentDir.length2(); distance2 = currentDir.length2();
currentDir.normalize(); if (distance2 > SIMD_EPSILON)
/* Ageia's C.C. took this test from Quake2: "If velocity is against original velocity, stop ead to avoid tiny oscilations in sloping corners." */
if (currentDir.dot(originalDir) <= btScalar(0.0))
{ {
currentDir.normalize();
/* See Quake2: "If velocity is against original velocity, stop ead to avoid tiny oscilations in sloping corners." */
if (currentDir.dot(originalDir) <= btScalar(0.0))
{
break;
}
} else
{
// printf("currentDir: don't normalize a zero vector\n");
break; break;
} }
} else { } else {
// we moved whole way // we moved whole way
m_currentPosition = m_targetPosition; m_currentPosition = m_targetPosition;
} }
// if (callback.m_closestHitFraction == 0.f)
// break;
} }
} }
void KinematicCharacterController::stepDown (btDynamicsWorld* dynamicsWorld, btScalar dt) void KinematicCharacterController::stepDown (const btDynamicsWorld* dynamicsWorld, btScalar dt)
{ {
btTransform start, end; btTransform start, end;
@@ -341,13 +392,15 @@ void KinematicCharacterController::warp (const btVector3& origin)
m_collisionObject->setWorldTransform (xform); m_collisionObject->setWorldTransform (xform);
} }
void KinematicCharacterController::registerPairCache (btOverlappingPairCache* pairCache) void KinematicCharacterController::registerPairCacheAndDispatcher (btOverlappingPairCache* pairCache, btCollisionDispatcher* dispatcher)
{ {
m_pairCache = pairCache; m_pairCache = pairCache;
m_dispatcher = dispatcher;
} }
void KinematicCharacterController::preStep (btDynamicsWorld* dynamicsWorld) void KinematicCharacterController::preStep (const btDynamicsWorld* dynamicsWorld)
{ {
int numPenetrationLoops = 0; int numPenetrationLoops = 0;
m_touchingContact = false; m_touchingContact = false;
while (recoverFromPenetration (dynamicsWorld)) while (recoverFromPenetration (dynamicsWorld))
@@ -356,7 +409,7 @@ void KinematicCharacterController::preStep (btDynamicsWorld* dynamicsWorld)
m_touchingContact = true; m_touchingContact = true;
if (numPenetrationLoops > 4) if (numPenetrationLoops > 4)
{ {
printf("character could not recover from penetration = %d\n", numPenetrationLoops); // printf("character could not recover from penetration = %d\n", numPenetrationLoops);
break; break;
} }
} }
@@ -364,6 +417,7 @@ void KinematicCharacterController::preStep (btDynamicsWorld* dynamicsWorld)
xform = m_collisionObject->getWorldTransform (); xform = m_collisionObject->getWorldTransform ();
btVector3 forwardDir = xform.getBasis()[2]; btVector3 forwardDir = xform.getBasis()[2];
// printf("forwardDir=%f,%f,%f\n",forwardDir[0],forwardDir[1],forwardDir[2]);
btVector3 upDir = xform.getBasis()[1]; btVector3 upDir = xform.getBasis()[1];
btVector3 strafeDir = xform.getBasis()[0]; btVector3 strafeDir = xform.getBasis()[0];
forwardDir.normalize (); forwardDir.normalize ();
@@ -376,11 +430,12 @@ void KinematicCharacterController::preStep (btDynamicsWorld* dynamicsWorld)
m_currentPosition = xform.getOrigin(); 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]);
} }
void KinematicCharacterController::playerStep (btDynamicsWorld* dynamicsWorld, void KinematicCharacterController::playerStep (const btDynamicsWorld* dynamicsWorld,
btScalar dt, btScalar dt,
int forward, int forward,
int backward, int backward,
@@ -406,6 +461,9 @@ void KinematicCharacterController::playerStep (btDynamicsWorld* dynamicsWorld,
btTransform xform; btTransform xform;
xform = m_collisionObject->getWorldTransform (); xform = m_collisionObject->getWorldTransform ();
// printf("walkDirection(%f,%f,%f)\n",walkDirection[0],walkDirection[1],walkDirection[2]);
// printf("walkSpeed=%f\n",walkSpeed);
stepUp (dynamicsWorld); stepUp (dynamicsWorld);
stepForwardAndStrafe (dynamicsWorld, walkDirection * walkSpeed); stepForwardAndStrafe (dynamicsWorld, walkDirection * walkSpeed);
stepDown (dynamicsWorld, dt); stepDown (dynamicsWorld, dt);

View File

@@ -8,7 +8,12 @@
class btCollisionShape; class btCollisionShape;
class btRigidBody; class btRigidBody;
class btDynamicsWorld; class btDynamicsWorld;
class btCollisionDispatcher;
///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 class KinematicCharacterController : public CharacterControllerInterface
{ {
protected: protected:
@@ -16,6 +21,7 @@ protected:
btConvexShape* m_shape; btConvexShape* m_shape;
btCollisionObject* m_collisionObject; btCollisionObject* m_collisionObject;
btOverlappingPairCache* m_pairCache; btOverlappingPairCache* m_pairCache;
btCollisionDispatcher* m_dispatcher;
btScalar m_fallSpeed; btScalar m_fallSpeed;
btScalar m_jumpSpeed; btScalar m_jumpSpeed;
@@ -36,28 +42,30 @@ protected:
btScalar m_currentStepOffset; btScalar m_currentStepOffset;
btVector3 m_targetPosition; btVector3 m_targetPosition;
btManifoldArray m_manifoldArray;
bool m_touchingContact; bool m_touchingContact;
btVector3 m_touchingNormal; btVector3 m_touchingNormal;
bool recoverFromPenetration (btDynamicsWorld* dynamicsWorld); bool recoverFromPenetration (const btDynamicsWorld* dynamicsWorld);
void stepUp (btDynamicsWorld* dynamicsWorld); void stepUp (const btDynamicsWorld* dynamicsWorld);
void updateTargetPositionBasedOnCollision (const btVector3& hit_normal, btScalar tangentMag = btScalar(1.0), btScalar normalMag = btScalar(0.0)); void updateTargetPositionBasedOnCollision (const btVector3& hit_normal, btScalar tangentMag = btScalar(0.0), btScalar normalMag = btScalar(1.0));
void stepForwardAndStrafe (btDynamicsWorld* dynamicsWorld, const btVector3& walkMove); void stepForwardAndStrafe (const btDynamicsWorld* dynamicsWorld, const btVector3& walkMove);
void stepDown (btDynamicsWorld* dynamicsWorld, btScalar dt); void stepDown (const btDynamicsWorld* dynamicsWorld, btScalar dt);
public: public:
KinematicCharacterController (); KinematicCharacterController ();
~KinematicCharacterController (); ~KinematicCharacterController ();
void setup (btDynamicsWorld* dynamicsWorld, btScalar height = btScalar(1.75), btScalar width = btScalar(0.4), btScalar stepHeight = btScalar(0.35)); void setup (btScalar height = btScalar(1.75), btScalar width = btScalar(0.4), btScalar stepHeight = btScalar(0.35));
void destroy (btDynamicsWorld* dynamicsWorld); void destroy ();
btCollisionObject* getCollisionObject (); btCollisionObject* getCollisionObject ();
void reset (); void reset ();
void warp (const btVector3& origin); void warp (const btVector3& origin);
void registerPairCache (btOverlappingPairCache* pairCache); virtual void registerPairCacheAndDispatcher (btOverlappingPairCache* pairCache, btCollisionDispatcher* dispatcher);
void preStep (btDynamicsWorld* dynamicsWorld); void preStep (const btDynamicsWorld* dynamicsWorld);
void playerStep (btDynamicsWorld* dynamicsWorld, btScalar dt, void playerStep (const btDynamicsWorld* dynamicsWorld, btScalar dt,
int forward, int forward,
int backward, int backward,
int left, int left,

View File

@@ -82,12 +82,12 @@ SpuGatheringCollisionDispatcher::~SpuGatheringCollisionDispatcher()
///this is useful for the collision dispatcher. ///this is useful for the collision dispatcher.
class btSpuCollisionPairCallback : public btOverlapCallback class btSpuCollisionPairCallback : public btOverlapCallback
{ {
btDispatcherInfo& m_dispatchInfo; const btDispatcherInfo& m_dispatchInfo;
SpuGatheringCollisionDispatcher* m_dispatcher; SpuGatheringCollisionDispatcher* m_dispatcher;
public: public:
btSpuCollisionPairCallback(btDispatcherInfo& dispatchInfo,SpuGatheringCollisionDispatcher* dispatcher) btSpuCollisionPairCallback(const btDispatcherInfo& dispatchInfo, SpuGatheringCollisionDispatcher* dispatcher)
:m_dispatchInfo(dispatchInfo), :m_dispatchInfo(dispatchInfo),
m_dispatcher(dispatcher) m_dispatcher(dispatcher)
{ {
@@ -141,7 +141,7 @@ public:
} }
}; };
void SpuGatheringCollisionDispatcher::dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,btDispatcherInfo& dispatchInfo,btDispatcher* dispatcher) void SpuGatheringCollisionDispatcher::dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,const btDispatcherInfo& dispatchInfo, btDispatcher* dispatcher)
{ {
if (dispatchInfo.m_enableSPU) if (dispatchInfo.m_enableSPU)

View File

@@ -55,7 +55,7 @@ public:
bool supportsDispatchPairOnSpu(int proxyType0,int proxyType1); bool supportsDispatchPairOnSpu(int proxyType0,int proxyType1);
virtual void dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,btDispatcherInfo& dispatchInfo,btDispatcher* dispatcher); virtual void dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,const btDispatcherInfo& dispatchInfo,btDispatcher* dispatcher) ;
}; };

View File

@@ -44,6 +44,8 @@ struct btDispatcherInfo
m_debugDraw(0), m_debugDraw(0),
m_enableSatConvex(false), m_enableSatConvex(false),
m_enableSPU(true), m_enableSPU(true),
m_useEpa(true),
m_allowedCcdPenetration(btScalar(0.04)),
m_stackAllocator(0) m_stackAllocator(0)
{ {
@@ -51,12 +53,13 @@ struct btDispatcherInfo
btScalar m_timeStep; btScalar m_timeStep;
int m_stepCount; int m_stepCount;
int m_dispatchFunc; int m_dispatchFunc;
btScalar m_timeOfImpact; mutable btScalar m_timeOfImpact;
bool m_useContinuous; bool m_useContinuous;
class btIDebugDraw* m_debugDraw; class btIDebugDraw* m_debugDraw;
bool m_enableSatConvex; bool m_enableSatConvex;
bool m_enableSPU; bool m_enableSPU;
bool m_useEpa; bool m_useEpa;
btScalar m_allowedCcdPenetration;
btStackAlloc* m_stackAllocator; btStackAlloc* m_stackAllocator;
}; };
@@ -82,7 +85,7 @@ public:
virtual bool needsResponse(btCollisionObject* body0,btCollisionObject* body1)=0; virtual bool needsResponse(btCollisionObject* body0,btCollisionObject* body1)=0;
virtual void dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,btDispatcherInfo& dispatchInfo,btDispatcher* dispatcher)=0; virtual void dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,const btDispatcherInfo& dispatchInfo,btDispatcher* dispatcher) =0;
virtual int getNumManifolds() const = 0; virtual int getNumManifolds() const = 0;
@@ -90,7 +93,7 @@ public:
virtual btPersistentManifold** getInternalManifoldPointer() = 0; virtual btPersistentManifold** getInternalManifoldPointer() = 0;
virtual void* allocateCollisionAlgorithm(int size) = 0; virtual void* allocateCollisionAlgorithm(int size) = 0;
virtual void freeCollisionAlgorithm(void* ptr) = 0; virtual void freeCollisionAlgorithm(void* ptr) = 0;

View File

@@ -399,7 +399,7 @@ public:
{ {
} }
virtual void processAllOverlappingPairs(btOverlapCallback*,btDispatcher* /*dispatcher*/) virtual void processAllOverlappingPairs(btOverlapCallback*,const btDispatcher* /*dispatcher*/)
{ {
} }

View File

@@ -191,23 +191,25 @@ bool btCollisionDispatcher::needsCollision(btCollisionObject* body0,btCollisionO
///this is useful for the collision dispatcher. ///this is useful for the collision dispatcher.
class btCollisionPairCallback : public btOverlapCallback class btCollisionPairCallback : public btOverlapCallback
{ {
btDispatcherInfo& m_dispatchInfo; const btDispatcherInfo& m_dispatchInfo;
btCollisionDispatcher* m_dispatcher; btCollisionDispatcher* m_dispatcher;
public: public:
btCollisionPairCallback(btDispatcherInfo& dispatchInfo,btCollisionDispatcher* dispatcher) btCollisionPairCallback(const btDispatcherInfo& dispatchInfo,btCollisionDispatcher* dispatcher)
:m_dispatchInfo(dispatchInfo), :m_dispatchInfo(dispatchInfo),
m_dispatcher(dispatcher) m_dispatcher(dispatcher)
{ {
} }
btCollisionPairCallback& operator=(btCollisionPairCallback& other) /*btCollisionPairCallback& operator=(btCollisionPairCallback& other)
{ {
m_dispatchInfo = other.m_dispatchInfo; m_dispatchInfo = other.m_dispatchInfo;
m_dispatcher = other.m_dispatcher; m_dispatcher = other.m_dispatcher;
return *this; return *this;
} }
*/
virtual ~btCollisionPairCallback() {} virtual ~btCollisionPairCallback() {}
@@ -221,7 +223,8 @@ public:
}; };
void btCollisionDispatcher::dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,btDispatcherInfo& dispatchInfo,btDispatcher* dispatcher)
void btCollisionDispatcher::dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,const btDispatcherInfo& dispatchInfo,btDispatcher* dispatcher)
{ {
//m_blockedForChanges = true; //m_blockedForChanges = true;
@@ -237,7 +240,7 @@ void btCollisionDispatcher::dispatchAllCollisionPairs(btOverlappingPairCache* pa
//by default, Bullet will use this near callback //by default, Bullet will use this near callback
void btCollisionDispatcher::defaultNearCallback(btBroadphasePair& collisionPair, btCollisionDispatcher& dispatcher, btDispatcherInfo& dispatchInfo) void btCollisionDispatcher::defaultNearCallback(btBroadphasePair& collisionPair, btCollisionDispatcher& dispatcher, const btDispatcherInfo& dispatchInfo)
{ {
btCollisionObject* colObj0 = (btCollisionObject*)collisionPair.m_pProxy0->m_clientObject; btCollisionObject* colObj0 = (btCollisionObject*)collisionPair.m_pProxy0->m_clientObject;
btCollisionObject* colObj1 = (btCollisionObject*)collisionPair.m_pProxy1->m_clientObject; btCollisionObject* colObj1 = (btCollisionObject*)collisionPair.m_pProxy1->m_clientObject;

View File

@@ -35,7 +35,7 @@ class btCollisionConfiguration;
class btCollisionDispatcher; class btCollisionDispatcher;
///user can override this nearcallback for collision filtering and more finegrained control over collision detection ///user can override this nearcallback for collision filtering and more finegrained control over collision detection
typedef void (*btNearCallback)(btBroadphasePair& collisionPair, btCollisionDispatcher& dispatcher, btDispatcherInfo& dispatchInfo); typedef void (*btNearCallback)(btBroadphasePair& collisionPair, btCollisionDispatcher& dispatcher, const btDispatcherInfo& dispatchInfo);
///btCollisionDispatcher supports algorithms that handle ConvexConvex and ConvexConcave collision pairs. ///btCollisionDispatcher supports algorithms that handle ConvexConvex and ConvexConcave collision pairs.
@@ -107,7 +107,7 @@ public:
virtual bool needsResponse(btCollisionObject* body0,btCollisionObject* body1); virtual bool needsResponse(btCollisionObject* body0,btCollisionObject* body1);
virtual void dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,btDispatcherInfo& dispatchInfo,btDispatcher* dispatcher); virtual void dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,const btDispatcherInfo& dispatchInfo,btDispatcher* dispatcher) ;
void setNearCallback(btNearCallback nearCallback) void setNearCallback(btNearCallback nearCallback)
{ {
@@ -120,7 +120,7 @@ public:
} }
//by default, Bullet will use this near callback //by default, Bullet will use this near callback
static void defaultNearCallback(btBroadphasePair& collisionPair, btCollisionDispatcher& dispatcher, btDispatcherInfo& dispatchInfo); static void defaultNearCallback(btBroadphasePair& collisionPair, btCollisionDispatcher& dispatcher, const btDispatcherInfo& dispatchInfo);
virtual void* allocateCollisionAlgorithm(int size); virtual void* allocateCollisionAlgorithm(int size);

View File

@@ -4,8 +4,8 @@ Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
This software is provided 'as-is', without any express or implied warranty. 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. 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, Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely, including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions: 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. 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.
@@ -57,7 +57,7 @@ btCollisionWorld::~btCollisionWorld()
for (i=0;i<m_collisionObjects.size();i++) for (i=0;i<m_collisionObjects.size();i++)
{ {
btCollisionObject* collisionObject= m_collisionObjects[i]; btCollisionObject* collisionObject= m_collisionObjects[i];
btBroadphaseProxy* bp = collisionObject->getBroadphaseHandle(); btBroadphaseProxy* bp = collisionObject->getBroadphaseHandle();
if (bp) if (bp)
{ {
@@ -107,7 +107,7 @@ void btCollisionWorld::addCollisionObject(btCollisionObject* collisionObject,sho
m_dispatcher1,0 m_dispatcher1,0
)) ; )) ;
@@ -116,12 +116,12 @@ void btCollisionWorld::addCollisionObject(btCollisionObject* collisionObject,sho
void btCollisionWorld::updateAabbs() void btCollisionWorld::updateAabbs()
{ {
BT_PROFILE("updateAabbs"); BT_PROFILE("updateAabbs");
btTransform predictedTrans; btTransform predictedTrans;
for ( int i=0;i<m_collisionObjects.size();i++) for ( int i=0;i<m_collisionObjects.size();i++)
{ {
btCollisionObject* colObj = m_collisionObjects[i]; btCollisionObject* colObj = m_collisionObjects[i];
//only update aabb of active objects //only update aabb of active objects
if (colObj->isActive()) if (colObj->isActive())
{ {
@@ -138,7 +138,7 @@ void btCollisionWorld::updateAabbs()
//something went wrong, investigate //something went wrong, investigate
//this assert is unwanted in 3D modelers (danger of loosing work) //this assert is unwanted in 3D modelers (danger of loosing work)
colObj->setActivationState(DISABLE_SIMULATION); colObj->setActivationState(DISABLE_SIMULATION);
static bool reportMe = true; static bool reportMe = true;
if (reportMe && m_debugDrawer) if (reportMe && m_debugDrawer)
{ {
@@ -151,7 +151,7 @@ void btCollisionWorld::updateAabbs()
} }
} }
} }
} }
@@ -183,12 +183,12 @@ void btCollisionWorld::performDiscreteCollisionDetection()
void btCollisionWorld::removeCollisionObject(btCollisionObject* collisionObject) void btCollisionWorld::removeCollisionObject(btCollisionObject* collisionObject)
{ {
//bool removeFromBroadphase = false; //bool removeFromBroadphase = false;
{ {
btBroadphaseProxy* bp = collisionObject->getBroadphaseHandle(); btBroadphaseProxy* bp = collisionObject->getBroadphaseHandle();
if (bp) if (bp)
{ {
@@ -233,12 +233,12 @@ void btCollisionWorld::rayTestSingle(const btTransform& rayFromTrans,const btTra
//btGjkConvexCast convexCaster(castShape,convexShape,&simplexSolver); //btGjkConvexCast convexCaster(castShape,convexShape,&simplexSolver);
//btContinuousConvexCollision convexCaster(castShape,convexShape,&simplexSolver,0); //btContinuousConvexCollision convexCaster(castShape,convexShape,&simplexSolver,0);
#endif //#USE_SUBSIMPLEX_CONVEX_CAST #endif //#USE_SUBSIMPLEX_CONVEX_CAST
if (convexCaster.calcTimeOfImpact(rayFromTrans,rayToTrans,colObjWorldTransform,colObjWorldTransform,castResult)) if (convexCaster.calcTimeOfImpact(rayFromTrans,rayToTrans,colObjWorldTransform,colObjWorldTransform,castResult))
{ {
//add hit //add hit
if (castResult.m_normal.length2() > btScalar(0.0001)) if (castResult.m_normal.length2() > btScalar(0.0001))
{ {
if (castResult.m_fraction < resultCallback.m_closestHitFraction) if (castResult.m_fraction < resultCallback.m_closestHitFraction)
{ {
#ifdef USE_SUBSIMPLEX_CONVEX_CAST #ifdef USE_SUBSIMPLEX_CONVEX_CAST
@@ -249,7 +249,7 @@ void btCollisionWorld::rayTestSingle(const btTransform& rayFromTrans,const btTra
castResult.m_normal.normalize(); castResult.m_normal.normalize();
btCollisionWorld::LocalRayResult localRayResult btCollisionWorld::LocalRayResult localRayResult
( (
collisionObject, collisionObject,
0, 0,
castResult.m_normal, castResult.m_normal,
castResult.m_fraction castResult.m_fraction
@@ -273,7 +273,7 @@ void btCollisionWorld::rayTestSingle(const btTransform& rayFromTrans,const btTra
btVector3 rayToLocal = worldTocollisionObject * rayToTrans.getOrigin(); btVector3 rayToLocal = worldTocollisionObject * rayToTrans.getOrigin();
//ConvexCast::CastResult //ConvexCast::CastResult
struct BridgeTriangleRaycastCallback : public btTriangleRaycastCallback struct BridgeTriangleRaycastCallback : public btTriangleRaycastCallback
{ {
btCollisionWorld::RayResultCallback* m_resultCallback; btCollisionWorld::RayResultCallback* m_resultCallback;
btCollisionObject* m_collisionObject; btCollisionObject* m_collisionObject;
@@ -294,13 +294,13 @@ void btCollisionWorld::rayTestSingle(const btTransform& rayFromTrans,const btTra
btCollisionWorld::LocalShapeInfo shapeInfo; btCollisionWorld::LocalShapeInfo shapeInfo;
shapeInfo.m_shapePart = partId; shapeInfo.m_shapePart = partId;
shapeInfo.m_triangleIndex = triangleIndex; shapeInfo.m_triangleIndex = triangleIndex;
btCollisionWorld::LocalRayResult rayResult btCollisionWorld::LocalRayResult rayResult
(m_collisionObject, (m_collisionObject,
&shapeInfo, &shapeInfo,
hitNormalLocal, hitNormalLocal,
hitFraction); hitFraction);
bool normalInWorldSpace = false; bool normalInWorldSpace = false;
return m_resultCallback->AddSingleResult(rayResult,normalInWorldSpace); return m_resultCallback->AddSingleResult(rayResult,normalInWorldSpace);
} }
@@ -313,7 +313,7 @@ void btCollisionWorld::rayTestSingle(const btTransform& rayFromTrans,const btTra
} else } else
{ {
btTriangleMeshShape* triangleMesh = (btTriangleMeshShape*)collisionShape; btTriangleMeshShape* triangleMesh = (btTriangleMeshShape*)collisionShape;
btTransform worldTocollisionObject = colObjWorldTransform.inverse(); btTransform worldTocollisionObject = colObjWorldTransform.inverse();
btVector3 rayFromLocal = worldTocollisionObject * rayFromTrans.getOrigin(); btVector3 rayFromLocal = worldTocollisionObject * rayFromTrans.getOrigin();
@@ -321,7 +321,7 @@ void btCollisionWorld::rayTestSingle(const btTransform& rayFromTrans,const btTra
//ConvexCast::CastResult //ConvexCast::CastResult
struct BridgeTriangleRaycastCallback : public btTriangleRaycastCallback struct BridgeTriangleRaycastCallback : public btTriangleRaycastCallback
{ {
btCollisionWorld::RayResultCallback* m_resultCallback; btCollisionWorld::RayResultCallback* m_resultCallback;
btCollisionObject* m_collisionObject; btCollisionObject* m_collisionObject;
@@ -342,17 +342,17 @@ void btCollisionWorld::rayTestSingle(const btTransform& rayFromTrans,const btTra
btCollisionWorld::LocalShapeInfo shapeInfo; btCollisionWorld::LocalShapeInfo shapeInfo;
shapeInfo.m_shapePart = partId; shapeInfo.m_shapePart = partId;
shapeInfo.m_triangleIndex = triangleIndex; shapeInfo.m_triangleIndex = triangleIndex;
btCollisionWorld::LocalRayResult rayResult btCollisionWorld::LocalRayResult rayResult
(m_collisionObject, (m_collisionObject,
&shapeInfo, &shapeInfo,
hitNormalLocal, hitNormalLocal,
hitFraction); hitFraction);
bool normalInWorldSpace = false; bool normalInWorldSpace = false;
return m_resultCallback->AddSingleResult(rayResult,normalInWorldSpace); return m_resultCallback->AddSingleResult(rayResult,normalInWorldSpace);
} }
}; };
@@ -395,29 +395,39 @@ void btCollisionWorld::objectQuerySingle(const btConvexShape* castShape,const bt
btCollisionObject* collisionObject, btCollisionObject* collisionObject,
const btCollisionShape* collisionShape, const btCollisionShape* collisionShape,
const btTransform& colObjWorldTransform, const btTransform& colObjWorldTransform,
ConvexResultCallback& resultCallback,short int collisionFilterMask) ConvexResultCallback& resultCallback, btScalar allowedPenetration,short int collisionFilterMask)
{ {
if (collisionShape->isConvex()) if (collisionShape->isConvex())
{ {
btConvexCast::CastResult castResult; btConvexCast::CastResult castResult;
castResult.m_allowedPenetration = allowedPenetration;
castResult.m_fraction = btScalar(1.);//?? castResult.m_fraction = btScalar(1.);//??
btConvexShape* convexShape = (btConvexShape*) collisionShape; btConvexShape* convexShape = (btConvexShape*) collisionShape;
btVoronoiSimplexSolver simplexSolver; btVoronoiSimplexSolver simplexSolver;
btGjkEpaPenetrationDepthSolver gjkEpaPenetrationSolver; btGjkEpaPenetrationDepthSolver gjkEpaPenetrationSolver;
btContinuousConvexCollision convexCaster(castShape,convexShape,&simplexSolver,&gjkEpaPenetrationSolver);
bool result = false;
if (convexCaster.calcTimeOfImpact(convexFromTrans,convexToTrans,colObjWorldTransform,colObjWorldTransform,castResult)) btContinuousConvexCollision convexCaster1(castShape,convexShape,&simplexSolver,&gjkEpaPenetrationSolver);
//btGjkConvexCast convexCaster2(castShape,convexShape,&simplexSolver);
//btSubsimplexConvexCast convexCaster3(castShape,convexShape,&simplexSolver);
btConvexCast* castPtr = &convexCaster1;
if (castPtr->calcTimeOfImpact(convexFromTrans,convexToTrans,colObjWorldTransform,colObjWorldTransform,castResult))
{ {
//add hit //add hit
if (castResult.m_normal.length2() > btScalar(0.0001)) if (castResult.m_normal.length2() > btScalar(0.0001))
{ {
if (castResult.m_fraction < resultCallback.m_closestHitFraction) if (castResult.m_fraction < resultCallback.m_closestHitFraction)
{ {
castResult.m_normal.normalize(); castResult.m_normal.normalize();
btCollisionWorld::LocalConvexResult localConvexResult btCollisionWorld::LocalConvexResult localConvexResult
( (
collisionObject, collisionObject,
0, 0,
castResult.m_normal, castResult.m_normal,
castResult.m_hitPoint, castResult.m_hitPoint,
@@ -443,7 +453,7 @@ void btCollisionWorld::objectQuerySingle(const btConvexShape* castShape,const bt
btTransform rotationXform = btTransform(worldTocollisionObject.getBasis() * convexToTrans.getBasis()); btTransform rotationXform = btTransform(worldTocollisionObject.getBasis() * convexToTrans.getBasis());
//ConvexCast::CastResult //ConvexCast::CastResult
struct BridgeTriangleConvexcastCallback : public btTriangleConvexcastCallback struct BridgeTriangleConvexcastCallback : public btTriangleConvexcastCallback
{ {
btCollisionWorld::ConvexResultCallback* m_resultCallback; btCollisionWorld::ConvexResultCallback* m_resultCallback;
btCollisionObject* m_collisionObject; btCollisionObject* m_collisionObject;
@@ -468,15 +478,15 @@ void btCollisionWorld::objectQuerySingle(const btConvexShape* castShape,const bt
{ {
btCollisionWorld::LocalConvexResult convexResult btCollisionWorld::LocalConvexResult convexResult
(m_collisionObject, (m_collisionObject,
&shapeInfo, &shapeInfo,
hitNormalLocal, hitNormalLocal,
hitPointLocal, hitPointLocal,
hitFraction); hitFraction);
bool normalInWorldSpace = true; bool normalInWorldSpace = true;
return m_resultCallback->AddSingleResult(convexResult,normalInWorldSpace); return m_resultCallback->AddSingleResult(convexResult,normalInWorldSpace);
} }
return hitFraction; return hitFraction;
@@ -499,7 +509,7 @@ void btCollisionWorld::objectQuerySingle(const btConvexShape* castShape,const bt
btTransform rotationXform = btTransform(worldTocollisionObject.getBasis() * convexToTrans.getBasis()); btTransform rotationXform = btTransform(worldTocollisionObject.getBasis() * convexToTrans.getBasis());
//ConvexCast::CastResult //ConvexCast::CastResult
struct BridgeTriangleConvexcastCallback : public btTriangleConvexcastCallback struct BridgeTriangleConvexcastCallback : public btTriangleConvexcastCallback
{ {
btCollisionWorld::ConvexResultCallback* m_resultCallback; btCollisionWorld::ConvexResultCallback* m_resultCallback;
btCollisionObject* m_collisionObject; btCollisionObject* m_collisionObject;
@@ -524,12 +534,12 @@ void btCollisionWorld::objectQuerySingle(const btConvexShape* castShape,const bt
{ {
btCollisionWorld::LocalConvexResult convexResult btCollisionWorld::LocalConvexResult convexResult
(m_collisionObject, (m_collisionObject,
&shapeInfo, &shapeInfo,
hitNormalLocal, hitNormalLocal,
hitPointLocal, hitPointLocal,
hitFraction); hitFraction);
bool normalInWorldSpace = false; bool normalInWorldSpace = false;
return m_resultCallback->AddSingleResult(convexResult,normalInWorldSpace); return m_resultCallback->AddSingleResult(convexResult,normalInWorldSpace);
@@ -543,7 +553,7 @@ void btCollisionWorld::objectQuerySingle(const btConvexShape* castShape,const bt
tccb.m_hitFraction = resultCallback.m_closestHitFraction; tccb.m_hitFraction = resultCallback.m_closestHitFraction;
btVector3 boxMinLocal, boxMaxLocal; btVector3 boxMinLocal, boxMaxLocal;
castShape->getAabb(rotationXform, boxMinLocal, boxMaxLocal); castShape->getAabb(rotationXform, boxMinLocal, boxMaxLocal);
btVector3 rayAabbMinLocal = convexFromLocal; btVector3 rayAabbMinLocal = convexFromLocal;
rayAabbMinLocal.setMin(convexToLocal); rayAabbMinLocal.setMin(convexToLocal);
btVector3 rayAabbMaxLocal = convexFromLocal; btVector3 rayAabbMaxLocal = convexFromLocal;
@@ -567,26 +577,26 @@ void btCollisionWorld::objectQuerySingle(const btConvexShape* castShape,const bt
collisionObject, collisionObject,
childCollisionShape, childCollisionShape,
childWorldTrans, childWorldTrans,
resultCallback, collisionFilterMask); resultCallback, allowedPenetration,collisionFilterMask);
} }
} }
} }
} }
} }
void btCollisionWorld::rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, RayResultCallback& resultCallback,short int collisionFilterMask) void btCollisionWorld::rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, RayResultCallback& resultCallback,short int collisionFilterMask) const
{ {
btTransform rayFromTrans,rayToTrans; btTransform rayFromTrans,rayToTrans;
rayFromTrans.setIdentity(); rayFromTrans.setIdentity();
rayFromTrans.setOrigin(rayFromWorld); rayFromTrans.setOrigin(rayFromWorld);
rayToTrans.setIdentity(); rayToTrans.setIdentity();
rayToTrans.setOrigin(rayToWorld); rayToTrans.setOrigin(rayToWorld);
/// go over all objects, and if the ray intersects their aabb, do a ray-shape query using convexCaster (CCD) /// go over all objects, and if the ray intersects their aabb, do a ray-shape query using convexCaster (CCD)
int i; int i;
for (i=0;i<m_collisionObjects.size();i++) for (i=0;i<m_collisionObjects.size();i++)
{ {
@@ -596,7 +606,7 @@ void btCollisionWorld::rayTest(const btVector3& rayFromWorld, const btVector3& r
btCollisionObject* collisionObject= m_collisionObjects[i]; btCollisionObject* collisionObject= m_collisionObjects[i];
//only perform raycast if filterMask matches //only perform raycast if filterMask matches
if(collisionObject->getBroadphaseHandle()->m_collisionFilterGroup & collisionFilterMask) { if(collisionObject->getBroadphaseHandle()->m_collisionFilterGroup & collisionFilterMask) {
//RigidcollisionObject* collisionObject = ctrl->GetRigidcollisionObject(); //RigidcollisionObject* collisionObject = ctrl->GetRigidcollisionObject();
btVector3 collisionObjectAabbMin,collisionObjectAabbMax; btVector3 collisionObjectAabbMin,collisionObjectAabbMax;
collisionObject->getCollisionShape()->getAabb(collisionObject->getWorldTransform(),collisionObjectAabbMin,collisionObjectAabbMax); collisionObject->getCollisionShape()->getAabb(collisionObject->getWorldTransform(),collisionObjectAabbMin,collisionObjectAabbMax);
@@ -610,14 +620,14 @@ void btCollisionWorld::rayTest(const btVector3& rayFromWorld, const btVector3& r
collisionObject->getCollisionShape(), collisionObject->getCollisionShape(),
collisionObject->getWorldTransform(), collisionObject->getWorldTransform(),
resultCallback); resultCallback);
} }
} }
} }
} }
void btCollisionWorld::convexSweepTest(const btConvexShape* castShape, const btTransform& convexFromWorld, const btTransform& convexToWorld, ConvexResultCallback& resultCallback,short int collisionFilterMask) void btCollisionWorld::convexSweepTest(const btConvexShape* castShape, const btTransform& convexFromWorld, const btTransform& convexToWorld, ConvexResultCallback& resultCallback,short int collisionFilterMask) const
{ {
btTransform convexFromTrans,convexToTrans; btTransform convexFromTrans,convexToTrans;
convexFromTrans = convexFromWorld; convexFromTrans = convexFromWorld;
@@ -640,7 +650,7 @@ void btCollisionWorld::convexSweepTest(const btConvexShape* castShape, const btT
{ {
btCollisionObject* collisionObject= m_collisionObjects[i]; btCollisionObject* collisionObject= m_collisionObjects[i];
//only perform raycast if filterMask matches //only perform raycast if filterMask matches
if(collisionObject->getBroadphaseHandle()->m_collisionFilterGroup & collisionFilterMask) { if(collisionObject->getBroadphaseHandle()->m_collisionFilterGroup & collisionFilterMask) {
//RigidcollisionObject* collisionObject = ctrl->GetRigidcollisionObject(); //RigidcollisionObject* collisionObject = ctrl->GetRigidcollisionObject();
btVector3 collisionObjectAabbMin,collisionObjectAabbMax; btVector3 collisionObjectAabbMin,collisionObjectAabbMax;
collisionObject->getCollisionShape()->getAabb(collisionObject->getWorldTransform(),collisionObjectAabbMin,collisionObjectAabbMax); collisionObject->getCollisionShape()->getAabb(collisionObject->getWorldTransform(),collisionObjectAabbMin,collisionObjectAabbMax);
@@ -653,8 +663,10 @@ void btCollisionWorld::convexSweepTest(const btConvexShape* castShape, const btT
collisionObject, collisionObject,
collisionObject->getCollisionShape(), collisionObject->getCollisionShape(),
collisionObject->getWorldTransform(), collisionObject->getWorldTransform(),
resultCallback); resultCallback,
} getDispatchInfo().m_allowedCcdPenetration,
collisionFilterMask);
}
} }
} }

View File

@@ -123,6 +123,11 @@ public:
return m_dispatcher1; return m_dispatcher1;
} }
const btDispatcher* getDispatcher() const
{
return m_dispatcher1;
}
virtual void updateAabbs(); virtual void updateAabbs();
virtual void setDebugDrawer(btIDebugDraw* debugDrawer) virtual void setDebugDrawer(btIDebugDraw* debugDrawer)
@@ -309,11 +314,11 @@ public:
/// rayTest performs a raycast on all objects in the btCollisionWorld, and calls the resultCallback /// rayTest performs a raycast on all objects in the btCollisionWorld, and calls the resultCallback
/// This allows for several queries: first hit, all hits, any hit, dependent on the value returned by the callback. /// This allows for several queries: first hit, all hits, any hit, dependent on the value returned by the callback.
void rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, RayResultCallback& resultCallback, short int collisionFilterMask=-1); void rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, RayResultCallback& resultCallback, short int collisionFilterMask=-1) const;
// convexTest performs a swept convex cast on all objects in the btCollisionWorld, and calls the resultCallback // convexTest performs a swept convex cast on all objects in the btCollisionWorld, and calls the resultCallback
// This allows for several queries: first hit, all hits, any hit, dependent on the value return by the callback. // This allows for several queries: first hit, all hits, any hit, dependent on the value return by the callback.
void convexSweepTest (const btConvexShape* castShape, const btTransform& from, const btTransform& to, ConvexResultCallback& resultCallback, short int collisionFilterMask=-1); void convexSweepTest (const btConvexShape* castShape, const btTransform& from, const btTransform& to, ConvexResultCallback& resultCallback, short int collisionFilterMask=-1) const;
/// rayTestSingle performs a raycast call and calls the resultCallback. It is used internally by rayTest. /// rayTestSingle performs a raycast call and calls the resultCallback. It is used internally by rayTest.
@@ -330,7 +335,7 @@ public:
btCollisionObject* collisionObject, btCollisionObject* collisionObject,
const btCollisionShape* collisionShape, const btCollisionShape* collisionShape,
const btTransform& colObjWorldTransform, const btTransform& colObjWorldTransform,
ConvexResultCallback& resultCallback, short int collisionFilterMask=-1); ConvexResultCallback& resultCallback, btScalar allowedPenetration, short int collisionFilterMask=-1);
void addCollisionObject(btCollisionObject* collisionObject,short int collisionFilterGroup=1,short int collisionFilterMask=1); void addCollisionObject(btCollisionObject* collisionObject,short int collisionFilterGroup=1,short int collisionFilterMask=1);
@@ -354,6 +359,11 @@ public:
return m_dispatchInfo; return m_dispatchInfo;
} }
const btDispatcherInfo& getDispatchInfo() const
{
return m_dispatchInfo;
}
}; };

View File

@@ -51,10 +51,18 @@ bool btContinuousConvexCollision::calcTimeOfImpact(
btTransformUtil::calculateVelocity(fromA,toA,btScalar(1.),linVelA,angVelA); btTransformUtil::calculateVelocity(fromA,toA,btScalar(1.),linVelA,angVelA);
btTransformUtil::calculateVelocity(fromB,toB,btScalar(1.),linVelB,angVelB); btTransformUtil::calculateVelocity(fromB,toB,btScalar(1.),linVelB,angVelB);
btScalar boundingRadiusA = m_convexA->getAngularMotionDisc(); btScalar boundingRadiusA = m_convexA->getAngularMotionDisc();
btScalar boundingRadiusB = m_convexB->getAngularMotionDisc(); btScalar boundingRadiusB = m_convexB->getAngularMotionDisc();
btScalar maxAngularProjectedVelocity = angVelA.length() * boundingRadiusA + angVelB.length() * boundingRadiusB; btScalar maxAngularProjectedVelocity = angVelA.length() * boundingRadiusA + angVelB.length() * boundingRadiusB;
btVector3 relLinVel = (linVelB-linVelA);
btScalar relLinVelocLength = (linVelB-linVelA).length();
if ((relLinVelocLength+maxAngularProjectedVelocity) == 0.f)
return false;
btScalar radius = btScalar(0.001); btScalar radius = btScalar(0.001);
@@ -108,8 +116,8 @@ bool btContinuousConvexCollision::calcTimeOfImpact(
dist = pointCollector1.m_distance; dist = pointCollector1.m_distance;
n = pointCollector1.m_normalOnBInWorld; n = pointCollector1.m_normalOnBInWorld;
btScalar projectedLinearVelocity = relLinVel.dot(n);
//not close enough //not close enough
while (dist > radius) while (dist > radius)
{ {
@@ -120,7 +128,7 @@ bool btContinuousConvexCollision::calcTimeOfImpact(
} }
btScalar dLambda = btScalar(0.); btScalar dLambda = btScalar(0.);
btScalar projectedLinearVelocity = (linVelB-linVelA).dot(n); projectedLinearVelocity = relLinVel.dot(n);
//calculate safe moving fraction from distance / (linear+rotational velocity) //calculate safe moving fraction from distance / (linear+rotational velocity)
@@ -130,6 +138,8 @@ bool btContinuousConvexCollision::calcTimeOfImpact(
dLambda = dist / (projectedLinearVelocity+ maxAngularProjectedVelocity); dLambda = dist / (projectedLinearVelocity+ maxAngularProjectedVelocity);
lambda = lambda + dLambda; lambda = lambda + dLambda;
if (lambda > btScalar(1.)) if (lambda > btScalar(1.))
@@ -187,6 +197,10 @@ bool btContinuousConvexCollision::calcTimeOfImpact(
} }
//don't report time of impact for motion away from the contact normal (or causes minor penetration)
if ((projectedLinearVelocity+ maxAngularProjectedVelocity)<=result.m_allowedPenetration)//SIMD_EPSILON)
return false;
result.m_fraction = lambda; result.m_fraction = lambda;
result.m_normal = n; result.m_normal = n;
result.m_hitPoint = c; result.m_hitPoint = c;

View File

@@ -42,20 +42,21 @@ public:
CastResult() CastResult()
:m_fraction(btScalar(1e30)), :m_fraction(btScalar(1e30)),
m_debugDrawer(0) m_debugDrawer(0),
m_allowedPenetration(btScalar(0))
{ {
} }
virtual ~CastResult() {}; virtual ~CastResult() {};
btVector3 m_normal;
btVector3 m_hitPoint;
btScalar m_fraction;
btTransform m_hitTransformA; btTransform m_hitTransformA;
btTransform m_hitTransformB; btTransform m_hitTransformB;
btVector3 m_normal;
btVector3 m_hitPoint;
btScalar m_fraction; //input and output
btIDebugDraw* m_debugDrawer; btIDebugDraw* m_debugDrawer;
btScalar m_allowedPenetration;
}; };

View File

@@ -158,6 +158,11 @@ bool btGjkConvexCast::calcTimeOfImpact(
} }
//is n normalized?
//don't report time of impact for motion away from the contact normal (or causes minor penetration)
if (n.dot(r)>=-result.m_allowedPenetration)
return false;
result.m_fraction = lambda; result.m_fraction = lambda;
result.m_normal = n; result.m_normal = n;
result.m_hitPoint = c; result.m_hitPoint = c;

View File

@@ -119,6 +119,8 @@ bool btSubsimplexConvexCast::calcTimeOfImpact(
{ {
dist2 = v.length2(); dist2 = v.length2();
hasResult = true; hasResult = true;
//todo: check this normal for validity
n=v;
//printf("V=%f , %f, %f\n",v[0],v[1],v[2]); //printf("V=%f , %f, %f\n",v[0],v[1],v[2]);
//printf("DIST2=%f\n",dist2); //printf("DIST2=%f\n",dist2);
//printf("numverts = %i\n",m_simplexSolver->numVertices()); //printf("numverts = %i\n",m_simplexSolver->numVertices());
@@ -130,8 +132,17 @@ bool btSubsimplexConvexCast::calcTimeOfImpact(
//int numiter = MAX_ITERATIONS - maxIter; //int numiter = MAX_ITERATIONS - maxIter;
// printf("number of iterations: %d", numiter); // printf("number of iterations: %d", numiter);
//don't report a time of impact when moving 'away' from the hitnormal
result.m_fraction = lambda; result.m_fraction = lambda;
result.m_normal = n.normalized(); result.m_normal = n.normalized();
//don't report time of impact for motion away from the contact normal (or causes minor penetration)
if (result.m_normal.dot(r)>=-result.m_allowedPenetration)
return false;
btVector3 hitA,hitB; btVector3 hitA,hitB;
m_simplexSolver->compute_points(hitA,hitB); m_simplexSolver->compute_points(hitA,hitB);
result.m_hitPoint=hitB; result.m_hitPoint=hitB;

View File

@@ -39,15 +39,16 @@ class btDynamicsWorld : public btCollisionWorld
{ {
protected: protected:
btInternalTickCallback m_internalTickCallback; btInternalTickCallback m_internalTickCallback;
void* m_worldUserInfo;
btContactSolverInfo m_solverInfo; btContactSolverInfo m_solverInfo;
public: public:
btDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* broadphase,btCollisionConfiguration* collisionConfiguration) btDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* broadphase,btCollisionConfiguration* collisionConfiguration)
:btCollisionWorld(dispatcher,broadphase,collisionConfiguration), m_internalTickCallback(0) :btCollisionWorld(dispatcher,broadphase,collisionConfiguration), m_internalTickCallback(0), m_worldUserInfo(0)
{ {
} }
@@ -95,8 +96,17 @@ public:
virtual void clearForces() = 0; virtual void clearForces() = 0;
/// Set the callback for when an internal tick (simulation substep) happens /// Set the callback for when an internal tick (simulation substep) happens, optional user info
void setInternalTickCallback(btInternalTickCallback cb) { m_internalTickCallback = cb; } void setInternalTickCallback(btInternalTickCallback cb, void* worldUserInfo=0)
{
m_internalTickCallback = cb;
m_worldUserInfo = worldUserInfo;
}
void* getWorldUserInfo() const
{
return m_worldUserInfo;
}
btContactSolverInfo& getSolverInfo() btContactSolverInfo& getSolverInfo()
{ {

View File

@@ -23,7 +23,7 @@ subject to the following restrictions:
#include <cfloat> #include <cfloat>
#include <float.h> #include <float.h>
#define BT_BULLET_VERSION 269 #define BT_BULLET_VERSION 270
inline int btGetVersion() inline int btGetVersion()
{ {