Fix in btGjkPairDetector, possibly causing a floating point overflow

Thanks Ole for the report and suggested fix:
http://code.google.com/p/bullet/issues/detail?id=220&can=1&start=200

Applied Character/btKinematicCharacterController.cpp patch:
Thanks Thomas for the patch!
http://code.google.com/p/bullet/issues/detail?id=196#makechanges

 - added a normalizedDirection member variable.  This is
     slightly more efficient than recalculating the normalized
     direction every simulation step.

 - I overloaded the m_walkDirection member variable to hold
     either the walkDirection or the Velocity, and used a boolean
     flag to determine which behavior was required.

 - The normalization behavior seemed custom, and I needed it
     twice, so I moved it to a static helper method.

 - I added the setVelocityForTimeInterval() method to the
     base interface class.  This to me is the scariest change
     since people inheriting from it will need to make changes
     (if only to add an empty function).
This commit is contained in:
erwin.coumans 2009-05-23 02:28:58 +00:00
parent badf723257
commit 0ada7cbb1e
4 changed files with 104 additions and 17 deletions

View File

@ -107,7 +107,7 @@ void btGjkPairDetector::getClosestPoints(const ClosestPointInput& input,Result&
m_lastUsedMethod = -1;
{
btScalar squaredDistance = SIMD_INFINITY;
btScalar squaredDistance = BT_LARGE_FLOAT;
btScalar delta = btScalar(0.);
btScalar margin = marginA + marginB;

View File

@ -30,6 +30,7 @@ public:
virtual ~btCharacterControllerInterface () {};
virtual void setWalkDirection(const btVector3& walkDirection) = 0;
virtual void setVelocityForTimeInterval(const btVector3& velocity, btScalar timeInterval) = 0;
virtual void reset () = 0;
virtual void warp (const btVector3& origin) = 0;

View File

@ -13,6 +13,7 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
#include "LinearMath/btIDebugDraw.h"
#include "BulletCollision/CollisionDispatch/btGhostObject.h"
#include "BulletCollision/CollisionShapes/btMultiSphereShape.h"
@ -24,6 +25,19 @@ subject to the following restrictions:
static btVector3 upAxisDirection[3] = { btVector3(1.0f, 0.0f, 0.0f), btVector3(0.0f, 1.0f, 0.0f), btVector3(0.0f, 0.0f, 1.0f) };
// static helper method
static btVector3
getNormalizedVector(const btVector3& v)
{
btVector3 n = v.normalized();
if (n.length() < SIMD_EPSILON) {
n.setValue(0, 0, 0);
}
return n;
}
///@todo Interact with dynamic objects,
///Ride kinematicly animated platforms properly
///More realistic (or maybe just a config option) falling
@ -105,6 +119,8 @@ btKinematicCharacterController::btKinematicCharacterController (btPairCachingGho
m_stepHeight = stepHeight;
m_turnAngle = btScalar(0.0);
m_convexShape=convexShape;
m_useWalkDirection = true; // use walk direction by default, legacy behavior
m_velocityTimeInterval = 0.0;
}
btKinematicCharacterController::~btKinematicCharacterController ()
@ -244,13 +260,8 @@ void btKinematicCharacterController::updateTargetPositionBasedOnCollision (const
void btKinematicCharacterController::stepForwardAndStrafe ( btCollisionWorld* collisionWorld, const btVector3& walkMove)
{
btVector3 originalDir = walkMove.normalized();
if (walkMove.length() < SIMD_EPSILON)
{
originalDir.setValue(0.f,0.f,0.f);
}
// printf("originalDir=%f,%f,%f\n",originalDir[0],originalDir[1],originalDir[2]);
// printf("m_normalizedDirection=%f,%f,%f\n",
// m_normalizedDirection[0],m_normalizedDirection[1],m_normalizedDirection[2]);
// phase 2: forward and strafe
btTransform start, end;
m_targetPosition = m_currentPosition + walkMove;
@ -263,7 +274,7 @@ void btKinematicCharacterController::stepForwardAndStrafe ( btCollisionWorld* co
if (m_touchingContact)
{
if (originalDir.dot(m_touchingNormal) > btScalar(0.0))
if (m_normalizedDirection.dot(m_touchingNormal) > btScalar(0.0))
updateTargetPositionBasedOnCollision (m_touchingNormal);
}
@ -319,7 +330,7 @@ void btKinematicCharacterController::stepForwardAndStrafe ( btCollisionWorld* co
{
currentDir.normalize();
/* See Quake2: "If velocity is against original velocity, stop ead to avoid tiny oscilations in sloping corners." */
if (currentDir.dot(originalDir) <= btScalar(0.0))
if (currentDir.dot(m_normalizedDirection) <= btScalar(0.0))
{
break;
}
@ -377,6 +388,39 @@ void btKinematicCharacterController::stepDown ( btCollisionWorld* collisionWorld
}
}
void btKinematicCharacterController::setWalkDirection
(
const btVector3& walkDirection
)
{
m_useWalkDirection = true;
m_walkDirection = walkDirection;
m_normalizedDirection = getNormalizedVector(m_walkDirection);
}
void btKinematicCharacterController::setVelocityForTimeInterval
(
const btVector3& velocity,
btScalar timeInterval
)
{
// printf("setVelocity!\n");
// printf(" interval: %f\n", timeInterval);
// printf(" velocity: (%f, %f, %f)\n",
// velocity.x(), velocity.y(), velocity.z());
m_useWalkDirection = false;
m_walkDirection = velocity;
m_normalizedDirection = getNormalizedVector(m_walkDirection);
m_velocityTimeInterval = timeInterval;
}
void btKinematicCharacterController::reset ()
{
}
@ -415,6 +459,15 @@ void btKinematicCharacterController::preStep ( btCollisionWorld* collisionWorld
void btKinematicCharacterController::playerStep ( btCollisionWorld* collisionWorld, btScalar dt)
{
// printf("playerStep(): ");
// printf(" dt = %f", dt);
// quick check...
if (!m_useWalkDirection && m_velocityTimeInterval <= 0.0) {
// printf("\n");
return; // no motion
}
btTransform xform;
xform = m_ghostObject->getWorldTransform ();
@ -422,9 +475,27 @@ void btKinematicCharacterController::playerStep ( btCollisionWorld* collisionWo
// printf("walkSpeed=%f\n",walkSpeed);
stepUp (collisionWorld);
stepForwardAndStrafe (collisionWorld, m_walkDirection);
if (m_useWalkDirection) {
stepForwardAndStrafe (collisionWorld, m_walkDirection);
} else {
//printf(" time: %f", m_velocityTimeInterval);
// still have some time left for moving!
btScalar dtMoving =
(dt < m_velocityTimeInterval) ? dt : m_velocityTimeInterval;
m_velocityTimeInterval -= dt;
// how far will we move while we are moving?
btVector3 move = m_walkDirection * dtMoving;
// printf(" dtMoving: %f", dtMoving);
// okay, step
stepForwardAndStrafe(collisionWorld, move);
}
stepDown (collisionWorld, dt);
// printf("\n");
xform.setOrigin (m_currentPosition);
m_ghostObject->setWorldTransform (xform);
}
@ -473,4 +544,4 @@ bool btKinematicCharacterController::onGround () const
void btKinematicCharacterController::debugDraw(btIDebugDraw* debugDrawer)
{
}
}

View File

@ -20,6 +20,9 @@ subject to the following restrictions:
#include "btCharacterControllerInterface.h"
#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
class btCollisionShape;
class btRigidBody;
class btCollisionWorld;
@ -49,6 +52,7 @@ protected:
///this is the desired walk direction, set by the user
btVector3 m_walkDirection;
btVector3 m_normalizedDirection;
//some internal variables
btVector3 m_currentPosition;
@ -62,7 +66,8 @@ protected:
btVector3 m_touchingNormal;
bool m_useGhostObjectSweepTest;
bool m_useWalkDirection;
float m_velocityTimeInterval;
int m_upAxis;
btVector3 computeReflectionDirection (const btVector3& direction, const btVector3& normal);
@ -98,10 +103,20 @@ public:
m_upAxis = axis;
}
virtual void setWalkDirection(const btVector3& walkDirection)
{
m_walkDirection = walkDirection;
}
/// 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().
virtual void setWalkDirection(const btVector3& walkDirection);
/// 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,
btScalar timeInterval);
void reset ();
void warp (const btVector3& origin);