Skip to main content

gizmo_animation/
clip.rs

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, // Which entity this track applies to (by name)
13    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    /// Interpolates the track at a given time `t`.
23    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        // Find the segment
37        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/// Repesents an animation sequence
85#[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}