didigw / bullet

Automatically exported from code.google.com/p/bullet
0 stars 0 forks source link

Bullet extrapolates instead of interpolates + unnecessary extrapolation when using variable time steps #746

Closed GoogleCodeExporter closed 8 years ago

GoogleCodeExporter commented 8 years ago
This is a defect in / feature request for 
BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp.

What steps will reproduce the problem?

The first problem can be easily reproduced by having a body free fall in at a 
certain gravity and then checking the Y-translation of the transform from 
MotionState.setWorldTransform(). By measuring how big steps, I can see a huge 
jump after each update. This is caused by line 361 in btDiscreteDynamicsWorld. 
Bullet actually extrapolates from the current transform using the current 
linear and angular velocities. Although this minimizes input latency at 
constant velocity, it cannot predict changes in velocity. The solution is to 
extrapolate into the past instead of extrapolating into the future. On line 361 
the value (m_localTime * body->getHitFraction()) is passed into the integration 
function. By changing this value to (m_localTime - m_fixedTimeStep) instead 
where m_fixedTimeStep is the fixedTimeStep fed into stepSimulation, it'd 
"extrapolate" into the past, giving a smooth transition from the previous known 
transform to the current transform, AKA interpolation. 

For compatibility the current method should still be usable since it does 
minimize perceived input latency, but it should be possible to switch to 
interpolation instead in games that value smoothness higher. 

Regardless of if interpolation or extrapolation is used, when variable time 
steps are used both m_localTime and m_fixedTimeStep should be set to 0 so no 
extrapolation or interpolation is done.

What is the expected output? What do you see instead?

Here's the output for the current method and my proposed method. Notice how the 
current method causes a big jump after each internal tick since the 
extrapolation turns out to be wrong due to gravity changing the velocity. By 
switching to my proposed method the movement is butter smooth.
http://pastebin.com/ndgUmkY7

The code that produced that result is written in Java using the Bullet wrapper 
from LibGDX. The fix has been tested and is working.

What version of the product are you using? On what operating system?

Not really relevant, but I'm using the LibGDX wrapper on Windows 7 64-bit.

Please provide any additional information below.

Relevant forum thread: 
http://www.bulletphysics.org/Bullet/phpBB3/viewtopic.php?f=9&t=9463

And a big thanks to Xoppa on the #libgdx IRC channel for helping me test the 
changes in LibGDX!!!

Original issue reported on code.google.com by daniel.i...@gmail.com on 7 Oct 2013 at 6:56

GoogleCodeExporter commented 8 years ago
Is there a patch that doesn't change the current behavior?  If we, we can apply 
it.

In other words, the fixed/better interpolation needs to be enabled by some 
flag, to maintain backwards compatibility.

Original comment by erwin.coumans on 19 Oct 2013 at 4:45

GoogleCodeExporter commented 8 years ago
Here's the patch we added (using a public flag, defaulting to old behavior): 
https://github.com/libgdx/libgdx/commit/75bd5d25e1b996ebb9871dcac7ee5e1e2d792db3
Only the first two files are relevant.

Original comment by xopp...@gmail.com on 19 Oct 2013 at 10:05

GoogleCodeExporter commented 8 years ago
thanks, I'll have a look at it soon.

Original comment by erwin.coumans on 22 Oct 2013 at 9:28

GoogleCodeExporter commented 8 years ago
Created a patch for latest trunk, still have to test/look at it closer before 
applying.

Original comment by erwin.coumans on 23 Oct 2013 at 6:39

Attachments:

GoogleCodeExporter commented 8 years ago
Applied in latest trunk, and made default
https://code.google.com/p/bullet/source/detail?r=2702

thanks for the contibution!

Original comment by erwin.coumans on 24 Oct 2013 at 12:23