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); + } + } + } + } }