Skip to content
New issue

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

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

Already on GitHub? Sign in 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
@fire
Copy link
Member

fire commented Mar 3, 2025

In godot engine the common conversion from Basis to quaternion is get_rotation_quaternion. I don't know why we're doing it this way.

Copy link
Member

@fire fire left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please explain why we can't use get_rotation_quaternion or orthogonalize?

https://github.com/godotengine/godot/blob/master/core/math/basis.cpp#L80

Sign up for free to join this conversation on GitHub. Already have an account? Sign in 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
4 participants