NVIDIAGameWorks / PhysX-3.4

NVIDIA PhysX SDK 3.4
https://www.nvidia.com/
2.35k stars 277 forks source link

Damping Formula #43

Open GregSlazinski opened 7 years ago

GregSlazinski commented 7 years ago

In the source code: https://github.com/NVIDIAGameWorks/PhysX-3.4/blob/master/PhysX_3.4/Source/LowLevelDynamics/src/DyBodyCoreIntegrator.h#L71 I can see the damping formula,

However based on information I've found in the Bullet engine, it looks like that formula will produce different results depending on the timestep, see here: https://github.com/bulletphysics/bullet3/blob/master/src/BulletDynamics/Dynamics/btRigidBody.cpp#L163 With the discussion here: https://code.google.com/archive/p/bullet/issues/74

Perhaps PhysX's formula should be updated as well?

kstorey-nvidia commented 6 years ago

Do you have a particular use-case that you feel would require better damping behavior?

This is a damping approach that we've used for quite some time. What we have at the moment approximates the damping curve linearly to avoid having to use more expensive operations like powf in our integrator. While it is unlikely that this particular function would become a bottleneck so the performance argument is questionable, its debatable whether adjusting damping to use powf would provide much benefit to end users. Assuming the time-steps being used are not orders of magnitude different, this approximation is expected to be quite reasonable.

Making damping work perfectly wouldn't make the simulation produce the same results with variable timesteps. As soon as you add in gravity or any other external forces, the motion of an object will diverge with different time-steps due to Euler integration. Our current damping approach is similar to how we integrate forces to update velocities and how we integrate velocities to update body poses.

Unfortunately, even switching to a perfect integrator wouldn't guarantee identical results with different time-steps if there were any constraints or collisions involved.

GregSlazinski commented 6 years ago

Hi and thanks for your reply.

Please consider the following scenario: -an application runs at 60fps fixed timesteps -however when it detects a monitor that supports for example a 120hz refresh rate, then it makes more sense to perform the physics timesteps using 120hz rate In that case, I have 1 application, 1 code, but supporting 60hz and 120hz depending on what system is offering. In that case, the timesteps being 2x bigger, I expect there will be a very big difference in the damping between the 2 systems.

If you don't want to sacrifice this part of performance, then please add a "#if #define" option allowing the end user to choose the solution he wants. This way I could compile PhysX with the more precise damping formula.

Example:

#if PX_PRECISE_DAMPING
...
#else
...
#endif

You could even offer 3 approaches to the #if, the 3rd being a run-time option via a configurable bool

0 = always off

1 = always precise

2 = depending on some run-time configurable "bool precise_damping"

if(PX_PRECISE_DAMPING==1 || (PX_PRECISE_DAMPING==2 && precise_damping))
{
..powf..
}else
{
..
}

Thank you

kstorey-nvidia commented 6 years ago

Please give it a go and report back what your results are. Inaccuracies in how we compute damping is just the tip of the iceberg. There are too many components that come together to make a physics simulation that can be influenced by timestep for us to provide any guarantees about determinism if the timestep is not consistent.

There are other parts of the integrator that would not produce the same output if you were to use variable time-steps regardless of damping - confirm this by setting damping to 0 and comparing an object falling under gravity at 30hz, 60hz and 120hz. The trajectories will all look reasonable but they will all be subtly different.

Even if integration produced identical results given variable timesteps, contact gen and the solver would not. Contact gen would be instantiated at a different frequency and therefore generate different contacts because the objects would be in different configurations. The solver would produce different velocities because it had different contact constraints to solve. Once the simulation diverges, even just a by the LSB in a float, the difference compounds over 100s of frames and you end up with visibly different outcomes.

Unless your intention is to simulate objects floating in a vacuum, you are not going to get consistent results simulating at 60hz and 120hz regardless of the integrator being used.

asdasdasdasdasdf commented 5 years ago

If your simulation is cheap enough that you can tick it at 120Hz you do have the option to do so even for a 60Hz renderer and only render every second physics state. In general I think it's a good idea to pick the physics tick rate that gives you a good trade off between performance and accuracy independent of your render frequency.