three_d_asset/
animation.rs

1use crate::{prelude::*, Interpolation};
2
3/// A  set of key frames and transformations associated with a specific animation for a specific [Primitive](crate::Primitive).
4#[derive(Debug, Clone, Default)]
5#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
6pub struct KeyFrameAnimation {
7    /// Optional name of the animation.
8    ///
9    /// Can be used to distinguish between different types of animations for the same [Primitive](crate::Primitive), for example between a "walk" and a "run" animation.
10    pub name: Option<String>,
11    /// A list of [KeyFrames] and transformations which are the result of traversing a [Scene](crate::Scene) from root to the leaves.
12    pub key_frames: Vec<(Mat4, std::sync::Arc<KeyFrames>)>,
13}
14
15impl KeyFrameAnimation {
16    /// Calculates a transformation for this animation at the given time.
17    pub fn transformation(&self, time: f32) -> Mat4 {
18        let mut transformation = Mat4::identity();
19        for (t, animation) in self.key_frames.iter() {
20            transformation = transformation * t * animation.transformation(time);
21        }
22        transformation
23    }
24}
25
26///
27/// Contains a set of key frames for rotations, translations, scales and morph weights.
28///
29#[derive(Debug, Clone, Default)]
30#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
31pub struct KeyFrames {
32    /// Optional time where the animation repeats itself.
33    pub loop_time: Option<f32>,
34    /// The type of interpolation used in between the key frames.
35    pub interpolation: Interpolation,
36    /// The time value for each key frame.
37    pub times: Vec<f32>,
38    /// The rotation for each key frame.
39    pub rotations: Option<Vec<Quat>>,
40    /// The rotation for each key frame.
41    pub translations: Option<Vec<Vec3>>,
42    /// The non uniform scale for each key frame.
43    pub scales: Option<Vec<Vec3>>,
44    /// The morph weights for each key frame.
45    pub weights: Option<Vec<Vec<f32>>>,
46}
47
48impl KeyFrames {
49    /// The rotation at the specified time.
50    pub fn rotation(&self, time: f32) -> Option<Quat> {
51        self.rotations
52            .as_ref()
53            .map(|values| self.interpolate_rotation(time, values))
54    }
55    /// The translation at the specified time.
56    pub fn translation(&self, time: f32) -> Option<Vec3> {
57        self.translations
58            .as_ref()
59            .map(|values| self.interpolate(time, values))
60    }
61    /// The scale at the specified time.
62    pub fn scale(&self, time: f32) -> Option<Vec3> {
63        self.scales
64            .as_ref()
65            .map(|values| self.interpolate(time, values))
66    }
67
68    /// The transformation at the specified time.
69    pub fn transformation(&self, time: f32) -> Mat4 {
70        let mut transformation = Mat4::identity();
71        if let Some(value) = self.scale(time) {
72            transformation =
73                Mat4::from_nonuniform_scale(value.x, value.y, value.z) * transformation;
74        }
75        if let Some(value) = self.rotation(time) {
76            transformation = transformation * Mat4::from(value);
77        }
78        if let Some(value) = self.translation(time) {
79            transformation = Mat4::from_translation(value) * transformation;
80        }
81        transformation
82    }
83
84    /// The morph weights at the specified time.
85    pub fn weights(&self, time: f32) -> Option<Vec<f32>> {
86        self.weights
87            .as_ref()
88            .map(|values| self.interpolate_array(time, values))
89    }
90
91    fn interpolate_rotation(&self, time: f32, values: &[Quat]) -> Quat {
92        let time = self.loop_time.map(|t| time % t).unwrap_or(time);
93        if time < self.times[0] {
94            values[0]
95        } else {
96            for i in 0..self.times.len() - 1 {
97                if self.times[i] <= time && time < self.times[i + 1] {
98                    let t = (time - self.times[i]) / (self.times[i + 1] - self.times[i]);
99                    return values[i].slerp(values[i + 1], t);
100                }
101            }
102            *values.last().unwrap()
103        }
104    }
105
106    fn interpolate_array(&self, time: f32, values: &[Vec<f32>]) -> Vec<f32> {
107        let time = self.loop_time.map(|t| time % t).unwrap_or(time);
108        if time < self.times[0] {
109            values[0].clone()
110        } else {
111            for i in 0..self.times.len() - 1 {
112                if self.times[i] <= time && time < self.times[i + 1] {
113                    let t = (time - self.times[i]) / (self.times[i + 1] - self.times[i]);
114                    let mut result = Vec::new();
115                    for j in 0..values[i].len() {
116                        result.push(values[i][j] * (1.0 - t) + values[i + 1][j] * t);
117                    }
118                    return result;
119                }
120            }
121            values.last().unwrap().clone()
122        }
123    }
124
125    fn interpolate<T: Copy + std::ops::Mul<f32, Output = T> + std::ops::Add<T, Output = T>>(
126        &self,
127        time: f32,
128        values: &[T],
129    ) -> T {
130        let time = self.loop_time.map(|t| time % t).unwrap_or(time);
131        if time < self.times[0] {
132            values[0]
133        } else {
134            for i in 0..self.times.len() - 1 {
135                if self.times[i] <= time && time < self.times[i + 1] {
136                    let t = (time - self.times[i]) / (self.times[i + 1] - self.times[i]);
137                    return values[i] * (1.0 - t) + values[i + 1] * t;
138                }
139            }
140            *values.last().unwrap()
141        }
142    }
143}