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}