1use mod3d_base::hierarchy::NodeEnumOp;
3use mod3d_base::{
4 BufferData, BufferDataAccessor, BufferDescriptor, BufferIndexAccessor, ByteBuffer, Renderable,
5 VertexDesc,
6};
7
8use crate::try_buf_parse_base64;
9use crate::Gltf;
10use crate::{
11 AccessorIndex, BufferIndex, BufferUsage, ImageIndex, MaterialIndex, MeshIndex, NodeIndex,
12 PrimitiveIndex, SamplerIndex, TextureIndex, ViewIndex,
13};
14use crate::{Error, Result};
15use crate::{
16 Indexable, ODAccIndex, ODBufDescIndex, ODImagesIndex, ODMaterialsIndex, ODTexturesIndex,
17 ODUses, ODVerticesIndex,
18};
19
20#[derive(Debug)]
46pub struct ObjectData {
47 nodes_used: Vec<NodeIndex>,
50 #[allow(dead_code)]
58 joints_used: Vec<NodeIndex>,
59 materials_used: ODUses<MaterialIndex, ODMaterialsIndex>,
60
61 images_used: ODUses<ImageIndex, ODImagesIndex>,
64
65 samplers_used: ODUses<SamplerIndex, ()>,
70
71 textures_used: ODUses<TextureIndex, ODTexturesIndex>,
74
75 buffer_usage: Vec<BufferUsage>,
79
80 buffer_descriptors: Vec<Option<ODBufDescIndex>>,
83
84 accessors_as_bd: Vec<Option<(ODBufDescIndex, u8)>>,
89
90 accessors: Vec<Option<ODAccIndex>>,
95
96 meshes: Vec<Option<Vec<Option<ODVerticesIndex>>>>,
103}
104
105impl std::ops::Index<BufferIndex> for ObjectData {
107 type Output = BufferUsage;
108 fn index(&self, index: BufferIndex) -> &Self::Output {
109 &self.buffer_usage[index.as_usize()]
110 }
111}
112
113impl std::ops::IndexMut<BufferIndex> for ObjectData {
115 fn index_mut(&mut self, index: BufferIndex) -> &mut Self::Output {
116 &mut self.buffer_usage[index.as_usize()]
117 }
118}
119
120impl std::ops::Index<ViewIndex> for ObjectData {
122 type Output = Option<ODBufDescIndex>;
123 fn index(&self, index: ViewIndex) -> &Self::Output {
124 &self.buffer_descriptors[index.as_usize()]
125 }
126}
127
128impl std::ops::IndexMut<ViewIndex> for ObjectData {
130 fn index_mut(&mut self, index: ViewIndex) -> &mut Self::Output {
131 &mut self.buffer_descriptors[index.as_usize()]
132 }
133}
134
135impl std::ops::Index<AccessorIndex> for ObjectData {
137 type Output = Option<ODAccIndex>;
138 fn index(&self, index: AccessorIndex) -> &Self::Output {
139 &self.accessors[index.as_usize()]
140 }
141}
142
143impl std::ops::IndexMut<AccessorIndex> for ObjectData {
145 fn index_mut(&mut self, index: AccessorIndex) -> &mut Self::Output {
146 &mut self.accessors[index.as_usize()]
147 }
148}
149
150impl std::ops::Index<MeshIndex> for ObjectData {
152 type Output = Option<Vec<Option<ODVerticesIndex>>>;
153 fn index(&self, index: MeshIndex) -> &Self::Output {
154 &self.meshes[index.as_usize()]
155 }
156}
157
158impl std::ops::IndexMut<MeshIndex> for ObjectData {
160 fn index_mut(&mut self, index: MeshIndex) -> &mut Self::Output {
161 &mut self.meshes[index.as_usize()]
162 }
163}
164
165impl ObjectData {
167 pub fn new(gltf: &Gltf) -> Self {
170 let num_buffers = gltf.buffers().len();
171 let num_views = gltf.buffer_views().len();
172 let num_meshes = gltf.meshes().len();
173 let num_accessors = gltf.accessors().len();
174
175 let nodes_used = vec![];
176 let joints_used = vec![];
177 let materials_used = ODUses::new();
178 let textures_used = ODUses::new();
179 let images_used = ODUses::new();
180 let samplers_used = ODUses::new();
181 let buffer_usage = vec![Default::default(); num_buffers];
182 let buffer_descriptors = vec![Default::default(); num_views];
183 let meshes = vec![Default::default(); num_meshes];
184 let accessors_as_bd = vec![Default::default(); num_accessors];
185 let accessors = vec![Default::default(); num_accessors];
186 Self {
187 nodes_used,
188 joints_used,
189 materials_used,
190 textures_used,
191 buffer_usage,
192 buffer_descriptors,
193 meshes,
194 accessors_as_bd,
195 accessors,
196 images_used,
197 samplers_used,
198 }
199 }
200
201 fn first_buffer(&mut self) -> Option<&mut BufferUsage> {
203 self.buffer_usage.get_mut(0)
204 }
205
206 #[allow(dead_code)]
209 fn add_joint_node(&mut self, node: NodeIndex) {
210 if !self.joints_used.contains(&node) {
211 self.joints_used.push(node);
212 }
213 }
214
215 fn add_node(&mut self, node: NodeIndex) {
218 if !self.nodes_used.contains(&node) {
219 self.nodes_used.push(node);
220 }
221 }
222
223 pub fn add_object(&mut self, gltf: &Gltf, node: NodeIndex) {
227 let nh_index = gltf.nh_index(node);
228 for eo in gltf.node_hierarchy().iter_from(nh_index.as_usize()) {
229 if let NodeEnumOp::Push((_, n), _) = eo {
230 self.add_node(*n);
231 }
232 }
233 }
234
235 fn use_buffer(
242 &mut self,
243 as_index: bool,
244 buffer: BufferIndex,
245 byte_start: usize,
246 byte_length: usize,
247 ) {
248 self[buffer].use_buffer(as_index, byte_start, byte_length);
249 }
250
251 fn derive_uses_of_meshes(&mut self, gltf: &Gltf) {
254 for n in 0..self.nodes_used.len() {
255 let ni: NodeIndex = n.into();
256 let node = &gltf[ni];
257 if let Some(node_mesh) = node.mesh() {
258 let mesh = &mut self[node_mesh];
259 if mesh.is_none() {
260 let num_primitives = gltf[node_mesh].primitives().len();
261 *mesh = Some(vec![None; num_primitives]);
262 }
263 }
264 }
265 }
266
267 fn derive_uses_of_materials(&mut self, gltf: &Gltf) -> Vec<(bool, AccessorIndex)> {
270 let mut accessors = vec![];
271 for m in 0..self.meshes.len() {
272 let mi: MeshIndex = m.into();
273 if self[mi].is_some() {
274 let mesh = &gltf[mi];
275 for p in mesh.primitives() {
276 if let Some(a) = p.indices() {
277 accessors.push((true, a));
278 }
279 for (_, a) in p.attributes() {
280 accessors.push((false, *a));
281 }
282 if let Some(m) = p.material() {
283 self.materials_used.set_required(m);
284 }
285 }
286 }
287 }
288 accessors
289 }
290
291 fn derive_uses_of_accessors(&mut self, gltf: &Gltf, accessors: Vec<(bool, AccessorIndex)>) {
294 for (as_index, a) in accessors {
295 if let Some(bv) = gltf[a].buffer_view() {
296 let buffer = gltf[bv].buffer();
297 let byte_start = gltf[bv].byte_offset();
298 let byte_length = gltf[bv].byte_length();
299 self.use_buffer(as_index, buffer, byte_start, byte_length);
300 }
301 }
302 }
303
304 fn derive_uses_of_textures(&mut self, gltf: &Gltf) {
307 for (mi, _use) in self.materials_used.iter_required() {
308 let material = &gltf[mi];
309 if let Some(ti) = material.normal_texture() {
310 self.textures_used.set_required(ti.index());
311 }
312 if let Some(ti) = material.occlusion_texture() {
313 self.textures_used.set_required(ti.index());
314 }
315 if let Some(ti) = material.emissive_texture() {
316 self.textures_used.set_required(ti.index());
317 }
318 if let Some(pbr) = material.pbr_metallic_roughness() {
319 if let Some(ti) = pbr.base_color_texture() {
320 self.textures_used.set_required(ti.index());
321 }
322 if let Some(ti) = pbr.metallic_roughness_texture() {
323 self.textures_used.set_required(ti.index());
324 }
325 }
326 }
327 }
328
329 fn derive_uses_of_images_and_samplers(&mut self, gltf: &Gltf) {
332 for (ti, _use) in self.textures_used.iter_required() {
333 let texture = &gltf[ti];
334 self.images_used.set_required(texture.image());
335 self.samplers_used.set_required(texture.sampler());
336 }
337 }
338
339 pub fn derive_uses(&mut self, gltf: &Gltf) {
343 self.derive_uses_of_meshes(gltf);
344 let accessors = self.derive_uses_of_materials(gltf);
345 self.derive_uses_of_accessors(gltf, accessors);
346 self.derive_uses_of_textures(gltf);
347 self.derive_uses_of_images_and_samplers(gltf);
348 eprintln!("gltf : object_data : does not yet derive buffer uses of images - it won't gen_buffers for them");
349 self.images_used.complete_uses();
351 }
352
353 pub fn uses_buffer_zero(&self) -> bool {
358 if let Some(b) = self.buffer_usage.first() {
359 b.is_used()
360 } else {
361 false
362 }
363 }
364
365 pub fn gen_buffers<B, BP>(
376 &mut self,
377 gltf: &mut Gltf,
378 buf_parse: &BP,
379 opt_buffer_0: Option<B>,
380 ) -> Result<Vec<B>>
381 where
382 BP: Fn(&str, usize) -> Result<B>,
383 {
384 let mut result = vec![];
385 let mut used_opt_0 = false;
386 if let Some(b) = self.first_buffer() {
387 if b.is_used() && opt_buffer_0.is_some() {
388 result.push(opt_buffer_0.unwrap());
389 used_opt_0 = true;
390 b.set_buffer_index(0.into());
391 }
392 }
393 for i in 0..self.buffer_usage.len() {
394 let bi: BufferIndex = i.into();
395 let buffer = gltf.take_buffer_data(bi);
396 if !self[bi].is_used() {
397 continue;
398 }
399 if i > 0 || !used_opt_0 {
400 self[bi].set_buffer_index(result.len().into());
401 result.push(buf_parse(buffer.uri(), buffer.byte_length())?);
402 }
403 }
404 Ok(result)
405 }
406
407 pub fn gen_byte_buffers<BP>(
415 &mut self,
416 gltf: &mut Gltf,
417 buf_parse: &BP,
418 opt_buffer_0: Option<Vec<u8>>,
419 ) -> Result<Vec<Vec<u8>>>
420 where
421 BP: Fn(&str, usize) -> Result<Vec<u8>>,
422 {
423 let bp = |uri: &str, byte_length: usize| {
424 if let Some(buf) = try_buf_parse_base64(uri, byte_length)? {
425 Ok(buf)
426 } else {
427 buf_parse(uri, byte_length)
428 }
429 };
430 self.gen_buffers(gltf, &bp, opt_buffer_0)
431 }
432
433 pub fn gen_buffer_data<'buffers, B, F, R>(&mut self, buffer: &F) -> Vec<BufferData<'buffers, R>>
440 where
441 B: ByteBuffer + ?Sized + 'buffers,
442 F: Fn(usize) -> &'buffers B,
443 R: Renderable,
444 {
445 let mut buffer_data = vec![];
446 for i in 0..self.buffer_usage.len() {
447 let bi: BufferIndex = i.into();
448 if !self[bi].is_used() {
449 continue;
450 }
451 let b = buffer(self[bi].buffer_index().as_usize());
452 if self[bi].has_index_data() {
453 self[bi].set_buffer_data(true, buffer_data.len().into());
454 let byte_offset = self[bi].index_data().start;
455 let byte_length = self[bi].index_data().end - byte_offset;
456 let bd = mod3d_base::BufferData::new(b, byte_offset as u32, byte_length as u32);
457 buffer_data.push(bd);
458 }
459 if self[bi].has_vertex_data() {
460 self[bi].set_buffer_data(false, buffer_data.len().into());
461 let byte_offset = self[bi].vertex_data().start;
462 let byte_length = self[bi].vertex_data().end - byte_offset;
463 let bd = mod3d_base::BufferData::new(b, byte_offset as u32, byte_length as u32);
464 buffer_data.push(bd);
465 }
466 }
467 buffer_data
468 }
469
470 pub fn gen_images<Image, F>(&mut self, gltf: &Gltf, get_image: &F) -> Result<Vec<Image>>
473 where
474 F: for<'a> Fn((usize, usize, usize), &'a str) -> std::result::Result<Image, String>,
475 {
476 let mut result = vec![];
477 for (ii, image_use) in self.images_used.iter_mut_required() {
478 let image = &gltf[ii];
479 let od_image = {
480 if let Some(uri) = image.uri() {
481 get_image((0, 0, 0), uri)
482 } else {
483 let bv = &gltf[image.buffer_view()];
484 let buffer = self.buffer_usage[bv.buffer().as_usize()].buffer_index();
488 let byte_offset = bv.byte_offset();
489 let byte_length = bv.byte_length();
490 get_image(
491 (buffer.as_usize(), byte_offset, byte_length),
492 image.mime_type(),
493 )
494 }
495 }
496 .map_err(|e| Error::ImageLoad { reason: e })?;
497 let n = result.len();
498 result.push(od_image);
499 image_use.set_use(n.into());
500 }
501 Ok(result)
502 }
503
504 fn make_index_accessor<'buffers, F, R>(
506 &self,
507 gltf: &Gltf,
508 buffer_data: &F,
509 acc: AccessorIndex,
510 ) -> BufferIndexAccessor<'buffers, R>
511 where
512 F: Fn(usize) -> &'buffers BufferData<'buffers, R>,
513 R: Renderable,
514 {
515 let ba = &gltf[acc];
516 let bv = ba.buffer_view().unwrap();
517 let bv = &gltf[bv];
518 let buffer = &self[bv.buffer()];
519 let data = buffer.index_bd();
520 let data = buffer_data(data.as_usize());
521 let byte_offset = ba.byte_offset() + bv.byte_offset() - (data.byte_offset() as usize);
522 let count = ba.count();
523 eprintln!("make_index_accessor ba:? {data:?}, {count}, {byte_offset}");
524 BufferIndexAccessor::new(data, count as u32, ba.component_type(), byte_offset as u32)
525 }
526
527 fn make_descriptor<'buffers, F, R>(
529 &self,
530 gltf: &Gltf,
531 buffer_data: &F,
532 view: ViewIndex,
533 ) -> BufferDescriptor<'buffers, R>
534 where
535 F: Fn(usize) -> &'buffers BufferData<'buffers, R>,
536 R: Renderable,
537 {
538 let bv = &gltf[view];
539 let buffer = &self[bv.buffer()];
540 let data = buffer.vertex_bd();
541 let data = buffer_data(data.as_usize());
542
543 let byte_offset = bv.byte_offset() - (data.byte_offset() as usize);
544 let byte_stride = bv.byte_stride(0);
545 let byte_length = bv.byte_length();
546 eprintln!("make_descriptor {view:?} {data:?}, {byte_offset}+{byte_length}, {byte_stride}");
547 BufferDescriptor::new(
548 data,
549 byte_offset as u32,
550 byte_length as u32,
551 byte_stride as u32,
552 vec![],
553 )
554 }
555
556 pub fn gen_descriptors<'buffers, F, R>(
567 &mut self,
568 gltf: &Gltf,
569 buffer_data: &F,
570 ) -> Vec<BufferDescriptor<'buffers, R>>
571 where
572 F: Fn(usize) -> &'buffers BufferData<'buffers, R>,
573 R: Renderable,
574 {
575 let mut buffer_descriptors = vec![];
576
577 for i in 0..self.meshes.len() {
578 let mi: MeshIndex = i.into();
579 if self[mi].is_none() {
580 continue;
581 }
582 let mesh = &gltf[mi];
583 for p in mesh.primitives() {
584 for (vertex_attr, va) in p.attributes() {
585 if self[*va].is_some() {
586 continue;
587 }
588 let ba = &gltf[*va];
589 let bv = ba.buffer_view().unwrap();
590 if self[bv].is_none() {
591 let bd = self.make_descriptor(gltf, buffer_data, bv);
592 self.buffer_descriptors[*bv] = Some(buffer_descriptors.len().into());
593 buffer_descriptors.push(bd);
594 }
595 let n = self[bv].unwrap();
596 let dims = {
597 match ba.elements_per_data() {
598 1 => [0, 0],
599 9 => [3, 3],
600 16 => [4, 4],
601 n => [n as u8, 0],
602 }
603 };
604 let vertex_desc = VertexDesc::new(
605 *vertex_attr,
606 ba.component_type(),
607 dims,
608 ba.byte_offset() as u16,
609 );
610 eprintln!(
611 "add_data_accessor {} {vertex_desc:?}",
612 buffer_descriptors[n.as_usize()]
613 );
614 let v = buffer_descriptors[n.as_usize()].add_vertex_desc(vertex_desc);
615 self.accessors_as_bd[(*va).as_usize()] = Some((n, v))
616 }
617 }
618 }
619 buffer_descriptors
620 }
621
622 pub fn gen_accessors<'buffers, F, G, R>(
629 &mut self,
630 gltf: &Gltf,
631 buffer_data: &F,
632 buffer_desc: &G,
633 ) -> (
634 Vec<BufferIndexAccessor<'buffers, R>>,
635 Vec<BufferDataAccessor<'buffers, R>>,
636 )
637 where
638 F: Fn(usize) -> &'buffers BufferData<'buffers, R>,
639 G: Fn(usize) -> &'buffers BufferDescriptor<'buffers, R>,
640 R: Renderable,
641 {
642 let mut buffer_index_accessors = vec![];
643 let mut buffer_data_accessors = vec![];
644 for i in 0..self.meshes.len() {
645 let mi: MeshIndex = i.into();
646 if self[mi].is_none() {
647 continue;
648 }
649 let mesh = &gltf[mi];
650 for p in mesh.primitives() {
651 if let Some(ia) = p.indices() {
652 if self[ia].is_some() {
653 continue;
654 }
655 let b = self.make_index_accessor(gltf, buffer_data, ia);
656 self[ia] = Some(buffer_index_accessors.len().into());
657 buffer_index_accessors.push(b);
658 }
659 }
660 for (i, opt_n_v) in self.accessors_as_bd.iter().enumerate() {
661 let Some((n, v)) = opt_n_v else {
662 continue;
663 };
664 let acc = BufferDataAccessor::new(buffer_desc(n.as_usize()), *v);
665 let n = buffer_data_accessors.len();
666 self.accessors[i] = Some(n.into());
667 buffer_data_accessors.push(acc);
668 }
669 }
670 (buffer_index_accessors, buffer_data_accessors)
671 }
672
673 pub fn gen_vertices<'vertices, F, G, R>(
677 &mut self,
678 gltf: &Gltf,
679 buffer_index_accessor: &F,
680 buffer_data_accessor: &G,
681 ) -> Vec<mod3d_base::Vertices<'vertices, R>>
682 where
683 F: Fn(usize) -> &'vertices BufferIndexAccessor<'vertices, R>,
684 G: Fn(usize) -> &'vertices BufferDataAccessor<'vertices, R>,
685 R: Renderable,
686 {
687 let mut vertices = vec![];
688 for i in 0..self.meshes.len() {
689 let mi: MeshIndex = i.into();
690 if self[mi].is_none() {
691 continue;
692 }
693 let mesh = &gltf[mi];
694 for (pi, p) in mesh.primitives().iter().enumerate() {
695 let Some(ia) = p.indices() else {
696 continue;
697 };
698 let mut pa = None;
699 for (va, vpa) in p.attributes() {
700 if *va == mod3d_base::VertexAttr::Position {
701 pa = Some(vpa);
702 break;
703 }
704 }
705 let Some(pa) = pa else {
706 continue;
707 };
708 let Some(ia) = self[ia] else {
709 continue;
710 };
711 let Some(pa) = self[*pa] else {
712 continue;
713 };
714 let indices = buffer_index_accessor(ia.as_usize());
715 let positions = buffer_data_accessor(pa.as_usize());
716 let mut v = mod3d_base::Vertices::new(Some(indices), positions);
717 for (va, vpa) in p.attributes() {
718 if *va == mod3d_base::VertexAttr::Position {
719 continue;
720 }
721 if let Some(vpa) = self[*vpa] {
722 v.add_attr(buffer_data_accessor(vpa.as_usize()));
723 }
724 }
725 let primitve_v = vertices.len();
726 vertices.push(v);
727 self[mi].as_mut().unwrap()[pi] = Some(primitve_v.into());
728 }
729 }
730
731 vertices
732 }
733
734 pub fn gen_textures<'call, 'textures, F, I, R, T>(
738 &mut self,
739 gltf: &Gltf,
740 image: F,
741 texture_of_image: T,
742 ) -> Vec<mod3d_base::Texture<'textures, R>>
743 where
744 F: Fn(usize) -> &'call I,
745 I: 'call,
746 T: Fn(&'call I) -> mod3d_base::Texture<'textures, R>,
747 R: Renderable,
748 {
749 let mut textures = vec![];
750 for (ti, texture_use) in self.textures_used.iter_mut_required() {
751 let texture = &gltf[ti];
752 let image = image(self.images_used[texture.image].data().unwrap().as_usize());
753 let model_texture = texture_of_image(image);
754 let n = textures.len();
755 textures.push(model_texture);
756 texture_use.set_use(n.into());
757 }
758 textures
759 }
760
761 pub fn gen_materials(&mut self, gltf: &Gltf) -> Vec<mod3d_base::PbrMaterial> {
764 let mut materials = vec![];
765
766 for (mi, material_use) in self.materials_used.iter_mut_required() {
767 let material = &gltf[mi];
768 let mut pbr_mat = mod3d_base::PbrMaterial::of_rgba(0xff112233);
769 if let Some(ti) = material.normal_texture() {
770 if let Some(ti) = self.textures_used[ti.index()].data() {
771 pbr_mat.set_texture(mod3d_base::MaterialAspect::Normal, ti.into());
772 }
773 }
774 if let Some(ti) = material.occlusion_texture() {
775 if let Some(ti) = self.textures_used[ti.index()].data() {
776 pbr_mat.set_texture(mod3d_base::MaterialAspect::Occlusion, ti.into());
777 }
778 }
779 if let Some(ti) = material.emissive_texture() {
780 if let Some(ti) = self.textures_used[ti.index()].data() {
781 pbr_mat.set_texture(mod3d_base::MaterialAspect::Emission, ti.into());
782 }
783 }
784 pbr_mat.set_rgba((255, 255, 255, 255));
785 if let Some(pbr) = material.pbr_metallic_roughness() {
786 if let Some(ti) = pbr.base_color_texture() {
787 if let Some(ti) = self.textures_used[ti.index()].data() {
788 pbr_mat.set_texture(mod3d_base::MaterialAspect::Color, ti.into());
789 }
790 }
791 if let Some(ti) = pbr.metallic_roughness_texture() {
792 if let Some(ti) = self.textures_used[ti.index()].data() {
793 pbr_mat
794 .set_texture(mod3d_base::MaterialAspect::MetallicRoughness, ti.into());
795 }
796 }
797 if let Some(color) = pbr.base_color_factor.as_ref() {
798 if color.len() == 4 {
800 let r = (color[0] * 255.0) as u8;
801 let g = (color[1] * 255.0) as u8;
802 let b = (color[2] * 255.0) as u8;
803 let a = (color[3] * 255.0) as u8;
804 pbr_mat.set_rgba((r, g, b, a));
805 }
806 }
807 pbr_mat.set_mr(pbr.metallic_factor, pbr.roughness_factor);
808 }
809 {
810 let r = (material.emissive_factor[0] * 255.0) as u8;
811 let g = (material.emissive_factor[1] * 255.0) as u8;
812 let b = (material.emissive_factor[2] * 255.0) as u8;
813 pbr_mat.set_emissive_rgb((r, g, b));
814 }
815 let n = materials.len();
816 materials.push(pbr_mat);
817 material_use.set_use(n.into());
818 }
819
820 materials
821 }
822
823 pub fn gen_object<'object, M, R>(
826 &mut self,
827 gltf: &Gltf,
828 vertices: &'object [mod3d_base::Vertices<'object, R>],
829 textures: &'object [mod3d_base::Texture<'object, R>],
830 materials: &'object [M],
831 ) -> mod3d_base::Object<'object, M, R>
832 where
833 M: mod3d_base::Material + 'object,
834 R: Renderable,
835 {
836 let mut object = mod3d_base::Object::new();
837 for v in vertices {
838 object.add_vertices(v);
839 }
840 for t in textures {
841 object.add_texture(t);
842 }
843 for m in materials {
844 object.add_material(m);
845 }
846
847 for n in &self.nodes_used {
848 let node = &gltf[*n];
849 let Some(mi) = node.mesh() else {
850 continue;
851 };
852 let gltf_mesh = &gltf[mi];
853 let Some(od_mesh_prims) = &self[mi] else {
854 continue;
855 };
856 let mut mesh = mod3d_base::Mesh::default();
857 for (m_pi, opt_od_vi) in od_mesh_prims.iter().enumerate() {
858 let m_pi: PrimitiveIndex = m_pi.into();
859 let Some(od_vi) = *opt_od_vi else {
860 continue;
861 };
862 let gltf_prim = &gltf_mesh[m_pi];
863 let ia = gltf_prim.indices().unwrap();
864 let index_count = gltf[ia].count() as u32;
865 let mat_ind: Option<usize> = Some(0);
866 let primitive = mod3d_base::Primitive::new(
867 gltf_prim.primitive_type(),
868 od_vi.into(),
869 0,
870 index_count,
871 mat_ind.into(),
872 );
873 eprintln!("Add mesh {mesh:?} {m_pi} {primitive:?}");
874 mesh.add_primitive(primitive);
875 }
876 object.add_component(None, Some(*node.global_transformation()), mesh);
877 }
878 object
879 }
880}