tiny_game_framework/graphics/
model.rs1use 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}