shine_gltf/
animation.rs

1use crate::validation::{Checked, Error, Validate};
2use crate::{accessor, extensions, scene, Index, Path, Root};
3use serde::{de, ser};
4use serde_derive::{Deserialize, Serialize};
5use shine_gltf_macro::Validate;
6use std::fmt;
7
8/// All valid animation interpolation algorithms.
9pub const VALID_INTERPOLATIONS: &[&str] = &["LINEAR", "STEP", "CATMULLROMSPLINE", "CUBICSPLINE"];
10
11/// All valid animation property names.
12pub const VALID_PROPERTIES: &[&str] = &["translation", "rotation", "scale", "weights"];
13
14/// Specifies an interpolation algorithm.
15#[derive(Clone, Copy, Debug, Eq, PartialEq, Deserialize)]
16pub enum Interpolation {
17    /// Linear interpolation.
18    ///
19    /// The animated values are linearly interpolated between keyframes.
20    /// When targeting a rotation, spherical linear interpolation (slerp) should be
21    /// used to interpolate quaternions. The number output of elements must equal
22    /// the number of input elements.
23    Linear = 1,
24
25    /// Step interpolation.
26    ///
27    /// The animated values remain constant to the output of the first keyframe,
28    /// until the next keyframe. The number of output elements must equal the number
29    /// of input elements.
30    Step,
31
32    /// Uniform Catmull-Rom spline interpolation.
33    ///
34    /// The animation's interpolation is computed using a uniform Catmull-Rom spline.
35    /// The number of output elements must equal two more than the number of input
36    /// elements. The first and last output elements represent the start and end
37    /// tangents of the spline. There must be at least four keyframes when using this
38    /// interpolation.
39    CatmullRomSpline,
40
41    /// Cubic spline interpolation.
42    ///
43    /// The animation's interpolation is computed using a uniform Catmull-Rom spline.
44    /// The number of output elements must equal two more than the number of input
45    /// elements. The first and last output elements represent the start and end
46    /// tangents of the spline. There must be at least four keyframes when using this
47    /// interpolation.
48    CubicSpline,
49}
50
51/// Specifies a property to animate.
52#[derive(Clone, Copy, Debug, Eq, PartialEq, Deserialize)]
53pub enum Property {
54    /// XYZ translation vector.
55    Translation = 1,
56
57    /// XYZW rotation quaternion.
58    Rotation,
59
60    /// XYZ scale vector.
61    Scale,
62
63    /// Weights of morph targets.
64    MorphTargetWeights,
65}
66
67/// A keyframe animation.
68#[derive(Clone, Debug, Deserialize, Serialize)]
69pub struct Animation {
70    /// Extension specific data.
71    #[serde(default, skip_serializing_if = "Option::is_none")]
72    pub extensions: Option<extensions::animation::Animation>,
73
74    /// An array of channels, each of which targets an animation's sampler at a
75    /// node's property.
76    ///
77    /// Different channels of the same animation must not have equal targets.
78    #[serde(skip_serializing_if = "Vec::is_empty")]
79    pub channels: Vec<Channel>,
80
81    /// An array of samplers that combine input and output accessors with an
82    /// interpolation algorithm to define a keyframe graph (but not its target).
83    #[serde(skip_serializing_if = "Vec::is_empty")]
84    pub samplers: Vec<Sampler>,
85}
86
87/// Targets an animation's sampler at a node's property.
88#[derive(Clone, Debug, Deserialize, Serialize)]
89pub struct Channel {
90    /// The index of a sampler in this animation used to compute the value for the
91    /// target.
92    pub sampler: Index<Sampler>,
93
94    /// The index of the node and TRS property to target.
95    pub target: Target,
96
97    /// Extension specific data.
98    #[serde(default, skip_serializing_if = "Option::is_none")]
99    pub extensions: Option<extensions::animation::Channel>,
100}
101
102/// The index of the node and TRS property that an animation channel targets.
103#[derive(Clone, Debug, Deserialize, Serialize, Validate)]
104pub struct Target {
105    /// Extension specific data.
106    #[serde(default, skip_serializing_if = "Option::is_none")]
107    pub extensions: Option<extensions::animation::Target>,
108
109    /// The index of the node to target.
110    pub node: Index<scene::Node>,
111
112    /// The name of the node's property to modify or the 'weights' of the
113    /// morph targets it instantiates.
114    pub path: Checked<Property>,
115}
116
117/// Defines a keyframe graph but not its target.
118#[derive(Clone, Debug, Deserialize, Serialize, Validate)]
119pub struct Sampler {
120    /// Extension specific data.
121    #[serde(default, skip_serializing_if = "Option::is_none")]
122    pub extensions: Option<extensions::animation::Sampler>,
123
124    /// The index of an accessor containing keyframe input values, e.g., time.
125    pub input: Index<accessor::Accessor>,
126
127    /// The interpolation algorithm.
128    #[serde(default)]
129    pub interpolation: Checked<Interpolation>,
130
131    /// The index of an accessor containing keyframe output values.
132    pub output: Index<accessor::Accessor>,
133}
134
135impl Validate for Animation {
136    fn validate_minimally<P, R>(&self, root: &Root, path: P, report: &mut R)
137    where
138        P: Fn() -> Path,
139        R: FnMut(&dyn Fn() -> Path, Error),
140    {
141        self.samplers.validate_minimally(root, || path().field("samplers"), report);
142        for (index, channel) in self.channels.iter().enumerate() {
143            if channel.sampler.value() as usize >= self.samplers.len() {
144                let path = || path().field("channels").index(index).field("sampler");
145                report(&path, Error::IndexOutOfBounds);
146            }
147        }
148    }
149}
150
151impl Default for Interpolation {
152    fn default() -> Self {
153        Interpolation::Linear
154    }
155}
156
157impl<'de> de::Deserialize<'de> for Checked<Interpolation> {
158    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
159    where
160        D: de::Deserializer<'de>,
161    {
162        struct Visitor;
163        impl<'de> de::Visitor<'de> for Visitor {
164            type Value = Checked<Interpolation>;
165
166            fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
167                write!(f, "any of: {:?}", VALID_INTERPOLATIONS)
168            }
169
170            fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
171            where
172                E: de::Error,
173            {
174                use self::Interpolation::*;
175                use crate::validation::Checked::*;
176                Ok(match value {
177                    "LINEAR" => Valid(Linear),
178                    "STEP" => Valid(Step),
179                    "CATMULLROMSPLINE" => Valid(CatmullRomSpline),
180                    "CUBICSPLINE" => Valid(CubicSpline),
181                    _ => Invalid,
182                })
183            }
184        }
185        deserializer.deserialize_str(Visitor)
186    }
187}
188
189impl ser::Serialize for Interpolation {
190    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
191    where
192        S: ser::Serializer,
193    {
194        serializer.serialize_str(match *self {
195            Interpolation::Linear => "LINEAR",
196            Interpolation::Step => "STEP",
197            Interpolation::CatmullRomSpline => "CATMULLROMSPLINE",
198            Interpolation::CubicSpline => "CUBICSPLINE",
199        })
200    }
201}
202
203impl<'de> de::Deserialize<'de> for Checked<Property> {
204    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
205    where
206        D: de::Deserializer<'de>,
207    {
208        struct Visitor;
209        impl<'de> de::Visitor<'de> for Visitor {
210            type Value = Checked<Property>;
211
212            fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
213                write!(f, "any of: {:?}", VALID_PROPERTIES)
214            }
215
216            fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
217            where
218                E: de::Error,
219            {
220                use self::Property::*;
221                use crate::validation::Checked::*;
222                Ok(match value {
223                    "translation" => Valid(Translation),
224                    "rotation" => Valid(Rotation),
225                    "scale" => Valid(Scale),
226                    "weights" => Valid(MorphTargetWeights),
227                    _ => Invalid,
228                })
229            }
230        }
231        deserializer.deserialize_str(Visitor)
232    }
233}
234
235impl ser::Serialize for Property {
236    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
237    where
238        S: ser::Serializer,
239    {
240        serializer.serialize_str(match *self {
241            Property::Translation => "translation",
242            Property::Rotation => "rotation",
243            Property::Scale => "scale",
244            Property::MorphTargetWeights => "weights",
245        })
246    }
247}