Note that this answer could be more complete, but, as I'm not a Bullet/physics engine guru, and that I'm not able to easily set up a project right now, I did not have the chance to try and debug the code to see exactly what was going on.
I have formatted the code a bit from the source to ease the reading.
After digging around a bit in the code, then remembering that something was said about motion states in the documentation, I found this page again that discussed
MotionStates in BulletPhysics, which states:
Bullet knows how to interpolate body movement for you. As mentioned, implementation of interpolation is handled through MotionStates.
If you attempt to ask a body for its position, it will return the position at the end of the last physics tick. That's useful for many things, but for rendering you will want some interpolation. Bullet interpolates the transform of the body before passing the value to setWorldTransform.
If you want the non-interpolated position of a body [which will be the position as it was calculated at the end of the last physics tick], use btRigidBody::getWorldTransform() and query the body directly.
To get the interpolated values for rendering it is necessary to call StepSimulation(deltaTime) in your rendering loop. Only include a deltaTime parameter, no other arguments.
Furthermore, browsing the code of Bullet, stemming from
int btDiscreteDynamicsWorld::stepSimulation( btScalar timeStep,int maxSubSteps, btScalar fixedTimeStep)s part:
for (int i=0;i<clampedSimulationSteps;i++)
we find this function:
void btRigidBody::predictIntegratedTransform(btScalar timeStep,btTransform& predictedTransform)
that is called at some point to do a simulation step to update the
body world transform (
predictedTransform here is called with
body->getInterpolationWorldTransform()); and this other method that is called to update the
void btDiscreteDynamicsWorld::synchronizeSingleMotionState(btRigidBody* body)
if (body->getMotionState() && !body->isStaticOrKinematicObject())
(m_latencyMotionStateInterpolation && m_fixedTimeStep) ?
m_localTime - m_fixedTimeStep :
We see that there is an extra step done to
synchronizeMotionStates, which seems to base it's calculations on the calculated
body information and potentially on a different time step for the integration.
The key element here is
m_latencyMotionStateInterpolation which is
true by default. Looking at the documentation for this variable (emphasis mine):
Interpolate motion state between previous and current transform, instead of current and next transform. This can relieve discontinuities in the rendering, due to penetrations
This seems to be why you get lag when using the motion state's value instead of the body's value.
In your situation, if you are able to update your graphics 60 times per second, and you're able to update your physics simulation 60 times per second, and you do it on a 1:1 basis, and don't care about movement prediction, it seems to be recommended to call:
m_DynamicsWorld->stepSimulation(1 / 60.0f, 1, 1 / 60.0f);
and to get your transform directly from the body, as you have discovered.
I hope it helps :)