|
5 | 5 |
|
6 | 6 | use crate::{
|
7 | 7 | curve::{Curve, CurveExt, FunctionCurve, Interval},
|
8 |
| - Dir2, Dir3, Dir3A, Quat, Rot2, VectorSpace, |
| 8 | + Dir2, Dir3, Dir3A, Isometry2d, Isometry3d, Quat, Rot2, VectorSpace, |
9 | 9 | };
|
10 | 10 |
|
11 | 11 | use variadics_please::all_tuples_enumerated;
|
@@ -74,6 +74,42 @@ impl Ease for Dir3A {
|
74 | 74 | }
|
75 | 75 | }
|
76 | 76 |
|
| 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 | + |
77 | 113 | macro_rules! impl_ease_tuple {
|
78 | 114 | ($(#[$meta:meta])* $(($n:tt, $T:ident)),*) => {
|
79 | 115 | $(#[$meta])*
|
@@ -627,6 +663,9 @@ impl EaseFunction {
|
627 | 663 |
|
628 | 664 | #[cfg(test)]
|
629 | 665 | mod tests {
|
| 666 | + use crate::{Vec2, Vec3, Vec3A}; |
| 667 | + use approx::assert_abs_diff_eq; |
| 668 | + |
630 | 669 | use super::*;
|
631 | 670 | const MONOTONIC_IN_OUT_INOUT: &[[EaseFunction; 3]] = {
|
632 | 671 | use EaseFunction::*;
|
@@ -719,4 +758,70 @@ mod tests {
|
719 | 758 | );
|
720 | 759 | }
|
721 | 760 | }
|
| 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 | + } |
722 | 827 | }
|
0 commit comments