applied Character controller patch #20 from Issue 198
See https://code.google.com/p/bullet/issues/detail?id=198
This commit is contained in:
1 parent
d50be40f8e
commit
c160bfe74c
4 files changed
+148
-28
No files matched your search
@@ -341,7 +341,7 @@ void CharacterDemo::clientResetScene()
|
|||||||
{
|
{
|
||||||
m_dynamicsWorld->getBroadphase()->getOverlappingPairCache()->cleanProxyFromPairs(m_ghostObject->getBroadphaseHandle(),getDynamicsWorld()->getDispatcher());
|
m_dynamicsWorld->getBroadphase()->getOverlappingPairCache()->cleanProxyFromPairs(m_ghostObject->getBroadphaseHandle(),getDynamicsWorld()->getDispatcher());
|
||||||
|
|
||||||
m_character->reset ();
|
m_character->reset (m_dynamicsWorld);
|
||||||
///WTF
|
///WTF
|
||||||
m_character->warp (btVector3(10.210001,-2.0306311,16.576973));
|
m_character->warp (btVector3(10.210001,-2.0306311,16.576973));
|
||||||
|
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ public:
|
|||||||
|
|
||||||
virtual void setWalkDirection(const btVector3& walkDirection) = 0;
|
virtual void setWalkDirection(const btVector3& walkDirection) = 0;
|
||||||
virtual void setVelocityForTimeInterval(const btVector3& velocity, btScalar timeInterval) = 0;
|
virtual void setVelocityForTimeInterval(const btVector3& velocity, btScalar timeInterval) = 0;
|
||||||
virtual void reset () = 0;
|
virtual void reset ( btCollisionWorld* collisionWorld ) = 0;
|
||||||
virtual void warp (const btVector3& origin) = 0;
|
virtual void warp (const btVector3& origin) = 0;
|
||||||
|
|
||||||
virtual void preStep ( btCollisionWorld* collisionWorld) = 0;
|
virtual void preStep ( btCollisionWorld* collisionWorld) = 0;
|
||||||
@@ -40,6 +40,7 @@ public:
|
|||||||
virtual void jump () = 0;
|
virtual void jump () = 0;
|
||||||
|
|
||||||
virtual bool onGround () const = 0;
|
virtual bool onGround () const = 0;
|
||||||
|
virtual void setUpInterpolate (bool value) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //BT_CHARACTER_CONTROLLER_INTERFACE_H
|
#endif //BT_CHARACTER_CONTROLLER_INTERFACE_H
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ subject to the following restrictions:
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
#include "LinearMath/btIDebugDraw.h"
|
#include "LinearMath/btIDebugDraw.h"
|
||||||
#include "BulletCollision/CollisionDispatch/btGhostObject.h"
|
#include "BulletCollision/CollisionDispatch/btGhostObject.h"
|
||||||
#include "BulletCollision/CollisionShapes/btMultiSphereShape.h"
|
#include "BulletCollision/CollisionShapes/btMultiSphereShape.h"
|
||||||
@@ -77,6 +78,9 @@ public:
|
|||||||
if (convexResult.m_hitCollisionObject == m_me)
|
if (convexResult.m_hitCollisionObject == m_me)
|
||||||
return btScalar(1.0);
|
return btScalar(1.0);
|
||||||
|
|
||||||
|
if (!convexResult.m_hitCollisionObject->hasContactResponse())
|
||||||
|
return btScalar(1.0);
|
||||||
|
|
||||||
btVector3 hitNormalWorld;
|
btVector3 hitNormalWorld;
|
||||||
if (normalInWorldSpace)
|
if (normalInWorldSpace)
|
||||||
{
|
{
|
||||||
@@ -146,7 +150,11 @@ btKinematicCharacterController::btKinematicCharacterController (btPairCachingGho
|
|||||||
m_jumpSpeed = 10.0; // ?
|
m_jumpSpeed = 10.0; // ?
|
||||||
m_wasOnGround = false;
|
m_wasOnGround = false;
|
||||||
m_wasJumping = false;
|
m_wasJumping = false;
|
||||||
|
m_interpolateUp = true;
|
||||||
setMaxSlope(btRadians(45.0));
|
setMaxSlope(btRadians(45.0));
|
||||||
|
m_currentStepOffset = 0;
|
||||||
|
full_drop = false;
|
||||||
|
bounce_fix = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
btKinematicCharacterController::~btKinematicCharacterController ()
|
btKinematicCharacterController::~btKinematicCharacterController ()
|
||||||
@@ -188,6 +196,12 @@ bool btKinematicCharacterController::recoverFromPenetration ( btCollisionWorld*
|
|||||||
|
|
||||||
btBroadphasePair* collisionPair = &m_ghostObject->getOverlappingPairCache()->getOverlappingPairArray()[i];
|
btBroadphasePair* collisionPair = &m_ghostObject->getOverlappingPairCache()->getOverlappingPairArray()[i];
|
||||||
|
|
||||||
|
btCollisionObject* obj0 = static_cast<btCollisionObject*>(collisionPair->m_pProxy0->m_clientObject);
|
||||||
|
btCollisionObject* obj1 = static_cast<btCollisionObject*>(collisionPair->m_pProxy1->m_clientObject);
|
||||||
|
|
||||||
|
if ((obj0 && !obj0->hasContactResponse()) || (obj1 && !obj1->hasContactResponse()))
|
||||||
|
continue;
|
||||||
|
|
||||||
if (collisionPair->m_algorithm)
|
if (collisionPair->m_algorithm)
|
||||||
collisionPair->m_algorithm->getAllContactManifolds(m_manifoldArray);
|
collisionPair->m_algorithm->getAllContactManifolds(m_manifoldArray);
|
||||||
|
|
||||||
@@ -260,7 +274,10 @@ void btKinematicCharacterController::stepUp ( btCollisionWorld* world)
|
|||||||
{
|
{
|
||||||
// we moved up only a fraction of the step height
|
// we moved up only a fraction of the step height
|
||||||
m_currentStepOffset = m_stepHeight * callback.m_closestHitFraction;
|
m_currentStepOffset = m_stepHeight * callback.m_closestHitFraction;
|
||||||
m_currentPosition.setInterpolate3 (m_currentPosition, m_targetPosition, callback.m_closestHitFraction);
|
if (m_interpolateUp == true)
|
||||||
|
m_currentPosition.setInterpolate3 (m_currentPosition, m_targetPosition, callback.m_closestHitFraction);
|
||||||
|
else
|
||||||
|
m_currentPosition = m_targetPosition;
|
||||||
}
|
}
|
||||||
m_verticalVelocity = 0.0;
|
m_verticalVelocity = 0.0;
|
||||||
m_verticalOffset = 0.0;
|
m_verticalOffset = 0.0;
|
||||||
@@ -325,7 +342,8 @@ void btKinematicCharacterController::stepForwardAndStrafe ( btCollisionWorld* co
|
|||||||
{
|
{
|
||||||
if (m_normalizedDirection.dot(m_touchingNormal) > btScalar(0.0))
|
if (m_normalizedDirection.dot(m_touchingNormal) > btScalar(0.0))
|
||||||
{
|
{
|
||||||
updateTargetPositionBasedOnCollision (m_touchingNormal);
|
//interferes with step movement
|
||||||
|
//updateTargetPositionBasedOnCollision (m_touchingNormal);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -397,7 +415,8 @@ void btKinematicCharacterController::stepForwardAndStrafe ( btCollisionWorld* co
|
|||||||
|
|
||||||
void btKinematicCharacterController::stepDown ( btCollisionWorld* collisionWorld, btScalar dt)
|
void btKinematicCharacterController::stepDown ( btCollisionWorld* collisionWorld, btScalar dt)
|
||||||
{
|
{
|
||||||
btTransform start, end;
|
btTransform start, end, end_double;
|
||||||
|
bool runonce = false;
|
||||||
|
|
||||||
// phase 3: down
|
// phase 3: down
|
||||||
/*btScalar additionalDownStep = (m_wasOnGround && !onGround()) ? m_stepHeight : 0.0;
|
/*btScalar additionalDownStep = (m_wasOnGround && !onGround()) ? m_stepHeight : 0.0;
|
||||||
@@ -406,44 +425,124 @@ void btKinematicCharacterController::stepDown ( btCollisionWorld* collisionWorld
|
|||||||
btVector3 gravity_drop = getUpAxisDirections()[m_upAxis] * downVelocity;
|
btVector3 gravity_drop = getUpAxisDirections()[m_upAxis] * downVelocity;
|
||||||
m_targetPosition -= (step_drop + gravity_drop);*/
|
m_targetPosition -= (step_drop + gravity_drop);*/
|
||||||
|
|
||||||
|
btVector3 orig_position = m_targetPosition;
|
||||||
|
|
||||||
btScalar downVelocity = (m_verticalVelocity<0.f?-m_verticalVelocity:0.f) * dt;
|
btScalar downVelocity = (m_verticalVelocity<0.f?-m_verticalVelocity:0.f) * dt;
|
||||||
if(downVelocity > 0.0 && downVelocity < m_stepHeight
|
|
||||||
|
if(downVelocity > 0.0 && downVelocity > m_fallSpeed
|
||||||
&& (m_wasOnGround || !m_wasJumping))
|
&& (m_wasOnGround || !m_wasJumping))
|
||||||
{
|
downVelocity = m_fallSpeed;
|
||||||
downVelocity = m_stepHeight;
|
|
||||||
}
|
|
||||||
|
|
||||||
btVector3 step_drop = getUpAxisDirections()[m_upAxis] * (m_currentStepOffset + downVelocity);
|
btVector3 step_drop = getUpAxisDirections()[m_upAxis] * (m_currentStepOffset + downVelocity);
|
||||||
m_targetPosition -= step_drop;
|
m_targetPosition -= step_drop;
|
||||||
|
|
||||||
start.setIdentity ();
|
|
||||||
end.setIdentity ();
|
|
||||||
|
|
||||||
start.setOrigin (m_currentPosition);
|
|
||||||
end.setOrigin (m_targetPosition);
|
|
||||||
|
|
||||||
btKinematicClosestNotMeConvexResultCallback callback (m_ghostObject, getUpAxisDirections()[m_upAxis], m_maxSlopeCosine);
|
btKinematicClosestNotMeConvexResultCallback callback (m_ghostObject, getUpAxisDirections()[m_upAxis], m_maxSlopeCosine);
|
||||||
callback.m_collisionFilterGroup = getGhostObject()->getBroadphaseHandle()->m_collisionFilterGroup;
|
callback.m_collisionFilterGroup = getGhostObject()->getBroadphaseHandle()->m_collisionFilterGroup;
|
||||||
callback.m_collisionFilterMask = getGhostObject()->getBroadphaseHandle()->m_collisionFilterMask;
|
callback.m_collisionFilterMask = getGhostObject()->getBroadphaseHandle()->m_collisionFilterMask;
|
||||||
|
|
||||||
if (m_useGhostObjectSweepTest)
|
btKinematicClosestNotMeConvexResultCallback callback2 (m_ghostObject, getUpAxisDirections()[m_upAxis], m_maxSlopeCosine);
|
||||||
|
callback2.m_collisionFilterGroup = getGhostObject()->getBroadphaseHandle()->m_collisionFilterGroup;
|
||||||
|
callback2.m_collisionFilterMask = getGhostObject()->getBroadphaseHandle()->m_collisionFilterMask;
|
||||||
|
|
||||||
|
while (1)
|
||||||
{
|
{
|
||||||
m_ghostObject->convexSweepTest (m_convexShape, start, end, callback, collisionWorld->getDispatchInfo().m_allowedCcdPenetration);
|
start.setIdentity ();
|
||||||
} else
|
end.setIdentity ();
|
||||||
{
|
|
||||||
collisionWorld->convexSweepTest (m_convexShape, start, end, callback, collisionWorld->getDispatchInfo().m_allowedCcdPenetration);
|
end_double.setIdentity ();
|
||||||
|
|
||||||
|
start.setOrigin (m_currentPosition);
|
||||||
|
end.setOrigin (m_targetPosition);
|
||||||
|
|
||||||
|
//set double test for 2x the step drop, to check for a large drop vs small drop
|
||||||
|
end_double.setOrigin (m_targetPosition - step_drop);
|
||||||
|
|
||||||
|
if (m_useGhostObjectSweepTest)
|
||||||
|
{
|
||||||
|
m_ghostObject->convexSweepTest (m_convexShape, start, end, callback, collisionWorld->getDispatchInfo().m_allowedCcdPenetration);
|
||||||
|
|
||||||
|
if (!callback.hasHit())
|
||||||
|
{
|
||||||
|
//test a double fall height, to see if the character should interpolate it's fall (full) or not (partial)
|
||||||
|
m_ghostObject->convexSweepTest (m_convexShape, start, end_double, callback2, collisionWorld->getDispatchInfo().m_allowedCcdPenetration);
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
collisionWorld->convexSweepTest (m_convexShape, start, end, callback, collisionWorld->getDispatchInfo().m_allowedCcdPenetration);
|
||||||
|
|
||||||
|
if (!callback.hasHit())
|
||||||
|
{
|
||||||
|
//test a double fall height, to see if the character should interpolate it's fall (large) or not (small)
|
||||||
|
collisionWorld->convexSweepTest (m_convexShape, start, end_double, callback2, collisionWorld->getDispatchInfo().m_allowedCcdPenetration);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
btScalar downVelocity2 = (m_verticalVelocity<0.f?-m_verticalVelocity:0.f) * dt;
|
||||||
|
bool has_hit = false;
|
||||||
|
if (bounce_fix == true)
|
||||||
|
has_hit = callback.hasHit() || callback2.hasHit();
|
||||||
|
else
|
||||||
|
has_hit = callback2.hasHit();
|
||||||
|
|
||||||
|
if(downVelocity2 > 0.0 && downVelocity2 < m_stepHeight && has_hit == true && runonce == false
|
||||||
|
&& (m_wasOnGround || !m_wasJumping))
|
||||||
|
{
|
||||||
|
//redo the velocity calculation when falling a small amount, for fast stairs motion
|
||||||
|
//for larger falls, use the smoother/slower interpolated movement by not touching the target position
|
||||||
|
|
||||||
|
m_targetPosition = orig_position;
|
||||||
|
downVelocity = m_stepHeight;
|
||||||
|
|
||||||
|
btVector3 step_drop = getUpAxisDirections()[m_upAxis] * (m_currentStepOffset + downVelocity);
|
||||||
|
m_targetPosition -= step_drop;
|
||||||
|
runonce = true;
|
||||||
|
continue; //re-run previous tests
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (callback.hasHit())
|
if (callback.hasHit() || runonce == true)
|
||||||
{
|
{
|
||||||
// we dropped a fraction of the height -> hit floor
|
// we dropped a fraction of the height -> hit floor
|
||||||
m_currentPosition.setInterpolate3 (m_currentPosition, m_targetPosition, callback.m_closestHitFraction);
|
|
||||||
|
btScalar fraction = (m_currentPosition.getY() - callback.m_hitPointWorld.getY()) / 2;
|
||||||
|
|
||||||
|
//printf("hitpoint: %g - pos %g\n", callback.m_hitPointWorld.getY(), m_currentPosition.getY());
|
||||||
|
|
||||||
|
if (bounce_fix == true)
|
||||||
|
{
|
||||||
|
if (full_drop == true)
|
||||||
|
m_currentPosition.setInterpolate3 (m_currentPosition, m_targetPosition, callback.m_closestHitFraction);
|
||||||
|
else
|
||||||
|
//due to errors in the closestHitFraction variable when used with large polygons, calculate the hit fraction manually
|
||||||
|
m_currentPosition.setInterpolate3 (m_currentPosition, m_targetPosition, fraction);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
m_currentPosition.setInterpolate3 (m_currentPosition, m_targetPosition, callback.m_closestHitFraction);
|
||||||
|
|
||||||
|
full_drop = false;
|
||||||
|
|
||||||
m_verticalVelocity = 0.0;
|
m_verticalVelocity = 0.0;
|
||||||
m_verticalOffset = 0.0;
|
m_verticalOffset = 0.0;
|
||||||
m_wasJumping = false;
|
m_wasJumping = false;
|
||||||
} else {
|
} else {
|
||||||
// we dropped the full height
|
// we dropped the full height
|
||||||
|
|
||||||
|
full_drop = true;
|
||||||
|
|
||||||
|
if (bounce_fix == true)
|
||||||
|
{
|
||||||
|
downVelocity = (m_verticalVelocity<0.f?-m_verticalVelocity:0.f) * dt;
|
||||||
|
if (downVelocity > m_fallSpeed && (m_wasOnGround || !m_wasJumping))
|
||||||
|
{
|
||||||
|
m_targetPosition += step_drop; //undo previous target change
|
||||||
|
downVelocity = m_fallSpeed;
|
||||||
|
step_drop = getUpAxisDirections()[m_upAxis] * (m_currentStepOffset + downVelocity);
|
||||||
|
m_targetPosition -= step_drop;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//printf("full drop - %g, %g\n", m_currentPosition.getY(), m_targetPosition.getY());
|
||||||
|
|
||||||
m_currentPosition = m_targetPosition;
|
m_currentPosition = m_targetPosition;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -479,10 +578,21 @@ btScalar timeInterval
|
|||||||
m_velocityTimeInterval = timeInterval;
|
m_velocityTimeInterval = timeInterval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void btKinematicCharacterController::reset ( btCollisionWorld* collisionWorld )
|
||||||
|
|
||||||
void btKinematicCharacterController::reset ()
|
|
||||||
{
|
{
|
||||||
|
m_verticalVelocity = 0.0;
|
||||||
|
m_verticalOffset = 0.0;
|
||||||
|
m_wasOnGround = false;
|
||||||
|
m_wasJumping = false;
|
||||||
|
m_walkDirection.setValue(0,0,0);
|
||||||
|
m_velocityTimeInterval = 0.0;
|
||||||
|
|
||||||
|
//clear pair cache
|
||||||
|
btHashedOverlappingPairCache *cache = m_ghostObject->getOverlappingPairCache();
|
||||||
|
while (cache->getOverlappingPairArray().size() > 0)
|
||||||
|
{
|
||||||
|
cache->removeOverlappingPair(cache->getOverlappingPairArray()[0].m_pProxy0, cache->getOverlappingPairArray()[0].m_pProxy1, collisionWorld->getDispatcher());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void btKinematicCharacterController::warp (const btVector3& origin)
|
void btKinematicCharacterController::warp (const btVector3& origin)
|
||||||
@@ -653,3 +763,8 @@ btVector3* btKinematicCharacterController::getUpAxisDirections()
|
|||||||
void btKinematicCharacterController::debugDraw(btIDebugDraw* debugDrawer)
|
void btKinematicCharacterController::debugDraw(btIDebugDraw* debugDrawer)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void btKinematicCharacterController::setUpInterpolate(bool value)
|
||||||
|
{
|
||||||
|
m_interpolateUp = value;
|
||||||
|
}
|
||||||
@@ -81,6 +81,9 @@ protected:
|
|||||||
int m_upAxis;
|
int m_upAxis;
|
||||||
|
|
||||||
static btVector3* getUpAxisDirections();
|
static btVector3* getUpAxisDirections();
|
||||||
|
bool m_interpolateUp;
|
||||||
|
bool full_drop;
|
||||||
|
bool bounce_fix;
|
||||||
|
|
||||||
btVector3 computeReflectionDirection (const btVector3& direction, const btVector3& normal);
|
btVector3 computeReflectionDirection (const btVector3& direction, const btVector3& normal);
|
||||||
btVector3 parallelComponent (const btVector3& direction, const btVector3& normal);
|
btVector3 parallelComponent (const btVector3& direction, const btVector3& normal);
|
||||||
@@ -133,7 +136,7 @@ public:
|
|||||||
virtual void setVelocityForTimeInterval(const btVector3& velocity,
|
virtual void setVelocityForTimeInterval(const btVector3& velocity,
|
||||||
btScalar timeInterval);
|
btScalar timeInterval);
|
||||||
|
|
||||||
void reset ();
|
void reset ( btCollisionWorld* collisionWorld );
|
||||||
void warp (const btVector3& origin);
|
void warp (const btVector3& origin);
|
||||||
|
|
||||||
void preStep ( btCollisionWorld* collisionWorld);
|
void preStep ( btCollisionWorld* collisionWorld);
|
||||||
@@ -161,6 +164,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool onGround () const;
|
bool onGround () const;
|
||||||
|
void setUpInterpolate (bool value);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // BT_KINEMATIC_CHARACTER_CONTROLLER_H
|
#endif // BT_KINEMATIC_CHARACTER_CONTROLLER_H
|
||||||
Reference in new issue
Block a user