(From btDiscreteDynamicsWorld::stepSimulation)...
Code: Select all
if (numSimulationSubSteps)
{
saveKinematicState(fixedTimeStep);
applyGravity();
//clamp the number of substeps, to prevent simulation grinding spiralling down to a halt
int clampedSimulationSteps = (numSimulationSubSteps > maxSubSteps)? maxSubSteps : numSimulationSubSteps;
for (int i=0;i<clampedSimulationSteps;i++)
{
internalSingleStepSimulation(fixedTimeStep);
synchronizeMotionStates();
}
}
synchronizeMotionStates();
clearForces();
There are several solutions; the simplest is probably to apply gravity to all objects, sleeping or not. I think that is harmless because the force will never be integrated, and cleared at the end of 'stepSimulation'.
I think there is another bug lurking here too: I contest whether it is feasible to have a single accumulated force and torque vector. Since the addition of callbacks tied into the internal framerate, if you apply forces in one of these callbacks they will actually compound over internal timesteps which they should not do. My solution, in the end, is to have an 'internal' force and torque and an 'external' force and torque. Internal forces are cleared after each internal timestep, and external forces are cleared only after each 'stepSimultion'. If you apply forces at the 'game' framerate (i.e. between calls to 'stepSimulation' then you apply external forces, if you apply forces in a physics callback, you apply internal forces. It feels like a shame to have to bloat the data structures like this, but I couldn't see a better solution; I'm suprised nobody has noticed this problem since 'setInternalTickCallback' was added. Anyway, I moved gravity to be an internal force, which is an alternate fix for the problem.
Erwin, I'm afraid my changes are now so extensive I can't easily provide a patch for either of these issues, but I would be happy to prepare one if you let me know which solution you prefer, the changes are very simple to implement anyhow.
EDIT: thinking about it more, the cleanest solution is probably just to remove the 'isActive' clause from btRigidBody::applyGravity. Infact, it's probably faster overall, it's probably quicker to add gravity than to check and branch. I haven't tried this solution, it may have side-effects.
Many thanks,
Rob