added gyroscopic force option for btRigidBody, body->setFlags(BT_ENABLE_GYROPSCOPIC_FORCE);

Note that it can easily introduce instability at regular (60Hertz) simulation steps so it is generally best to not use the option.
If needed, use a very small internal step, such as 1000 Hertz (world->stepSimulation(dt,100,1./1000.f); or stepSimulation(1./1000.,0);
This commit is contained in:
erwin.coumans
2012-09-14 21:39:48 +00:00
parent 3e9f35c0fd
commit 54744b6ab9
11 changed files with 464 additions and 7 deletions

View File

@@ -56,6 +56,7 @@ struct btContactSolverInfoData
int m_solverMode;
int m_restingContactRestitutionThreshold;
int m_minimumSolverBatchSize;
btScalar m_maxGyroscopicForce;
};
@@ -86,6 +87,7 @@ struct btContactSolverInfo : public btContactSolverInfoData
//m_solverMode = SOLVER_USE_WARMSTARTING | SOLVER_SIMD | SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION|SOLVER_USE_2_FRICTION_DIRECTIONS|SOLVER_ENABLE_FRICTION_DIRECTION_CACHING;// | SOLVER_RANDMIZE_ORDER;
m_solverMode = SOLVER_USE_WARMSTARTING | SOLVER_SIMD;// | SOLVER_RANDMIZE_ORDER;
m_minimumSolverBatchSize = 128; //try to combine islands until the amount of constraints reaches this limit
m_maxGyroscopicForce = 100.f; ///only used to clamp forces for bodies that have their BT_ENABLE_GYROPSCOPIC_FORCE flag set (using btRigidBody::setFlag)
}
};

View File

@@ -837,8 +837,13 @@ btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySetup(btCol
if (body && body->getInvMass())
{
btSolverBody& solverBody = m_tmpSolverBodyPool[bodyId];
btVector3 gyroForce (0,0,0);
if (body->getFlags()&BT_ENABLE_GYROPSCOPIC_FORCE)
{
gyroForce = body->computeGyroscopicForce(infoGlobal.m_maxGyroscopicForce);
}
solverBody.m_linearVelocity += body->getTotalForce()*body->getInvMass()*infoGlobal.m_timeStep;
solverBody.m_angularVelocity += body->getTotalTorque()*body->getInvInertiaTensorWorld()*infoGlobal.m_timeStep;
solverBody.m_angularVelocity += (body->getTotalTorque()-gyroForce)*body->getInvInertiaTensorWorld()*infoGlobal.m_timeStep;
}
}

View File

@@ -256,6 +256,23 @@ void btRigidBody::updateInertiaTensor()
}
btVector3 btRigidBody::computeGyroscopicForce(btScalar maxGyroscopicForce) const
{
btVector3 inertiaLocal;
inertiaLocal[0] = 1.f/getInvInertiaDiagLocal()[0];
inertiaLocal[1] = 1.f/getInvInertiaDiagLocal()[1];
inertiaLocal[2] = 1.f/getInvInertiaDiagLocal()[2];
btMatrix3x3 inertiaTensorWorld = getWorldTransform().getBasis().scaled(inertiaLocal) * getWorldTransform().getBasis().transpose();
btVector3 tmp = inertiaTensorWorld*getAngularVelocity();
btVector3 gf = getAngularVelocity().cross(tmp);
btScalar l2 = gf.length2();
if (l2>maxGyroscopicForce*maxGyroscopicForce)
{
gf *= btScalar(1.)/btSqrt(l2)*maxGyroscopicForce;
}
return gf;
}
void btRigidBody::integrateVelocities(btScalar step)
{
if (isStaticOrKinematicObject())

View File

@@ -40,7 +40,11 @@ extern bool gDisableDeactivation;
enum btRigidBodyFlags
{
BT_DISABLE_WORLD_GRAVITY = 1
BT_DISABLE_WORLD_GRAVITY = 1,
///The BT_ENABLE_GYROPSCOPIC_FORCE can easily introduce instability
///So generally it is best to not enable it.
///If really needed, run at a high frequency like 1000 Hertz: ///See Demos/GyroscopicDemo for an example use
BT_ENABLE_GYROPSCOPIC_FORCE = 2
};
@@ -519,8 +523,7 @@ public:
return m_rigidbodyFlags;
}
btVector3 computeGyroscopicForce(btScalar maxGyroscopicForce) const;
///////////////////////////////////////////////