Conversions for Isometry3d ⟷ Transform/GlobalTransform (#14478)

# 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`.
This commit is contained in:
Matty 2024-07-25 16:23:32 -04:00 committed by GitHub
parent e7e10f2c0f
commit 5aa998dc07
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 49 additions and 3 deletions

View file

@ -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`].
///

View file

@ -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 {

View file

@ -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>) -> Vec3 {
self.transform_point(point.into()).into()
}
}