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

@@ -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)
{
}
}