mirror of
https://github.com/storytold/storyteller-bevy.git
synced 2026-10-17 00:13:17 +00:00
63 lines
1.6 KiB
Rust
63 lines
1.6 KiB
Rust
use std::{f32::consts, ops};
|
|
|
|
use super::NearlyEq;
|
|
|
|
pub trait Lerp {
|
|
fn lerp(self, a: Self, b: Self) -> Self;
|
|
fn inv_lerp(self, a: Self, b: Self) -> Self;
|
|
fn remap(self, from: (Self, Self), to: (Self, Self)) -> Self
|
|
where
|
|
Self: Sized;
|
|
}
|
|
|
|
#[rustfmt::skip] trait One { fn one() -> Self; }
|
|
#[rustfmt::skip] impl One for f32 { fn one() -> Self { 1. } }
|
|
#[rustfmt::skip] impl One for f64 { fn one() -> Self { 1_f64 } }
|
|
|
|
#[rustfmt::skip] trait Zero { fn zero() -> Self; }
|
|
#[rustfmt::skip] impl Zero for f32 { fn zero() -> Self { 0. } }
|
|
#[rustfmt::skip] impl Zero for f64 { fn zero() -> Self { 0_f64 } }
|
|
|
|
// lol it would have been faster and less code to just copy/paste. At least I tried.
|
|
impl<T> Lerp for T
|
|
where
|
|
T: ops::Add<Output = T>
|
|
+ ops::Sub<Output = T>
|
|
+ ops::Mul<Output = T>
|
|
+ ops::Div<Output = T>
|
|
+ NearlyEq<T>
|
|
+ One
|
|
+ Zero
|
|
+ Sized
|
|
+ Copy,
|
|
{
|
|
fn lerp(self, a: Self, b: Self) -> Self {
|
|
(<Self as One>::one() - self) * a + b * self
|
|
}
|
|
|
|
fn inv_lerp(self, a: Self, b: Self) -> Self {
|
|
let dividend = b - a;
|
|
if !dividend.nearly_eq(<Self as Zero>::zero()) {
|
|
(self - a) / dividend
|
|
} else {
|
|
b
|
|
}
|
|
}
|
|
|
|
fn remap(self, from: (Self, Self), to: (Self, Self)) -> Self
|
|
where
|
|
Self: Sized,
|
|
{
|
|
let t = self.inv_lerp(from.0, from.1);
|
|
t.lerp(to.0, to.1)
|
|
}
|
|
}
|
|
|
|
/// Fit a [0, 1] `t` interpolation parameter to a sine curve
|
|
///
|
|
/// https://www.desmos.com/calculator/k9x4c4cr5y
|
|
#[inline]
|
|
pub fn curve_sin(t: f32) -> f32 {
|
|
-1. * (f32::cos(t * consts::PI) / 2.) + 0.5
|
|
}
|