tiny_game_framework/graphics/
model.rs

1use std::path::Path;
2
3use glam::{vec2, vec3, vec4, Vec3, Vec4};
4use tobj::LoadOptions;
5
6use crate::{EventLoop, Mesh, Renderer, Texture, Vertex};
7
8#[derive(Default)]
9pub struct Model {
10    pub meshes: Vec<Mesh>,
11    pub loaded_textures: Vec<Texture>,
12}
13
14impl Model {
15    pub fn new(path: &str) -> Self {
16        let mut model = Model::default();
17        model.load(path);
18
19        model
20    }
21
22    pub fn extract_mesh(&mut self, path: &str, u: usize) -> Mesh {
23        let path = Path::new(path);
24        
25        let obj = tobj::load_obj(path, &LoadOptions::default()).expect("Failed to load OBJ file");
26        let (models, _) = obj;
27
28        for model in models {
29            let mesh = &model.mesh;
30            let num_vertices = mesh.positions.len() / 3;
31            let indices: Vec<u32> = mesh.indices.clone();
32
33            let mut vertices = Vec::with_capacity(num_vertices);
34
35            let (p, n, t, c) = (&mesh.positions, &mesh.normals, &mesh.texcoords, &mesh.vertex_color);
36
37            for i in 0..num_vertices {
38                let pos = vec3(p[i*3], p[i*3+1], p[i*3+2]);
39                let tex_coords = vec2(t[i*2], t[i*2+1]);
40                let normal = if n.len() >= (i + 1) * 3 {
41                    vec3(n[i * 3], n[i * 3 + 1], n[i * 3 + 2])
42                } else {
43                    Vec3::ZERO
44                };
45                let color = if c.len() >= (i + 1) * 3 {
46                    vec4(c[i * 3], c[i * 3 + 1], c[i * 3 + 2], 1.0)
47                } else {
48                    Vec4::ONE
49                };
50                vertices.push(
51                    Vertex::new(pos, color, tex_coords, normal)
52                );
53            }
54
55            
56            self.meshes.push(Mesh::new(&vertices, &indices));
57        }
58
59        self.meshes[u].clone()
60    }
61
62    pub fn load(&mut self, path: &str) {
63        let path = Path::new(path);
64
65        let obj = tobj::load_obj(path, &LoadOptions::default()).expect("Failed to load OBJ file");
66        let (models, _) = obj;
67
68        for model in models {
69            let mesh = &model.mesh;
70            let num_vertices = mesh.positions.len() / 3;
71            let indices: Vec<u32> = mesh.indices.clone();
72
73            let mut vertices = Vec::with_capacity(num_vertices);
74
75            let (p, n, t, c) = (&mesh.positions, &mesh.normals, &mesh.texcoords, &mesh.vertex_color);
76
77            for i in 0..num_vertices {
78                let pos = vec3(p[i*3], p[i*3+1], p[i*3+2]);
79                let tex_coords = vec2(t[i*2], t[i*2+1]);
80                let normal = if n.len() >= (i + 1) * 3 {
81                    vec3(n[i * 3], n[i * 3 + 1], n[i * 3 + 2])
82                } else {
83                    Vec3::ZERO
84                };
85                let color = if c.len() >= (i + 1) * 3 {
86                    vec4(c[i * 3], c[i * 3 + 1], c[i * 3 + 2], 1.0)
87                } else {
88                    Vec4::ONE
89                };
90                vertices.push(
91                    Vertex::new(pos, color, tex_coords, normal)
92                );
93            }
94
95            let mut final_mesh = Mesh::new(&vertices, &indices);
96
97            for face in &mut final_mesh.indices.chunks_mut(6) {
98                face.reverse();
99            }
100
101            final_mesh.setup_mesh();
102
103            self.meshes.push(final_mesh);
104        }
105    }
106
107    pub fn load_texture(&mut self, path: &str) -> Texture {
108        let texture = Texture::Path(path.to_owned());
109        self.loaded_textures.push(texture.clone());
110        texture
111    }
112
113    pub unsafe fn draw(&self) {
114        for mesh in &self.meshes {
115            mesh.draw();
116        }
117    } 
118}
119
120
121impl Renderer {
122    pub fn add_model(&mut self, name: &str, model: Model) {
123        self.models.insert(name.to_string(), model);
124    }
125
126    pub fn get_model(&self, name: &str) -> Option<&Model> {
127        self.models.get(name)
128    }
129
130    pub fn get_model_mut(&mut self, name: &str) -> Option<&mut Model> {
131        self.models.get_mut(name)
132    }
133}