60 return ClosestRayResultCallback::addSingleResult (rayResult, normalInWorldSpace);
73 , m_minSlopeDot(minSlopeDot)
86 if (normalInWorldSpace)
96 if (dotUp < m_minSlopeDot) {
100 return ClosestConvexResultCallback::addSingleResult (convexResult, normalInWorldSpace);
115 return direction - (
btScalar(2.0) * direction.
dot(normal)) * normal;
124 return normal * magnitude;
132 return direction - parallelComponent(direction, normal);
137 m_ghostObject = ghostObject;
138 m_up.setValue(0.0f, 0.0f, 1.0f);
139 m_jumpAxis.setValue(0.0f, 0.0f, 1.0f);
141 setStepHeight(stepHeight);
142 m_addedMargin = 0.02;
143 m_walkDirection.setValue(0.0,0.0,0.0);
144 m_AngVel.setValue(0.0, 0.0, 0.0);
145 m_useGhostObjectSweepTest =
true;
147 m_convexShape=convexShape;
148 m_useWalkDirection =
true;
149 m_velocityTimeInterval = 0.0;
150 m_verticalVelocity = 0.0;
151 m_verticalOffset = 0.0;
152 m_gravity = 9.8 * 3.0 ;
155 m_SetjumpSpeed = m_jumpSpeed;
156 m_wasOnGround =
false;
157 m_wasJumping =
false;
158 m_interpolateUp =
true;
160 m_currentStepOffset = 0.0;
161 m_maxPenetrationDepth = 0.2;
174 return m_ghostObject;
188 m_convexShape->getAabb(m_ghostObject->getWorldTransform(), minAabb,maxAabb);
194 bool penetration =
false;
198 m_currentPosition = m_ghostObject->getWorldTransform().getOrigin();
201 for (
int i = 0; i < m_ghostObject->getOverlappingPairCache()->getNumOverlappingPairs(); i++)
203 m_manifoldArray.resize(0);
205 btBroadphasePair* collisionPair = &m_ghostObject->getOverlappingPairCache()->getOverlappingPairArray()[i];
220 for (
int j=0;j<m_manifoldArray.size();j++)
230 if (dist < -m_maxPenetrationDepth)
249 btTransform newTrans = m_ghostObject->getWorldTransform();
251 m_ghostObject->setWorldTransform(newTrans);
259 if (m_verticalVelocity < 0.0)
260 stepHeight = m_stepHeight;
271 m_targetPosition = m_currentPosition + m_up * (stepHeight) + m_jumpAxis * ((m_verticalOffset > 0.f ? m_verticalOffset : 0.f));
272 m_currentPosition = m_targetPosition;
283 if (m_useGhostObjectSweepTest)
299 if (m_interpolateUp ==
true)
300 m_currentPosition.setInterpolate3 (m_currentPosition, m_targetPosition, callback.
m_closestHitFraction);
302 m_currentPosition = m_targetPosition;
305 btTransform& xform = m_ghostObject->getWorldTransform();
307 m_ghostObject->setWorldTransform(xform);
310 int numPenetrationLoops = 0;
311 m_touchingContact =
false;
312 while (recoverFromPenetration(world))
314 numPenetrationLoops++;
315 m_touchingContact =
true;
316 if (numPenetrationLoops > 4)
322 m_targetPosition = m_ghostObject->getWorldTransform().getOrigin();
323 m_currentPosition = m_targetPosition;
325 if (m_verticalOffset > 0)
327 m_verticalOffset = 0.0;
328 m_verticalVelocity = 0.0;
329 m_currentStepOffset = m_stepHeight;
332 m_currentStepOffset = stepHeight;
333 m_currentPosition = m_targetPosition;
346 btVector3 movementDirection = m_targetPosition - m_currentPosition;
352 btVector3 reflectDir = computeReflectionDirection (movementDirection, hitNormal);
357 parallelDir = parallelComponent (reflectDir, hitNormal);
358 perpindicularDir = perpindicularComponent (reflectDir, hitNormal);
360 m_targetPosition = m_currentPosition;
365 m_targetPosition += parComponent;
368 if (normalMag != 0.0)
370 btVector3 perpComponent = perpindicularDir *
btScalar (normalMag*movementLength);
372 m_targetPosition += perpComponent;
387 m_targetPosition = m_currentPosition + walkMove;
393 btScalar distance2 = (m_currentPosition-m_targetPosition).length2();
398 while (fraction >
btScalar(0.01) && maxIter-- > 0)
402 btVector3 sweepDirNegative(m_currentPosition - m_targetPosition);
412 btScalar margin = m_convexShape->getMargin();
413 m_convexShape->setMargin(margin + m_addedMargin);
417 if (m_useGhostObjectSweepTest)
426 m_convexShape->setMargin(margin);
440 btVector3 currentDir = m_targetPosition - m_currentPosition;
441 distance2 = currentDir.
length2();
446 if (currentDir.
dot(m_normalizedDirection) <=
btScalar(0.0))
459 m_currentPosition = m_targetPosition;
467 bool runonce =
false;
476 btVector3 orig_position = m_targetPosition;
478 btScalar downVelocity = (m_verticalVelocity<0.f?-m_verticalVelocity:0.f) * dt;
480 if (m_verticalVelocity > 0.0)
483 if(downVelocity > 0.0 && downVelocity > m_fallSpeed
484 && (m_wasOnGround || !m_wasJumping))
485 downVelocity = m_fallSpeed;
487 btVector3 step_drop = m_up * (m_currentStepOffset + downVelocity);
488 m_targetPosition -= step_drop;
512 end_double.
setOrigin (m_targetPosition - step_drop);
514 if (m_useGhostObjectSweepTest)
518 if (!callback.
hasHit() && m_ghostObject->hasContactResponse())
527 if (!callback.
hasHit() && m_ghostObject->hasContactResponse())
534 btScalar downVelocity2 = (m_verticalVelocity<0.f?-m_verticalVelocity:0.f) * dt;
536 if (bounce_fix ==
true)
542 if (m_verticalVelocity < 0.0)
543 stepHeight = m_stepHeight;
545 if (downVelocity2 > 0.0 && downVelocity2 < stepHeight && has_hit ==
true && runonce ==
false 546 && (m_wasOnGround || !m_wasJumping))
551 m_targetPosition = orig_position;
552 downVelocity = stepHeight;
554 step_drop = m_up * (m_currentStepOffset + downVelocity);
555 m_targetPosition -= step_drop;
569 if (bounce_fix ==
true)
571 if (full_drop ==
true)
575 m_currentPosition.setInterpolate3 (m_currentPosition, m_targetPosition, fraction);
578 m_currentPosition.setInterpolate3 (m_currentPosition, m_targetPosition, callback.
m_closestHitFraction);
582 m_verticalVelocity = 0.0;
583 m_verticalOffset = 0.0;
584 m_wasJumping =
false;
590 if (bounce_fix ==
true)
592 downVelocity = (m_verticalVelocity<0.f?-m_verticalVelocity:0.f) * dt;
593 if (downVelocity > m_fallSpeed && (m_wasOnGround || !m_wasJumping))
595 m_targetPosition += step_drop;
596 downVelocity = m_fallSpeed;
597 step_drop = m_up * (m_currentStepOffset + downVelocity);
598 m_targetPosition -= step_drop;
603 m_currentPosition = m_targetPosition;
614 m_useWalkDirection =
true;
615 m_walkDirection = walkDirection;
632 m_useWalkDirection =
false;
633 m_walkDirection = velocity;
635 m_velocityTimeInterval += timeInterval;
650 m_walkDirection = velocity;
653 if (m_walkDirection.length2() > 0)
661 m_walkDirection -= upComponent;
662 m_verticalVelocity = (c < 0.0f ? -1 : 1) * upComponent.
length();
667 m_jumpPosition = m_ghostObject->getWorldTransform().getOrigin();
672 m_verticalVelocity = 0.0f;
677 return m_walkDirection + (m_verticalVelocity * m_up);
682 m_verticalVelocity = 0.0;
683 m_verticalOffset = 0.0;
684 m_wasOnGround =
false;
685 m_wasJumping =
false;
686 m_walkDirection.setValue(0,0,0);
687 m_velocityTimeInterval = 0.0;
702 m_ghostObject->setWorldTransform (xform);
708 m_currentPosition = m_ghostObject->getWorldTransform().getOrigin();
709 m_targetPosition = m_currentPosition;
711 m_currentOrientation = m_ghostObject->getWorldTransform().getRotation();
712 m_targetOrientation = m_currentOrientation;
721 if (m_AngVel.length2() > 0.0f)
727 if (m_AngVel.length2() > 0.0f)
730 xform = m_ghostObject->getWorldTransform();
732 btQuaternion rot(m_AngVel.normalized(), m_AngVel.length() * dt);
737 m_ghostObject->setWorldTransform(xform);
739 m_currentPosition = m_ghostObject->getWorldTransform().getOrigin();
740 m_targetPosition = m_currentPosition;
741 m_currentOrientation = m_ghostObject->getWorldTransform().getRotation();
742 m_targetOrientation = m_currentOrientation;
746 if (!m_useWalkDirection && (m_velocityTimeInterval <= 0.0)) {
751 m_wasOnGround = onGround();
756 if (m_walkDirection.length2() > 0)
762 m_verticalVelocity *=
btPow(
btScalar(1) - m_linearDamping, dt);
765 m_verticalVelocity -= m_gravity * dt;
766 if (m_verticalVelocity > 0.0 && m_verticalVelocity > m_jumpSpeed)
768 m_verticalVelocity = m_jumpSpeed;
770 if (m_verticalVelocity < 0.0 &&
btFabs(m_verticalVelocity) >
btFabs(m_fallSpeed))
772 m_verticalVelocity = -
btFabs(m_fallSpeed);
774 m_verticalOffset = m_verticalVelocity * dt;
777 xform = m_ghostObject->getWorldTransform();
782 stepUp(collisionWorld);
801 if (m_useWalkDirection) {
802 stepForwardAndStrafe (collisionWorld, m_walkDirection);
807 (dt < m_velocityTimeInterval) ? dt : m_velocityTimeInterval;
808 m_velocityTimeInterval -= dt;
811 btVector3 move = m_walkDirection * dtMoving;
816 stepForwardAndStrafe(collisionWorld, move);
818 stepDown (collisionWorld, dt);
838 m_ghostObject->setWorldTransform (xform);
840 int numPenetrationLoops = 0;
841 m_touchingContact =
false;
842 while (recoverFromPenetration(collisionWorld))
844 numPenetrationLoops++;
845 m_touchingContact =
true;
846 if (numPenetrationLoops > 4)
856 m_fallSpeed = fallSpeed;
861 m_jumpSpeed = jumpSpeed;
862 m_SetjumpSpeed = m_jumpSpeed;
867 m_maxJumpHeight = maxJumpHeight;
877 m_jumpSpeed = v.
length2() == 0 ? m_SetjumpSpeed : v.
length();
878 m_verticalVelocity = m_jumpSpeed;
883 m_jumpPosition = m_ghostObject->getWorldTransform().getOrigin();
886 currently no jumping.
888 m_rigidBody->getMotionState()->getWorldTransform (xform);
892 m_rigidBody->applyCentralImpulse (up * magnitude);
898 if (gravity.
length2() > 0) setUpVector(-gravity);
900 m_gravity = gravity.
length();
905 return -m_gravity * m_up;
910 m_maxSlopeRadians = slopeRadians;
911 m_maxSlopeCosine =
btCos(slopeRadians);
916 return m_maxSlopeRadians;
921 m_maxPenetrationDepth = d;
926 return m_maxPenetrationDepth;
943 return sUpAxisDirection;
952 m_interpolateUp = value;
957 if (up.
length2() > 0 && m_gravity > 0.0f)
978 if (!m_ghostObject)
return;
983 xform = m_ghostObject->getWorldTransform();
986 m_ghostObject->setWorldTransform(xform);
btPersistentManifold is a contact point cache, it stays persistent as long as objects are overlapping...
void playerStep(btCollisionWorld *collisionWorld, btScalar dt)
void setUpVector(const btVector3 &up)
virtual btScalar addSingleResult(btCollisionWorld::LocalRayResult &rayResult, bool normalInWorldSpace)
void stepDown(btCollisionWorld *collisionWorld, btScalar dt)
btKinematicClosestNotMeRayResultCallback(btCollisionObject *me)
~btKinematicCharacterController()
btScalar btRadians(btScalar x)
virtual btVector3 getLinearVelocity() const
void setJumpSpeed(btScalar jumpSpeed)
btQuaternion getRotation(btVector3 &v0, btVector3 &v1) const
short int m_collisionFilterGroup
short int m_collisionFilterGroup
btScalar length2() const
Return the length of the vector squared.
virtual void dispatchAllCollisionPairs(btOverlappingPairCache *pairCache, const btDispatcherInfo &dispatchInfo, btDispatcher *dispatcher)=0
btVector3 computeReflectionDirection(const btVector3 &direction, const btVector3 &normal)
int getNumContacts() const
btBroadphasePairArray & getOverlappingPairArray()
const btScalar & getY() const
Return the y value.
btVector3 getGravity() const
btScalar getMaxSlope() const
ManifoldContactPoint collects and maintains persistent contactpoints.
btVector3 m_hitPointWorld
virtual void setVelocityForTimeInterval(const btVector3 &velocity, btScalar timeInterval)
Caller provides a velocity with which the character should move for the given time period...
void debugDraw(btIDebugDraw *debugDrawer)
btActionInterface interface
btVector3 & normalize()
Normalize this vector x^2 + y^2 + z^2 = 1.
btVector3 normalized() const
Return a normalized version of this vector.
The btConvexShape is an abstract shape interface, implemented by all convex shapes such as btBoxShape...
const btManifoldPoint & getContactPoint(int index) const
const btCollisionObject * m_hitCollisionObject
btQuaternion inverse() const
Return the inverse of this quaternion.
btTransform & getWorldTransform()
btVector3 m_normalWorldOnB
btBroadphaseProxy * getBroadphaseHandle()
static btVector3 getNormalizedVector(const btVector3 &v)
const btCollisionObject * getBody0() const
btVector3 m_hitNormalLocal
virtual void setLinearVelocity(const btVector3 &velocity)
btQuaternion shortestArcQuatNormalize2(btVector3 &v0, btVector3 &v1)
virtual bool needsCollision(btBroadphaseProxy *proxy0) const
btScalar dot(const btVector3 &v) const
Return the dot product.
void setGravity(const btVector3 &gravity)
void jump(const btVector3 &v=btVector3())
void setMaxSlope(btScalar slopeRadians)
The max slope determines the maximum angle that the controller can walk up.
btCollisionObject can be used to manage collision detection objects.
bool recoverFromPenetration(btCollisionWorld *collisionWorld)
bool hasContactResponse() const
The btIDebugDraw interface class allows hooking up a debug renderer to visually debug simulations...
void setFallSpeed(btScalar fallSpeed)
btVector3 m_hitNormalWorld
const btCollisionObject * m_collisionObject
btDispatcher * getDispatcher()
btVector3 parallelComponent(const btVector3 &direction, const btVector3 &normal)
short int m_collisionFilterMask
void setStepHeight(btScalar h)
btBroadphaseProxy * m_pProxy1
btCollisionAlgorithm * m_algorithm
void warp(const btVector3 &origin)
virtual btScalar addSingleResult(btCollisionWorld::LocalConvexResult &convexResult, bool normalInWorldSpace)
btVector3 can be used to represent 3D points and vectors.
virtual void * removeOverlappingPair(btBroadphaseProxy *proxy0, btBroadphaseProxy *proxy1, btDispatcher *dispatcher)
btScalar btPow(btScalar x, btScalar y)
virtual void getAllContactManifolds(btManifoldArray &manifoldArray)=0
int size() const
return the number of elements in the array
btBroadphaseProxy * m_pProxy0
void updateTargetPositionBasedOnCollision(const btVector3 &hit_normal, btScalar tangentMag=btScalar(0.0), btScalar normalMag=btScalar(1.0))
CollisionWorld is interface and container for the collision detection.
void convexSweepTest(const btConvexShape *castShape, const btTransform &from, const btTransform &to, ConvexResultCallback &resultCallback, btScalar allowedCcdPenetration=btScalar(0.)) const
convexTest performs a swept convex cast on all objects in the btCollisionWorld, and calls the resultC...
btDispatcherInfo & getDispatchInfo()
btPairCachingGhostObject * getGhostObject()
void stepUp(btCollisionWorld *collisionWorld)
btScalar m_allowedCcdPenetration
virtual void setAngularVelocity(const btVector3 &velocity)
void setMaxPenetrationDepth(btScalar d)
btVector3 perpindicularComponent(const btVector3 &direction, const btVector3 &normal)
void reset(btCollisionWorld *collisionWorld)
const btCollisionObject * m_hitCollisionObject
virtual const btVector3 & getAngularVelocity() const
btScalar m_closestHitFraction
btKinematicClosestNotMeConvexResultCallback(btCollisionObject *me, const btVector3 &up, btScalar minSlopeDot)
virtual void setAabb(btBroadphaseProxy *proxy, const btVector3 &aabbMin, const btVector3 &aabbMax, btDispatcher *dispatcher)=0
short int m_collisionFilterMask
void stepForwardAndStrafe(btCollisionWorld *collisionWorld, const btVector3 &walkMove)
btScalar getMaxPenetrationDepth() const
void preStep(btCollisionWorld *collisionWorld)
The btQuaternion implements quaternion to perform linear algebra rotations in combination with btMatr...
virtual void setWalkDirection(const btVector3 &walkDirection)
This should probably be called setPositionIncrementPerSimulatorStep.
void setUpInterpolate(bool value)
virtual bool needsCollision(const btCollisionObject *body0, const btCollisionObject *body1)
btKinematicCharacterController(btPairCachingGhostObject *ghostObject, btConvexShape *convexShape, btScalar stepHeight, const btVector3 &up=btVector3(1.0, 0.0, 0.0))
void setUp(const btVector3 &up)
void setMaxJumpHeight(btScalar maxJumpHeight)
void setInterpolate3(const btVector3 &v0, const btVector3 &v1, btScalar rt)
const btBroadphaseInterface * getBroadphase() const
static btVector3 * getUpAxisDirections()
Hash-space based Pair Cache, thanks to Erin Catto, Box2D, http://www.box2d.org, and Pierre Terdiman...
btScalar getDistance() const
ClosestRayResultCallback(const btVector3 &rayFromWorld, const btVector3 &rayToWorld)
float btScalar
The btScalar type abstracts floating point numbers, to easily switch between double and single floati...
btScalar btCos(btScalar x)
btScalar length() const
Return the length of the vector.
btScalar btFabs(btScalar x)
The btBroadphasePair class contains a pair of aabb-overlapping objects.