From 5aa998dc07d5769c82a224a2d21ae0c78df3743a Mon Sep 17 00:00:00 2001 From: Matty Date: Thu, 25 Jul 2024 16:23:32 -0400 Subject: [PATCH] =?UTF-8?q?Conversions=20for=20Isometry3d=20=E2=9F=B7=20Tr?= =?UTF-8?q?ansform/GlobalTransform=20(#14478)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # Objective Allow interoperation between `Isometry3d` and the transform types from bevy_transform. At least in the short term, the primary goal is to allow the extraction of isometries from transform components by users. ## Solution - Add explicit `from_isometry`/`to_isometry` methods to `Transform`. - Add explicit `from_isometry`/`to_isometry` methods to `GlobalTransform`. The former is hidden (primarily for internal use), and the latter has the caveats originating in [`Affine3A::to_scale_rotation_translation`](https://docs.rs/glam/latest/glam/f32/struct.Affine3A.html#method.to_scale_rotation_translation). - Implement the `TransformPoint` trait for `Isometry3d`. --- .../src/components/global_transform.rs | 21 +++++++++++++++++- .../src/components/transform.rs | 22 ++++++++++++++++++- crates/bevy_transform/src/traits.rs | 9 +++++++- 3 files changed, 49 insertions(+), 3 deletions(-) diff --git a/crates/bevy_transform/src/components/global_transform.rs b/crates/bevy_transform/src/components/global_transform.rs index 0b206813fc..dd8f4ca08f 100644 --- a/crates/bevy_transform/src/components/global_transform.rs +++ b/crates/bevy_transform/src/components/global_transform.rs @@ -3,7 +3,7 @@ use std::ops::Mul; use super::Transform; #[cfg(feature = "bevy-support")] use bevy_ecs::{component::Component, reflect::ReflectComponent}; -use bevy_math::{Affine3A, Dir3, Mat4, Quat, Vec3, Vec3A}; +use bevy_math::{Affine3A, Dir3, Isometry3d, Mat4, Quat, Vec3, Vec3A}; #[cfg(feature = "bevy-support")] use bevy_reflect::{std_traits::ReflectDefault, Reflect}; @@ -87,6 +87,12 @@ impl GlobalTransform { GlobalTransform(Affine3A::from_scale(scale)) } + #[doc(hidden)] + #[inline] + pub fn from_isometry(iso: Isometry3d) -> Self { + Self(iso.into()) + } + /// Returns the 3d affine transformation matrix as a [`Mat4`]. #[inline] pub fn compute_matrix(&self) -> Mat4 { @@ -113,6 +119,19 @@ impl GlobalTransform { } } + /// Returns the isometric part of the transformation as an [isometry]. Any scaling done by the + /// transformation will be ignored. + /// + /// The transform is expected to be non-degenerate and without shearing, or the output + /// will be invalid. + /// + /// [isometry]: Isometry3d + #[inline] + pub fn to_isometry(&self) -> Isometry3d { + let (_, rotation, translation) = self.0.to_scale_rotation_translation(); + Isometry3d::new(translation, rotation) + } + /// Returns the [`Transform`] `self` would have if it was a child of an entity /// with the `parent` [`GlobalTransform`]. /// diff --git a/crates/bevy_transform/src/components/transform.rs b/crates/bevy_transform/src/components/transform.rs index 0555ec2e76..f0d8901745 100644 --- a/crates/bevy_transform/src/components/transform.rs +++ b/crates/bevy_transform/src/components/transform.rs @@ -1,7 +1,7 @@ use super::GlobalTransform; #[cfg(feature = "bevy-support")] use bevy_ecs::{component::Component, reflect::ReflectComponent}; -use bevy_math::{Affine3A, Dir3, Mat3, Mat4, Quat, Vec3}; +use bevy_math::{Affine3A, Dir3, Isometry3d, Mat3, Mat4, Quat, Vec3}; #[cfg(feature = "bevy-support")] use bevy_reflect::{prelude::*, Reflect}; use std::ops::Mul; @@ -120,6 +120,18 @@ impl Transform { } } + /// Creates a new [`Transform`] that is equivalent to the given [isometry]. + /// + /// [isometry]: Isometry3d + #[inline] + pub fn from_isometry(iso: Isometry3d) -> Self { + Transform { + translation: iso.translation.into(), + rotation: iso.rotation, + ..Self::IDENTITY + } + } + /// Returns this [`Transform`] with a new rotation so that [`Transform::forward`] /// points towards the `target` position and [`Transform::up`] points towards `up`. /// @@ -525,6 +537,14 @@ impl Transform { pub fn is_finite(&self) -> bool { self.translation.is_finite() && self.rotation.is_finite() && self.scale.is_finite() } + + /// Get the [isometry] defined by this transform's rotation and translation, ignoring scale. + /// + /// [isometry]: Isometry3d + #[inline] + pub fn to_isometry(&self) -> Isometry3d { + Isometry3d::new(self.translation, self.rotation) + } } impl Default for Transform { diff --git a/crates/bevy_transform/src/traits.rs b/crates/bevy_transform/src/traits.rs index f0984272ab..6770ebb9c2 100644 --- a/crates/bevy_transform/src/traits.rs +++ b/crates/bevy_transform/src/traits.rs @@ -1,4 +1,4 @@ -use bevy_math::{Affine3A, Mat4, Vec3}; +use bevy_math::{Affine3A, Isometry3d, Mat4, Vec3}; use crate::prelude::{GlobalTransform, Transform}; @@ -35,3 +35,10 @@ impl TransformPoint for Affine3A { self.transform_point3(point.into()) } } + +impl TransformPoint for Isometry3d { + #[inline] + fn transform_point(&self, point: impl Into) -> Vec3 { + self.transform_point(point.into()).into() + } +}