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#[derive(Clone, Debug)]
16pub enum Transform {
17 Matrix {
19 matrix: [[f32; 4]; 4],
21 },
22
23 Decomposed {
25 translation: [f32; 3],
27
28 rotation: [f32; 4],
30
31 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 document: &'a Document,
86
87 index: &'a String,
89
90 json: &'a json::Node,
92}
93
94impl<'a> Node<'a> {
95 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 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 pub(crate) document: &'a Document,
183
184 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 pub(crate) iter: indexmap::map::Iter<'a, String, gltf_v1_json::Node>,
218
219 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}