tiny_game_framework/utils/
mesh_geometry.rs

1use glam::{vec2, vec3, Vec3, Vec4};
2
3use crate::graphics::{Mesh, Vertex};
4
5pub struct Quad{
6    pub size: Vec3,
7    pub color: Vec4,
8}
9
10impl Quad{
11    pub fn new(size: Vec3, color: Vec4) -> Self{
12        Self{
13            size,
14            color,
15        }
16    }
17
18    pub fn mesh(&self) -> Mesh {
19        let vertices = vec![
20            Vertex::new(vec3(0.0, 0.0, 0.0), self.color, vec2(0.0, 0.0), vec3(0., 0., 1.)),                    // Bottom-left
21            Vertex::new(vec3(0.0, self.size.y, 0.0), self.color, vec2(0.0, 1.0), vec3(0., 0., 1.)),             // Top-left
22            Vertex::new(vec3(self.size.x, 0.0, 0.0), self.color, vec2(1.0, 0.0), vec3(0., 0., 1.)),             // Bottom-right
23            Vertex::new(vec3(self.size.x, self.size.y, 0.0), self.color, vec2(1.0, 1.0), vec3(0., 0., 1.)),      // Top-right
24        ];
25
26
27        let indices = vec![0, 2, 1, 2, 3, 1];
28        
29        Mesh::new(&vertices, &indices)
30    }
31}
32
33pub struct Circle{
34    pub iterations: i32,
35    pub radius: f32,
36    pub color: Vec4,
37}
38
39impl Circle {
40    pub fn new(iterations: i32, radius: f32, color: Vec4) -> Self{
41        let mut fixed_iterations = iterations;
42        if iterations <= 3{
43            fixed_iterations = 4;
44        }
45
46        Self {
47            iterations: fixed_iterations,
48            radius,
49            color,
50        }
51    }
52
53    pub fn mesh(&self) -> Mesh {
54        let mut vertices = vec![];
55        
56        for i in 0..self.iterations {
57            let angle = 2.0 * std::f32::consts::PI * (i as f32 / self.iterations as f32);
58            let tex_coord = vec2(f32::cos(angle) * 0.5 + 0.5, f32::sin(angle) * 0.5 + 0.5); // Normalize to [0, 1] range
59        
60            vertices.push(Vertex::new(
61                vec3(f32::sin(angle), f32::cos(angle), 0.0) * self.radius,
62                self.color,
63                tex_coord,
64                vec3(0., 0., 1.),
65            ));
66        }
67        
68        let mut indices = vec![];
69        for i in 1..=self.iterations-2 {
70            indices.push(0); 
71            indices.push(i as u32); 
72            indices.push((i % self.iterations + 1) as u32);
73        }
74
75        Mesh::new(&vertices, &indices)
76    }
77}
78 
79pub struct Triangle{
80    pub size: f32,
81    pub color: Vec4,
82}
83
84impl Triangle{
85    pub fn new(size: f32, color: Vec4) -> Self{
86        Self {
87            size,
88            color,
89        }
90    }
91
92    pub fn mesh(&self) -> Mesh {
93        let mut vertices = vec![];
94        for i in 0..3 {
95            let angle = 2.0 * std::f32::consts::PI * (i as f32 / 3.0);
96            let tex_coord = match i {
97                0 => vec2(0.5, 1.0),   // Bottom vertex
98                1 => vec2(0.0, 0.0),   // Left vertex
99                2 => vec2(1.0, 0.0),   // Right vertex
100                _ => panic!("Unexpected index"),
101            };
102        
103            vertices.push(Vertex::new(
104                vec3(f32::sin(angle), f32::cos(angle), 0.0) * self.size,
105                self.color,
106                tex_coord,
107                vec3(0., 0., 1.),
108            ));
109        }
110
111        let mut indices = vec![];
112            indices.push(0); 
113            indices.push(1 as u32); 
114            indices.push(2 as u32);
115            // Shamelessly (ok theres a bit of shame) stole my own circle rendering code so I just set it to three vertices
116
117        Mesh::new(&vertices, &indices)
118    }
119}
120
121pub struct Cuboid{
122    pub size: Vec3,
123    pub color: Vec4,
124}
125
126impl Cuboid{
127    pub fn new(size: Vec3, color: Vec4) -> Self{
128        Self{
129            size,
130            color,
131        }
132    }
133
134    pub fn mesh(&self) -> Mesh {
135        let half_size = self.size/2.;
136        let x = half_size.x;
137        let y = half_size.y;
138        let z = half_size.z;
139
140        let vertices = vec![
141            // Front face
142            Vertex::new(vec3(-x, -y, z), self.color, vec2(0.0, 0.0), vec3(0.0, 0.0, 1.0)),    // 0
143            Vertex::new(vec3(x, -y, z), self.color, vec2(1.0, 0.0), vec3(0.0, 0.0, 1.0)),     // 1
144            Vertex::new(vec3(x, y, z), self.color, vec2(1.0, 1.0), vec3(0.0, 0.0, 1.0)),      // 2
145            Vertex::new(vec3(-x, y, z), self.color, vec2(0.0, 1.0), vec3(0.0, 0.0, 1.0)),     // 3
146
147            // Back face
148            Vertex::new(vec3(-x, -y, -z), self.color, vec2(0.0, 0.0), vec3(0.0, 0.0, -1.0)),   // 4
149            Vertex::new(vec3(x, -y, -z), self.color, vec2(1.0, 0.0), vec3(0.0, 0.0, -1.0)),    // 5
150            Vertex::new(vec3(x, y, -z), self.color, vec2(1.0, 1.0), vec3(0.0, 0.0, -1.0)),     // 6
151            Vertex::new(vec3(-x, y, -z), self.color, vec2(0.0, 1.0), vec3(0.0, 0.0, -1.0)),    // 7
152
153            // Left face
154            Vertex::new(vec3(-x, -y, -z), self.color, vec2(0.0, 0.0), vec3(-1.0, 0.0, 0.0)),   // 8
155            Vertex::new(vec3(-x, -y, z), self.color, vec2(1.0, 0.0), vec3(-1.0, 0.0, 0.0)),    // 9
156            Vertex::new(vec3(-x, y, z), self.color, vec2(1.0, 1.0), vec3(-1.0, 0.0, 0.0)),     // 10
157            Vertex::new(vec3(-x, y, -z), self.color, vec2(0.0, 1.0), vec3(-1.0, 0.0, 0.0)),    // 11
158
159            // Right face
160            Vertex::new(vec3(x, -y, -z), self.color, vec2(0.0, 0.0), vec3(1.0, 0.0, 0.0)),    // 12
161            Vertex::new(vec3(x, -y, z), self.color, vec2(1.0, 0.0), vec3(1.0, 0.0, 0.0)),     // 13
162            Vertex::new(vec3(x, y, z), self.color, vec2(1.0, 1.0), vec3(1.0, 0.0, 0.0)),      // 14
163            Vertex::new(vec3(x, y, -z), self.color, vec2(0.0, 1.0), vec3(1.0, 0.0, 0.0)),     // 15
164
165            // Top face
166            Vertex::new(vec3(-x, y, -z), self.color, vec2(0.0, 0.0), vec3(0.0, 1.0, 0.0)),    // 16
167            Vertex::new(vec3(x, y, -z), self.color, vec2(1.0, 0.0), vec3(0.0, 1.0, 0.0)),     // 17
168            Vertex::new(vec3(x, y, z), self.color, vec2(1.0, 1.0), vec3(0.0, 1.0, 0.0)),      // 18
169            Vertex::new(vec3(-x, y, z), self.color, vec2(0.0, 1.0), vec3(0.0, 1.0, 0.0)),     // 19
170
171            // Bottom face
172            Vertex::new(vec3(-x, -y, -z), self.color, vec2(0.0, 0.0), vec3(0.0, -1.0, 0.0)),   // 20
173            Vertex::new(vec3(x, -y, -z), self.color, vec2(1.0, 0.0), vec3(0.0, -1.0, 0.0)),    // 21
174            Vertex::new(vec3(x, -y, z), self.color, vec2(1.0, 1.0), vec3(0.0, -1.0, 0.0)),     // 22
175            Vertex::new(vec3(-x, -y, z), self.color, vec2(0.0, 1.0), vec3(0.0, -1.0, 0.0)),    // 23
176        ];
177
178        let indices = vec![
179            // Front face
180            0, 3, 2, 2, 1, 0,
181            // Back face
182            4, 5, 6, 6, 7, 4,
183            // Left face
184            8, 11, 10, 10, 9, 8,
185            // Right face
186            12, 13, 14, 14, 15, 12,
187            // Top face
188            16, 17, 18, 18, 19, 16,
189            // Bottom face
190            20, 23, 22, 22, 21, 20
191        ];
192        
193        Mesh::new(&vertices, &indices)
194    }
195}
196
197pub struct Sphere{
198    pub iterations: i32,
199    pub radius: f32,
200    pub color: Vec4,
201}
202
203impl Sphere {
204    pub fn new(iterations: i32, radius: f32, color: Vec4) -> Self{
205        let mut fixed_iterations = iterations;
206        if iterations <= 3{
207            fixed_iterations = 4;
208        }
209
210        Self {
211            iterations: fixed_iterations,
212            radius,
213            color,
214        }
215    }
216
217    pub fn mesh(&self) -> Mesh {
218        let mut vertices = vec![];
219        let pi = std::f32::consts::PI;
220
221        for lat in 0..=self.iterations {
222            let theta = pi * lat as f32 / self.iterations as f32;
223            let sin_theta = theta.sin();
224            let cos_theta = theta.cos();
225
226            for lon in 0..=self.iterations {
227                let phi = 2.0 * pi * lon as f32 / self.iterations as f32;
228                let sin_phi = phi.sin();
229                let cos_phi = phi.cos();
230
231                let x = cos_phi * sin_theta * self.radius;
232                let y = cos_theta * self.radius;
233                let z = sin_phi * sin_theta * self.radius;
234
235                // Calculate texture coordinates (cylindrical projection)
236                let s = lon as f32 / self.iterations as f32;
237                let t = 1.0 - (lat as f32 / self.iterations as f32);
238
239                let normal = vec3(x, y, z).normalize();
240
241                vertices.push(Vertex::new(vec3(x, y, z), self.color, vec2(s, t), normal));
242            }
243        }
244
245        let mut indices = vec![];
246        for lat in 0..self.iterations {
247            for lon in 0..self.iterations {
248                let first = lat * (self.iterations + 1) + lon;
249                let second = first + self.iterations + 1;
250
251                indices.push(first as u32);
252                indices.push(second as u32);
253                indices.push((first + 1) as u32);
254
255                indices.push(second as u32);
256                indices.push((second + 1) as u32);
257                indices.push((first + 1) as u32);
258            }
259        }
260
261        Mesh::new(&vertices, &indices)
262    }
263}