feo_oop_engine/scene/game_object/
obj.rs

1//! A GameObject that can be built from an obj file.
2//! 
3//! TODO: explain OOP here
4//! 
5use {
6    super::{
7        GameObject,
8        camera::Camera,
9        light::Light,
10    },
11    crate::{
12        registration::{
13            relation::{ParentWrapper, Child, Parent},
14            named::Named,
15            id::{
16                ID
17            }
18        },
19        scripting::{
20            Script,
21            executor::Spawner,
22            Scriptable, 
23            globals::{
24                EngineGlobals, 
25                Global
26            }
27        },
28        graphics::{
29            Drawable,
30            draw_pass_manager::DrawPassManager,
31            lighting_pass_manager::LightingPassManager,
32        },
33        components::{
34            Vertex,
35            TextureIndex,
36            Normal
37        },
38        term_ui,
39        event::UserEvent,
40        components::{material::Material, triangle_mesh::TriangleMesh}
41    },
42    feo_math::{
43        utils::space::Space, 
44        rotation::quaternion::Quaternion,
45        linear_algebra::vector3::Vector3
46    },
47    std::{
48        any::Any, 
49        collections::HashMap, 
50        fs, 
51        io::stdout, 
52        mem, 
53        sync::{Arc, RwLock}
54    },
55    futures::executor::block_on,
56    vulkano::{
57        descriptor::{
58            descriptor_set::PersistentDescriptorSet,
59        },
60        sync::GpuFuture
61    },
62    winit::event::Event
63};
64
65#[derive(Scriptable, GameObject, Drawable, Child, Parent, Named)] // import
66pub struct Obj {
67    pub id: ID,
68    pub name: String,
69    pub parent: ParentWrapper,
70
71    pub visible: bool,
72
73    pub subspace: Space, // note is the subspace within the parent space
74
75    pub triangle_mesh: Vec<Arc<TriangleMesh>>,
76    // pub material: Option<Material>, // object does not have material triangle mesh does
77
78    pub script: Option<Box<Script<Self>>>,
79
80    pub children: Vec<Arc<RwLock<dyn GameObject>>>,
81}
82
83impl std::fmt::Debug for Obj {
84    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
85        f.debug_struct("Obj")
86            .field("id", &self.id)
87            .field("name", &self.name)
88            .field("parent", &self.parent)
89            .field("visible", &self.visible)
90            .field("subspace", &self.subspace)
91            .field("triangle_mesh", &self.triangle_mesh)
92            .field("script", &self.script)
93            .field("children", &self.children).finish()
94    }
95}
96
97impl Clone for Obj {
98    fn clone(&self) -> Self {
99        let id = self.id.get_system().take();
100        Obj{
101            id,
102            name: self.name.clone(),
103            parent: self.parent.clone(),
104            visible: self.visible,
105            subspace: self.subspace,
106            triangle_mesh: self.triangle_mesh.clone(),
107            script: self.script.clone(),
108            children: self.children.clone().into_iter().map(|_child| {
109                // Dangerous
110                todo!();
111            }).collect::<Vec<Arc<RwLock<dyn GameObject>>>>(),
112        }
113    }
114}
115
116impl PartialEq for Obj { // auto-generate this somehow
117    fn eq(&self, other: &Self) -> bool {
118        self.get_id() == other.get_id()
119    }
120}
121
122// TODO: rename to builders and build gameobjects with them
123impl Obj {
124    #[allow(clippy::too_many_arguments, clippy::or_fun_call)]
125    pub fn new_empty(
126            name: Option<&str>,
127
128            parent: Option<Arc<RwLock<dyn GameObject>>>, 
129
130            position: Option<Vector3<f32>>, 
131            rotation: Option<Quaternion<f32>>,
132            scale_factor: Option<Vector3<f32>>,
133
134            visible: bool,
135
136            engine_globals: EngineGlobals,
137
138            script: Option<Box<Script<Self>>>) -> Arc<RwLock<Self>> {
139        let id = engine_globals.id_system.take();
140
141        return Arc::new(RwLock::new( Obj {
142            name: name.unwrap_or((String::from("obj_") + id.to_string().as_str()).as_str()).to_owned(),
143            id,
144            parent: match parent {
145                Some(game_object) => {
146                    ParentWrapper::GameObject(game_object)
147                },
148                None => {
149                    ParentWrapper::Scene(engine_globals.scene)
150                }
151            },
152
153            visible,
154
155            subspace: Space::new(position, rotation, scale_factor),
156
157            triangle_mesh: Vec::new(),
158
159            script,
160
161            children: Vec::new()
162        }));
163    }
164
165    #[allow(clippy::too_many_arguments, clippy::or_fun_call)]
166    pub fn from_triangle_mesh_vec(
167            name: Option<&str>, 
168            triangle_mesh_vec: Vec<Arc<TriangleMesh>>,
169
170            parent: Option<Arc<RwLock<dyn GameObject>>>, 
171
172            position: Option<Vector3<f32>>, 
173            rotation: Option<Quaternion<f32>>,
174            scale_factor: Option<Vector3<f32>>,
175
176            visible: bool,
177
178            engine_globals: EngineGlobals,
179
180            script: Option<Box<Script<Self>>>) -> Arc<RwLock<Self>> {
181        let id = engine_globals.id_system.take();
182        return Arc::new(RwLock::new( Obj{
183            name: name.unwrap_or((String::from("obj_") + id.to_string().as_str()).as_str()).to_owned(),
184            id,
185            parent: match parent {
186                Some(game_object) => {
187                    ParentWrapper::GameObject(game_object)
188                },
189                None => {
190                    ParentWrapper::Scene(engine_globals.scene)
191                }
192            },
193
194            visible,
195
196            subspace: Space::new(position, rotation, scale_factor),
197
198            triangle_mesh: triangle_mesh_vec,
199
200            script,
201
202            children: Vec::new(),
203        }));
204    }
205    
206    #[allow(clippy::too_many_arguments)]
207    pub fn from_obj<'a>( // TODO: cut file into groups pass groups into triangle mesh for parsing
208            name: Option<&str>, 
209            path: &str, 
210
211            parent: Option<Arc<RwLock<dyn GameObject>>>, 
212
213            position: Option<Vector3<f32>>, 
214            rotation: Option<Quaternion<f32>>,
215            scale_factor: Option<Vector3<f32>>,
216            
217            visible: bool,
218
219            engine_globals: EngineGlobals,
220
221            script: Option<Box<Script<Self>>>) -> Result<Arc<RwLock<Self>>, &'a str>{
222        
223        //   Data Pools   //
224
225        let mut vertex_positions= Vec::new();
226        let mut texture_indices = Vec::new();
227        let mut normals = Vec::new();
228        
229        let mut mtls_hashmap: HashMap<String, (Arc<Material>, Box<dyn GpuFuture>)> = HashMap::new();
230
231        //   Read In String Data   //
232        
233        let content = fs::read_to_string(path)
234            .unwrap_or_else(|_| panic!("Something went wrong when trying to read {}.", path));
235        let mut last_block = Box::new(Vec::new());
236        let lines: Vec<(&str, Vec<&str>)> = content.lines().filter_map(|line| {
237            if !line.is_empty() {
238                let mut e = line.split_whitespace();
239                let ty: &str = e.next().unwrap();
240                match &*ty {
241
242                    "" | "#" | "s" | "l" => None,
243
244                    //   Vertex Data   //
245
246                    "v" => {
247                        vertex_positions.push(Box::new(Vertex::new(
248                            e.next().unwrap().parse::<f32>().unwrap(),
249                            e.next().unwrap().parse::<f32>().unwrap(),
250                            e.next().unwrap().parse::<f32>().unwrap()
251                        )));
252
253                        None
254                    },
255                    "vt" => {
256                        texture_indices.push(Box::new(TextureIndex::new(
257                            e.next().unwrap().parse::<f32>().unwrap(),
258                            e.next().unwrap().parse::<f32>().unwrap()
259                        )));
260
261                        None
262                    },
263                    "vn" => {
264                        normals.push(Box::new(Normal::new(
265                            e.next().unwrap().parse::<f32>().unwrap(),
266                            e.next().unwrap().parse::<f32>().unwrap(),
267                            e.next().unwrap().parse::<f32>().unwrap()
268                        )));
269                        
270                        None
271                    },
272
273                    //   Materials   //
274
275                    "mtllib" => {
276                        let files = e.fold(String::new(), |mut a, b| {
277                            a.reserve(b.len() + 1);
278                            a.push_str(b);
279                            a.push(' ');
280                            a
281                        });
282
283                        let files = files.trim_end_matches(".mtl ");
284
285                        files.split(".mtl ").for_each(|file| {
286                            let file = "/".to_owned() + file + ".mtl";
287                            let path = path.rsplitn(2, '/').nth(1).unwrap();
288                            let path = path.to_owned() + file.as_str();
289
290                            mtls_hashmap.extend(Material::from_mtllib(&path, engine_globals.clone().queue));
291                        });
292
293                        None
294                    },
295
296                    
297                    //   Faces and Materials   //
298
299                    "f" | "usemtl" => {
300                        last_block.push(line);
301                        None
302                    },
303                    
304                    //   Groupings   //
305
306                    "g" | "o" => {
307                        let tmp_block = *last_block.clone();
308                        last_block = Box::new(Vec::new());
309                        Some((line, tmp_block))
310                    },
311
312                    //   Other   //
313
314                    a => {println!("\n\nA: {} \n", a); None}
315                }
316            } else {
317                None
318            }
319        }).collect();
320        
321        //   Create A New Container For The Model   //
322
323        let name = name.unwrap_or_else(|| path.split('/').last().unwrap()).to_string();
324        let this = Obj::new_empty(
325            Some(name.as_str()), 
326            parent, 
327            position, 
328            rotation, 
329            scale_factor, 
330            visible, 
331            engine_globals.clone(), 
332            script
333        );
334
335        //   Group Data   //
336
337        // The current group/container being written to
338        let mut current_group: Option<Arc<RwLock<dyn GameObject>>> = None;
339
340        //   Loading Bar   //
341
342        // standard output handle
343        let mut stdout = stdout();
344
345        // name of file and current group to be displayed
346        let file_name = path.split('/').last().unwrap();
347        let current_group_name: Option<&str> = None;
348
349        // line number and total number of lines
350        let mut line_n: usize = 0;
351        let file_size = lines.len();
352
353        // how often to update the loading bar
354        let update = file_size / 100; // or just use 500 very small impact
355
356        lines.into_iter().for_each(|line| {
357
358            //   Loading Bar   //
359            
360            line_n += 1;
361            
362            // Get the terminal width
363            let terminal_width = terminal_size::terminal_size().unwrap().0.0 as usize;
364
365            // Don't always draw. unless on the final stretch
366            let draw = update == 0 || line_n % update == 4; // || line_n >= file_size - update;
367
368            // store the current_group name so it is 'static
369            let future_s_current_group_name = &*current_group_name.unwrap_or("");
370
371            // create the loading bar future
372            let future = async {
373                if draw {
374                    term_ui::progress_bar(&mut stdout, file_name, future_s_current_group_name, line_n, file_size, terminal_width).await
375                }
376            };
377            
378            let mut e = line.0.split_whitespace();
379            #[allow(clippy::or_fun_call)]
380            let ty: &str = e.next().ok_or(format!("error on line {} of {}", line_n, path).as_str()).unwrap();
381
382
383            // replaces flush
384            if let Some(group) = current_group.clone() {
385                let mut group_write_lock = group.write().unwrap();
386                // create the triangle mesh and add it to the current group
387                let triangle_mesh = TriangleMesh::from_obj_block(&line.1, &mut mtls_hashmap, (&vertex_positions, &texture_indices, &normals), engine_globals.queue.clone()).unwrap();
388                
389                group_write_lock.add_triangle_mesh( 
390                    Arc::new(triangle_mesh)
391                ).unwrap();
392            }
393
394            match &*ty {
395                "g" => {
396                    current_group = Some(this.clone() as Arc<RwLock<dyn GameObject>>);
397                    let mut groups = e.collect::<Vec<&str>>();
398                    while let Some(group_name) = groups.pop() {
399                        let group = current_group.clone().unwrap();
400                        let mut wlock_current_group = group.write().unwrap();
401                        if let Ok(group) = wlock_current_group.get_child_by_name(group_name) {
402                            drop(wlock_current_group);
403                            current_group = Some(group);
404                        } else {
405                            let new_group = Obj::new_empty(
406                                Some(group_name),
407                                current_group.clone(),
408                                None,
409                                None,
410                                None,
411                                true,
412                                engine_globals.clone(),
413                                None
414                            );
415                            wlock_current_group.add_child(new_group.clone());
416                            drop(wlock_current_group);
417                            current_group = Some(new_group);
418                        }
419                    }
420                },
421                "o" => {
422                    current_group = Some(this.clone() as Arc<RwLock<dyn GameObject>>);
423                    
424                    let object_name = e.next().expect("The o tag does not permit default/no names");
425                    let new_object = Obj::new_empty(
426                        Some(object_name),
427                        current_group.clone(),
428                        None,
429                        None,
430                        None,
431                        true,
432                        engine_globals.clone(),
433                        None
434                    );
435
436                    current_group.clone().unwrap().write().unwrap().add_child(new_object.clone());
437                    current_group = Some(new_object);
438                },
439
440                _ => unreachable!()
441            }
442
443            block_on(future);
444        });
445
446        let group = match current_group {
447            Some(group) => group.clone(),
448            None => this.clone()
449        };
450
451        let mut group_write_lock = group.write().unwrap();
452        // create the triangle mesh and add it to the current group
453        let triangle_mesh = TriangleMesh::from_obj_block(&last_block, &mut mtls_hashmap, (&vertex_positions, &texture_indices, &normals), engine_globals.queue.clone()).unwrap();
454        
455        group_write_lock.add_triangle_mesh( 
456            Arc::new(triangle_mesh)
457        ).unwrap();
458
459        Ok(this)
460    }
461    
462    // pub fn from_obj_old<'a>( // couple mistakes I caught are still in here
463    //         name: Option<&str>, 
464    //         path: &str, 
465
466    //         parent: Option<Arc<RwLock<dyn GameObject>>>, 
467
468    //         position: Option<Vector3<f32>>, 
469    //         rotation: Option<Quaternion<f32>>,
470    //         scale_factor: Option<Vector3<f32>>,
471            
472    //         visible: bool,
473
474    //         engine_globals: EngineGlobals,
475
476    //         script: Option<Box<Script<Self>>>) -> Result<Arc<RwLock<Self>>, &'a str>{
477        
478    //     //   Read In String Data   //
479        
480    //     let content = fs::read_to_string(path)
481    //         .expect(&format!("Something went wrong when trying to read {}.", path));
482    //     let lines = content.lines();
483
484    //     //   Create A New Container For The Model   //
485
486    //     let name = name.unwrap_or(path.split('/').last().unwrap()).to_string();
487    //     let this = Obj::new_empty(
488    //         Some(name.as_str()), 
489    //         parent, 
490    //         position, 
491    //         rotation, 
492    //         scale_factor, 
493    //         visible, 
494    //         engine_globals.clone(), 
495    //         script
496    //     );
497
498    //     //   Group Data   //
499
500    //     // The current group/container being written to
501    //     let mut current_group = None;
502
503    //     // Ordered mesh data
504    //     let mut ordered_vertices = Vec::new();
505    //     let mut ordered_normals = Vec::new();
506    //     let mut ordered_texture_indices = Vec::new();
507
508    //     let mut current_material: Option<Arc<Material>> = None;
509        
510    //     /// fn that flushes the ordered_vertices, ordered_normals, and ordered_texture_indices buffers 
511    //     /// and writes the data into the current group
512    //     /// Note it does not reset the current group
513    //     fn flush(
514    //             current_group: Option<Arc<RwLock<dyn GameObject>>>, 
515
516    //             ordered_vertices: &mut Vec<Vertex>, 
517    //             ordered_normals: &mut Vec<Normal>, 
518    //             ordered_texture_indices: &mut Vec<TextureIndex>, 
519
520    //             current_material: &mut Option<Arc<Material>>,
521                
522    //             engine_globals: EngineGlobals) {
523    //         if let Some(group) = current_group.clone() {
524    //             let group = group.clone();
525    //             let mut group_write_lock = group.write().unwrap();
526    //             // create the triangle mesh and add it to the current group
527    //             let triangle_mesh = TriangleMesh::new(
528    //                     ordered_vertices.clone(),
529    //                     ordered_normals.clone(), 
530    //                     ordered_texture_indices.clone(),
531    //                     current_material.clone().unwrap_or(Arc::new(Material::default())),
532    //                     engine_globals.queue
533    //                 );
534                
535    //             group_write_lock.add_triangle_mesh( 
536    //                 Arc::new(triangle_mesh)
537    //             ).unwrap();
538
539    //             // Reset the ordered vecs
540    //             *ordered_vertices = Vec::new();
541    //             *ordered_normals = Vec::new();
542    //             *ordered_texture_indices = Vec::new();
543
544    //             // reset the current material
545    //             *current_material = None;
546    //         }
547    //     }
548
549    //     //   Loading Bar   //
550
551    //     // standard output handle
552    //     let mut stdout = stdout();
553
554    //     // name of file and current group to be displayed
555    //     let file_name = path.split('/').last().unwrap();
556    //     let current_group_name: Option<&str> = None;
557
558    //     // line number and total number of lines
559    //     let mut line_n: usize = 0;
560    //     let file_size = lines.clone().count();
561
562    //     // how often to update the loading bar
563    //     let update = file_size / 100; // or just use 500 very small impact
564
565    //     //   Data Pools   //
566
567    //     let mut vertex_positions: Vec<Vertex> = Vec::new();
568    //     let mut texture_indices: Vec<TextureIndex> = Vec::new();
569    //     let mut normals: Vec<Normal> = Vec::new();
570        
571    //     let mut mtls_hashmap: HashMap<String, (Arc<Material>, Box<dyn GpuFuture>)> = HashMap::new();
572
573
574        
575    //     lines.for_each(|line| {
576
577    //         //   Loading Bar   //
578            
579    //         line_n += 1;
580            
581    //         // Get the terminal width
582    //         let terminal_width = terminal_size::terminal_size().unwrap().0.0 as usize;
583
584    //         // Don't always draw. unless on the final stretch
585    //         let draw = update == 0 || line_n % update == 4; // || line_n >= file_size - update;
586
587    //         // store the current_group name so it is 'static
588    //         let future_s_current_group_name = &*current_group_name.unwrap_or("");
589
590    //         // create the loading bar future
591    //         let future = async {
592    //             if draw {
593    //                 term_ui::progress_bar(&mut stdout, file_name, future_s_current_group_name, line_n, file_size, terminal_width).await
594    //             }
595    //         };
596            
597    //         if !line.is_empty() {
598    //             let mut e = line.split_whitespace();
599    //             let ty: &str = e.next().ok_or(format!("error on line {} of {}", line_n, path).as_str()).unwrap();
600    //             match &*ty {
601
602    //                 //   Groupings   //
603
604    //                 "g" => {
605    //                     flush(current_group.clone(), &mut ordered_vertices, &mut ordered_normals, &mut ordered_texture_indices, &mut current_material, engine_globals.clone());
606    //                     current_group = Some(this.clone() as Arc<RwLock<dyn GameObject>>);
607    //                     let mut groups = e.collect::<Vec<&str>>();
608    //                     while let Some(group_name) = groups.pop() {
609    //                         let group = current_group.clone().unwrap();
610    //                         let mut wlock_current_group = group.write().unwrap();
611    //                         if let Ok(group) = wlock_current_group.get_child_by_name(group_name) {
612    //                             drop(wlock_current_group);
613    //                             current_group = Some(group);
614    //                         } else {
615    //                             let new_group = Obj::new_empty(
616    //                                 Some(group_name),
617    //                                 current_group.clone(),
618    //                                 None,
619    //                                 None,
620    //                                 None,
621    //                                 true,
622    //                                 engine_globals.clone(),
623    //                                 None
624    //                             );
625    //                             wlock_current_group.add_child(new_group.clone());
626    //                             drop(wlock_current_group);
627    //                             current_group = Some(new_group);
628    //                         }
629    //                     }
630    //                 },
631    //                 "o" => {
632    //                     flush(current_group.clone(), &mut ordered_vertices, &mut ordered_normals, &mut ordered_texture_indices, &mut current_material, engine_globals.clone());
633    //                     current_group = Some(this.clone() as Arc<RwLock<dyn GameObject>>);
634                        
635    //                     let object_name = e.next().expect("The o tag does not permit default/no names");
636    //                     let new_object = Obj::new_empty(
637    //                         Some(object_name),
638    //                         current_group.clone(),
639    //                         None,
640    //                         None,
641    //                         None,
642    //                         true,
643    //                         engine_globals.clone(),
644    //                         None
645    //                     );
646
647    //                     current_group.clone().unwrap().write().unwrap().add_child(new_object.clone());
648    //                     current_group = Some(new_object);
649    //                 },
650
651    //                 //   Vertex Data   //
652
653    //                 "v" => {
654    //                     vertex_positions.push(Vertex::new(
655    //                         e.next().unwrap().parse::<f32>().unwrap(),
656    //                         e.next().unwrap().parse::<f32>().unwrap(),
657    //                         e.next().unwrap().parse::<f32>().unwrap()
658    //                     ));
659    //                 },
660    //                 "vt" => {
661    //                     texture_indices.push(TextureIndex::new(
662    //                         e.next().unwrap().parse::<f32>().unwrap(),
663    //                         e.next().unwrap().parse::<f32>().unwrap()
664    //                     ));
665    //                 },
666    //                 "vn" => {
667    //                     normals.push(Normal::new(
668    //                         e.next().unwrap().parse::<f32>().unwrap(),
669    //                         e.next().unwrap().parse::<f32>().unwrap(),
670    //                         e.next().unwrap().parse::<f32>().unwrap()
671    //                     ));
672    //                 },
673
674    //                 //   Faces   //
675
676    //                 "f" => {
677    //                     let mut tris = Vec::new();
678    //                     let mut i = 0;
679    //                     for coord in &mut e {
680    //                         i += 1;
681    //                         if i > 3{ // not perfect but good enough for now
682    //                             tris.push(tris[0]);
683    //                             tris.push(tris[i - 2]);
684    //                         }
685    //                         tris.push(coord);
686    //                     }
687
688    //                     let mut vertex_fmt: i8 = -1;
689    //                     let mut developing_normal: Vec<Vertex> = Vec::new();
690    //                     for raw in tris{
691    //                         let part = raw.split('/').collect::<Vec<&str>>();
692                            
693    //                         if vertex_fmt != part.len() as i8 {
694    //                             if vertex_fmt == -1 {
695    //                                 vertex_fmt = part.len() as i8;
696    //                             }else {
697    //                                 panic! ("Inconsistent face vertex format in {}.", path)
698    //                             }
699    //                         }
700                            
701    //                         let position = vertex_positions[part[0].parse::<usize>().unwrap() - 1_usize];
702
703    //                         let mut texture_index = TextureIndex::new(0.0, 0.0);
704
705    //                         if vertex_fmt > 1 && !part[1].is_empty() {
706    //                             texture_index = texture_indices[part[1].parse::<usize>().unwrap() - 1_usize];
707    //                         }
708    //                         // I could have sworn I have separated these multiple times now
709    //                         if developing_normal.is_empty() && vertex_fmt == 3 && !part[2].is_empty() { // a false second case is a result of improper formatting
710    //                             ordered_normals.push(normals[part[2].parse::<usize>().unwrap() - 1_usize]);
711    //                         } else {
712    //                             developing_normal.push(position);
713    //                         }
714
715    //                         ordered_vertices.push(position);
716    //                         ordered_texture_indices.push(texture_index);
717    //                     }
718
719    //                     if developing_normal.len() > 2 {
720    //                         let normal = Normal::calculate_normal(&developing_normal[0], &developing_normal[1], developing_normal.last().unwrap());
721
722    //                         for _ in 0..developing_normal.len() {
723    //                             ordered_normals.push(normal);
724    //                         }
725    //                     }
726    //                 },
727                    
728    //                 //   Materials   //
729
730    //                 "mtllib" => {
731    //                     let files = e.fold(String::new(), |mut a, b| {
732    //                         a.reserve(b.len() + 1);
733    //                         a.push_str(b);
734    //                         a.push(' ');
735    //                         a
736    //                     });
737
738    //                     let files = files.trim_end_matches(".mtl ");
739
740    //                     files.split(".mtl ").for_each(|file| {
741    //                         let file = "/".to_owned() + file + ".mtl";
742    //                         let path = path.rsplitn(2, '/').nth(1).unwrap();
743    //                         let path = path.to_owned() + file.as_str();
744
745    //                         mtls_hashmap.extend(Material::from_mtllib(&path, engine_globals.clone().queue));
746    //                     });
747    //                 },
748    //                 "usemtl" => {
749    //                     let key = e.next().expect(format!("formatting error in {}", path).as_str());
750    //                     let (cm, fut ) = mtls_hashmap.remove(key).unwrap();
751    //                     current_material = Some(cm.clone());
752    //                     if fut.queue().is_some() {
753    //                         let _ = Arc::new(fut.then_signal_fence_and_flush().unwrap()).wait(None); // for now state does not matter                            
754    //                     }
755    //                     mtls_hashmap.insert(key.to_string(), (cm, sync::now(engine_globals.queue.device().clone()).boxed()));
756                        
757    //                 },
758
759    //                 //   Other   //
760
761    //                 "#" => (),
762    //                 "" => (),
763    //                 &_ => {
764    //                     //panic!(format!("unsupported type on line {} of {}", line_n, path)); 
765    //                 }
766                    
767    //                 //   TODO: Other Geometry   //
768
769    //                 #[allow(unreachable_patterns)] // fr now just ignore it TODO: fix
770
771    //                 "line" => {
772    //                     /* remember that a normal of 0.0, 0.0, 0.0 is perfect because it is visible from any angle */
773    //                     todo!();
774    //                 },
775    //             };
776    //         }
777            
778    //         block_on(future);
779    //     });
780
781    //     flush(current_group, &mut ordered_vertices, &mut ordered_normals, &mut ordered_texture_indices, &mut current_material, engine_globals);
782
783    //     Ok(this)
784    // }
785}