feat: impl Ease for Isometry[2/3]d (#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 #17539

## Testing

- wrote some minimal tests
- ~~noticed that quat easing isn't working as expected yet~~ I just
confused degrees and radians once again 🙈
This commit is contained in:
RobWalt 2025-02-02 15:07:35 +00:00 committed by GitHub
parent 89a1c49377
commit a893c5d572
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -5,7 +5,7 @@
use crate::{
curve::{Curve, CurveExt, FunctionCurve, Interval},
Dir2, Dir3, Dir3A, Quat, Rot2, VectorSpace,
Dir2, Dir3, Dir3A, Isometry2d, Isometry3d, Quat, Rot2, VectorSpace,
};
use variadics_please::all_tuples_enumerated;
@ -74,6 +74,42 @@ impl Ease for Dir3A {
}
}
impl Ease for Isometry3d {
fn interpolating_curve_unbounded(start: Self, end: Self) -> impl Curve<Self> {
FunctionCurve::new(Interval::EVERYWHERE, move |t| {
// we can use sample_unchecked here, since both interpolating_curve_unbounded impls
// used are defined on the whole domain
Isometry3d {
rotation: Quat::interpolating_curve_unbounded(start.rotation, end.rotation)
.sample_unchecked(t),
translation: crate::Vec3A::interpolating_curve_unbounded(
start.translation,
end.translation,
)
.sample_unchecked(t),
}
})
}
}
impl Ease for Isometry2d {
fn interpolating_curve_unbounded(start: Self, end: Self) -> impl Curve<Self> {
FunctionCurve::new(Interval::EVERYWHERE, move |t| {
// we can use sample_unchecked here, since both interpolating_curve_unbounded impls
// used are defined on the whole domain
Isometry2d {
rotation: Rot2::interpolating_curve_unbounded(start.rotation, end.rotation)
.sample_unchecked(t),
translation: crate::Vec2::interpolating_curve_unbounded(
start.translation,
end.translation,
)
.sample_unchecked(t),
}
})
}
}
macro_rules! impl_ease_tuple {
($(#[$meta:meta])* $(($n:tt, $T:ident)),*) => {
$(#[$meta])*
@ -627,6 +663,9 @@ impl EaseFunction {
#[cfg(test)]
mod tests {
use crate::{Vec2, Vec3, Vec3A};
use approx::assert_abs_diff_eq;
use super::*;
const MONOTONIC_IN_OUT_INOUT: &[[EaseFunction; 3]] = {
use EaseFunction::*;
@ -719,4 +758,70 @@ mod tests {
);
}
}
#[test]
fn ease_quats() {
let quat_start = Quat::from_axis_angle(Vec3::Z, 0.0);
let quat_end = Quat::from_axis_angle(Vec3::Z, 90.0_f32.to_radians());
let quat_curve = Quat::interpolating_curve_unbounded(quat_start, quat_end);
assert_abs_diff_eq!(
quat_curve.sample(0.0).unwrap(),
Quat::from_axis_angle(Vec3::Z, 0.0)
);
{
let (before_mid_axis, before_mid_angle) =
quat_curve.sample(0.25).unwrap().to_axis_angle();
assert_abs_diff_eq!(before_mid_axis, Vec3::Z);
assert_abs_diff_eq!(before_mid_angle, 22.5_f32.to_radians());
}
{
let (mid_axis, mid_angle) = quat_curve.sample(0.5).unwrap().to_axis_angle();
assert_abs_diff_eq!(mid_axis, Vec3::Z);
assert_abs_diff_eq!(mid_angle, 45.0_f32.to_radians());
}
{
let (after_mid_axis, after_mid_angle) =
quat_curve.sample(0.75).unwrap().to_axis_angle();
assert_abs_diff_eq!(after_mid_axis, Vec3::Z);
assert_abs_diff_eq!(after_mid_angle, 67.5_f32.to_radians());
}
assert_abs_diff_eq!(
quat_curve.sample(1.0).unwrap(),
Quat::from_axis_angle(Vec3::Z, 90.0_f32.to_radians())
);
}
#[test]
fn ease_isometries_2d() {
let angle = 90.0;
let iso_2d_start = Isometry2d::new(Vec2::ZERO, Rot2::degrees(0.0));
let iso_2d_end = Isometry2d::new(Vec2::ONE, Rot2::degrees(angle));
let iso_2d_curve = Isometry2d::interpolating_curve_unbounded(iso_2d_start, iso_2d_end);
[-1.0, 0.0, 0.5, 1.0, 2.0].into_iter().for_each(|t| {
assert_abs_diff_eq!(
iso_2d_curve.sample(t).unwrap(),
Isometry2d::new(Vec2::ONE * t, Rot2::degrees(angle * t))
);
});
}
#[test]
fn ease_isometries_3d() {
let angle = 90.0_f32.to_radians();
let iso_3d_start = Isometry3d::new(Vec3A::ZERO, Quat::from_axis_angle(Vec3::Z, 0.0));
let iso_3d_end = Isometry3d::new(Vec3A::ONE, Quat::from_axis_angle(Vec3::Z, angle));
let iso_3d_curve = Isometry3d::interpolating_curve_unbounded(iso_3d_start, iso_3d_end);
[-1.0, 0.0, 0.5, 1.0, 2.0].into_iter().for_each(|t| {
assert_abs_diff_eq!(
iso_3d_curve.sample(t).unwrap(),
Isometry3d::new(Vec3A::ONE * t, Quat::from_axis_angle(Vec3::Z, angle * t))
);
});
}
}