shine_gltf/
scene.rs

1use crate::validation::{Error, Validate};
2use crate::{camera, extensions, mesh, scene, skin, Index, Path, Root};
3use serde_derive::{Deserialize, Serialize};
4use shine_gltf_macro::Validate;
5
6/// A node in the node hierarchy.  When the node contains `skin`, all
7/// `mesh.primitives` must contain `JOINTS_0` and `WEIGHTS_0` attributes.
8/// A node can have either a `matrix` or any combination of
9/// `translation`/`rotation`/`scale` (TRS) properties. TRS properties are converted
10/// to matrices and postmultiplied in the `T * R * S` order to compose the
11/// transformation matrix; first the scale is applied to the vertices, then the
12/// rotation, and then the translation. If none are provided, the transform is the
13/// identity. When a node is targeted for animation (referenced by an
14/// animation.channel.target), only TRS properties may be present; `matrix` will not
15/// be present.
16#[derive(Clone, Debug, Default, Deserialize, Serialize, Validate)]
17pub struct Node {
18    /// The index of the camera referenced by this node.
19    #[serde(skip_serializing_if = "Option::is_none")]
20    pub camera: Option<Index<camera::Camera>>,
21
22    /// The indices of this node's children.
23    #[serde(skip_serializing_if = "Option::is_none")]
24    pub children: Option<Vec<Index<scene::Node>>>,
25
26    /// Extension specific data.
27    #[serde(default, skip_serializing_if = "Option::is_none")]
28    pub extensions: Option<extensions::scene::Node>,
29
30    /// 4x4 column-major transformation matrix.
31    ///
32    /// glTF 2.0 specification:
33    ///     When a node is targeted for animation (referenced by an
34    ///     animation.channel.target), only TRS properties may be present;
35    ///     matrix will not be present.
36    ///
37    /// TODO: Ensure that .matrix is set to None or otherwise skipped during
38    ///       serialization, if the node is targeted for animation.
39    ///
40    #[serde(skip_serializing_if = "Option::is_none")]
41    pub matrix: Option<[f32; 16]>,
42
43    /// The index of the mesh in this node.
44    #[serde(skip_serializing_if = "Option::is_none")]
45    pub mesh: Option<Index<mesh::Mesh>>,
46
47    /// The node's unit quaternion rotation in the order (x, y, z, w), where w is
48    /// the scalar.
49    #[serde(skip_serializing_if = "Option::is_none")]
50    pub rotation: Option<UnitQuaternion>,
51
52    /// The node's non-uniform scale.
53    #[serde(skip_serializing_if = "Option::is_none")]
54    pub scale: Option<[f32; 3]>,
55
56    /// The node's translation.
57    #[serde(skip_serializing_if = "Option::is_none")]
58    pub translation: Option<[f32; 3]>,
59
60    /// The index of the skin referenced by this node.
61    #[serde(skip_serializing_if = "Option::is_none")]
62    pub skin: Option<Index<skin::Skin>>,
63
64    /// The weights of the instantiated Morph Target. Number of elements must match
65    /// the number of Morph Targets of used mesh.
66    #[serde(skip_serializing_if = "Option::is_none")]
67    pub weights: Option<Vec<f32>>,
68}
69
70/// The root `Node`s of a scene.
71#[derive(Clone, Debug, Default, Deserialize, Serialize, Validate)]
72pub struct Scene {
73    /// Extension specific data.
74    #[serde(default, skip_serializing_if = "Option::is_none")]
75    pub extensions: Option<extensions::scene::Scene>,
76
77    /// The indices of each root node.
78    #[serde(skip_serializing_if = "Vec::is_empty")]
79    pub nodes: Vec<Index<Node>>,
80}
81
82/// Unit quaternion rotation in the order (x, y, z, w), where w is the scalar.
83#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
84pub struct UnitQuaternion(pub [f32; 4]);
85
86impl Default for UnitQuaternion {
87    fn default() -> Self {
88        UnitQuaternion([0.0, 0.0, 0.0, 1.0])
89    }
90}
91
92impl Validate for UnitQuaternion {
93    fn validate_completely<P, R>(&self, _: &Root, path: P, report: &mut R)
94    where
95        P: Fn() -> Path,
96        R: FnMut(&dyn Fn() -> Path, Error),
97    {
98        for x in &self.0 {
99            if *x < -1.0 || *x > 1.0 {
100                report(&path, Error::Invalid);
101                // Only report once
102                break;
103            }
104        }
105    }
106}