Skip to main content

gltf_json/
animation.rs

1use crate::validation::{Checked, Error, Validate};
2use crate::{accessor, extensions, scene, Extras, Index, Path, Root};
3use gltf_derive::Validate;
4use serde::{de, ser};
5use serde_derive::{Deserialize, Serialize};
6use std::fmt;
7
8/// All valid animation interpolation algorithms.
9pub const VALID_INTERPOLATIONS: &[&str] = &["LINEAR", "STEP", "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    /// Cubic spline interpolation.
33    ///
34    /// The animation's interpolation is computed using a cubic spline with specified
35    /// tangents. The number of output elements must equal three times the number of
36    /// input elements. For each input element, the output stores three elements, an
37    /// in-tangent, a spline vertex, and an out-tangent. There must be at least two
38    /// keyframes when using this interpolation
39    CubicSpline,
40}
41
42/// Specifies a property to animate.
43#[derive(Clone, Copy, Debug, Eq, PartialEq, Deserialize)]
44pub enum Property {
45    /// XYZ translation vector.
46    Translation = 1,
47    /// XYZW rotation quaternion.
48    Rotation,
49    /// XYZ scale vector.
50    Scale,
51    /// Weights of morph targets.
52    MorphTargetWeights,
53}
54
55/// A keyframe animation.
56#[derive(Clone, Debug, Deserialize, Serialize)]
57pub struct Animation {
58    /// Extension specific data.
59    #[serde(default, skip_serializing_if = "Option::is_none")]
60    pub extensions: Option<extensions::animation::Animation>,
61
62    /// Optional application specific data.
63    #[serde(default)]
64    #[cfg_attr(feature = "extras", serde(skip_serializing_if = "Option::is_none"))]
65    #[cfg_attr(not(feature = "extras"), serde(skip_serializing))]
66    pub extras: Extras,
67
68    /// An array of channels, each of which targets an animation's sampler at a
69    /// node's property.
70    ///
71    /// Different channels of the same animation must not have equal targets.
72    #[serde(skip_serializing_if = "Vec::is_empty")]
73    pub channels: Vec<Channel>,
74
75    /// Optional user-defined name for this object.
76    #[cfg(feature = "names")]
77    #[cfg_attr(feature = "names", serde(skip_serializing_if = "Option::is_none"))]
78    pub name: Option<String>,
79
80    /// An array of samplers that combine input and output accessors with an
81    /// interpolation algorithm to define a keyframe graph (but not its target).
82    #[serde(skip_serializing_if = "Vec::is_empty")]
83    pub samplers: Vec<Sampler>,
84}
85
86/// Targets an animation's sampler at a node's property.
87#[derive(Clone, Debug, Deserialize, Serialize)]
88pub struct Channel {
89    /// The index of a sampler in this animation used to compute the value for the
90    /// target.
91    pub sampler: Index<Sampler>,
92
93    /// The index of the node and TRS property to target.
94    pub target: Target,
95
96    /// Extension specific data.
97    #[serde(default, skip_serializing_if = "Option::is_none")]
98    pub extensions: Option<extensions::animation::Channel>,
99
100    /// Optional application specific data.
101    #[serde(default)]
102    #[cfg_attr(feature = "extras", serde(skip_serializing_if = "Option::is_none"))]
103    #[cfg_attr(not(feature = "extras"), serde(skip_serializing))]
104    pub extras: Extras,
105}
106
107fn node_default() -> Index<scene::Node> {
108    Index::new(u32::MAX)
109}
110
111fn node_is_empty(node: &Index<scene::Node>) -> bool {
112    node.value() == u32::MAX as usize
113}
114
115fn node_validate<P, R>(node: &Index<scene::Node>, root: &Root, path: P, report: &mut R)
116where
117    P: Fn() -> Path,
118    R: FnMut(&dyn Fn() -> Path, Error),
119{
120    if cfg!(feature = "allow_empty_animation_target_node") {
121        if !node_is_empty(node) {
122            node.validate(root, path, report);
123        }
124    } else if node_is_empty(node) {
125        report(&path, Error::Missing);
126    } else {
127        node.validate(root, &path, report);
128    }
129}
130
131/// Selects the target of an animation channel.
132#[derive(Clone, Debug, Deserialize, Serialize)]
133pub struct Target {
134    /// Extension specific data.
135    #[serde(default, skip_serializing_if = "Option::is_none")]
136    pub extensions: Option<extensions::animation::Target>,
137
138    /// Optional application specific data.
139    #[serde(default)]
140    #[cfg_attr(feature = "extras", serde(skip_serializing_if = "Option::is_none"))]
141    #[cfg_attr(not(feature = "extras"), serde(skip_serializing))]
142    pub extras: Extras,
143
144    /// The index of the node to target.
145    #[serde(default = "node_default", skip_serializing_if = "node_is_empty")]
146    pub node: Index<scene::Node>,
147
148    /// The name of the node's property to modify or the 'weights' of the
149    /// morph targets it instantiates.
150    pub path: Checked<Property>,
151}
152
153impl Validate for Target {
154    fn validate<P, R>(&self, root: &Root, path: P, report: &mut R)
155    where
156        P: Fn() -> Path,
157        R: FnMut(&dyn Fn() -> Path, Error),
158    {
159        self.extensions
160            .validate(root, || path().field("extensions"), report);
161        node_validate(&self.node, root, || path().field("node"), report);
162        self.path.validate(root, || path().field("path"), report);
163    }
164}
165
166/// Defines a keyframe graph but not its target.
167#[derive(Clone, Debug, Deserialize, Serialize, Validate)]
168pub struct Sampler {
169    /// Extension specific data.
170    #[serde(default, skip_serializing_if = "Option::is_none")]
171    pub extensions: Option<extensions::animation::Sampler>,
172
173    /// Optional application specific data.
174    #[serde(default)]
175    #[cfg_attr(feature = "extras", serde(skip_serializing_if = "Option::is_none"))]
176    #[cfg_attr(not(feature = "extras"), serde(skip_serializing))]
177    pub extras: Extras,
178
179    /// The index of an accessor containing keyframe input values, e.g., time.
180    pub input: Index<accessor::Accessor>,
181
182    /// The interpolation algorithm.
183    #[serde(default)]
184    pub interpolation: Checked<Interpolation>,
185
186    /// The index of an accessor containing keyframe output values.
187    pub output: Index<accessor::Accessor>,
188}
189
190impl Validate for Animation {
191    fn validate<P, R>(&self, root: &Root, path: P, report: &mut R)
192    where
193        P: Fn() -> Path,
194        R: FnMut(&dyn Fn() -> Path, Error),
195    {
196        self.samplers
197            .validate(root, || path().field("samplers"), report);
198        for (index, channel) in self.channels.iter().enumerate() {
199            if channel.sampler.value() >= self.samplers.len() {
200                let path = || path().field("channels").index(index).field("sampler");
201                report(&path, Error::IndexOutOfBounds);
202            }
203        }
204    }
205}
206
207impl Default for Interpolation {
208    fn default() -> Self {
209        Interpolation::Linear
210    }
211}
212
213impl<'de> de::Deserialize<'de> for Checked<Interpolation> {
214    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
215    where
216        D: de::Deserializer<'de>,
217    {
218        struct Visitor;
219        impl de::Visitor<'_> for Visitor {
220            type Value = Checked<Interpolation>;
221
222            fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
223                write!(f, "any of: {:?}", VALID_INTERPOLATIONS)
224            }
225
226            fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
227            where
228                E: de::Error,
229            {
230                use self::Interpolation::*;
231                use crate::validation::Checked::*;
232                Ok(match value {
233                    "LINEAR" => Valid(Linear),
234                    "STEP" => Valid(Step),
235                    "CUBICSPLINE" => Valid(CubicSpline),
236                    _ => Invalid,
237                })
238            }
239        }
240        deserializer.deserialize_str(Visitor)
241    }
242}
243
244impl ser::Serialize for Interpolation {
245    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
246    where
247        S: ser::Serializer,
248    {
249        serializer.serialize_str(match *self {
250            Interpolation::Linear => "LINEAR",
251            Interpolation::Step => "STEP",
252            Interpolation::CubicSpline => "CUBICSPLINE",
253        })
254    }
255}
256
257impl<'de> de::Deserialize<'de> for Checked<Property> {
258    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
259    where
260        D: de::Deserializer<'de>,
261    {
262        struct Visitor;
263        impl de::Visitor<'_> for Visitor {
264            type Value = Checked<Property>;
265
266            fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
267                write!(f, "any of: {:?}", VALID_PROPERTIES)
268            }
269
270            fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
271            where
272                E: de::Error,
273            {
274                use self::Property::*;
275                use crate::validation::Checked::*;
276                Ok(match value {
277                    "translation" => Valid(Translation),
278                    "rotation" => Valid(Rotation),
279                    "scale" => Valid(Scale),
280                    "weights" => Valid(MorphTargetWeights),
281                    _ => Invalid,
282                })
283            }
284        }
285        deserializer.deserialize_str(Visitor)
286    }
287}
288
289impl ser::Serialize for Property {
290    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
291    where
292        S: ser::Serializer,
293    {
294        serializer.serialize_str(match *self {
295            Property::Translation => "translation",
296            Property::Rotation => "rotation",
297            Property::Scale => "scale",
298            Property::MorphTargetWeights => "weights",
299        })
300    }
301}