More KinematicCharacterController work.
This commit is contained in:
@@ -15,14 +15,18 @@ public:
|
|||||||
virtual void setup (btDynamicsWorld* dynamicsWorld, btScalar height = 2.0, btScalar width = 0.25, btScalar stepHeight = 0.25) = 0;
|
virtual void setup (btDynamicsWorld* dynamicsWorld, btScalar height = 2.0, btScalar width = 0.25, btScalar stepHeight = 0.25) = 0;
|
||||||
virtual void destroy (btDynamicsWorld* dynamicsWorld) = 0;
|
virtual void destroy (btDynamicsWorld* dynamicsWorld) = 0;
|
||||||
|
|
||||||
virtual btRigidBody* getRigidBody () = 0;
|
virtual btCollisionObject* getCollisionObject () = 0;
|
||||||
|
|
||||||
|
virtual void reset () = 0;
|
||||||
|
virtual void warp (const btVector3& origin) = 0;
|
||||||
|
|
||||||
virtual void preStep (btDynamicsWorld* dynamicsWorld) = 0;
|
virtual void preStep (btDynamicsWorld* dynamicsWorld) = 0;
|
||||||
virtual void playerStep (btDynamicsWorld* dynamicsWorld, btScalar dt,
|
virtual void playerStep (btDynamicsWorld* dynamicsWorld, btScalar dt,
|
||||||
int forward,
|
int forward,
|
||||||
int backward,
|
int backward,
|
||||||
int left,
|
int left,
|
||||||
int right) = 0;
|
int right,
|
||||||
|
int jump) = 0;
|
||||||
virtual bool canJump () const = 0;
|
virtual bool canJump () const = 0;
|
||||||
virtual void jump () = 0;
|
virtual void jump () = 0;
|
||||||
|
|
||||||
|
|||||||
@@ -159,6 +159,15 @@ class MyCustomOverlappingPairCallback : public btOverlappingPairCallback
|
|||||||
|
|
||||||
btHashedOverlappingPairCache* m_hashPairCache;
|
btHashedOverlappingPairCache* m_hashPairCache;
|
||||||
|
|
||||||
|
struct customOverlapFilterCallback : public btOverlapFilterCallback
|
||||||
|
{
|
||||||
|
bool needBroadphaseCollision(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) const
|
||||||
|
{
|
||||||
|
// we already know that the character proxy is either proxy0 or proxy1
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} myCustomOverlapFilterCallback;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
MyCustomOverlappingPairCallback(CharacterDemo* demo,btCollisionObject* characterCollider)
|
MyCustomOverlappingPairCallback(CharacterDemo* demo,btCollisionObject* characterCollider)
|
||||||
@@ -166,6 +175,7 @@ public:
|
|||||||
m_characterCollider(characterCollider)
|
m_characterCollider(characterCollider)
|
||||||
{
|
{
|
||||||
m_hashPairCache = new btHashedOverlappingPairCache();
|
m_hashPairCache = new btHashedOverlappingPairCache();
|
||||||
|
m_hashPairCache->setOverlapFilterCallback (&myCustomOverlapFilterCallback);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~MyCustomOverlappingPairCallback()
|
virtual ~MyCustomOverlappingPairCallback()
|
||||||
@@ -177,7 +187,7 @@ public:
|
|||||||
{
|
{
|
||||||
if (proxy0->m_clientObject==m_characterCollider || proxy1->m_clientObject==m_characterCollider)
|
if (proxy0->m_clientObject==m_characterCollider || proxy1->m_clientObject==m_characterCollider)
|
||||||
{
|
{
|
||||||
printf("addOverlappingPair (%x,%x)\n",proxy0,proxy1);
|
//printf("addOverlappingPair (%p,%p)\n",proxy0,proxy1);
|
||||||
return m_hashPairCache->addOverlappingPair(proxy0,proxy1);
|
return m_hashPairCache->addOverlappingPair(proxy0,proxy1);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@@ -187,7 +197,7 @@ public:
|
|||||||
{
|
{
|
||||||
if (proxy0->m_clientObject==m_characterCollider || proxy1->m_clientObject==m_characterCollider)
|
if (proxy0->m_clientObject==m_characterCollider || proxy1->m_clientObject==m_characterCollider)
|
||||||
{
|
{
|
||||||
printf("removeOverlappingPair (%x,%x)\n",proxy0,proxy1);
|
//printf("removeOverlappingPair (%p,%p)\n",proxy0,proxy1);
|
||||||
return m_hashPairCache->removeOverlappingPair(proxy0,proxy1,dispatcher);
|
return m_hashPairCache->removeOverlappingPair(proxy0,proxy1,dispatcher);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@@ -197,7 +207,7 @@ public:
|
|||||||
{
|
{
|
||||||
if (proxy0->m_clientObject==m_characterCollider)
|
if (proxy0->m_clientObject==m_characterCollider)
|
||||||
{
|
{
|
||||||
printf("removeOverlappingPairsContainingProxy (%x)\n",proxy0);
|
//printf("removeOverlappingPairsContainingProxy (%p)\n",proxy0);
|
||||||
m_hashPairCache->removeOverlappingPairsContainingProxy(proxy0,dispatcher);
|
m_hashPairCache->removeOverlappingPairsContainingProxy(proxy0,dispatcher);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -469,12 +479,9 @@ const float TRIANGLE_SIZE=20.f;
|
|||||||
#endif
|
#endif
|
||||||
m_character->setup (m_dynamicsWorld);
|
m_character->setup (m_dynamicsWorld);
|
||||||
|
|
||||||
//we need to remove the rigid body from the broadphase in order to register all collisions
|
|
||||||
m_dynamicsWorld->removeRigidBody(m_character->getRigidBody());
|
|
||||||
//some custom callback sample
|
//some custom callback sample
|
||||||
m_customPairCallback = new MyCustomOverlappingPairCallback(this,m_character->getRigidBody());
|
m_customPairCallback = new MyCustomOverlappingPairCallback(this,m_character->getCollisionObject());
|
||||||
sweepBP->setOverlappingPairUserCallback(m_customPairCallback);
|
sweepBP->setOverlappingPairUserCallback(m_customPairCallback);
|
||||||
m_dynamicsWorld->addRigidBody(m_character->getRigidBody());
|
|
||||||
m_character->registerPairCache (m_customPairCallback->getOverlappingPairCache());
|
m_character->registerPairCache (m_customPairCallback->getOverlappingPairCache());
|
||||||
clientResetScene();
|
clientResetScene();
|
||||||
|
|
||||||
@@ -502,14 +509,10 @@ void CharacterDemo::clientMoveAndDisplay()
|
|||||||
if (m_character)
|
if (m_character)
|
||||||
{
|
{
|
||||||
m_character->preStep (m_dynamicsWorld);
|
m_character->preStep (m_dynamicsWorld);
|
||||||
m_character->playerStep (m_dynamicsWorld, dt, gForward, gBackward, gLeft, gRight);
|
m_character->playerStep (m_dynamicsWorld, dt, gForward, gBackward, gLeft, gRight, gJump);
|
||||||
if (gJump)
|
|
||||||
{
|
|
||||||
gJump = 0;
|
|
||||||
m_character->jump ();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
printf("numPairs = %d\n",m_customPairCallback->getOverlappingPairArray().size());
|
printf("numPairs = %d\n",m_customPairCallback->getOverlappingPairArray().size());
|
||||||
{
|
{
|
||||||
btManifoldArray manifoldArray;
|
btManifoldArray manifoldArray;
|
||||||
@@ -520,6 +523,9 @@ void CharacterDemo::clientMoveAndDisplay()
|
|||||||
const btBroadphasePair& pair = m_customPairCallback->getOverlappingPairArray()[i];
|
const btBroadphasePair& pair = m_customPairCallback->getOverlappingPairArray()[i];
|
||||||
btBroadphasePair* collisionPair = m_overlappingPairCache->getOverlappingPairCache()->findPair(pair.m_pProxy0,pair.m_pProxy1);
|
btBroadphasePair* collisionPair = m_overlappingPairCache->getOverlappingPairCache()->findPair(pair.m_pProxy0,pair.m_pProxy1);
|
||||||
|
|
||||||
|
if (!collisionPair)
|
||||||
|
continue;
|
||||||
|
|
||||||
if (collisionPair->m_algorithm)
|
if (collisionPair->m_algorithm)
|
||||||
collisionPair->m_algorithm->getAllContactManifolds(manifoldArray);
|
collisionPair->m_algorithm->getAllContactManifolds(manifoldArray);
|
||||||
|
|
||||||
@@ -535,6 +541,7 @@ void CharacterDemo::clientMoveAndDisplay()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -610,20 +617,12 @@ void CharacterDemo::displayCallback(void)
|
|||||||
glutSwapBuffers();
|
glutSwapBuffers();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void CharacterDemo::clientResetScene()
|
void CharacterDemo::clientResetScene()
|
||||||
{
|
{
|
||||||
m_dynamicsWorld->getBroadphase()->getOverlappingPairCache()->cleanProxyFromPairs(m_character->getRigidBody()->getBroadphaseHandle(),getDynamicsWorld()->getDispatcher());
|
m_dynamicsWorld->getBroadphase()->getOverlappingPairCache()->cleanProxyFromPairs(m_character->getCollisionObject()->getBroadphaseHandle(),getDynamicsWorld()->getDispatcher());
|
||||||
|
|
||||||
btTransform startTransform;
|
m_character->reset ();
|
||||||
startTransform.setIdentity ();
|
m_character->warp (btVector3(0.0, 1.75, 0.0));
|
||||||
startTransform.setOrigin (btVector3(0.0, 2.0, 0.0));
|
|
||||||
|
|
||||||
m_character->getRigidBody()->getMotionState()->setWorldTransform(startTransform);
|
|
||||||
m_character->getRigidBody()->setLinearVelocity(btVector3(0,0,0));
|
|
||||||
m_character->getRigidBody()->setAngularVelocity(btVector3(0,0,0));
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CharacterDemo::specialKeyboardUp(int key, int x, int y)
|
void CharacterDemo::specialKeyboardUp(int key, int x, int y)
|
||||||
@@ -715,14 +714,14 @@ void CharacterDemo::updateCamera()
|
|||||||
btTransform characterWorldTrans;
|
btTransform characterWorldTrans;
|
||||||
|
|
||||||
//look at the vehicle
|
//look at the vehicle
|
||||||
m_character->getRigidBody()->getMotionState()->getWorldTransform(characterWorldTrans);
|
characterWorldTrans = m_character->getCollisionObject()->getWorldTransform();
|
||||||
btVector3 up = characterWorldTrans.getBasis()[1];
|
btVector3 up = characterWorldTrans.getBasis()[1];
|
||||||
btVector3 backward = -characterWorldTrans.getBasis()[2];
|
btVector3 backward = -characterWorldTrans.getBasis()[2];
|
||||||
up.normalize ();
|
up.normalize ();
|
||||||
backward.normalize ();
|
backward.normalize ();
|
||||||
|
|
||||||
m_cameraTargetPosition = characterWorldTrans.getOrigin();
|
m_cameraTargetPosition = characterWorldTrans.getOrigin();
|
||||||
m_cameraPosition = m_cameraTargetPosition + up * 5.0 + backward * 5.0;
|
m_cameraPosition = m_cameraTargetPosition + up * 2.0 + backward * 2.0;
|
||||||
|
|
||||||
//update OpenGL camera settings
|
//update OpenGL camera settings
|
||||||
glFrustum(-1.0, 1.0, -1.0, 1.0, 1.0, 10000.0);
|
glFrustum(-1.0, 1.0, -1.0, 1.0, 1.0, 10000.0);
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ void DynamicCharacterController::destroy (btDynamicsWorld* dynamicsWorld)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
btRigidBody* DynamicCharacterController::getRigidBody ()
|
btCollisionObject* DynamicCharacterController::getCollisionObject ()
|
||||||
{
|
{
|
||||||
return m_rigidBody;
|
return m_rigidBody;
|
||||||
}
|
}
|
||||||
@@ -122,7 +122,8 @@ void DynamicCharacterController::playerStep (btScalar dt,
|
|||||||
int forward,
|
int forward,
|
||||||
int backward,
|
int backward,
|
||||||
int left,
|
int left,
|
||||||
int right)
|
int right,
|
||||||
|
int jump)
|
||||||
{
|
{
|
||||||
btTransform xform;
|
btTransform xform;
|
||||||
m_rigidBody->getMotionState()->getWorldTransform (xform);
|
m_rigidBody->getMotionState()->getWorldTransform (xform);
|
||||||
|
|||||||
@@ -32,14 +32,15 @@ public:
|
|||||||
void setup (btDynamicsWorld* dynamicsWorld, btScalar height = 2.0, btScalar width = 0.25, btScalar stepHeight = 0.25);
|
void setup (btDynamicsWorld* dynamicsWorld, btScalar height = 2.0, btScalar width = 0.25, btScalar stepHeight = 0.25);
|
||||||
void destroy (btDynamicsWorld* dynamicsWorld);
|
void destroy (btDynamicsWorld* dynamicsWorld);
|
||||||
|
|
||||||
btRigidBody* getRigidBody ();
|
btCollisionObject* getCollisionObject ();
|
||||||
|
|
||||||
void preStep (btDynamicsWorld* dynamicsWorld);
|
void preStep (btDynamicsWorld* dynamicsWorld);
|
||||||
void playerStep (btScalar dt,
|
void playerStep (btScalar dt,
|
||||||
int forward,
|
int forward,
|
||||||
int backward,
|
int backward,
|
||||||
int left,
|
int left,
|
||||||
int right);
|
int right,
|
||||||
|
int jump);
|
||||||
bool canJump () const;
|
bool canJump () const;
|
||||||
void jump ();
|
void jump ();
|
||||||
|
|
||||||
|
|||||||
@@ -11,16 +11,18 @@
|
|||||||
#include "KinematicCharacterController.h"
|
#include "KinematicCharacterController.h"
|
||||||
|
|
||||||
/* TODO:
|
/* TODO:
|
||||||
* Handle projecting/slide along surfaces
|
* Fix jitter
|
||||||
* Deal with starting in penetration
|
|
||||||
* Interact with dynamic objects
|
* Interact with dynamic objects
|
||||||
* Ride kinematicly animated platforms properly
|
* Ride kinematicly animated platforms properly
|
||||||
* Step climbing
|
* More realistic (or maybe just a config option) falling
|
||||||
|
* -> Should integrate falling velocity manually and use that in stepDown()
|
||||||
|
* Support jumping
|
||||||
|
* Support ducking
|
||||||
*/
|
*/
|
||||||
class ClosestNotMeRayResultCallback : public btCollisionWorld::ClosestRayResultCallback
|
class ClosestNotMeRayResultCallback : public btCollisionWorld::ClosestRayResultCallback
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ClosestNotMeRayResultCallback (btRigidBody* me) : btCollisionWorld::ClosestRayResultCallback(btVector3(0.0, 0.0, 0.0), btVector3(0.0, 0.0, 0.0))
|
ClosestNotMeRayResultCallback (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,13 +35,13 @@ public:
|
|||||||
return ClosestRayResultCallback::AddSingleResult (rayResult, normalInWorldSpace);
|
return ClosestRayResultCallback::AddSingleResult (rayResult, normalInWorldSpace);
|
||||||
}
|
}
|
||||||
protected:
|
protected:
|
||||||
btRigidBody* m_me;
|
btCollisionObject* m_me;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ClosestNotMeConvexResultCallback : public btCollisionWorld::ClosestConvexResultCallback
|
class ClosestNotMeConvexResultCallback : public btCollisionWorld::ClosestConvexResultCallback
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ClosestNotMeConvexResultCallback (btRigidBody* me) : btCollisionWorld::ClosestConvexResultCallback(btVector3(0.0, 0.0, 0.0), btVector3(0.0, 0.0, 0.0))
|
ClosestNotMeConvexResultCallback (btCollisionObject* me) : btCollisionWorld::ClosestConvexResultCallback(btVector3(0.0, 0.0, 0.0), btVector3(0.0, 0.0, 0.0))
|
||||||
{
|
{
|
||||||
m_me = me;
|
m_me = me;
|
||||||
}
|
}
|
||||||
@@ -52,7 +54,7 @@ public:
|
|||||||
return ClosestConvexResultCallback::AddSingleResult (convexResult, normalInWorldSpace);
|
return ClosestConvexResultCallback::AddSingleResult (convexResult, normalInWorldSpace);
|
||||||
}
|
}
|
||||||
protected:
|
protected:
|
||||||
btRigidBody* m_me;
|
btCollisionObject* m_me;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -88,7 +90,7 @@ KinematicCharacterController::KinematicCharacterController ()
|
|||||||
m_walkVelocity = btScalar(1.1) * 4.0; // 4 km/h -> 1.1 m/s
|
m_walkVelocity = btScalar(1.1) * 4.0; // 4 km/h -> 1.1 m/s
|
||||||
m_shape = NULL;
|
m_shape = NULL;
|
||||||
m_pairCache = NULL;
|
m_pairCache = NULL;
|
||||||
m_rigidBody = NULL;
|
m_collisionObject = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
KinematicCharacterController::~KinematicCharacterController ()
|
KinematicCharacterController::~KinematicCharacterController ()
|
||||||
@@ -116,19 +118,18 @@ void KinematicCharacterController::setup (btDynamicsWorld* dynamicsWorld, btScal
|
|||||||
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_rigidBody = new btRigidBody(cInfo);
|
m_collisionObject = new btCollisionObject ();
|
||||||
m_rigidBody->setCollisionFlags( m_rigidBody->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT | btCollisionObject::CF_NO_CONTACT_RESPONSE);
|
m_collisionObject->setCollisionShape (m_shape);
|
||||||
m_rigidBody->setSleepingThresholds (0.0, 0.0);
|
m_collisionObject->setCollisionFlags (btCollisionObject::CF_KINEMATIC_OBJECT);
|
||||||
m_rigidBody->setAngularFactor (0.0);
|
dynamicsWorld->addCollisionObject (m_collisionObject);
|
||||||
dynamicsWorld->addRigidBody (m_rigidBody);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void KinematicCharacterController::destroy (btDynamicsWorld* dynamicsWorld)
|
void KinematicCharacterController::destroy (btDynamicsWorld* dynamicsWorld)
|
||||||
{
|
{
|
||||||
if (m_rigidBody)
|
if (m_collisionObject)
|
||||||
{
|
{
|
||||||
dynamicsWorld->removeRigidBody (m_rigidBody);
|
dynamicsWorld->removeCollisionObject (m_collisionObject);
|
||||||
delete m_rigidBody;
|
delete m_collisionObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_shape)
|
if (m_shape)
|
||||||
@@ -137,23 +138,24 @@ void KinematicCharacterController::destroy (btDynamicsWorld* dynamicsWorld)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
btRigidBody* KinematicCharacterController::getRigidBody ()
|
btCollisionObject* KinematicCharacterController::getCollisionObject ()
|
||||||
{
|
{
|
||||||
return m_rigidBody;
|
return m_collisionObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
void KinematicCharacterController::recoverFromPenetration (btDynamicsWorld* dynamicsWorld)
|
bool KinematicCharacterController::recoverFromPenetration (btDynamicsWorld* dynamicsWorld)
|
||||||
{
|
{
|
||||||
if (m_pairCache == NULL)
|
if (m_pairCache == NULL)
|
||||||
return;
|
return false;
|
||||||
|
|
||||||
printf("%d\n", m_pairCache->getNumOverlappingPairs());
|
bool penetration = false;
|
||||||
|
|
||||||
dynamicsWorld->getDispatcher()->dispatchAllCollisionPairs (m_pairCache, dynamicsWorld->getDispatchInfo(), dynamicsWorld->getDispatcher());
|
dynamicsWorld->getDispatcher()->dispatchAllCollisionPairs (m_pairCache, dynamicsWorld->getDispatchInfo(), dynamicsWorld->getDispatcher());
|
||||||
|
|
||||||
btManifoldArray manifoldArray;
|
btManifoldArray manifoldArray;
|
||||||
|
btScalar maxPen = btScalar(0.0);
|
||||||
for (int i = 0; i < m_pairCache->getNumOverlappingPairs(); i++)
|
for (int i = 0; i < m_pairCache->getNumOverlappingPairs(); i++)
|
||||||
{
|
{
|
||||||
printf("%d\n",i);
|
|
||||||
manifoldArray.clear();
|
manifoldArray.clear();
|
||||||
|
|
||||||
btBroadphasePair* collisionPair = &m_pairCache->getOverlappingPairArray()[i];
|
btBroadphasePair* collisionPair = &m_pairCache->getOverlappingPairArray()[i];
|
||||||
@@ -164,19 +166,28 @@ void KinematicCharacterController::recoverFromPenetration (btDynamicsWorld* dyna
|
|||||||
for (int j=0;j<manifoldArray.size();j++)
|
for (int j=0;j<manifoldArray.size();j++)
|
||||||
{
|
{
|
||||||
btPersistentManifold* manifold = manifoldArray[j];
|
btPersistentManifold* manifold = manifoldArray[j];
|
||||||
|
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++)
|
||||||
{
|
{
|
||||||
const btManifoldPoint&pt = manifold->getContactPoint(p);
|
const btManifoldPoint&pt = manifold->getContactPoint(p);
|
||||||
|
|
||||||
if (pt.getDistance() < 0.0)
|
if (pt.getDistance() < 0.0)
|
||||||
{
|
{
|
||||||
printf("penetration %f\n", pt.getDistance());
|
if (pt.getDistance() < maxPen)
|
||||||
|
{
|
||||||
|
maxPen = pt.getDistance();
|
||||||
|
m_touchingNormal = pt.m_normalWorldOnB * directionSign;
|
||||||
|
}
|
||||||
|
m_currentPosition += pt.m_normalWorldOnB * directionSign * pt.getDistance() * btScalar(0.2);
|
||||||
|
penetration = true;
|
||||||
} else {
|
} else {
|
||||||
printf("touching %f\n", pt.getDistance());
|
//printf("touching %f\n", pt.getDistance());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
manifold->clearManifold();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return penetration;
|
||||||
}
|
}
|
||||||
|
|
||||||
void KinematicCharacterController::stepUp (btDynamicsWorld* dynamicsWorld)
|
void KinematicCharacterController::stepUp (btDynamicsWorld* dynamicsWorld)
|
||||||
@@ -192,7 +203,7 @@ void KinematicCharacterController::stepUp (btDynamicsWorld* dynamicsWorld)
|
|||||||
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_rigidBody);
|
ClosestNotMeConvexResultCallback callback (m_collisionObject);
|
||||||
|
|
||||||
dynamicsWorld->convexSweepTest (m_shape, start, end, callback);
|
dynamicsWorld->convexSweepTest (m_shape, start, end, callback);
|
||||||
|
|
||||||
@@ -235,6 +246,7 @@ void KinematicCharacterController::updateTargetPositionBasedOnCollision (const b
|
|||||||
|
|
||||||
void KinematicCharacterController::stepForwardAndStrafe (btDynamicsWorld* dynamicsWorld, const btVector3& walkMove)
|
void KinematicCharacterController::stepForwardAndStrafe (btDynamicsWorld* dynamicsWorld, const btVector3& walkMove)
|
||||||
{
|
{
|
||||||
|
btVector3 originalDir = walkMove.normalized();
|
||||||
// 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;
|
||||||
@@ -244,12 +256,18 @@ 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();
|
||||||
|
|
||||||
|
if (m_touchingContact)
|
||||||
|
{
|
||||||
|
if (originalDir.dot(m_touchingNormal) > btScalar(0.0))
|
||||||
|
updateTargetPositionBasedOnCollision (m_touchingNormal);
|
||||||
|
}
|
||||||
|
|
||||||
while (fraction > btScalar(0.01))
|
while (fraction > btScalar(0.01))
|
||||||
{
|
{
|
||||||
start.setOrigin (m_currentPosition);
|
start.setOrigin (m_currentPosition);
|
||||||
end.setOrigin (m_targetPosition);
|
end.setOrigin (m_targetPosition);
|
||||||
|
|
||||||
ClosestNotMeConvexResultCallback callback (m_rigidBody);
|
ClosestNotMeConvexResultCallback callback (m_collisionObject);
|
||||||
dynamicsWorld->convexSweepTest (m_shape, start, end, callback);
|
dynamicsWorld->convexSweepTest (m_shape, start, end, callback);
|
||||||
|
|
||||||
fraction -= callback.m_closestHitFraction;
|
fraction -= callback.m_closestHitFraction;
|
||||||
@@ -257,9 +275,23 @@ void KinematicCharacterController::stepForwardAndStrafe (btDynamicsWorld* dynami
|
|||||||
if (callback.HasHit())
|
if (callback.HasHit())
|
||||||
{
|
{
|
||||||
// we moved only a fraction
|
// we moved only a fraction
|
||||||
m_currentPosition.setInterpolate3 (m_currentPosition, m_targetPosition, callback.m_closestHitFraction);
|
btScalar hitDistance = (callback.m_hitPointWorld - m_currentPosition).length();
|
||||||
|
|
||||||
|
/* If the distance is farther than the collision margin, move */
|
||||||
|
if (hitDistance > 0.05)
|
||||||
|
{
|
||||||
|
m_currentPosition.setInterpolate3 (m_currentPosition, m_targetPosition, callback.m_closestHitFraction);
|
||||||
|
}
|
||||||
|
|
||||||
updateTargetPositionBasedOnCollision (callback.m_hitNormalWorld);
|
updateTargetPositionBasedOnCollision (callback.m_hitNormalWorld);
|
||||||
distance2 = (m_currentPosition-m_targetPosition).length2();
|
btVector3 currentDir = m_targetPosition - m_currentPosition;
|
||||||
|
distance2 = currentDir.length2();
|
||||||
|
currentDir.normalize();
|
||||||
|
/* 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))
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// we moved whole way
|
// we moved whole way
|
||||||
m_currentPosition = m_targetPosition;
|
m_currentPosition = m_targetPosition;
|
||||||
@@ -282,7 +314,7 @@ void KinematicCharacterController::stepDown (btDynamicsWorld* dynamicsWorld, btS
|
|||||||
start.setOrigin (m_currentPosition);
|
start.setOrigin (m_currentPosition);
|
||||||
end.setOrigin (m_targetPosition);
|
end.setOrigin (m_targetPosition);
|
||||||
|
|
||||||
ClosestNotMeConvexResultCallback callback (m_rigidBody);
|
ClosestNotMeConvexResultCallback callback (m_collisionObject);
|
||||||
|
|
||||||
dynamicsWorld->convexSweepTest (m_shape, start, end, callback);
|
dynamicsWorld->convexSweepTest (m_shape, start, end, callback);
|
||||||
|
|
||||||
@@ -297,6 +329,18 @@ void KinematicCharacterController::stepDown (btDynamicsWorld* dynamicsWorld, btS
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void KinematicCharacterController::reset ()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void KinematicCharacterController::warp (const btVector3& origin)
|
||||||
|
{
|
||||||
|
btTransform xform;
|
||||||
|
xform.setIdentity();
|
||||||
|
xform.setOrigin (origin);
|
||||||
|
m_collisionObject->setWorldTransform (xform);
|
||||||
|
}
|
||||||
|
|
||||||
void KinematicCharacterController::registerPairCache (btOverlappingPairCache* pairCache)
|
void KinematicCharacterController::registerPairCache (btOverlappingPairCache* pairCache)
|
||||||
{
|
{
|
||||||
m_pairCache = pairCache;
|
m_pairCache = pairCache;
|
||||||
@@ -304,8 +348,20 @@ void KinematicCharacterController::registerPairCache (btOverlappingPairCache* pa
|
|||||||
|
|
||||||
void KinematicCharacterController::preStep (btDynamicsWorld* dynamicsWorld)
|
void KinematicCharacterController::preStep (btDynamicsWorld* dynamicsWorld)
|
||||||
{
|
{
|
||||||
|
int numPenetrationLoops = 0;
|
||||||
|
m_touchingContact = false;
|
||||||
|
while (recoverFromPenetration (dynamicsWorld))
|
||||||
|
{
|
||||||
|
numPenetrationLoops++;
|
||||||
|
m_touchingContact = true;
|
||||||
|
if (numPenetrationLoops > 4)
|
||||||
|
{
|
||||||
|
printf("character could not recover from penetration = %d\n", numPenetrationLoops);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
btTransform xform;
|
btTransform xform;
|
||||||
m_rigidBody->getMotionState()->getWorldTransform (xform);
|
xform = m_collisionObject->getWorldTransform ();
|
||||||
|
|
||||||
btVector3 forwardDir = xform.getBasis()[2];
|
btVector3 forwardDir = xform.getBasis()[2];
|
||||||
btVector3 upDir = xform.getBasis()[1];
|
btVector3 upDir = xform.getBasis()[1];
|
||||||
@@ -320,7 +376,8 @@ void KinematicCharacterController::preStep (btDynamicsWorld* dynamicsWorld)
|
|||||||
|
|
||||||
m_currentPosition = xform.getOrigin();
|
m_currentPosition = xform.getOrigin();
|
||||||
m_targetPosition = m_currentPosition;
|
m_targetPosition = m_currentPosition;
|
||||||
recoverFromPenetration (dynamicsWorld);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void KinematicCharacterController::playerStep (btDynamicsWorld* dynamicsWorld,
|
void KinematicCharacterController::playerStep (btDynamicsWorld* dynamicsWorld,
|
||||||
@@ -328,7 +385,8 @@ void KinematicCharacterController::playerStep (btDynamicsWorld* dynamicsWorld,
|
|||||||
int forward,
|
int forward,
|
||||||
int backward,
|
int backward,
|
||||||
int left,
|
int left,
|
||||||
int right)
|
int right,
|
||||||
|
int jump)
|
||||||
{
|
{
|
||||||
btVector3 walkDirection = btVector3(0.0, 0.0, 0.0);
|
btVector3 walkDirection = btVector3(0.0, 0.0, 0.0);
|
||||||
btScalar walkSpeed = m_walkVelocity * dt;
|
btScalar walkSpeed = m_walkVelocity * dt;
|
||||||
@@ -346,15 +404,29 @@ void KinematicCharacterController::playerStep (btDynamicsWorld* dynamicsWorld,
|
|||||||
walkDirection -= m_forwardDirection;
|
walkDirection -= m_forwardDirection;
|
||||||
|
|
||||||
btTransform xform;
|
btTransform xform;
|
||||||
m_rigidBody->getMotionState()->getWorldTransform (xform);
|
xform = m_collisionObject->getWorldTransform ();
|
||||||
|
|
||||||
stepUp (dynamicsWorld);
|
stepUp (dynamicsWorld);
|
||||||
stepForwardAndStrafe (dynamicsWorld, walkDirection * walkSpeed);
|
stepForwardAndStrafe (dynamicsWorld, walkDirection * walkSpeed);
|
||||||
stepDown (dynamicsWorld, dt);
|
stepDown (dynamicsWorld, dt);
|
||||||
|
|
||||||
xform.setOrigin (m_currentPosition);
|
xform.setOrigin (m_currentPosition);
|
||||||
m_rigidBody->getMotionState()->setWorldTransform (xform);
|
m_collisionObject->setWorldTransform (xform);
|
||||||
m_rigidBody->setCenterOfMassTransform (xform);
|
}
|
||||||
|
|
||||||
|
void KinematicCharacterController::setFallSpeed (btScalar fallSpeed)
|
||||||
|
{
|
||||||
|
m_fallSpeed = fallSpeed;
|
||||||
|
}
|
||||||
|
|
||||||
|
void KinematicCharacterController::setJumpSpeed (btScalar jumpSpeed)
|
||||||
|
{
|
||||||
|
m_jumpSpeed = jumpSpeed;
|
||||||
|
}
|
||||||
|
|
||||||
|
void KinematicCharacterController::setMaxJumpHeight (btScalar maxJumpHeight)
|
||||||
|
{
|
||||||
|
m_maxJumpHeight = maxJumpHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool KinematicCharacterController::canJump () const
|
bool KinematicCharacterController::canJump () const
|
||||||
|
|||||||
@@ -14,9 +14,13 @@ class KinematicCharacterController : public CharacterControllerInterface
|
|||||||
protected:
|
protected:
|
||||||
btScalar m_halfHeight;
|
btScalar m_halfHeight;
|
||||||
btConvexShape* m_shape;
|
btConvexShape* m_shape;
|
||||||
btRigidBody* m_rigidBody;
|
btCollisionObject* m_collisionObject;
|
||||||
btOverlappingPairCache* m_pairCache;
|
btOverlappingPairCache* m_pairCache;
|
||||||
|
|
||||||
|
btScalar m_fallSpeed;
|
||||||
|
btScalar m_jumpSpeed;
|
||||||
|
btScalar m_maxJumpHeight;
|
||||||
|
|
||||||
btScalar m_turnAngle;
|
btScalar m_turnAngle;
|
||||||
btScalar m_walkVelocity;
|
btScalar m_walkVelocity;
|
||||||
|
|
||||||
@@ -31,8 +35,11 @@ protected:
|
|||||||
btVector3 m_currentPosition;
|
btVector3 m_currentPosition;
|
||||||
btScalar m_currentStepOffset;
|
btScalar m_currentStepOffset;
|
||||||
btVector3 m_targetPosition;
|
btVector3 m_targetPosition;
|
||||||
|
|
||||||
|
bool m_touchingContact;
|
||||||
|
btVector3 m_touchingNormal;
|
||||||
|
|
||||||
void recoverFromPenetration (btDynamicsWorld* dynamicsWorld);
|
bool recoverFromPenetration (btDynamicsWorld* dynamicsWorld);
|
||||||
void stepUp (btDynamicsWorld* dynamicsWorld);
|
void stepUp (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(1.0), btScalar normalMag = btScalar(0.0));
|
||||||
void stepForwardAndStrafe (btDynamicsWorld* dynamicsWorld, const btVector3& walkMove);
|
void stepForwardAndStrafe (btDynamicsWorld* dynamicsWorld, const btVector3& walkMove);
|
||||||
@@ -43,7 +50,10 @@ public:
|
|||||||
void setup (btDynamicsWorld* dynamicsWorld, btScalar height = btScalar(1.75), btScalar width = btScalar(0.4), btScalar stepHeight = btScalar(0.35));
|
void setup (btDynamicsWorld* dynamicsWorld, btScalar height = btScalar(1.75), btScalar width = btScalar(0.4), btScalar stepHeight = btScalar(0.35));
|
||||||
void destroy (btDynamicsWorld* dynamicsWorld);
|
void destroy (btDynamicsWorld* dynamicsWorld);
|
||||||
|
|
||||||
btRigidBody* getRigidBody ();
|
btCollisionObject* getCollisionObject ();
|
||||||
|
|
||||||
|
void reset ();
|
||||||
|
void warp (const btVector3& origin);
|
||||||
|
|
||||||
void registerPairCache (btOverlappingPairCache* pairCache);
|
void registerPairCache (btOverlappingPairCache* pairCache);
|
||||||
void preStep (btDynamicsWorld* dynamicsWorld);
|
void preStep (btDynamicsWorld* dynamicsWorld);
|
||||||
@@ -51,7 +61,12 @@ public:
|
|||||||
int forward,
|
int forward,
|
||||||
int backward,
|
int backward,
|
||||||
int left,
|
int left,
|
||||||
int right);
|
int right,
|
||||||
|
int jump);
|
||||||
|
|
||||||
|
void setFallSpeed (btScalar fallSpeed);
|
||||||
|
void setJumpSpeed (btScalar jumpSpeed);
|
||||||
|
void setMaxJumpHeight (btScalar maxJumpHeight);
|
||||||
bool canJump () const;
|
bool canJump () const;
|
||||||
void jump ();
|
void jump ();
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user