-
-
Notifications
You must be signed in to change notification settings - Fork 3.7k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Transform and GlobalTransform are now Similarities (#596)
Transform and GlobalTransform are now Similarities. This resolves precision errors and simplifies the api Co-authored-by: Carter Anderson <[email protected]>
- Loading branch information
Showing
28 changed files
with
317 additions
and
369 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
223 changes: 106 additions & 117 deletions
223
crates/bevy_transform/src/components/global_transform.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,174 +1,163 @@ | ||
use bevy_math::{Mat3, Mat4, Quat, Vec3}; | ||
use bevy_property::Properties; | ||
use std::fmt; | ||
use std::ops::Mul; | ||
|
||
use super::Transform; | ||
|
||
#[derive(Debug, PartialEq, Clone, Copy, Properties)] | ||
pub struct GlobalTransform { | ||
value: Mat4, | ||
pub translation: Vec3, | ||
pub rotation: Quat, | ||
pub scale: Vec3, | ||
} | ||
|
||
impl GlobalTransform { | ||
#[inline(always)] | ||
pub fn new(value: Mat4) -> Self { | ||
GlobalTransform { value } | ||
} | ||
|
||
#[inline(always)] | ||
#[inline] | ||
pub fn identity() -> Self { | ||
GlobalTransform { | ||
value: Mat4::identity(), | ||
translation: Vec3::zero(), | ||
rotation: Quat::identity(), | ||
scale: Vec3::one(), | ||
} | ||
} | ||
|
||
pub fn from_translation(translation: Vec3) -> Self { | ||
GlobalTransform::new(Mat4::from_translation(translation)) | ||
} | ||
#[inline] | ||
pub fn from_matrix(matrix: Mat4) -> Self { | ||
let (scale, rotation, translation) = matrix.to_scale_rotation_translation(); | ||
|
||
pub fn from_rotation(rotation: Quat) -> Self { | ||
GlobalTransform::new(Mat4::from_quat(rotation)) | ||
} | ||
|
||
pub fn from_scale(scale: f32) -> Self { | ||
GlobalTransform::new(Mat4::from_scale(Vec3::splat(scale))) | ||
} | ||
|
||
pub fn from_translation_rotation(translation: Vec3, rotation: Quat) -> Self { | ||
GlobalTransform::new(Mat4::from_scale_rotation_translation( | ||
Vec3::splat(1.0), | ||
rotation, | ||
GlobalTransform { | ||
translation, | ||
)) | ||
} | ||
|
||
pub fn from_translation_rotation_scale(translation: Vec3, rotation: Quat, scale: f32) -> Self { | ||
GlobalTransform::new(Mat4::from_scale_rotation_translation( | ||
Vec3::splat(scale), | ||
rotation, | ||
translation, | ||
)) | ||
} | ||
|
||
pub fn from_non_uniform_scale(scale: Vec3) -> Self { | ||
GlobalTransform::new(Mat4::from_scale(scale)) | ||
} | ||
|
||
pub fn with_translation(mut self, translation: Vec3) -> Self { | ||
self.set_translation(translation); | ||
self | ||
} | ||
|
||
pub fn with_rotation(mut self, rotation: Quat) -> Self { | ||
self.set_rotation(rotation); | ||
self | ||
} | ||
|
||
pub fn with_scale(mut self, scale: f32) -> Self { | ||
self.set_scale(scale); | ||
self | ||
scale, | ||
} | ||
} | ||
|
||
pub fn with_non_uniform_scale(mut self, scale: Vec3) -> Self { | ||
self.set_non_uniform_scale(scale); | ||
self | ||
#[inline] | ||
pub fn from_translation(translation: Vec3) -> Self { | ||
GlobalTransform { | ||
translation, | ||
..Default::default() | ||
} | ||
} | ||
|
||
pub fn with_translate(mut self, translation: Vec3) -> Self { | ||
self.translate(translation); | ||
self | ||
#[inline] | ||
pub fn from_rotation(rotation: Quat) -> Self { | ||
GlobalTransform { | ||
rotation, | ||
..Default::default() | ||
} | ||
} | ||
|
||
pub fn with_rotate(mut self, rotation: Quat) -> Self { | ||
self.rotate(rotation); | ||
self | ||
#[inline] | ||
pub fn from_scale(scale: Vec3) -> Self { | ||
GlobalTransform { | ||
scale, | ||
..Default::default() | ||
} | ||
} | ||
|
||
pub fn with_apply_scale(mut self, scale: f32) -> Self { | ||
self.apply_scale(scale); | ||
self | ||
/// Returns transform with the same translation and scale, but rotation so that transform.forward() points at the origin | ||
#[inline] | ||
pub fn looking_at_origin(self) -> Self { | ||
self.looking_at(Vec3::zero(), Vec3::unit_y()) | ||
} | ||
|
||
pub fn with_apply_non_uniform_scale(mut self, scale: Vec3) -> Self { | ||
self.apply_non_uniform_scale(scale); | ||
/// Returns transform with the same translation and scale, but rotation so that transform.forward() points at target | ||
#[inline] | ||
pub fn looking_at(mut self, target: Vec3, up: Vec3) -> Self { | ||
self.look_at(target, up); | ||
self | ||
} | ||
|
||
pub fn value(&self) -> &Mat4 { | ||
&self.value | ||
#[inline] | ||
pub fn compute_matrix(&self) -> Mat4 { | ||
Mat4::from_scale_rotation_translation(self.scale, self.rotation, self.translation) | ||
} | ||
|
||
pub fn value_mut(&mut self) -> &mut Mat4 { | ||
&mut self.value | ||
#[inline] | ||
pub fn forward(&self) -> Vec3 { | ||
self.rotation * Vec3::unit_z() | ||
} | ||
|
||
pub fn translation(&self) -> Vec3 { | ||
Vec3::from(self.value.w_axis().truncate()) | ||
#[inline] | ||
/// Rotate the transform by the given rotation | ||
pub fn rotate(&mut self, rotation: Quat) { | ||
self.rotation *= rotation; | ||
} | ||
|
||
pub fn rotation(&self) -> Quat { | ||
let scale = self.scale(); | ||
|
||
Quat::from_rotation_mat3(&Mat3::from_cols( | ||
Vec3::from(self.value.x_axis().truncate()) / scale.x(), | ||
Vec3::from(self.value.y_axis().truncate()) / scale.y(), | ||
Vec3::from(self.value.z_axis().truncate()) / scale.z(), | ||
)) | ||
#[inline] | ||
pub fn mul_transform(&self, transform: Transform) -> GlobalTransform { | ||
let translation = self.mul_vec3(transform.translation); | ||
let rotation = self.rotation * transform.rotation; | ||
let scale = self.scale * transform.scale; | ||
GlobalTransform { | ||
scale, | ||
rotation, | ||
translation, | ||
} | ||
} | ||
|
||
pub fn scale(&self) -> Vec3 { | ||
Vec3::new( | ||
self.value.x_axis().truncate().length(), | ||
self.value.y_axis().truncate().length(), | ||
self.value.z_axis().truncate().length(), | ||
) | ||
#[inline] | ||
pub fn mul_vec3(&self, mut value: Vec3) -> Vec3 { | ||
value = self.rotation * value; | ||
value = self.scale * value; | ||
value += self.translation; | ||
value | ||
} | ||
|
||
pub fn set_translation(&mut self, translation: Vec3) { | ||
*self.value.w_axis_mut() = translation.extend(1.0); | ||
#[inline] | ||
pub fn apply_non_uniform_scale(&mut self, scale: Vec3) { | ||
self.scale *= scale; | ||
} | ||
|
||
pub fn set_rotation(&mut self, rotation: Quat) { | ||
self.value = | ||
Mat4::from_scale_rotation_translation(self.scale(), rotation, self.translation()); | ||
#[inline] | ||
pub fn look_at(&mut self, target: Vec3, up: Vec3) { | ||
let forward = Vec3::normalize(self.translation - target); | ||
let right = up.cross(forward).normalize(); | ||
let up = forward.cross(right); | ||
self.rotation = Quat::from_rotation_mat3(&Mat3::from_cols(right, up, forward)); | ||
} | ||
} | ||
|
||
pub fn set_scale(&mut self, scale: f32) { | ||
self.value = Mat4::from_scale_rotation_translation( | ||
Vec3::splat(scale), | ||
self.rotation(), | ||
self.translation(), | ||
); | ||
impl Default for GlobalTransform { | ||
fn default() -> Self { | ||
Self::identity() | ||
} | ||
} | ||
|
||
pub fn set_non_uniform_scale(&mut self, scale: Vec3) { | ||
self.value = | ||
Mat4::from_scale_rotation_translation(scale, self.rotation(), self.translation()); | ||
impl From<Transform> for GlobalTransform { | ||
fn from(transform: Transform) -> Self { | ||
Self { | ||
translation: transform.translation, | ||
rotation: transform.rotation, | ||
scale: transform.scale, | ||
} | ||
} | ||
} | ||
|
||
pub fn translate(&mut self, translation: Vec3) { | ||
*self.value.w_axis_mut() += translation.extend(0.0); | ||
} | ||
impl Mul<GlobalTransform> for GlobalTransform { | ||
type Output = GlobalTransform; | ||
|
||
pub fn rotate(&mut self, rotation: Quat) { | ||
self.value = Mat4::from_quat(rotation) * self.value; | ||
#[inline] | ||
fn mul(self, global_transform: GlobalTransform) -> Self::Output { | ||
self.mul_transform(global_transform.into()) | ||
} | ||
} | ||
|
||
pub fn apply_scale(&mut self, scale: f32) { | ||
self.value = Mat4::from_scale(Vec3::splat(scale)) * self.value; | ||
} | ||
impl Mul<Transform> for GlobalTransform { | ||
type Output = GlobalTransform; | ||
|
||
pub fn apply_non_uniform_scale(&mut self, scale: Vec3) { | ||
self.value = Mat4::from_scale(scale) * self.value; | ||
#[inline] | ||
fn mul(self, transform: Transform) -> Self::Output { | ||
self.mul_transform(transform) | ||
} | ||
} | ||
|
||
impl Default for GlobalTransform { | ||
fn default() -> Self { | ||
Self::identity() | ||
} | ||
} | ||
impl Mul<Vec3> for GlobalTransform { | ||
type Output = Vec3; | ||
|
||
impl fmt::Display for GlobalTransform { | ||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | ||
write!(f, "{}", self.value) | ||
#[inline] | ||
fn mul(self, value: Vec3) -> Self::Output { | ||
self.mul_vec3(value) | ||
} | ||
} |
Oops, something went wrong.