gltf_v1/
node.rs

1use std::slice;
2
3use json::StringIndex;
4
5use crate::{
6    Document,
7    camera::Camera,
8    light::Light,
9    math::{Matrix3, Matrix4, Quaternion, Vector3},
10    mesh::Mesh,
11    skin::Skin,
12};
13
14/// The transform for a `Node`.
15#[derive(Clone, Debug)]
16pub enum Transform {
17    /// 4x4 transformation matrix in column-major order.
18    Matrix {
19        /// 4x4 matrix.
20        matrix: [[f32; 4]; 4],
21    },
22
23    /// Decomposed TRS properties.
24    Decomposed {
25        /// `[x, y, z]` vector.
26        translation: [f32; 3],
27
28        /// `[x, y, z, w]` quaternion, where `w` is the scalar.
29        rotation: [f32; 4],
30
31        /// `[x, y, z]` vector.
32        scale: [f32; 3],
33    },
34}
35impl Transform {
36    pub fn matrix(self) -> [[f32; 4]; 4] {
37        match self {
38            Transform::Matrix { matrix } => matrix,
39            Transform::Decomposed {
40                translation: t,
41                rotation: r,
42                scale: s,
43            } => {
44                let t = Matrix4::from_translation(Vector3::new(t[0], t[1], t[2]));
45                let r = Matrix4::from(Quaternion::new(r[3], r[0], r[1], r[2]));
46                let s = Matrix4::from_nonuniform_scale(s[0], s[1], s[2]);
47                (t * r * s).into()
48            }
49        }
50    }
51
52    pub fn decomposed(self) -> ([f32; 3], [f32; 4], [f32; 3]) {
53        match self {
54            Transform::Matrix { matrix: m } => {
55                let translation = [m[3][0], m[3][1], m[3][2]];
56                #[rustfmt::skip]
57                let mut i = Matrix3::new(
58                    m[0][0], m[0][1], m[0][2],
59                    m[1][0], m[1][1], m[1][2],
60                    m[2][0], m[2][1], m[2][2],
61                );
62                let sx = i.x.magnitude();
63                let sy = i.y.magnitude();
64                let sz = i.determinant().signum() * i.z.magnitude();
65                let scale = [sx, sy, sz];
66                i.x.multiply(1.0 / sx);
67                i.y.multiply(1.0 / sy);
68                i.z.multiply(1.0 / sz);
69                let r = Quaternion::from_matrix(i);
70                let rotation = [r.v.x, r.v.y, r.v.z, r.s];
71                (translation, rotation, scale)
72            }
73            Transform::Decomposed {
74                translation,
75                rotation,
76                scale,
77            } => (translation, rotation, scale),
78        }
79    }
80}
81
82#[derive(Clone, Debug)]
83pub struct Node<'a> {
84    /// The parent `Document` struct.
85    document: &'a Document,
86
87    /// The corresponding JSON index.
88    index: &'a String,
89
90    /// The corresponding JSON struct.
91    json: &'a json::Node,
92}
93
94impl<'a> Node<'a> {
95    /// Constructs a `Node`.
96    pub(crate) fn new(document: &'a Document, index: &'a String, json: &'a json::Node) -> Self {
97        Self {
98            document,
99            index,
100            json,
101        }
102    }
103    pub fn index(&self) -> &str {
104        self.index
105    }
106    pub fn name(&self) -> Option<&'a str> {
107        self.json.name.as_deref()
108    }
109    pub fn camera(&self) -> Option<Camera<'a>> {
110        self.json
111            .camera
112            .as_ref()
113            .and_then(|index| self.document.cameras().find(|x| x.index() == index.value()))
114    }
115    pub fn light(&self) -> Option<Light<'a>> {
116        #[cfg(feature = "KHR_materials_common")]
117        return self
118            .json
119            .extensions
120            .as_ref()
121            .and_then(|x| x.ktr_materials_common.as_ref())
122            .and_then(|node_light| {
123                self.document
124                    .lights()
125                    .and_then(|mut l| l.find(|x| x.index() == node_light.light.value()))
126            });
127        #[cfg(not(feature = "KHR_materials_common"))]
128        None
129    }
130    pub fn children(&self) -> Children<'a> {
131        Children {
132            document: self.document,
133            iter: self.json.children.iter(),
134        }
135    }
136    pub fn skeletons(&self) -> Children<'a> {
137        Children {
138            document: self.document,
139            iter: self.json.skeletons.iter(),
140        }
141    }
142    pub fn skin(&self) -> Option<Skin<'a>> {
143        self.json
144            .skin
145            .as_ref()
146            .and_then(|index| self.document.skins().find(|x| x.index() == index.value()))
147    }
148    pub fn meshes(&self) -> Vec<Mesh<'a>> {
149        self.json
150            .meshes
151            .iter()
152            .filter_map(|index| self.document.meshes().find(|x| x.index() == index.value()))
153            .collect()
154    }
155    pub fn joint_name(&self) -> Option<&'a str> {
156        self.json.joint_name.as_deref()
157    }
158    /// Returns the node's transform.
159    pub fn transform(&self) -> Transform {
160        if let Some(m) = self.json.matrix {
161            Transform::Matrix {
162                matrix: [
163                    [m[0], m[1], m[2], m[3]],
164                    [m[4], m[5], m[6], m[7]],
165                    [m[8], m[9], m[10], m[11]],
166                    [m[12], m[13], m[14], m[15]],
167                ],
168            }
169        } else {
170            Transform::Decomposed {
171                translation: self.json.translation.unwrap_or([0.0, 0.0, 0.0]),
172                rotation: self.json.rotation.unwrap_or([0.0, 0.0, 0.0, 1.0]),
173                scale: self.json.scale.unwrap_or([1.0, 1.0, 1.0]),
174            }
175        }
176    }
177}
178
179#[derive(Clone, Debug)]
180pub struct Children<'a> {
181    /// The parent `Document` struct.
182    pub(crate) document: &'a Document,
183
184    /// The internal node index iterator.
185    pub(crate) iter: slice::Iter<'a, StringIndex<json::Node>>,
186}
187
188impl ExactSizeIterator for Children<'_> {}
189impl<'a> Iterator for Children<'a> {
190    type Item = Node<'a>;
191
192    fn next(&mut self) -> Option<Self::Item> {
193        self.iter
194            .next()
195            .and_then(|index| self.document.nodes().find(|x| x.index() == index.value()))
196    }
197    fn size_hint(&self) -> (usize, Option<usize>) {
198        self.iter.size_hint()
199    }
200    fn count(self) -> usize {
201        self.iter.count()
202    }
203    fn last(self) -> Option<Self::Item> {
204        self.iter
205            .last()
206            .and_then(|index| self.document.nodes().find(|x| x.index() == index.value()))
207    }
208    fn nth(&mut self, n: usize) -> Option<Self::Item> {
209        self.iter
210            .nth(n)
211            .and_then(|index| self.document.nodes().find(|x| x.index() == index.value()))
212    }
213}
214#[derive(Clone, Debug)]
215pub struct Nodes<'a> {
216    /// Internal accessor iterator.
217    pub(crate) iter: indexmap::map::Iter<'a, String, gltf_v1_json::Node>,
218
219    /// The internal root glTF object.
220    pub(crate) document: &'a Document,
221}
222
223impl ExactSizeIterator for Nodes<'_> {}
224impl<'a> Iterator for Nodes<'a> {
225    type Item = Node<'a>;
226
227    fn next(&mut self) -> Option<Self::Item> {
228        self.iter
229            .next()
230            .map(|(index, json)| Node::new(self.document, index, json))
231    }
232    fn size_hint(&self) -> (usize, Option<usize>) {
233        self.iter.size_hint()
234    }
235    fn count(self) -> usize {
236        self.iter.count()
237    }
238    fn last(self) -> Option<Self::Item> {
239        let document = self.document;
240        self.iter
241            .last()
242            .map(|(index, json)| Node::new(document, index, json))
243    }
244    fn nth(&mut self, n: usize) -> Option<Self::Item> {
245        self.iter
246            .nth(n)
247            .map(|(index, json)| Node::new(self.document, index, json))
248    }
249}