Skip to main content

gltf_reader/
animation.rs

1use alloc::borrow::Cow;
2use alloc::vec::Vec;
3use ownable::IntoOwned;
4use serde::Deserialize;
5
6use crate::accessor::Accessor;
7use crate::node::Node;
8use crate::{Extensions, Extras, Idx};
9
10/// glTF known interpolation algorithms.
11#[derive(Debug, Clone, Copy, PartialEq, Eq)]
12pub enum InterpolationEnum {
13    Linear,
14    Step,
15    CubicSpline,
16}
17
18/// Interpolation algorithm.
19#[derive(Clone, PartialEq, Eq, Deserialize, IntoOwned)]
20#[serde(transparent)]
21pub struct Interpolation<'a>(#[serde(borrow)] pub Cow<'a, str>);
22
23impl Default for Interpolation<'_> {
24    fn default() -> Self {
25        Self::LINEAR
26    }
27}
28
29impl core::fmt::Debug for Interpolation<'_> {
30    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
31        if let Some(e) = self.to_enum() {
32            e.fmt(f)
33        } else {
34            self.0.fmt(f)
35        }
36    }
37}
38
39impl Interpolation<'_> {
40    pub const LINEAR: Self = Self(Cow::Borrowed("LINEAR"));
41    pub const STEP: Self = Self(Cow::Borrowed("STEP"));
42    pub const CUBICSPLINE: Self = Self(Cow::Borrowed("CUBICSPLINE"));
43
44    pub fn to_enum(&self) -> Option<InterpolationEnum> {
45        if *self == Self::LINEAR {
46            return Some(InterpolationEnum::Linear);
47        } else if *self == Self::STEP {
48            return Some(InterpolationEnum::Step);
49        } else if *self == Self::CUBICSPLINE {
50            return Some(InterpolationEnum::CubicSpline);
51        }
52
53        None
54    }
55}
56
57/// An animation sampler combines timestamps with a sequence of output values and defines an
58/// interpolation algorithm.
59#[derive(Debug, Clone, Deserialize, IntoOwned)]
60pub struct AnimationSampler<'a> {
61    /// The index of an accessor containing keyframe timestamps.
62    pub input: Idx<Accessor<'static>>,
63    /// The index of an accessor containing keyframe output values.
64    pub output: Idx<Accessor<'static>>,
65    /// Interpolation algorithm.
66    #[serde(default, borrow)]
67    pub interpolation: Interpolation<'a>,
68
69    #[serde(borrow)]
70    pub extensions: Option<Extensions<'a>>,
71    #[serde(borrow)]
72    pub extras: Option<Extras<'a>>,
73}
74
75/// glTF known animation properties.
76#[derive(Debug, Clone, Copy, PartialEq, Eq)]
77pub enum PropertyEnum {
78    Translation,
79    Rotation,
80    Scale,
81    Weights,
82}
83
84/// The name of a node's TRS property to animate, or the `weights` of the Morph Targets it
85/// instantiates.
86#[derive(Clone, PartialEq, Eq, Deserialize, IntoOwned)]
87#[serde(transparent)]
88pub struct Property<'a>(#[serde(borrow)] pub Cow<'a, str>);
89
90impl core::fmt::Debug for Property<'_> {
91    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
92        if let Some(e) = self.to_enum() {
93            e.fmt(f)
94        } else {
95            self.0.fmt(f)
96        }
97    }
98}
99
100impl Property<'_> {
101    pub const TRANSLATION: Self = Self(Cow::Borrowed("translation"));
102    pub const ROTATION: Self = Self(Cow::Borrowed("rotation"));
103    pub const SCALE: Self = Self(Cow::Borrowed("scale"));
104    pub const WEIGHTS: Self = Self(Cow::Borrowed("weights"));
105
106    pub fn to_enum(&self) -> Option<PropertyEnum> {
107        if *self == Self::TRANSLATION {
108            return Some(PropertyEnum::Translation);
109        } else if *self == Self::ROTATION {
110            return Some(PropertyEnum::Rotation);
111        } else if *self == Self::SCALE {
112            return Some(PropertyEnum::Scale);
113        } else if *self == Self::WEIGHTS {
114            return Some(PropertyEnum::Weights);
115        }
116
117        None
118    }
119}
120
121/// The descriptor of an animated property.
122#[derive(Debug, Clone, Deserialize, IntoOwned)]
123pub struct ChannelTarget<'a> {
124    /// The index of the node to animate.
125    pub node: Option<Idx<Node<'static>>>,
126    /// The name of the node's TRS property to animate, or the `weights` of the Morph Targets it
127    /// instantiates.
128    #[serde(borrow)]
129    pub path: Property<'a>,
130
131    #[serde(borrow)]
132    pub extensions: Option<Extensions<'a>>,
133    #[serde(borrow)]
134    pub extras: Option<Extras<'a>>,
135}
136
137/// An animation channel combines an animation sampler with a target property being animated.
138#[derive(Debug, Clone, Deserialize, IntoOwned)]
139pub struct Channel<'a> {
140    /// The index of a sampler in an animation used to compute the value for the target.
141    pub sampler: Idx<AnimationSampler<'static>>,
142    /// The descriptor of the animated property.
143    #[serde(borrow)]
144    pub target: ChannelTarget<'a>,
145
146    #[serde(borrow)]
147    pub extensions: Option<Extensions<'a>>,
148    #[serde(borrow)]
149    pub extras: Option<Extras<'a>>,
150}
151
152/// A keyframe animation.
153#[derive(Debug, Clone, Deserialize, IntoOwned)]
154pub struct Animation<'a> {
155    /// The user-defined name of this object.
156    #[serde(borrow)]
157    pub name: Option<Cow<'a, str>>,
158
159    /// An array of animation samplers.
160    #[serde(borrow)]
161    pub samplers: Vec<AnimationSampler<'a>>,
162    /// An array of animation channels.
163    #[serde(borrow)]
164    pub channels: Vec<Channel<'a>>,
165
166    #[serde(borrow)]
167    pub extensions: Option<Extensions<'a>>,
168    #[serde(borrow)]
169    pub extras: Option<Extras<'a>>,
170}