bevy_xpbd
bevy_xpbd copied to clipboard
Store square roots for world-space inverse angular inertia
Rapier stores world-space angular inertia as the square root of the inverse angular inertia tensor, effective_world_inv_inertia_sqrt. Avian and most other physics engines on the other hand just store the inverse angular inertia tensor, not its square root.
The reason Rapier stores square roots is to keep angular inertia values more reasonable, allowing the use of larger mass properties before numerical problems start causing simulation artifacts. For example, an inverse angular inertia of 10e-16 becomes just 10e-8.
In a simple test with 1x1x1 cubes colliding with each other, Avian "only" supported a mass of 10e13 before the inverse angular inertia became 0.0, while Rapier supported at least a mass of 10e19 before visible simulation artifacts started showing up. This is likely thanks to the use of square roots.
Pros
- Larger objects!
- Larger mass properties!
- More resistent to numerical issues without resorting to f64!
Cons
- Adds complexity to solver internals.
- Many places would need to perform two (matrix) multiplications instead of one.
Is It Worth It?
I think we should definitely experiment with this; it would be great to support larger objects and mass properties without stability issues.
However, we should carefully profile to see if there is a measurable performance impact, and determine if that cost is acceptable. I would perhaps wait until some of the current in-progress optimizations and reworks are complete before working on this.
Okay I might have had at least a partially wrong lead here, it seems like our inverse angular inertia becomes 0.0 because of our .inverse_or_zero() calls returning zero for very small values. If we replace the matrix inversion with an inverse tensor reconstruction from the inverse principal inertia and inertial frame, we instead seem to get the non-zero results we want.
The behavior itself is still wonky and somewhat unstable with these very low angular inertias however. It could be that the square root values could allow us to minimize error to some extent and improve stability a bit. There also seem to be problems with friction not working properly at low enough inertia. So definitely room for experimentation here.
#793 implemented the inertia tensor inversion fix. I think this issue is mostly redundant and it's likely not worth going the sqrt route. Still not entirely sure why exactly Rapier does it :)