Skip to content

Commit 94c289e

Browse files
RobWaltjoshua-holmes
authored andcommitted
feat: impl Ease for Isometry[2/3]d (bevyengine#17545)
# Objective - We kind of missed out on implementing the `Ease` trait for some objects like `Isometry2D` and `Isometry3D` even though it makes sense and isn't that hard - Fixes bevyengine#17539 ## Testing - wrote some minimal tests - ~~noticed that quat easing isn't working as expected yet~~ I just confused degrees and radians once again 🙈
1 parent 0dc1479 commit 94c289e

File tree

1 file changed

+106
-1
lines changed

1 file changed

+106
-1
lines changed

crates/bevy_math/src/curve/easing.rs

+106-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
66
use crate::{
77
curve::{Curve, CurveExt, FunctionCurve, Interval},
8-
Dir2, Dir3, Dir3A, Quat, Rot2, VectorSpace,
8+
Dir2, Dir3, Dir3A, Isometry2d, Isometry3d, Quat, Rot2, VectorSpace,
99
};
1010

1111
use variadics_please::all_tuples_enumerated;
@@ -74,6 +74,42 @@ impl Ease for Dir3A {
7474
}
7575
}
7676

77+
impl Ease for Isometry3d {
78+
fn interpolating_curve_unbounded(start: Self, end: Self) -> impl Curve<Self> {
79+
FunctionCurve::new(Interval::EVERYWHERE, move |t| {
80+
// we can use sample_unchecked here, since both interpolating_curve_unbounded impls
81+
// used are defined on the whole domain
82+
Isometry3d {
83+
rotation: Quat::interpolating_curve_unbounded(start.rotation, end.rotation)
84+
.sample_unchecked(t),
85+
translation: crate::Vec3A::interpolating_curve_unbounded(
86+
start.translation,
87+
end.translation,
88+
)
89+
.sample_unchecked(t),
90+
}
91+
})
92+
}
93+
}
94+
95+
impl Ease for Isometry2d {
96+
fn interpolating_curve_unbounded(start: Self, end: Self) -> impl Curve<Self> {
97+
FunctionCurve::new(Interval::EVERYWHERE, move |t| {
98+
// we can use sample_unchecked here, since both interpolating_curve_unbounded impls
99+
// used are defined on the whole domain
100+
Isometry2d {
101+
rotation: Rot2::interpolating_curve_unbounded(start.rotation, end.rotation)
102+
.sample_unchecked(t),
103+
translation: crate::Vec2::interpolating_curve_unbounded(
104+
start.translation,
105+
end.translation,
106+
)
107+
.sample_unchecked(t),
108+
}
109+
})
110+
}
111+
}
112+
77113
macro_rules! impl_ease_tuple {
78114
($(#[$meta:meta])* $(($n:tt, $T:ident)),*) => {
79115
$(#[$meta])*
@@ -627,6 +663,9 @@ impl EaseFunction {
627663

628664
#[cfg(test)]
629665
mod tests {
666+
use crate::{Vec2, Vec3, Vec3A};
667+
use approx::assert_abs_diff_eq;
668+
630669
use super::*;
631670
const MONOTONIC_IN_OUT_INOUT: &[[EaseFunction; 3]] = {
632671
use EaseFunction::*;
@@ -719,4 +758,70 @@ mod tests {
719758
);
720759
}
721760
}
761+
762+
#[test]
763+
fn ease_quats() {
764+
let quat_start = Quat::from_axis_angle(Vec3::Z, 0.0);
765+
let quat_end = Quat::from_axis_angle(Vec3::Z, 90.0_f32.to_radians());
766+
767+
let quat_curve = Quat::interpolating_curve_unbounded(quat_start, quat_end);
768+
769+
assert_abs_diff_eq!(
770+
quat_curve.sample(0.0).unwrap(),
771+
Quat::from_axis_angle(Vec3::Z, 0.0)
772+
);
773+
{
774+
let (before_mid_axis, before_mid_angle) =
775+
quat_curve.sample(0.25).unwrap().to_axis_angle();
776+
assert_abs_diff_eq!(before_mid_axis, Vec3::Z);
777+
assert_abs_diff_eq!(before_mid_angle, 22.5_f32.to_radians());
778+
}
779+
{
780+
let (mid_axis, mid_angle) = quat_curve.sample(0.5).unwrap().to_axis_angle();
781+
assert_abs_diff_eq!(mid_axis, Vec3::Z);
782+
assert_abs_diff_eq!(mid_angle, 45.0_f32.to_radians());
783+
}
784+
{
785+
let (after_mid_axis, after_mid_angle) =
786+
quat_curve.sample(0.75).unwrap().to_axis_angle();
787+
assert_abs_diff_eq!(after_mid_axis, Vec3::Z);
788+
assert_abs_diff_eq!(after_mid_angle, 67.5_f32.to_radians());
789+
}
790+
assert_abs_diff_eq!(
791+
quat_curve.sample(1.0).unwrap(),
792+
Quat::from_axis_angle(Vec3::Z, 90.0_f32.to_radians())
793+
);
794+
}
795+
796+
#[test]
797+
fn ease_isometries_2d() {
798+
let angle = 90.0;
799+
let iso_2d_start = Isometry2d::new(Vec2::ZERO, Rot2::degrees(0.0));
800+
let iso_2d_end = Isometry2d::new(Vec2::ONE, Rot2::degrees(angle));
801+
802+
let iso_2d_curve = Isometry2d::interpolating_curve_unbounded(iso_2d_start, iso_2d_end);
803+
804+
[-1.0, 0.0, 0.5, 1.0, 2.0].into_iter().for_each(|t| {
805+
assert_abs_diff_eq!(
806+
iso_2d_curve.sample(t).unwrap(),
807+
Isometry2d::new(Vec2::ONE * t, Rot2::degrees(angle * t))
808+
);
809+
});
810+
}
811+
812+
#[test]
813+
fn ease_isometries_3d() {
814+
let angle = 90.0_f32.to_radians();
815+
let iso_3d_start = Isometry3d::new(Vec3A::ZERO, Quat::from_axis_angle(Vec3::Z, 0.0));
816+
let iso_3d_end = Isometry3d::new(Vec3A::ONE, Quat::from_axis_angle(Vec3::Z, angle));
817+
818+
let iso_3d_curve = Isometry3d::interpolating_curve_unbounded(iso_3d_start, iso_3d_end);
819+
820+
[-1.0, 0.0, 0.5, 1.0, 2.0].into_iter().for_each(|t| {
821+
assert_abs_diff_eq!(
822+
iso_3d_curve.sample(t).unwrap(),
823+
Isometry3d::new(Vec3A::ONE * t, Quat::from_axis_angle(Vec3::Z, angle * t))
824+
);
825+
});
826+
}
722827
}

0 commit comments

Comments
 (0)