58 return ClosestRayResultCallback::addSingleResult(rayResult, normalInWorldSpace);
82 if (normalInWorldSpace)
93 if (dotUp < m_minSlopeDot)
98 return ClosestConvexResultCallback::addSingleResult(convexResult, normalInWorldSpace);
114 return direction - (
btScalar(2.0) * direction.
dot(normal)) * normal;
123 return normal * magnitude;
131 return direction - parallelComponent(direction, normal);
136 m_ghostObject = ghostObject;
137 m_up.setValue(0.0f, 0.0f, 1.0f);
138 m_jumpAxis.setValue(0.0f, 0.0f, 1.0f);
139 m_addedMargin = 0.02;
140 m_walkDirection.setValue(0.0, 0.0, 0.0);
141 m_AngVel.setValue(0.0, 0.0, 0.0);
142 m_useGhostObjectSweepTest =
true;
144 m_convexShape = convexShape;
145 m_useWalkDirection =
true;
146 m_velocityTimeInterval = 0.0;
147 m_verticalVelocity = 0.0;
148 m_verticalOffset = 0.0;
149 m_gravity = 9.8 * 3.0;
152 m_SetjumpSpeed = m_jumpSpeed;
153 m_wasOnGround =
false;
154 m_wasJumping =
false;
155 m_interpolateUp =
true;
156 m_currentStepOffset = 0.0;
157 m_maxPenetrationDepth = 0.2;
164 setStepHeight(stepHeight);
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];
219 for (
int j = 0; j < m_manifoldArray.size(); j++)
229 if (dist < -m_maxPenetrationDepth)
250 btTransform newTrans = m_ghostObject->getWorldTransform();
252 m_ghostObject->setWorldTransform(newTrans);
260 if (m_verticalVelocity < 0.0)
261 stepHeight = m_stepHeight;
272 m_targetPosition = m_currentPosition + m_up * (stepHeight) + m_jumpAxis * ((m_verticalOffset > 0.f ? m_verticalOffset : 0.f));
273 m_currentPosition = m_targetPosition;
284 if (m_useGhostObjectSweepTest)
300 if (m_interpolateUp ==
true)
301 m_currentPosition.setInterpolate3(m_currentPosition, m_targetPosition, callback.
m_closestHitFraction);
303 m_currentPosition = m_targetPosition;
306 btTransform& xform = m_ghostObject->getWorldTransform();
308 m_ghostObject->setWorldTransform(xform);
311 int numPenetrationLoops = 0;
312 m_touchingContact =
false;
313 while (recoverFromPenetration(world))
315 numPenetrationLoops++;
316 m_touchingContact =
true;
317 if (numPenetrationLoops > 4)
323 m_targetPosition = m_ghostObject->getWorldTransform().getOrigin();
324 m_currentPosition = m_targetPosition;
326 if (m_verticalOffset > 0)
328 m_verticalOffset = 0.0;
329 m_verticalVelocity = 0.0;
330 m_currentStepOffset = m_stepHeight;
335 m_currentStepOffset = stepHeight;
336 m_currentPosition = m_targetPosition;
349 btVector3 movementDirection = m_targetPosition - m_currentPosition;
355 btVector3 reflectDir = computeReflectionDirection(movementDirection, hitNormal);
360 parallelDir = parallelComponent(reflectDir, hitNormal);
361 perpindicularDir = perpindicularComponent(reflectDir, hitNormal);
363 m_targetPosition = m_currentPosition;
368 m_targetPosition += parComponent;
371 if (normalMag != 0.0)
373 btVector3 perpComponent = perpindicularDir *
btScalar(normalMag * movementLength);
375 m_targetPosition += perpComponent;
391 m_targetPosition = m_currentPosition + walkMove;
397 btScalar distance2 = (m_currentPosition - m_targetPosition).length2();
402 while (fraction >
btScalar(0.01) && maxIter-- > 0)
406 btVector3 sweepDirNegative(m_currentPosition - m_targetPosition);
415 btScalar margin = m_convexShape->getMargin();
416 m_convexShape->setMargin(margin + m_addedMargin);
420 if (m_useGhostObjectSweepTest)
429 m_convexShape->setMargin(margin);
442 btVector3 currentDir = m_targetPosition - m_currentPosition;
443 distance2 = currentDir.
length2();
448 if (currentDir.
dot(m_normalizedDirection) <=
btScalar(0.0))
461 m_currentPosition = m_targetPosition;
469 bool runonce =
false;
478 btVector3 orig_position = m_targetPosition;
480 btScalar downVelocity = (m_verticalVelocity < 0.f ? -m_verticalVelocity : 0.f) * dt;
482 if (m_verticalVelocity > 0.0)
485 if (downVelocity > 0.0 && downVelocity > m_fallSpeed && (m_wasOnGround || !m_wasJumping))
486 downVelocity = m_fallSpeed;
488 btVector3 step_drop = m_up * (m_currentStepOffset + downVelocity);
489 m_targetPosition -= step_drop;
513 end_double.
setOrigin(m_targetPosition - step_drop);
515 if (m_useGhostObjectSweepTest)
519 if (!callback.
hasHit() && m_ghostObject->hasContactResponse())
529 if (!callback.
hasHit() && m_ghostObject->hasContactResponse())
536 btScalar downVelocity2 = (m_verticalVelocity < 0.f ? -m_verticalVelocity : 0.f) * dt;
538 if (bounce_fix ==
true)
544 if (m_verticalVelocity < 0.0)
545 stepHeight = m_stepHeight;
547 if (downVelocity2 > 0.0 && downVelocity2 < stepHeight && has_hit ==
true && runonce ==
false && (m_wasOnGround || !m_wasJumping))
552 m_targetPosition = orig_position;
553 downVelocity = stepHeight;
555 step_drop = m_up * (m_currentStepOffset + downVelocity);
556 m_targetPosition -= step_drop;
570 if (bounce_fix ==
true)
572 if (full_drop ==
true)
576 m_currentPosition.setInterpolate3(m_currentPosition, m_targetPosition, fraction);
579 m_currentPosition.setInterpolate3(m_currentPosition, m_targetPosition, callback.
m_closestHitFraction);
583 m_verticalVelocity = 0.0;
584 m_verticalOffset = 0.0;
585 m_wasJumping =
false;
593 if (bounce_fix ==
true)
595 downVelocity = (m_verticalVelocity < 0.f ? -m_verticalVelocity : 0.f) * dt;
596 if (downVelocity > m_fallSpeed && (m_wasOnGround || !m_wasJumping))
598 m_targetPosition += step_drop;
599 downVelocity = m_fallSpeed;
600 step_drop = m_up * (m_currentStepOffset + downVelocity);
601 m_targetPosition -= step_drop;
606 m_currentPosition = m_targetPosition;
613 m_useWalkDirection =
true;
614 m_walkDirection = walkDirection;
627 m_useWalkDirection =
false;
628 m_walkDirection = velocity;
630 m_velocityTimeInterval += timeInterval;
645 m_walkDirection = velocity;
648 if (m_walkDirection.length2() > 0)
656 m_walkDirection -= upComponent;
657 m_verticalVelocity = (c < 0.0f ? -1 : 1) * upComponent.
length();
662 m_jumpPosition = m_ghostObject->getWorldTransform().getOrigin();
667 m_verticalVelocity = 0.0f;
672 return m_walkDirection + (m_verticalVelocity * m_up);
677 m_verticalVelocity = 0.0;
678 m_verticalOffset = 0.0;
679 m_wasOnGround =
false;
680 m_wasJumping =
false;
681 m_walkDirection.setValue(0, 0, 0);
682 m_velocityTimeInterval = 0.0;
697 m_ghostObject->setWorldTransform(xform);
702 m_currentPosition = m_ghostObject->getWorldTransform().getOrigin();
703 m_targetPosition = m_currentPosition;
705 m_currentOrientation = m_ghostObject->getWorldTransform().getRotation();
706 m_targetOrientation = m_currentOrientation;
715 if (m_AngVel.length2() > 0.0f)
721 if (m_AngVel.length2() > 0.0f)
724 xform = m_ghostObject->getWorldTransform();
726 btQuaternion rot(m_AngVel.normalized(), m_AngVel.length() * dt);
731 m_ghostObject->setWorldTransform(xform);
733 m_currentPosition = m_ghostObject->getWorldTransform().getOrigin();
734 m_targetPosition = m_currentPosition;
735 m_currentOrientation = m_ghostObject->getWorldTransform().getRotation();
736 m_targetOrientation = m_currentOrientation;
740 if (!m_useWalkDirection && (m_velocityTimeInterval <= 0.0 || m_walkDirection.fuzzyZero()))
746 m_wasOnGround = onGround();
751 if (m_walkDirection.length2() > 0)
757 m_verticalVelocity *=
btPow(
btScalar(1) - m_linearDamping, dt);
760 m_verticalVelocity -= m_gravity * dt;
761 if (m_verticalVelocity > 0.0 && m_verticalVelocity > m_jumpSpeed)
763 m_verticalVelocity = m_jumpSpeed;
765 if (m_verticalVelocity < 0.0 &&
btFabs(m_verticalVelocity) >
btFabs(m_fallSpeed))
767 m_verticalVelocity = -
btFabs(m_fallSpeed);
769 m_verticalOffset = m_verticalVelocity * dt;
772 xform = m_ghostObject->getWorldTransform();
777 stepUp(collisionWorld);
796 if (m_useWalkDirection)
798 stepForwardAndStrafe(collisionWorld, m_walkDirection);
805 (dt < m_velocityTimeInterval) ? dt : m_velocityTimeInterval;
806 m_velocityTimeInterval -= dt;
809 btVector3 move = m_walkDirection * dtMoving;
814 stepForwardAndStrafe(collisionWorld, move);
816 stepDown(collisionWorld, dt);
836 m_ghostObject->setWorldTransform(xform);
838 int numPenetrationLoops = 0;
839 m_touchingContact =
false;
840 while (recoverFromPenetration(collisionWorld))
842 numPenetrationLoops++;
843 m_touchingContact =
true;
844 if (numPenetrationLoops > 4)
854 m_fallSpeed = fallSpeed;
859 m_jumpSpeed = jumpSpeed;
860 m_SetjumpSpeed = m_jumpSpeed;
865 m_maxJumpHeight = maxJumpHeight;
875 m_jumpSpeed = v.
length2() == 0 ? m_SetjumpSpeed : v.
length();
876 m_verticalVelocity = m_jumpSpeed;
881 m_jumpPosition = m_ghostObject->getWorldTransform().getOrigin();
884 currently no jumping.
886 m_rigidBody->getMotionState()->getWorldTransform (xform);
890 m_rigidBody->applyCentralImpulse (up * magnitude);
896 if (gravity.
length2() > 0) setUpVector(-gravity);
898 m_gravity = gravity.
length();
903 return -m_gravity * m_up;
908 m_maxSlopeRadians = slopeRadians;
909 m_maxSlopeCosine =
btCos(slopeRadians);
914 return m_maxSlopeRadians;
919 m_maxPenetrationDepth = d;
924 return m_maxPenetrationDepth;
941 return sUpAxisDirection;
950 m_interpolateUp = value;
955 if (up.
length2() > 0 && m_gravity > 0.0f)
976 if (!m_ghostObject)
return;
981 xform = m_ghostObject->getWorldTransform();
984 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)
btScalar btSin(btScalar x)
btQuaternion getRotation(btVector3 &v0, btVector3 &v1) const
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
int m_collisionFilterGroup
const btCollisionObject * m_hitCollisionObject
btQuaternion inverse() const
Return the inverse of this quaternion.
int m_collisionFilterMask
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 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
int m_collisionFilterGroup
btDispatcher * getDispatcher()
btVector3 parallelComponent(const btVector3 &direction, const btVector3 &normal)
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
btScalar btAcos(btScalar x)
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
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)
void jump(const btVector3 &v=btVector3(0, 0, 0))
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.