1 #include "BulletCollision/CollisionShapes/btMultiSphereShape.h"
2 #include "BulletDynamics/Dynamics/btRigidBody.h"
3 #include "BulletCollision/CollisionDispatch/btCollisionWorld.h"
4 #include "LinearMath/btDefaultMotionState.h"
5 #include "DynamicCharacterController.h"
7 DynamicCharacterController::DynamicCharacterController ()
13 m_maxLinearVelocity = 10.0;
14 m_walkVelocity = 8.0; // meters/sec
15 m_turnVelocity = 1.0; // radians/sec
20 DynamicCharacterController::~DynamicCharacterController ()
24 void DynamicCharacterController::setup (btScalar height, btScalar width, btScalar stepHeight)
26 btVector3 spherePositions[2];
27 btScalar sphereRadii[2];
29 sphereRadii[0] = width;
30 sphereRadii[1] = width;
31 spherePositions[0] = btVector3 (0.0, (height/btScalar(2.0) - width), 0.0);
32 spherePositions[1] = btVector3 (0.0, (-height/btScalar(2.0) + width), 0.0);
34 m_halfHeight = height/btScalar(2.0);
36 m_shape = new btMultiSphereShape (&spherePositions[0], &sphereRadii[0], 2);
38 btTransform startTransform;
39 startTransform.setIdentity ();
40 startTransform.setOrigin (btVector3(0.0, 2.0, 0.0));
41 btDefaultMotionState* myMotionState = new btDefaultMotionState(startTransform);
42 btRigidBody::btRigidBodyConstructionInfo cInfo(1.0, myMotionState, m_shape);
43 m_rigidBody = new btRigidBody(cInfo);
44 // kinematic vs. static doesn't work
45 //m_rigidBody->setCollisionFlags( m_rigidBody->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT);
46 m_rigidBody->setSleepingThresholds (0.0, 0.0);
47 m_rigidBody->setAngularFactor (0.0);
51 void DynamicCharacterController::destroy ()
65 btCollisionObject* DynamicCharacterController::getCollisionObject ()
70 void DynamicCharacterController::preStep (const btCollisionWorld* collisionWorld)
73 m_rigidBody->getMotionState()->getWorldTransform (xform);
74 btVector3 down = -xform.getBasis()[1];
75 btVector3 forward = xform.getBasis()[2];
79 m_raySource[0] = xform.getOrigin();
80 m_raySource[1] = xform.getOrigin();
82 m_rayTarget[0] = m_raySource[0] + down * m_halfHeight * btScalar(1.1);
83 m_rayTarget[1] = m_raySource[1] + forward * m_halfHeight * btScalar(1.1);
85 class ClosestNotMe : public btCollisionWorld::ClosestRayResultCallback
88 ClosestNotMe (btRigidBody* me) : btCollisionWorld::ClosestRayResultCallback(btVector3(0.0, 0.0, 0.0), btVector3(0.0, 0.0, 0.0))
93 virtual btScalar addSingleResult(btCollisionWorld::LocalRayResult& rayResult,bool normalInWorldSpace)
95 if (rayResult.m_collisionObject == m_me)
98 return ClosestRayResultCallback::addSingleResult (rayResult, normalInWorldSpace
105 ClosestNotMe rayCallback(m_rigidBody);
108 for (i = 0; i < 2; i++)
110 rayCallback.m_closestHitFraction = 1.0;
111 collisionWorld->rayTest (m_raySource[i], m_rayTarget[i], rayCallback);
112 if (rayCallback.hasHit())
114 m_rayLambda[i] = rayCallback.m_closestHitFraction;
116 m_rayLambda[i] = 1.0;
121 void DynamicCharacterController::playerStep (const btCollisionWorld* dynaWorld,btScalar dt,
129 m_rigidBody->getMotionState()->getWorldTransform (xform);
133 m_turnAngle -= dt * m_turnVelocity;
135 m_turnAngle += dt * m_turnVelocity;
137 xform.setRotation (btQuaternion (btVector3(0.0, 1.0, 0.0), m_turnAngle));
139 btVector3 linearVelocity = m_rigidBody->getLinearVelocity();
140 btScalar speed = m_rigidBody->getLinearVelocity().length();
142 btVector3 forwardDir = xform.getBasis()[2];
143 forwardDir.normalize ();
144 btVector3 walkDirection = btVector3(0.0, 0.0, 0.0);
145 btScalar walkSpeed = m_walkVelocity * dt;
148 walkDirection += forwardDir;
150 walkDirection -= forwardDir;
154 if (!forward && !backward && onGround())
156 /* Dampen when on the ground and not being moved by the player */
157 linearVelocity *= btScalar(0.2);
158 m_rigidBody->setLinearVelocity (linearVelocity);
160 if (speed < m_maxLinearVelocity)
162 btVector3 velocity = linearVelocity + walkDirection * walkSpeed;
163 m_rigidBody->setLinearVelocity (velocity);
167 m_rigidBody->getMotionState()->setWorldTransform (xform);
168 m_rigidBody->setCenterOfMassTransform (xform);
171 bool DynamicCharacterController::canJump () const
176 void DynamicCharacterController::jump ()
182 m_rigidBody->getMotionState()->getWorldTransform (xform);
183 btVector3 up = xform.getBasis()[1];
185 btScalar magnitude = (btScalar(1.0)/m_rigidBody->getInvMass()) * btScalar(8.0);
186 m_rigidBody->applyCentralImpulse (up * magnitude);
189 bool DynamicCharacterController::onGround () const
191 return m_rayLambda[0] < btScalar(1.0);
194 void DynamicCharacterController::reset ()
197 void DynamicCharacterController::warp (const btVector3& origin)
200 void DynamicCharacterController::registerPairCacheAndDispatcher (btOverlappingPairCache* pairCache, btCollisionDispatcher* dispatcher)