2017-08-01 14:30:58 +02:00
/*
Bullet Continuous Collision Detection and Physics Library
Copyright ( c ) 2003 - 2008 Erwin Coumans http : //bulletphysics.com
This software is provided ' as - is ' , without any express or implied warranty .
In no event will the authors be held liable for any damages arising from the use of this software .
Permission is granted to anyone to use this software for any purpose ,
including commercial applications , and to alter it and redistribute it freely ,
subject to the following restrictions :
1. The origin of this software must not be misrepresented ; you must not claim that you wrote the original software . If you use this software in a product , an acknowledgment in the product documentation would be appreciated but is not required .
2. Altered source versions must be plainly marked as such , and must not be misrepresented as being the original software .
3. This notice may not be removed or altered from any source distribution .
*/
# ifndef BT_KINEMATIC_CHARACTER_CONTROLLER_H
# define BT_KINEMATIC_CHARACTER_CONTROLLER_H
# include "LinearMath/btVector3.h"
# include "btCharacterControllerInterface.h"
# include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
class btCollisionShape ;
class btConvexShape ;
class btRigidBody ;
class btCollisionWorld ;
class btCollisionDispatcher ;
class btPairCachingGhostObject ;
///btKinematicCharacterController is an object that supports a sliding motion in a world.
///It uses a ghost object and convex sweep test to test for upcoming collisions. This is combined with discrete collision detection to recover from penetrations.
///Interaction between btKinematicCharacterController and dynamic rigid bodies needs to be explicity implemented by the user.
2019-01-03 14:26:51 +01:00
ATTRIBUTE_ALIGNED16 ( class )
btKinematicCharacterController : public btCharacterControllerInterface
2017-08-01 14:30:58 +02:00
{
protected :
btScalar m_halfHeight ;
2019-01-03 14:26:51 +01:00
2017-08-01 14:30:58 +02:00
btPairCachingGhostObject * m_ghostObject ;
2019-01-03 14:26:51 +01:00
btConvexShape * m_convexShape ; //is also in m_ghostObject, but it needs to be convex, so we store it here to avoid upcast
2017-08-01 14:30:58 +02:00
btScalar m_maxPenetrationDepth ;
btScalar m_verticalVelocity ;
btScalar m_verticalOffset ;
btScalar m_fallSpeed ;
btScalar m_jumpSpeed ;
btScalar m_SetjumpSpeed ;
btScalar m_maxJumpHeight ;
2019-01-03 14:26:51 +01:00
btScalar m_maxSlopeRadians ; // Slope angle that is set (used for returning the exact value)
btScalar m_maxSlopeCosine ; // Cosine equivalent of m_maxSlopeRadians (calculated once when set, for optimization)
2017-08-01 14:30:58 +02:00
btScalar m_gravity ;
btScalar m_turnAngle ;
2019-01-03 14:26:51 +01:00
2017-08-01 14:30:58 +02:00
btScalar m_stepHeight ;
2019-01-03 14:26:51 +01:00
btScalar m_addedMargin ; //@todo: remove this and fix the code
2017-08-01 14:30:58 +02:00
///this is the desired walk direction, set by the user
2019-01-03 14:26:51 +01:00
btVector3 m_walkDirection ;
btVector3 m_normalizedDirection ;
btVector3 m_AngVel ;
2017-08-01 14:30:58 +02:00
2019-01-03 14:26:51 +01:00
btVector3 m_jumpPosition ;
2017-08-01 14:30:58 +02:00
//some internal variables
btVector3 m_currentPosition ;
2019-01-03 14:26:51 +01:00
btScalar m_currentStepOffset ;
2017-08-01 14:30:58 +02:00
btVector3 m_targetPosition ;
btQuaternion m_currentOrientation ;
btQuaternion m_targetOrientation ;
///keep track of the contact manifolds
2019-01-03 14:26:51 +01:00
btManifoldArray m_manifoldArray ;
2017-08-01 14:30:58 +02:00
bool m_touchingContact ;
btVector3 m_touchingNormal ;
btScalar m_linearDamping ;
btScalar m_angularDamping ;
2019-01-03 14:26:51 +01:00
bool m_wasOnGround ;
bool m_wasJumping ;
bool m_useGhostObjectSweepTest ;
bool m_useWalkDirection ;
btScalar m_velocityTimeInterval ;
2017-08-01 14:30:58 +02:00
btVector3 m_up ;
btVector3 m_jumpAxis ;
static btVector3 * getUpAxisDirections ( ) ;
2019-01-03 14:26:51 +01:00
bool m_interpolateUp ;
bool full_drop ;
bool bounce_fix ;
2017-08-01 14:30:58 +02:00
2019-01-03 14:26:51 +01:00
btVector3 computeReflectionDirection ( const btVector3 & direction , const btVector3 & normal ) ;
btVector3 parallelComponent ( const btVector3 & direction , const btVector3 & normal ) ;
btVector3 perpindicularComponent ( const btVector3 & direction , const btVector3 & normal ) ;
2017-08-01 14:30:58 +02:00
2019-01-03 14:26:51 +01:00
bool recoverFromPenetration ( btCollisionWorld * collisionWorld ) ;
void stepUp ( btCollisionWorld * collisionWorld ) ;
void updateTargetPositionBasedOnCollision ( const btVector3 & hit_normal , btScalar tangentMag = btScalar ( 0.0 ) , btScalar normalMag = btScalar ( 1.0 ) ) ;
void stepForwardAndStrafe ( btCollisionWorld * collisionWorld , const btVector3 & walkMove ) ;
void stepDown ( btCollisionWorld * collisionWorld , btScalar dt ) ;
2017-08-01 14:30:58 +02:00
virtual bool needsCollision ( const btCollisionObject * body0 , const btCollisionObject * body1 ) ;
void setUpVector ( const btVector3 & up ) ;
2019-01-03 14:26:51 +01:00
btQuaternion getRotation ( btVector3 & v0 , btVector3 & v1 ) const ;
2017-08-01 14:30:58 +02:00
public :
BT_DECLARE_ALIGNED_ALLOCATOR ( ) ;
2019-01-03 14:26:51 +01:00
btKinematicCharacterController ( btPairCachingGhostObject * ghostObject , btConvexShape * convexShape , btScalar stepHeight , const btVector3 & up = btVector3 ( 1.0 , 0.0 , 0.0 ) ) ;
~ btKinematicCharacterController ( ) ;
2017-08-01 14:30:58 +02:00
///btActionInterface interface
2019-01-03 14:26:51 +01:00
virtual void updateAction ( btCollisionWorld * collisionWorld , btScalar deltaTime )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
preStep ( collisionWorld ) ;
playerStep ( collisionWorld , deltaTime ) ;
2017-08-01 14:30:58 +02:00
}
2019-01-03 14:26:51 +01:00
2017-08-01 14:30:58 +02:00
///btActionInterface interface
2019-01-03 14:26:51 +01:00
void debugDraw ( btIDebugDraw * debugDrawer ) ;
2017-08-01 14:30:58 +02:00
void setUp ( const btVector3 & up ) ;
const btVector3 & getUp ( ) { return m_up ; }
/// This should probably be called setPositionIncrementPerSimulatorStep.
/// This is neither a direction nor a velocity, but the amount to
/// increment the position each simulation iteration, regardless
/// of dt.
/// This call will reset any velocity set by setVelocityForTimeInterval().
2019-01-03 14:26:51 +01:00
virtual void setWalkDirection ( const btVector3 & walkDirection ) ;
2017-08-01 14:30:58 +02:00
/// Caller provides a velocity with which the character should move for
/// the given time period. After the time period, velocity is reset
/// to zero.
/// This call will reset any walk direction set by setWalkDirection().
/// Negative time intervals will result in no motion.
virtual void setVelocityForTimeInterval ( const btVector3 & velocity ,
2019-01-03 14:26:51 +01:00
btScalar timeInterval ) ;
2017-08-01 14:30:58 +02:00
virtual void setAngularVelocity ( const btVector3 & velocity ) ;
virtual const btVector3 & getAngularVelocity ( ) const ;
virtual void setLinearVelocity ( const btVector3 & velocity ) ;
virtual btVector3 getLinearVelocity ( ) const ;
void setLinearDamping ( btScalar d ) { m_linearDamping = btClamped ( d , ( btScalar ) btScalar ( 0.0 ) , ( btScalar ) btScalar ( 1.0 ) ) ; }
2019-01-03 14:26:51 +01:00
btScalar getLinearDamping ( ) const { return m_linearDamping ; }
2017-08-01 14:30:58 +02:00
void setAngularDamping ( btScalar d ) { m_angularDamping = btClamped ( d , ( btScalar ) btScalar ( 0.0 ) , ( btScalar ) btScalar ( 1.0 ) ) ; }
2019-01-03 14:26:51 +01:00
btScalar getAngularDamping ( ) const { return m_angularDamping ; }
2017-08-01 14:30:58 +02:00
2019-01-03 14:26:51 +01:00
void reset ( btCollisionWorld * collisionWorld ) ;
void warp ( const btVector3 & origin ) ;
2017-08-01 14:30:58 +02:00
2019-01-03 14:26:51 +01:00
void preStep ( btCollisionWorld * collisionWorld ) ;
void playerStep ( btCollisionWorld * collisionWorld , btScalar dt ) ;
2017-08-01 14:30:58 +02:00
void setStepHeight ( btScalar h ) ;
btScalar getStepHeight ( ) const { return m_stepHeight ; }
2019-01-03 14:26:51 +01:00
void setFallSpeed ( btScalar fallSpeed ) ;
2017-08-01 14:30:58 +02:00
btScalar getFallSpeed ( ) const { return m_fallSpeed ; }
2019-01-03 14:26:51 +01:00
void setJumpSpeed ( btScalar jumpSpeed ) ;
2017-08-01 14:30:58 +02:00
btScalar getJumpSpeed ( ) const { return m_jumpSpeed ; }
2019-01-03 14:26:51 +01:00
void setMaxJumpHeight ( btScalar maxJumpHeight ) ;
bool canJump ( ) const ;
2017-08-01 14:30:58 +02:00
void jump ( const btVector3 & v = btVector3 ( 0 , 0 , 0 ) ) ;
void applyImpulse ( const btVector3 & v ) { jump ( v ) ; }
void setGravity ( const btVector3 & gravity ) ;
btVector3 getGravity ( ) const ;
/// The max slope determines the maximum angle that the controller can walk up.
/// The slope angle is measured in radians.
void setMaxSlope ( btScalar slopeRadians ) ;
btScalar getMaxSlope ( ) const ;
void setMaxPenetrationDepth ( btScalar d ) ;
btScalar getMaxPenetrationDepth ( ) const ;
btPairCachingGhostObject * getGhostObject ( ) ;
2019-01-03 14:26:51 +01:00
void setUseGhostSweepTest ( bool useGhostObjectSweepTest )
2017-08-01 14:30:58 +02:00
{
m_useGhostObjectSweepTest = useGhostObjectSweepTest ;
}
2019-01-03 14:26:51 +01:00
bool onGround ( ) const ;
void setUpInterpolate ( bool value ) ;
2017-08-01 14:30:58 +02:00
} ;
2019-01-03 14:26:51 +01:00
# endif // BT_KINEMATIC_CHARACTER_CONTROLLER_H