From 7329d60c629526386729cd10980efe74c1ee2a74 Mon Sep 17 00:00:00 2001 From: Sigma-dev <72008323+Sigma-dev@users.noreply.github.com> Date: Mon, 4 Nov 2024 16:35:16 +0100 Subject: [PATCH] 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 Co-authored-by: Alice Cecile --- .../src/components/global_transform.rs | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/crates/bevy_transform/src/components/global_transform.rs b/crates/bevy_transform/src/components/global_transform.rs index 796992edd0..9a9961c604 100644 --- a/crates/bevy_transform/src/components/global_transform.rs +++ b/crates/bevy_transform/src/components/global_transform.rs @@ -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); + } + } + } + } }