1use gizmo_math::{Vec3, Quat};
2
3#[derive(Clone, Debug)]
4pub enum Keyframes {
5 Translation(Vec<Vec3>),
6 Rotation(Vec<Quat>),
7 Scale(Vec<Vec3>),
8}
9
10#[derive(Clone, Debug)]
11pub struct Track {
12 pub target_name: String, pub keyframe_timestamps: Vec<f32>,
14 pub keyframes: Keyframes,
15}
16
17impl Track {
18 pub fn duration(&self) -> f32 {
19 self.keyframe_timestamps.last().copied().unwrap_or(0.0)
20 }
21
22 pub fn sample(&self, t: f32) -> InterpolatedValue {
24 if self.keyframe_timestamps.is_empty() {
25 return InterpolatedValue::None;
26 }
27
28 if t <= *self.keyframe_timestamps.first().unwrap() {
29 return self.get_value(0);
30 }
31
32 if t >= *self.keyframe_timestamps.last().unwrap() {
33 return self.get_value(self.keyframe_timestamps.len() - 1);
34 }
35
36 let idx = self.keyframe_timestamps.partition_point(|&ts| ts <= t);
38 let idx0 = idx - 1;
39 let idx1 = idx;
40
41 let t0 = self.keyframe_timestamps[idx0];
42 let t1 = self.keyframe_timestamps[idx1];
43 let factor = (t - t0) / (t1 - t0);
44
45 self.interpolate_values(idx0, idx1, factor)
46 }
47
48 fn get_value(&self, index: usize) -> InterpolatedValue {
49 match &self.keyframes {
50 Keyframes::Translation(v) => InterpolatedValue::Translation(v[index]),
51 Keyframes::Rotation(v) => InterpolatedValue::Rotation(v[index]),
52 Keyframes::Scale(v) => InterpolatedValue::Scale(v[index]),
53 }
54 }
55
56 fn interpolate_values(&self, idx0: usize, idx1: usize, factor: f32) -> InterpolatedValue {
57 match &self.keyframes {
58 Keyframes::Translation(v) => {
59 let v0 = v[idx0];
60 let v1 = v[idx1];
61 InterpolatedValue::Translation(v0.lerp(v1, factor))
62 }
63 Keyframes::Rotation(v) => {
64 let v0 = v[idx0];
65 let v1 = v[idx1];
66 InterpolatedValue::Rotation(v0.slerp(v1, factor))
67 }
68 Keyframes::Scale(v) => {
69 let v0 = v[idx0];
70 let v1 = v[idx1];
71 InterpolatedValue::Scale(v0.lerp(v1, factor))
72 }
73 }
74 }
75}
76
77pub enum InterpolatedValue {
78 None,
79 Translation(Vec3),
80 Rotation(Quat),
81 Scale(Vec3),
82}
83
84#[derive(Clone, Debug, Default)]
86pub struct AnimationClip {
87 pub name: String,
88 pub tracks: Vec<Track>,
89}
90
91impl AnimationClip {
92 pub fn duration(&self) -> f32 {
93 self.tracks
94 .iter()
95 .map(|t| t.duration())
96 .fold(0.0, f32::max)
97 }
98}