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);
138 m_addedMargin = 0.02;
139 m_walkDirection.setValue(0,0,0);
140 m_useGhostObjectSweepTest =
true;
141 m_ghostObject = ghostObject;
142 m_stepHeight = stepHeight;
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 ;
152 m_wasOnGround =
false;
153 m_wasJumping =
false;
154 m_interpolateUp =
true;
156 m_currentStepOffset = 0;
167 return m_ghostObject;
181 m_convexShape->getAabb(m_ghostObject->getWorldTransform(), minAabb,maxAabb);
187 bool penetration =
false;
191 m_currentPosition = m_ghostObject->getWorldTransform().getOrigin();
194 for (
int i = 0; i < m_ghostObject->getOverlappingPairCache()->getNumOverlappingPairs(); i++)
196 m_manifoldArray.resize(0);
198 btBroadphasePair* collisionPair = &m_ghostObject->getOverlappingPairCache()->getOverlappingPairArray()[i];
210 for (
int j=0;j<m_manifoldArray.size();j++)
238 btTransform newTrans = m_ghostObject->getWorldTransform();
240 m_ghostObject->setWorldTransform(newTrans);
249 m_targetPosition = m_currentPosition + getUpAxisDirections()[m_upAxis] * (m_stepHeight + (m_verticalOffset > 0.f?m_verticalOffset:0.f));
255 start.
setOrigin (m_currentPosition + getUpAxisDirections()[m_upAxis] * (m_convexShape->getMargin() + m_addedMargin));
262 if (m_useGhostObjectSweepTest)
278 if (m_interpolateUp ==
true)
279 m_currentPosition.setInterpolate3 (m_currentPosition, m_targetPosition, callback.
m_closestHitFraction);
281 m_currentPosition = m_targetPosition;
283 m_verticalVelocity = 0.0;
284 m_verticalOffset = 0.0;
286 m_currentStepOffset = m_stepHeight;
287 m_currentPosition = m_targetPosition;
293 btVector3 movementDirection = m_targetPosition - m_currentPosition;
299 btVector3 reflectDir = computeReflectionDirection (movementDirection, hitNormal);
304 parallelDir = parallelComponent (reflectDir, hitNormal);
305 perpindicularDir = perpindicularComponent (reflectDir, hitNormal);
307 m_targetPosition = m_currentPosition;
312 m_targetPosition += parComponent;
315 if (normalMag != 0.0)
317 btVector3 perpComponent = perpindicularDir *
btScalar (normalMag*movementLength);
319 m_targetPosition += perpComponent;
333 m_targetPosition = m_currentPosition + walkMove;
339 btScalar distance2 = (m_currentPosition-m_targetPosition).length2();
342 if (m_touchingContact)
344 if (m_normalizedDirection.dot(m_touchingNormal) >
btScalar(0.0))
353 while (fraction >
btScalar(0.01) && maxIter-- > 0)
357 btVector3 sweepDirNegative(m_currentPosition - m_targetPosition);
364 btScalar margin = m_convexShape->getMargin();
365 m_convexShape->setMargin(margin + m_addedMargin);
368 if (m_useGhostObjectSweepTest)
376 m_convexShape->setMargin(margin);
390 btVector3 currentDir = m_targetPosition - m_currentPosition;
391 distance2 = currentDir.
length2();
396 if (currentDir.
dot(m_normalizedDirection) <=
btScalar(0.0))
408 m_currentPosition = m_targetPosition;
420 bool runonce =
false;
429 btVector3 orig_position = m_targetPosition;
431 btScalar downVelocity = (m_verticalVelocity<0.f?-m_verticalVelocity:0.f) * dt;
433 if(downVelocity > 0.0 && downVelocity > m_fallSpeed
434 && (m_wasOnGround || !m_wasJumping))
435 downVelocity = m_fallSpeed;
437 btVector3 step_drop = getUpAxisDirections()[m_upAxis] * (m_currentStepOffset + downVelocity);
438 m_targetPosition -= step_drop;
459 end_double.
setOrigin (m_targetPosition - step_drop);
461 if (m_useGhostObjectSweepTest)
481 btScalar downVelocity2 = (m_verticalVelocity<0.f?-m_verticalVelocity:0.f) * dt;
482 bool has_hit =
false;
483 if (bounce_fix ==
true)
486 has_hit = callback2.
hasHit();
488 if(downVelocity2 > 0.0 && downVelocity2 < m_stepHeight && has_hit ==
true && runonce ==
false 489 && (m_wasOnGround || !m_wasJumping))
494 m_targetPosition = orig_position;
495 downVelocity = m_stepHeight;
497 btVector3 step_drop = getUpAxisDirections()[m_upAxis] * (m_currentStepOffset + downVelocity);
498 m_targetPosition -= step_drop;
505 if (callback.
hasHit() || runonce ==
true)
513 if (bounce_fix ==
true)
515 if (full_drop ==
true)
519 m_currentPosition.setInterpolate3 (m_currentPosition, m_targetPosition, fraction);
522 m_currentPosition.setInterpolate3 (m_currentPosition, m_targetPosition, callback.
m_closestHitFraction);
526 m_verticalVelocity = 0.0;
527 m_verticalOffset = 0.0;
528 m_wasJumping =
false;
534 if (bounce_fix ==
true)
536 downVelocity = (m_verticalVelocity<0.f?-m_verticalVelocity:0.f) * dt;
537 if (downVelocity > m_fallSpeed && (m_wasOnGround || !m_wasJumping))
539 m_targetPosition += step_drop;
540 downVelocity = m_fallSpeed;
541 step_drop = getUpAxisDirections()[m_upAxis] * (m_currentStepOffset + downVelocity);
542 m_targetPosition -= step_drop;
547 m_currentPosition = m_targetPosition;
558 m_useWalkDirection =
true;
559 m_walkDirection = walkDirection;
576 m_useWalkDirection =
false;
577 m_walkDirection = velocity;
579 m_velocityTimeInterval += timeInterval;
584 m_verticalVelocity = 0.0;
585 m_verticalOffset = 0.0;
586 m_wasOnGround =
false;
587 m_wasJumping =
false;
588 m_walkDirection.setValue(0,0,0);
589 m_velocityTimeInterval = 0.0;
604 m_ghostObject->setWorldTransform (xform);
611 int numPenetrationLoops = 0;
612 m_touchingContact =
false;
613 while (recoverFromPenetration (collisionWorld))
615 numPenetrationLoops++;
616 m_touchingContact =
true;
617 if (numPenetrationLoops > 4)
624 m_currentPosition = m_ghostObject->getWorldTransform().getOrigin();
625 m_targetPosition = m_currentPosition;
639 if (!m_useWalkDirection && (m_velocityTimeInterval <= 0.0 || m_walkDirection.fuzzyZero())) {
644 m_wasOnGround = onGround();
647 m_verticalVelocity -= m_gravity * dt;
648 if(m_verticalVelocity > 0.0 && m_verticalVelocity > m_jumpSpeed)
650 m_verticalVelocity = m_jumpSpeed;
652 if(m_verticalVelocity < 0.0 &&
btFabs(m_verticalVelocity) >
btFabs(m_fallSpeed))
654 m_verticalVelocity = -
btFabs(m_fallSpeed);
656 m_verticalOffset = m_verticalVelocity * dt;
660 xform = m_ghostObject->getWorldTransform ();
665 stepUp (collisionWorld);
666 if (m_useWalkDirection) {
667 stepForwardAndStrafe (collisionWorld, m_walkDirection);
672 (dt < m_velocityTimeInterval) ? dt : m_velocityTimeInterval;
673 m_velocityTimeInterval -= dt;
676 btVector3 move = m_walkDirection * dtMoving;
681 stepForwardAndStrafe(collisionWorld, move);
683 stepDown (collisionWorld, dt);
688 m_ghostObject->setWorldTransform (xform);
693 m_fallSpeed = fallSpeed;
698 m_jumpSpeed = jumpSpeed;
703 m_maxJumpHeight = maxJumpHeight;
716 m_verticalVelocity = m_jumpSpeed;
720 currently no jumping.
722 m_rigidBody->getMotionState()->getWorldTransform (xform);
726 m_rigidBody->applyCentralImpulse (up * magnitude);
742 m_maxSlopeRadians = slopeRadians;
743 m_maxSlopeCosine =
btCos(slopeRadians);
748 return m_maxSlopeRadians;
753 return m_verticalVelocity == 0.0 && m_verticalOffset == 0.0;
761 return sUpAxisDirection;
770 m_interpolateUp = value;
btPersistentManifold is a contact point cache, it stays persistent as long as objects are overlapping...
void playerStep(btCollisionWorld *collisionWorld, btScalar dt)
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)
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
btKinematicCharacterController(btPairCachingGhostObject *ghostObject, btConvexShape *convexShape, btScalar stepHeight, int upAxis=1)
btBroadphasePairArray & getOverlappingPairArray()
const btScalar & getY() const
Return the y value.
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
btTransform & getWorldTransform()
btVector3 m_normalWorldOnB
static btVector3 getNormalizedVector(const btVector3 &v)
const btCollisionObject * getBody0() const
btVector3 m_hitNormalLocal
btScalar dot(const btVector3 &v) const
Return the dot product.
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
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)
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
btVector3 perpindicularComponent(const btVector3 &direction, const btVector3 &normal)
btScalar getGravity() const
void reset(btCollisionWorld *collisionWorld)
void setGravity(btScalar gravity)
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)
virtual void setWalkDirection(const btVector3 &walkDirection)
This should probably be called setPositionIncrementPerSimulatorStep.
void setUpInterpolate(bool value)
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.