add "latency motion state interpolation", using previous frame/current, instead of current->next

See Demos/ForkLiftDemo for example (F7 to toggle, use single-frame stepping, press 'i' and 's' to see the effect)
This commit is contained in:
erwin.coumans@gmail.com
2013-10-24 00:13:43 +00:00
parent a1c962192c
commit f5320e4106
3 changed files with 56 additions and 25 deletions

View File

@@ -465,7 +465,7 @@ void ForkLiftDemo::renderme()
} }
int lineWidth=250; int lineWidth=400;
int xStart = m_glutScreenWidth - lineWidth; int xStart = m_glutScreenWidth - lineWidth;
int yStart = 20; int yStart = 20;
@@ -476,39 +476,44 @@ void ForkLiftDemo::renderme()
glColor3f(0, 0, 0); glColor3f(0, 0, 0);
char buf[124]; char buf[124];
glRasterPos3f(xStart, yStart, 0);
sprintf(buf,"SHIFT+Cursor Left/Right - rotate lift"); sprintf(buf,"SHIFT+Cursor Left/Right - rotate lift");
GLDebugDrawString(xStart,20,buf); GLDebugDrawString(xStart,20,buf);
yStart+=20; yStart+=20;
glRasterPos3f(xStart, yStart, 0); sprintf(buf,"SHIFT+Cursor UP/Down - fork up/down");
sprintf(buf,"SHIFT+Cursor UP/Down - move fork up/down");
yStart+=20; yStart+=20;
GLDebugDrawString(xStart,yStart,buf); GLDebugDrawString(xStart,yStart,buf);
yStart+=20; if (m_useDefaultCamera)
glRasterPos3f(xStart, yStart, 0);
sprintf(buf,"F6 - toggle solver");
GLDebugDrawString(xStart,yStart,buf);
yStart+=20;
glRasterPos3f(xStart, yStart, 0);
if (m_dynamicsWorld->getConstraintSolver()->getSolverType()==BT_MLCP_SOLVER)
{ {
sprintf(buf,"Using direct MLCP solver"); sprintf(buf,"F5 - camera mode (free)");
} else } else
{ {
sprintf(buf,"Using sequential impulse solver"); sprintf(buf,"F5 - camera mode (follow)");
} }
GLDebugDrawString(xStart,yStart,buf);
glRasterPos3f(xStart, yStart, 0);
sprintf(buf,"F5 - toggle camera mode");
yStart+=20; yStart+=20;
GLDebugDrawString(xStart,yStart,buf); GLDebugDrawString(xStart,yStart,buf);
glRasterPos3f(xStart, yStart, 0);
sprintf(buf,"Click inside this window for keyboard focus"); yStart+=20;
if (m_dynamicsWorld->getConstraintSolver()->getSolverType()==BT_MLCP_SOLVER)
{
sprintf(buf,"F6 - solver (direct MLCP)");
} else
{
sprintf(buf,"F6 - solver (sequential impulse)");
}
GLDebugDrawString(xStart,yStart,buf);
btDiscreteDynamicsWorld* world = (btDiscreteDynamicsWorld*) m_dynamicsWorld;
if (world->getLatencyMotionStateInterpolation())
{
sprintf(buf,"F7 - motionstate interpolation (on)");
} else
{
sprintf(buf,"F7 - motionstate interpolation (off)");
}
yStart+=20;
GLDebugDrawString(xStart,yStart,buf);
sprintf(buf,"Click window for keyboard focus");
yStart+=20; yStart+=20;
GLDebugDrawString(xStart,yStart,buf); GLDebugDrawString(xStart,yStart,buf);
@@ -809,6 +814,13 @@ void ForkLiftDemo::specialKeyboard(int key, int x, int y)
break; break;
} }
case GLUT_KEY_F7:
{
btDiscreteDynamicsWorld* world = (btDiscreteDynamicsWorld*)m_dynamicsWorld;
world->setLatencyMotionStateInterpolation(!world->getLatencyMotionStateInterpolation());
printf("world latencyMotionStateInterpolation = %d\n", world->getLatencyMotionStateInterpolation());
break;
}
case GLUT_KEY_F6: case GLUT_KEY_F6:
{ {
//switch solver (needs demo restart) //switch solver (needs demo restart)

View File

@@ -208,7 +208,9 @@ m_gravity(0,-10,0),
m_localTime(0), m_localTime(0),
m_synchronizeAllMotionStates(false), m_synchronizeAllMotionStates(false),
m_applySpeculativeContactRestitution(false), m_applySpeculativeContactRestitution(false),
m_profileTimings(0) m_profileTimings(0),
m_fixedTimeStep(0),
m_latencyMotionStateInterpolation(true)
{ {
if (!m_constraintSolver) if (!m_constraintSolver)
@@ -357,7 +359,9 @@ void btDiscreteDynamicsWorld::synchronizeSingleMotionState(btRigidBody* body)
{ {
btTransform interpolatedTransform; btTransform interpolatedTransform;
btTransformUtil::integrateTransform(body->getInterpolationWorldTransform(), btTransformUtil::integrateTransform(body->getInterpolationWorldTransform(),
body->getInterpolationLinearVelocity(),body->getInterpolationAngularVelocity(),m_localTime*body->getHitFraction(),interpolatedTransform); body->getInterpolationLinearVelocity(),body->getInterpolationAngularVelocity(),
(m_latencyMotionStateInterpolation && m_fixedTimeStep) ? m_localTime - m_fixedTimeStep : m_localTime*body->getHitFraction(),
interpolatedTransform);
body->getMotionState()->setWorldTransform(interpolatedTransform); body->getMotionState()->setWorldTransform(interpolatedTransform);
} }
} }
@@ -401,6 +405,7 @@ int btDiscreteDynamicsWorld::stepSimulation( btScalar timeStep,int maxSubSteps,
if (maxSubSteps) if (maxSubSteps)
{ {
//fixed timestep with interpolation //fixed timestep with interpolation
m_fixedTimeStep = fixedTimeStep;
m_localTime += timeStep; m_localTime += timeStep;
if (m_localTime >= fixedTimeStep) if (m_localTime >= fixedTimeStep)
{ {
@@ -411,7 +416,8 @@ int btDiscreteDynamicsWorld::stepSimulation( btScalar timeStep,int maxSubSteps,
{ {
//variable timestep //variable timestep
fixedTimeStep = timeStep; fixedTimeStep = timeStep;
m_localTime = timeStep; m_localTime = m_latencyMotionStateInterpolation ? 0 : timeStep;
m_fixedTimeStep = 0;
if (btFuzzyZero(timeStep)) if (btFuzzyZero(timeStep))
{ {
numSimulationSubSteps = 0; numSimulationSubSteps = 0;

View File

@@ -53,6 +53,7 @@ protected:
//for variable timesteps //for variable timesteps
btScalar m_localTime; btScalar m_localTime;
btScalar m_fixedTimeStep;
//for variable timesteps //for variable timesteps
bool m_ownsIslandManager; bool m_ownsIslandManager;
@@ -64,6 +65,8 @@ protected:
int m_profileTimings; int m_profileTimings;
bool m_latencyMotionStateInterpolation;
btAlignedObjectArray<btPersistentManifold*> m_predictiveManifolds; btAlignedObjectArray<btPersistentManifold*> m_predictiveManifolds;
virtual void predictUnconstraintMotion(btScalar timeStep); virtual void predictUnconstraintMotion(btScalar timeStep);
@@ -216,6 +219,16 @@ public:
///Preliminary serialization test for Bullet 2.76. Loading those files requires a separate parser (see Bullet/Demos/SerializeDemo) ///Preliminary serialization test for Bullet 2.76. Loading those files requires a separate parser (see Bullet/Demos/SerializeDemo)
virtual void serialize(btSerializer* serializer); virtual void serialize(btSerializer* serializer);
///Interpolate motion state between previous and current transform, instead of current and next transform.
///This can relieve discontinuities in the rendering, due to penetrations
void setLatencyMotionStateInterpolation(bool latencyInterpolation )
{
m_latencyMotionStateInterpolation = latencyInterpolation;
}
bool getLatencyMotionStateInterpolation() const
{
return m_latencyMotionStateInterpolation;
}
}; };
#endif //BT_DISCRETE_DYNAMICS_WORLD_H #endif //BT_DISCRETE_DYNAMICS_WORLD_H