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);
140 m_addedMargin = 0.02;
141 m_walkDirection.setValue(0.0,0.0,0.0);
142 m_AngVel.setValue(0.0, 0.0, 0.0);
143 m_useGhostObjectSweepTest =
true;
145 m_convexShape=convexShape;
146 m_useWalkDirection =
true;
147 m_velocityTimeInterval = 0.0;
148 m_verticalVelocity = 0.0;
149 m_verticalOffset = 0.0;
150 m_gravity = 9.8 * 3.0 ;
153 m_SetjumpSpeed = m_jumpSpeed;
154 m_wasOnGround =
false;
155 m_wasJumping =
false;
156 m_interpolateUp =
true;
157 m_currentStepOffset = 0.0;
158 m_maxPenetrationDepth = 0.2;
165 setStepHeight(stepHeight);
175 return m_ghostObject;
189 m_convexShape->getAabb(m_ghostObject->getWorldTransform(), minAabb,maxAabb);
195 bool penetration =
false;
199 m_currentPosition = m_ghostObject->getWorldTransform().getOrigin();
202 for (
int i = 0; i < m_ghostObject->getOverlappingPairCache()->getNumOverlappingPairs(); i++)
204 m_manifoldArray.resize(0);
206 btBroadphasePair* collisionPair = &m_ghostObject->getOverlappingPairCache()->getOverlappingPairArray()[i];
221 for (
int j=0;j<m_manifoldArray.size();j++)
231 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;
333 m_currentStepOffset = stepHeight;
334 m_currentPosition = m_targetPosition;
347 btVector3 movementDirection = m_targetPosition - m_currentPosition;
353 btVector3 reflectDir = computeReflectionDirection (movementDirection, hitNormal);
358 parallelDir = parallelComponent (reflectDir, hitNormal);
359 perpindicularDir = perpindicularComponent (reflectDir, hitNormal);
361 m_targetPosition = m_currentPosition;
366 m_targetPosition += parComponent;
369 if (normalMag != 0.0)
371 btVector3 perpComponent = perpindicularDir *
btScalar (normalMag*movementLength);
373 m_targetPosition += perpComponent;
388 m_targetPosition = m_currentPosition + walkMove;
394 btScalar distance2 = (m_currentPosition-m_targetPosition).length2();
399 while (fraction >
btScalar(0.01) && maxIter-- > 0)
403 btVector3 sweepDirNegative(m_currentPosition - m_targetPosition);
413 btScalar margin = m_convexShape->getMargin();
414 m_convexShape->setMargin(margin + m_addedMargin);
418 if (m_useGhostObjectSweepTest)
427 m_convexShape->setMargin(margin);
441 btVector3 currentDir = m_targetPosition - m_currentPosition;
442 distance2 = currentDir.
length2();
447 if (currentDir.
dot(m_normalizedDirection) <=
btScalar(0.0))
460 m_currentPosition = m_targetPosition;
468 bool runonce =
false;
477 btVector3 orig_position = m_targetPosition;
479 btScalar downVelocity = (m_verticalVelocity<0.f?-m_verticalVelocity:0.f) * dt;
481 if (m_verticalVelocity > 0.0)
484 if(downVelocity > 0.0 && downVelocity > m_fallSpeed
485 && (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())
528 if (!callback.
hasHit() && m_ghostObject->hasContactResponse())
535 btScalar downVelocity2 = (m_verticalVelocity<0.f?-m_verticalVelocity:0.f) * dt;
537 if (bounce_fix ==
true)
543 if (m_verticalVelocity < 0.0)
544 stepHeight = m_stepHeight;
546 if (downVelocity2 > 0.0 && downVelocity2 < stepHeight && has_hit ==
true && runonce ==
false 547 && (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;
591 if (bounce_fix ==
true)
593 downVelocity = (m_verticalVelocity<0.f?-m_verticalVelocity:0.f) * dt;
594 if (downVelocity > m_fallSpeed && (m_wasOnGround || !m_wasJumping))
596 m_targetPosition += step_drop;
597 downVelocity = m_fallSpeed;
598 step_drop = m_up * (m_currentStepOffset + downVelocity);
599 m_targetPosition -= step_drop;
604 m_currentPosition = m_targetPosition;
615 m_useWalkDirection =
true;
616 m_walkDirection = walkDirection;
633 m_useWalkDirection =
false;
634 m_walkDirection = velocity;
636 m_velocityTimeInterval += timeInterval;
651 m_walkDirection = velocity;
654 if (m_walkDirection.length2() > 0)
662 m_walkDirection -= upComponent;
663 m_verticalVelocity = (c < 0.0f ? -1 : 1) * upComponent.
length();
668 m_jumpPosition = m_ghostObject->getWorldTransform().getOrigin();
673 m_verticalVelocity = 0.0f;
678 return m_walkDirection + (m_verticalVelocity * m_up);
683 m_verticalVelocity = 0.0;
684 m_verticalOffset = 0.0;
685 m_wasOnGround =
false;
686 m_wasJumping =
false;
687 m_walkDirection.setValue(0,0,0);
688 m_velocityTimeInterval = 0.0;
703 m_ghostObject->setWorldTransform (xform);
709 m_currentPosition = m_ghostObject->getWorldTransform().getOrigin();
710 m_targetPosition = m_currentPosition;
712 m_currentOrientation = m_ghostObject->getWorldTransform().getRotation();
713 m_targetOrientation = m_currentOrientation;
722 if (m_AngVel.length2() > 0.0f)
728 if (m_AngVel.length2() > 0.0f)
731 xform = m_ghostObject->getWorldTransform();
733 btQuaternion rot(m_AngVel.normalized(), m_AngVel.length() * dt);
738 m_ghostObject->setWorldTransform(xform);
740 m_currentPosition = m_ghostObject->getWorldTransform().getOrigin();
741 m_targetPosition = m_currentPosition;
742 m_currentOrientation = m_ghostObject->getWorldTransform().getRotation();
743 m_targetOrientation = m_currentOrientation;
747 if (!m_useWalkDirection && (m_velocityTimeInterval <= 0.0)) {
752 m_wasOnGround = onGround();
757 if (m_walkDirection.length2() > 0)
763 m_verticalVelocity *=
btPow(
btScalar(1) - m_linearDamping, dt);
766 m_verticalVelocity -= m_gravity * dt;
767 if (m_verticalVelocity > 0.0 && m_verticalVelocity > m_jumpSpeed)
769 m_verticalVelocity = m_jumpSpeed;
771 if (m_verticalVelocity < 0.0 &&
btFabs(m_verticalVelocity) >
btFabs(m_fallSpeed))
773 m_verticalVelocity = -
btFabs(m_fallSpeed);
775 m_verticalOffset = m_verticalVelocity * dt;
778 xform = m_ghostObject->getWorldTransform();
783 stepUp(collisionWorld);
802 if (m_useWalkDirection) {
803 stepForwardAndStrafe (collisionWorld, m_walkDirection);
808 (dt < m_velocityTimeInterval) ? dt : m_velocityTimeInterval;
809 m_velocityTimeInterval -= dt;
812 btVector3 move = m_walkDirection * dtMoving;
817 stepForwardAndStrafe(collisionWorld, move);
819 stepDown (collisionWorld, dt);
839 m_ghostObject->setWorldTransform (xform);
841 int numPenetrationLoops = 0;
842 m_touchingContact =
false;
843 while (recoverFromPenetration(collisionWorld))
845 numPenetrationLoops++;
846 m_touchingContact =
true;
847 if (numPenetrationLoops > 4)
857 m_fallSpeed = fallSpeed;
862 m_jumpSpeed = jumpSpeed;
863 m_SetjumpSpeed = m_jumpSpeed;
868 m_maxJumpHeight = maxJumpHeight;
878 m_jumpSpeed = v.
length2() == 0 ? m_SetjumpSpeed : v.
length();
879 m_verticalVelocity = m_jumpSpeed;
884 m_jumpPosition = m_ghostObject->getWorldTransform().getOrigin();
887 currently no jumping.
889 m_rigidBody->getMotionState()->getWorldTransform (xform);
893 m_rigidBody->applyCentralImpulse (up * magnitude);
899 if (gravity.
length2() > 0) setUpVector(-gravity);
901 m_gravity = gravity.
length();
906 return -m_gravity * m_up;
911 m_maxSlopeRadians = slopeRadians;
912 m_maxSlopeCosine =
btCos(slopeRadians);
917 return m_maxSlopeRadians;
922 m_maxPenetrationDepth = d;
927 return m_maxPenetrationDepth;
944 return sUpAxisDirection;
953 m_interpolateUp = value;
958 if (up.
length2() > 0 && m_gravity > 0.0f)
979 if (!m_ghostObject)
return;
984 xform = m_ghostObject->getWorldTransform();
987 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 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
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)
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.