Improved the global transform api to access rotation and scale (#16211)

# Objective

GlobalTransform's current methods make it unintuitive, long and clunky
to access just the rotation or just the scale.

## Solution

Dedicated just_rotation() and scale() methods to access just these
properties.

I'm not sure about the naming, I chose just_rotation() to show that try
to indicate there is a waste since it also computes the other fields.

## Testing

- Did you test these changes? If so, how?
I tried logging the methods with a rotating and scaling cube and the
values were correct.
- Are there any parts that need more testing?
My methods are based on existing bevy/glam methods so should be correct
from the getgo.
- How can other people (reviewers) test your changes? Is there anything
specific they need to know?
Probably the easiest is using the 3d_rotations example, adding scaling
to it and then logging the methods I added

---

## Showcase
```rust
fn log(gt_query: Query<&GlobalTransform>) {
        for global_transform in gt_query().iter() {
                   println!("{} {}", global_transform.just_rotation(), global_transform.scale());
        }
}
```

---------

Co-authored-by: Sigma-dev <antonin.programming@gmail.com>
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
This commit is contained in:
Sigma-dev 2024-11-04 16:35:16 +01:00 committed by GitHub
parent b53ec4c35c
commit 3c2830d607
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -211,6 +211,36 @@ impl GlobalTransform {
self.0.translation
}
/// Get the rotation as a [`Quat`].
///
/// The transform is expected to be non-degenerate and without shearing, or the output will be invalid.
///
/// # Warning
///
/// This is calculated using `to_scale_rotation_translation`, meaning that you
/// should probably use it directly if you also need translation or scale.
#[inline]
pub fn rotation(&self) -> Quat {
self.to_scale_rotation_translation().1
}
/// Get the scale as a [`Vec3`].
///
/// The transform is expected to be non-degenerate and without shearing, or the output will be invalid.
///
/// Some of the computations overlap with `to_scale_rotation_translation`, which means you should use
/// it instead if you also need rotation.
#[inline]
pub fn scale(&self) -> Vec3 {
//Formula based on glam's implementation https://github.com/bitshifter/glam-rs/blob/2e4443e70c709710dfb25958d866d29b11ed3e2b/src/f32/affine3a.rs#L290
let det = self.0.matrix3.determinant();
Vec3::new(
self.0.matrix3.x_axis.length() * det.signum(),
self.0.matrix3.y_axis.length(),
self.0.matrix3.z_axis.length(),
)
}
/// Get an upper bound of the radius from the given `extents`.
#[inline]
pub fn radius_vec3a(&self, extents: Vec3A) -> f32 {
@ -363,4 +393,18 @@ mod test {
t1_prime.compute_transform(),
);
}
#[test]
fn scale() {
let test_values = [-42.42, 0., 42.42];
for x in test_values {
for y in test_values {
for z in test_values {
let scale = Vec3::new(x, y, z);
let gt = GlobalTransform::from_scale(scale);
assert_eq!(gt.scale(), gt.to_scale_rotation_translation().0);
}
}
}
}
}