1use mod3d_base::hierarchy::Hierarchy;
3use mod3d_base::Transformation;
4
5#[cfg(feature = "serde")]
6use serde::{Deserialize, Serialize};
7
8#[cfg(feature = "serde_json")]
9use serde_json::Value as JsonValue;
10
11#[cfg(not(feature = "serde_json"))]
12pub type JsonValue = ();
13
14use crate::{
15 AccessorIndex, BufferIndex, ImageIndex, Indexable, MaterialIndex, MeshIndex, NHIndex,
16 NodeIndex, SceneIndex, TextureIndex, ViewIndex,
17};
18use crate::{Error, Named, Result};
19use crate::{
20 GltfAccessor, GltfAsset, GltfBuffer, GltfBufferView, GltfImage, GltfMaterial, GltfMesh,
21 GltfNode, GltfScene, GltfTexture,
22};
23
24#[derive(Debug, Default)]
28#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
29#[cfg_attr(feature = "serde", serde(default))]
30pub struct Gltf {
31 asset: GltfAsset,
35
36 buffers: Vec<GltfBuffer>,
39
40 #[cfg_attr(feature = "serde", serde(rename = "bufferViews"))]
44 buffer_views: Vec<GltfBufferView>,
45
46 accessors: Vec<GltfAccessor>,
50
51 materials: Vec<GltfMaterial>,
54
55 meshes: Vec<GltfMesh>,
59
60 nodes: Vec<GltfNode>,
64
65 scene: Option<SceneIndex>,
67
68 scenes: Vec<GltfScene>,
72
73 cameras: Vec<JsonValue>,
75
76 images: Vec<GltfImage>,
79
80 samplers: JsonValue,
82
83 textures: Vec<GltfTexture>,
86
87 skins: Vec<JsonValue>,
89
90 animations: JsonValue,
92
93 #[cfg_attr(feature = "serde", serde(skip_deserializing))]
100 #[cfg_attr(feature = "serde", serde(skip_serializing))]
101 node_hierarchy: Hierarchy<NodeIndex>,
102
103 #[cfg_attr(feature = "serde", serde(skip_deserializing))]
107 #[cfg_attr(feature = "serde", serde(skip_serializing))]
108 nh_index: Vec<NHIndex>,
109}
110
111impl std::ops::Index<NodeIndex> for Gltf {
113 type Output = GltfNode;
114 fn index(&self, index: NodeIndex) -> &Self::Output {
115 &self.nodes[index.as_usize()]
116 }
117}
118
119impl std::ops::Index<AccessorIndex> for Gltf {
121 type Output = GltfAccessor;
122 fn index(&self, index: AccessorIndex) -> &Self::Output {
123 &self.accessors[index.as_usize()]
124 }
125}
126
127impl std::ops::Index<ViewIndex> for Gltf {
129 type Output = GltfBufferView;
130 fn index(&self, index: ViewIndex) -> &Self::Output {
131 &self.buffer_views[index.as_usize()]
132 }
133}
134
135impl std::ops::Index<MeshIndex> for Gltf {
137 type Output = GltfMesh;
138 fn index(&self, index: MeshIndex) -> &Self::Output {
139 &self.meshes[index.as_usize()]
140 }
141}
142
143impl std::ops::Index<ImageIndex> for Gltf {
145 type Output = GltfImage;
146 fn index(&self, index: ImageIndex) -> &Self::Output {
147 &self.images[index.as_usize()]
148 }
149}
150
151impl std::ops::Index<TextureIndex> for Gltf {
153 type Output = GltfTexture;
154 fn index(&self, index: TextureIndex) -> &Self::Output {
155 &self.textures[index.as_usize()]
156 }
157}
158
159impl std::ops::Index<MaterialIndex> for Gltf {
161 type Output = GltfMaterial;
162 fn index(&self, index: MaterialIndex) -> &Self::Output {
163 &self.materials[index.as_usize()]
164 }
165}
166
167impl Gltf {
169 pub fn set_asset(&mut self, asset: GltfAsset) {
170 self.asset = asset;
171 }
172
173 pub fn add_buffer(&mut self, buffer: GltfBuffer) -> BufferIndex {
174 let n = self.buffers.len();
175 self.buffers.push(buffer);
176 n.into()
177 }
178 pub fn add_mesh(&mut self, mesh: GltfMesh) -> MeshIndex {
179 let n = self.meshes.len();
180 self.meshes.push(mesh);
181 n.into()
182 }
183 pub fn add_node(&mut self, node: GltfNode) -> NodeIndex {
184 let n = self.nodes.len();
185 self.nodes.push(node);
186 n.into()
187 }
188 pub fn add_scene(&mut self, scene: GltfScene) -> SceneIndex {
189 let n = self.scenes.len();
190 self.scenes.push(scene);
191 n.into()
192 }
193 pub fn add_view(
194 &mut self,
195 buffer: BufferIndex,
196 byte_offset: usize,
197 byte_length: usize,
198 byte_stride: Option<usize>,
199 ) -> ViewIndex {
200 let view = GltfBufferView {
201 buffer,
202 byte_length,
203 byte_offset,
204 byte_stride,
205 };
206
207 let n = self.buffer_views.len();
208 self.buffer_views.push(view);
209 n.into()
210 }
211 pub fn add_accessor(
212 &mut self,
213 buffer_view: ViewIndex,
214 byte_offset: u32,
215 count: u32,
216 element_type: mod3d_base::BufferElementType,
217 elements_per_data: usize,
218 ) -> AccessorIndex {
219 let acc = GltfAccessor::new(
220 buffer_view,
221 byte_offset as usize,
222 count as usize,
223 element_type,
224 elements_per_data,
225 );
226
227 let n = self.accessors.len();
228 self.accessors.push(acc);
229 n.into()
230 }
231 fn validate_buffer_views(&self) -> Result<()> {
234 let n = self.buffers.len();
235 for (i, bv) in self.buffer_views.iter().enumerate() {
236 let b = bv.buffer();
237 if b.as_usize() >= n {
238 return Err(Error::BadJson(format!(
239 "Buffer view index {i} has buffer {b} out of range (must be < {n})",
240 )));
241 }
242 let l = self.buffers[b.as_usize()].byte_length();
243 if bv.byte_end() > l {
244 return Err(Error::BadJson(format!(
245 "Buffer view index {i} specifies subrange outside the buffer size {l})",
246 )));
247 }
248 }
249 Ok(())
250 }
251
252 fn validate_accessors(&self) -> Result<()> {
255 let n = self.buffer_views.len();
256 for acc in &self.accessors {
257 let bv_index = acc.buffer_view();
258 let Some(bv_index) = bv_index else {
259 return Err(Error::BadJson(
260 "Accessor is not permitted to not specify a BufferView in this GLTF reader"
261 .into(),
262 ));
263 };
264 if bv_index.as_usize() >= n {
265 return Err(Error::BadJson(format!(
266 "Accessor's buffer view index {bv_index} out of range (must be < {n})",
267 )));
268 }
269 let bv = &self.buffer_views[bv_index.as_usize()];
270 let acc_byte_end = acc.byte_view_end(bv.byte_stride(0));
271 if acc_byte_end > bv.byte_length() {
272 return Err(Error::BadJson(format!(
273 "Accessor's last element ends (@{0}) beyond end of buffer view index {1} (at {2})",
274 acc_byte_end,
275 bv.buffer(),
276 bv.byte_length()
277 )));
278 }
279 }
280 Ok(())
281 }
282
283 pub fn validate_nodes(&self) -> Result<()> {
285 let l = self.nodes.len();
286 for (i, n) in self.nodes.iter().enumerate() {
287 for c in n.iter_children() {
288 if c.as_usize() >= l {
289 return Err(Error::BadJson(format!(
290 "Node {i} has child index {c} out of range",
291 )));
292 }
293 }
294 if let Some(m) = n.mesh() {
295 if m.as_usize() > self.meshes.len() {
296 return Err(Error::BadJson(format!(
297 "Node {i} has mesh index {m} out of range",
298 )));
299 }
300 }
301 if let Some(c) = n.camera() {
302 if c.as_usize() > self.cameras.len() {
303 return Err(Error::BadJson(format!(
304 "Node {i} has camera index {c} out of range",
305 )));
306 }
307 }
308 if let Some(s) = n.skin() {
309 if s.as_usize() > self.skins.len() {
310 return Err(Error::BadJson(format!(
311 "Node {i} has skin index {s} out of range",
312 )));
313 }
314 }
315 n.validate(i.into())?;
316 }
317 Ok(())
318 }
319
320 pub fn validate(&self) -> Result<()> {
323 dbg!(self);
324 self.validate_buffer_views()?;
325 self.validate_accessors()?;
326 self.validate_nodes()?;
327 Ok(())
328 }
329
330 pub fn buffers(&self) -> &[GltfBuffer] {
332 &self.buffers
333 }
334
335 pub fn accessors(&self) -> &[GltfAccessor] {
338 &self.accessors
339 }
340
341 pub fn node_hierarchy(&self) -> &Hierarchy<NodeIndex> {
344 &self.node_hierarchy
345 }
346
347 pub fn get_node(&self, name: &str) -> Option<NodeIndex> {
353 GltfNode::get_named(self.nodes(), name)
354 }
355
356 pub fn take_buffer_data(&mut self, buffer: BufferIndex) -> GltfBuffer {
358 self.buffers[buffer.as_usize()].take_buffer()
359 }
360
361 pub fn buffer_views(&self) -> &[GltfBufferView] {
363 &self.buffer_views
364 }
365
366 pub fn nodes(&self) -> &[GltfNode] {
368 &self.nodes
369 }
370
371 pub fn meshes(&self) -> &[GltfMesh] {
373 &self.meshes
374 }
375
376 pub fn nh_index(&self, node: NodeIndex) -> NHIndex {
378 self.nh_index[node.as_usize()]
379 }
380
381 #[cfg(feature = "serde_json")]
385 pub fn of_json_value(json_value: JsonValue) -> Result<Self> {
386 let mut s: Self = serde_json::from_value(json_value)?;
387 s.validate()?;
388 s.gen_node_hierarchy();
389 s.derive();
390 Ok(s)
391 }
392
393 pub fn gen_node_hierarchy(&mut self) {
396 if !self.node_hierarchy.is_empty() {
397 return;
398 }
399 let n = self.nodes.len();
400 self.nh_index = vec![0.into(); n];
401 for i in 0..n {
402 let ni: NodeIndex = i.into();
403 self.nh_index[i] = self.node_hierarchy.add_node(ni).into();
404 }
405 for (i, n) in self.nodes.iter().enumerate() {
406 for c in n.iter_children() {
407 self.node_hierarchy.relate(i, c.as_usize());
408 }
409 }
410 self.node_hierarchy.find_roots();
411 }
412
413 pub fn derive(&mut self) {
416 for r in self.node_hierarchy.borrow_roots() {
417 let mut stack = vec![Transformation::default()];
418 for x in self.node_hierarchy.enum_from(*r) {
419 let (is_push, n, has_children) = x.unpack();
420 if is_push {
421 let t = self.nodes[*n].derive(stack.last().unwrap());
422 if has_children {
423 stack.push(*t);
424 }
425 } else if has_children {
426 stack.pop();
427 }
428 }
429 }
430 }
431}