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)
void setJumpSpeed(btScalar jumpSpeed)
btQuaternion getRotation(btVector3 &v0, btVector3 &v1) const
btScalar btSin(btScalar x)
virtual void dispatchAllCollisionPairs(btOverlappingPairCache *pairCache, const btDispatcherInfo &dispatchInfo, btDispatcher *dispatcher)=0
btVector3 computeReflectionDirection(const btVector3 &direction, const btVector3 &normal)
btBroadphasePairArray & getOverlappingPairArray()
ManifoldContactPoint collects and maintains persistent contactpoints.
const btCollisionObject * getBody0() const
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
btScalar dot(const btVector3 &v) const
Return the dot product.
bool hasContactResponse() const
virtual btVector3 getLinearVelocity() const
btVector3 & normalize()
Normalize this vector x^2 + y^2 + z^2 = 1.
The btConvexShape is an abstract shape interface, implemented by all convex shapes such as btBoxShape...
int m_collisionFilterGroup
const btCollisionObject * m_hitCollisionObject
int m_collisionFilterMask
btTransform & getWorldTransform()
btVector3 m_normalWorldOnB
int size() const
return the number of elements in the array
btBroadphaseProxy * getBroadphaseHandle()
static btVector3 getNormalizedVector(const btVector3 &v)
btVector3 m_hitNormalLocal
virtual void setLinearVelocity(const btVector3 &velocity)
btQuaternion shortestArcQuatNormalize2(btVector3 &v0, btVector3 &v1)
void setGravity(const btVector3 &gravity)
void setMaxSlope(btScalar slopeRadians)
The max slope determines the maximum angle that the controller can walk up.
const btScalar & getY() const
Return the y value.
btCollisionObject can be used to manage collision detection objects.
bool recoverFromPenetration(btCollisionWorld *collisionWorld)
The btIDebugDraw interface class allows hooking up a debug renderer to visually debug simulations...
void setFallSpeed(btScalar fallSpeed)
btVector3 m_hitNormalWorld
btQuaternion inverse() const
Return the inverse of this quaternion.
btScalar length() const
Return the length of the vector.
const btCollisionObject * m_collisionObject
int m_collisionFilterGroup
const btManifoldPoint & getContactPoint(int index) const
btDispatcher * getDispatcher()
btVector3 parallelComponent(const btVector3 &direction, const btVector3 &normal)
int m_collisionFilterMask
btScalar getMaxPenetrationDepth() const
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 length2() const
Return the length of the vector squared.
btScalar btAcos(btScalar x)
virtual bool needsCollision(btBroadphaseProxy *proxy0) const
btBroadphaseProxy * m_pProxy0
const btBroadphaseInterface * getBroadphase() const
void updateTargetPositionBasedOnCollision(const btVector3 &hit_normal, btScalar tangentMag=btScalar(0.0), btScalar normalMag=btScalar(1.0))
btScalar getMaxSlope() const
CollisionWorld is interface and container for the collision detection.
btDispatcherInfo & getDispatchInfo()
btPairCachingGhostObject * getGhostObject()
void stepUp(btCollisionWorld *collisionWorld)
btVector3 normalized() const
Return a normalized version of this vector.
btScalar m_allowedCcdPenetration
virtual void setAngularVelocity(const btVector3 &velocity)
void setMaxPenetrationDepth(btScalar d)
int getNumContacts() const
btVector3 perpindicularComponent(const btVector3 &direction, const btVector3 &normal)
void reset(btCollisionWorld *collisionWorld)
btVector3 getGravity() const
const btCollisionObject * m_hitCollisionObject
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)
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 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...
void setUpInterpolate(bool value)
void jump(const btVector3 &v=btVector3(0, 0, 0))
btScalar getDistance() const
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)
virtual const btVector3 & getAngularVelocity() const
static btVector3 * getUpAxisDirections()
Hash-space based Pair Cache, thanks to Erin Catto, Box2D, http://www.box2d.org, and Pierre Terdiman...
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 btFabs(btScalar x)
The btBroadphasePair class contains a pair of aabb-overlapping objects.