Skip to main content

pak/
anim.rs

1use {
2    super::{Quat, Vec3},
3    gltf::animation::Interpolation as GltfInterpolation,
4    serde::{Deserialize, Serialize},
5};
6
7/// Holds an `Animation` in a `.pak` file. For data transport only.
8#[derive(Debug, Deserialize, PartialEq, Serialize)]
9pub struct Animation {
10    channels: Vec<Channel>,
11}
12
13impl Animation {
14    pub(super) fn new(channels: Vec<Channel>) -> Self {
15        Self { channels }
16    }
17
18    /// The channels (joints/bones) of movement used in this `Animation`.
19    pub fn channels(&self) -> &[Channel] {
20        &self.channels
21    }
22}
23
24/// Describes the animation of one joint.
25#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
26pub struct Channel {
27    inputs: Vec<u32>,
28    interpolation: Interpolation,
29    outputs: Outputs,
30    target: String,
31}
32
33impl Channel {
34    #[allow(unused)]
35    pub(crate) fn new<T: AsRef<str>, I: IntoIterator<Item = u32>>(
36        target: T,
37        interpolation: GltfInterpolation,
38        inputs: I,
39        outputs: Outputs,
40    ) -> Self {
41        let inputs = inputs.into_iter().collect::<Vec<_>>();
42        let target = target.as_ref().to_owned();
43
44        assert!(!target.is_empty());
45        assert_ne!(inputs.len(), 0);
46
47        Self {
48            inputs,
49            interpolation: match interpolation {
50                GltfInterpolation::CubicSpline => Interpolation::CubicSpline,
51                GltfInterpolation::Linear => Interpolation::Linear,
52                GltfInterpolation::Step => Interpolation::Step,
53            },
54            outputs,
55            target,
56        }
57    }
58
59    pub fn inputs(&self) -> &[u32] {
60        &self.inputs
61    }
62
63    pub fn interpolation(&self) -> Interpolation {
64        self.interpolation
65    }
66
67    pub fn outputs(&self) -> &Outputs {
68        &self.outputs
69    }
70
71    /// The target joint/bone.
72    pub fn target(&self) -> &str {
73        &self.target
74    }
75}
76
77// This is here because GLTF doesn't provide serialize! TODO: Fix!
78/// Specifies an interpolation algorithm.
79#[derive(Clone, Copy, Debug, Eq, PartialEq, Deserialize, Serialize)]
80pub enum Interpolation {
81    /// Linear interpolation.
82    ///
83    /// The animated values are linearly interpolated between keyframes.
84    /// When targeting a rotation, spherical linear interpolation (slerp) should be
85    /// used to interpolate quaternions. The number output of elements must equal
86    /// the number of input elements.
87    Linear = 1,
88
89    /// Step interpolation.
90    ///
91    /// The animated values remain constant to the output of the first keyframe,
92    /// until the next keyframe. The number of output elements must equal the number
93    /// of input elements.
94    Step,
95
96    /// Cubic spline interpolation.
97    ///
98    /// The animation's interpolation is computed using a cubic spline with specified
99    /// tangents. The number of output elements must equal three times the number of
100    /// input elements. For each input element, the output stores three elements, an
101    /// in-tangent, a spline vertex, and an out-tangent. There must be at least two
102    /// keyframes when using this interpolation
103    CubicSpline,
104}
105
106#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
107pub enum Outputs {
108    Rotations(Vec<Quat>),
109    Scales(Vec<Vec3>),
110    Translations(Vec<Vec3>),
111}
112
113impl Outputs {
114    /// Returns `true` if the vector contains no elements.
115    pub fn is_empty(&self) -> bool {
116        match self {
117            Self::Rotations(rotations) => rotations.is_empty(),
118            Self::Scales(scales) => scales.is_empty(),
119            Self::Translations(translations) => translations.is_empty(),
120        }
121    }
122
123    /// The count of outputs
124    pub fn len(&self) -> usize {
125        match self {
126            Self::Rotations(rotations) => rotations.len(),
127            Self::Scales(scales) => scales.len(),
128            Self::Translations(translations) => translations.len(),
129        }
130    }
131}