mirror of
https://github.com/bulletphysics/bullet3
synced 2025-01-08 08:30:16 +00:00
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:
parent
badf723257
commit
0ada7cbb1e
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user