1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
|
use std::ops::{Add, Mul, Sub};
pub fn raw_lerp<T>(a: T, b: T, t: f64) -> T
where
T: Copy + Add<Output = T> + Sub<Output = T> + Mul<f64, Output = T>,
{
a + (b - a) * t
}
pub enum TimingFunction {
Lerp,
}
pub struct KeyFrame<ValueType> {
// We could make a TimeType generic (I initially did), however it's safe to assume we use a 64-bit float for this
pub time: f64,
pub val: ValueType,
}
impl<ValueType> KeyFrame<ValueType> {
pub fn new(time: f64, val: ValueType) -> KeyFrame<ValueType> {
KeyFrame { time, val }
}
}
impl<
ValueType: PartialOrd
+ Copy
+ Add<Output = ValueType>
+ Sub<Output = ValueType>
+ Mul<f64, Output = ValueType>,
> KeyFrame<ValueType>
{
/** Simply passes the data to the timing function involved. Does not do bounding. */
pub fn raw_value_at(
from: &KeyFrame<ValueType>,
to: &KeyFrame<ValueType>,
time: f64,
timing_function: TimingFunction,
) -> ValueType {
// Order them so `from` is always the lower bound
let (from, to) = if from.time < to.time {
(from, to)
} else {
(to, from)
};
let length = to.time - from.time;
let position = (time - from.time) / length;
match timing_function {
TimingFunction::Lerp => raw_lerp(from.val, to.val, position),
}
}
}
|