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
107/// The index of the node and TRS property that an animation channel targets.
108#[derive(Clone, Debug, Deserialize, Serialize, Validate)]
109pub struct Target {
110    /// Extension specific data.
111    #[serde(default, skip_serializing_if = "Option::is_none")]
112    pub extensions: Option<extensions::animation::Target>,
113
114    /// Optional application specific data.
115    #[serde(default)]
116    #[cfg_attr(feature = "extras", serde(skip_serializing_if = "Option::is_none"))]
117    #[cfg_attr(not(feature = "extras"), serde(skip_serializing))]
118    pub extras: Extras,
119
120    /// The index of the node to target.
121    pub node: Index<scene::Node>,
122
123    /// The name of the node's property to modify or the 'weights' of the
124    /// morph targets it instantiates.
125    pub path: Checked<Property>,
126}
127
128/// Defines a keyframe graph but not its target.
129#[derive(Clone, Debug, Deserialize, Serialize, Validate)]
130pub struct Sampler {
131    /// Extension specific data.
132    #[serde(default, skip_serializing_if = "Option::is_none")]
133    pub extensions: Option<extensions::animation::Sampler>,
134
135    /// Optional application specific data.
136    #[serde(default)]
137    #[cfg_attr(feature = "extras", serde(skip_serializing_if = "Option::is_none"))]
138    #[cfg_attr(not(feature = "extras"), serde(skip_serializing))]
139    pub extras: Extras,
140
141    /// The index of an accessor containing keyframe input values, e.g., time.
142    pub input: Index<accessor::Accessor>,
143
144    /// The interpolation algorithm.
145    #[serde(default)]
146    pub interpolation: Checked<Interpolation>,
147
148    /// The index of an accessor containing keyframe output values.
149    pub output: Index<accessor::Accessor>,
150}
151
152impl Validate for Animation {
153    fn validate<P, R>(&self, root: &Root, path: P, report: &mut R)
154    where
155        P: Fn() -> Path,
156        R: FnMut(&dyn Fn() -> Path, Error),
157    {
158        self.samplers
159            .validate(root, || path().field("samplers"), report);
160        for (index, channel) in self.channels.iter().enumerate() {
161            if channel.sampler.value() >= self.samplers.len() {
162                let path = || path().field("channels").index(index).field("sampler");
163                report(&path, Error::IndexOutOfBounds);
164            }
165        }
166    }
167}
168
169impl Default for Interpolation {
170    fn default() -> Self {
171        Interpolation::Linear
172    }
173}
174
175impl<'de> de::Deserialize<'de> for Checked<Interpolation> {
176    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
177    where
178        D: de::Deserializer<'de>,
179    {
180        struct Visitor;
181        impl<'de> de::Visitor<'de> for Visitor {
182            type Value = Checked<Interpolation>;
183
184            fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
185                write!(f, "any of: {:?}", VALID_INTERPOLATIONS)
186            }
187
188            fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
189            where
190                E: de::Error,
191            {
192                use self::Interpolation::*;
193                use crate::validation::Checked::*;
194                Ok(match value {
195                    "LINEAR" => Valid(Linear),
196                    "STEP" => Valid(Step),
197                    "CUBICSPLINE" => Valid(CubicSpline),
198                    _ => Invalid,
199                })
200            }
201        }
202        deserializer.deserialize_str(Visitor)
203    }
204}
205
206impl ser::Serialize for Interpolation {
207    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
208    where
209        S: ser::Serializer,
210    {
211        serializer.serialize_str(match *self {
212            Interpolation::Linear => "LINEAR",
213            Interpolation::Step => "STEP",
214            Interpolation::CubicSpline => "CUBICSPLINE",
215        })
216    }
217}
218
219impl<'de> de::Deserialize<'de> for Checked<Property> {
220    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
221    where
222        D: de::Deserializer<'de>,
223    {
224        struct Visitor;
225        impl<'de> de::Visitor<'de> for Visitor {
226            type Value = Checked<Property>;
227
228            fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
229                write!(f, "any of: {:?}", VALID_PROPERTIES)
230            }
231
232            fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
233            where
234                E: de::Error,
235            {
236                use self::Property::*;
237                use crate::validation::Checked::*;
238                Ok(match value {
239                    "translation" => Valid(Translation),
240                    "rotation" => Valid(Rotation),
241                    "scale" => Valid(Scale),
242                    "weights" => Valid(MorphTargetWeights),
243                    _ => Invalid,
244                })
245            }
246        }
247        deserializer.deserialize_str(Visitor)
248    }
249}
250
251impl ser::Serialize for Property {
252    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
253    where
254        S: ser::Serializer,
255    {
256        serializer.serialize_str(match *self {
257            Property::Translation => "translation",
258            Property::Rotation => "rotation",
259            Property::Scale => "scale",
260            Property::MorphTargetWeights => "weights",
261        })
262    }
263}