Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Fix broken negative scaling when using Jolt Physics #103440

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

mihe
Copy link
Contributor

@mihe mihe commented Mar 1, 2025

Fixes #103408.
Supersedes #103426.

This PR effectively just brings back some code (derived in part from Jolt's own JPH::Mat44::Decompose) that I had left behind when porting the Jolt integration from the Godot Jolt extension in #99895, due to wanting to keep things as minimal as possible.

What this code is meant to do is take a potentially scaled Basis (or Transform3D) and decompose it into a rotation part and a scale part, which must be done before passing any transform into Jolt, as Jolt takes scale separately from the rest of the transform in its API, and sometimes also takes rotation separately, in the form of a quaternion.

I had mistaken the following code:

Vector3 scale = some_basis.get_scale();
Basis rotation = some_basis.orthonormalized();

... as being a valid substitute for this code:

Basis rotation;
Vector3 scale;
decomposed(some_basis, rotation, scale);

... which it is not, because while Basis::orthonormalize does also use the Gram-Schmidt process to perform the orthonormalization, much like this "new" decompose function, it does not handle reflection (i.e. negative scaling) in any way, meaning we can end up with a Basis that is orthonormal, but is not in fact a valid (right-handed) rotation, which causes problems with things like Basis::get_quaternion, as it assumes a valid (right-handed) rotation.

This "new" decompose function solves this by essentially just flipping all the axes of the Basis when we find ourselves with a negative determinant (i.e. negative scaling) which seems to line up with the convention used by other Basis methods, like Basis::get_scale and Basis::get_rotation_quaternion.

It also serves as a minor optimization, since we can avoid some of the redundant vector normalizations that are shared between Basis::get_scale and Basis::orthonormalize.

@mihe mihe added bug topic:physics topic:3d cherrypick:4.4 Considered for cherry-picking into a future 4.4.x release labels Mar 1, 2025
@mihe mihe added this to the 4.5 milestone Mar 1, 2025
@mihe mihe requested a review from a team as a code owner March 1, 2025 19:14
@mihe
Copy link
Contributor Author

mihe commented Mar 1, 2025

I'd love for someone more mathematically inclined than myself to check that I'm not talking too much rubbish here, like perhaps @jrouwe or @rburing (or anyone else who feels up to it).

@mihe mihe force-pushed the jolt/transform-decomposition branch from 7e85cd5 to b125f2e Compare March 1, 2025 22:57
@mihe mihe force-pushed the jolt/transform-decomposition branch from b125f2e to 62e8b1e Compare March 2, 2025 00:24
# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
bug cherrypick:4.4 Considered for cherry-picking into a future 4.4.x release topic:physics topic:3d
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Negative scaling is broken when using Jolt Physics
2 participants