1use std::f32::consts::PI;
2
3use bytemuck::{Pod, Zeroable};
4use glam::Vec2;
5
6use crate::{Color, ImageHandle, Rect};
7
8#[repr(C)]
9#[derive(Clone, Copy, Debug, PartialEq, Pod, Zeroable)]
10pub struct Vertex {
11 pub position: Vec2,
12 pub uv: Vec2,
13 pub color: Color,
14}
15
16impl Default for Vertex {
17 fn default() -> Self {
18 Self {
19 position: Vec2::ZERO,
20 uv: Vec2::ZERO,
21 color: Color::WHITE,
22 }
23 }
24}
25
26impl Vertex {
27 pub const fn new(position: Vec2) -> Self {
28 Self {
29 position,
30 uv: Vec2::ZERO,
31 color: Color::WHITE,
32 }
33 }
34
35 pub const fn new_color(position: Vec2, color: Color) -> Self {
36 Self {
37 position,
38 uv: Vec2::ZERO,
39 color,
40 }
41 }
42}
43
44#[derive(Clone, Debug, Default)]
45pub struct Mesh {
46 pub vertices: Vec<Vertex>,
47 pub indices: Vec<u32>,
48 pub image: Option<ImageHandle>,
49}
50
51impl Mesh {
52 pub const fn new() -> Self {
53 Self {
54 vertices: Vec::new(),
55 indices: Vec::new(),
56 image: None,
57 }
58 }
59
60 pub fn circle(center: Vec2, radius: f32, color: Color) -> Self {
61 let mut mesh = Mesh::new();
62
63 let center = Vertex::new_color(center, color);
64 mesh.vertices.push(center);
65
66 for i in 0..=60 {
67 let angle = i as f32 / 60.0 * PI * 2.0;
68 let x = angle.cos();
69 let y = angle.sin();
70 let vertex = Vertex::new_color(center.position + Vec2::new(x, y) * radius, color);
71 mesh.vertices.push(vertex);
72 mesh.indices.push(0);
73 mesh.indices.push(i as u32 + 1);
74 mesh.indices.push(i as u32 + 2);
75 }
76
77 mesh
78 }
79
80 pub fn quad(rect: Rect) -> Self {
81 let mut mesh = Mesh::new();
82
83 mesh.vertices.push(Vertex {
84 position: rect.top_left(),
85 uv: Vec2::new(0.0, 0.0),
86 ..Vertex::default()
87 });
88 mesh.vertices.push(Vertex {
89 position: rect.top_right(),
90 uv: Vec2::new(1.0, 0.0),
91 ..Vertex::default()
92 });
93 mesh.vertices.push(Vertex {
94 position: rect.bottom_right(),
95 uv: Vec2::new(1.0, 1.0),
96 ..Vertex::default()
97 });
98 mesh.vertices.push(Vertex {
99 position: rect.bottom_left(),
100 uv: Vec2::new(0.0, 1.0),
101 ..Vertex::default()
102 });
103
104 mesh.indices.push(0);
105 mesh.indices.push(1);
106 mesh.indices.push(2);
107 mesh.indices.push(2);
108 mesh.indices.push(3);
109 mesh.indices.push(0);
110
111 mesh
112 }
113
114 pub fn image(rect: Rect, image: ImageHandle) -> Self {
115 Self {
116 image: Some(image),
117 ..Self::quad(rect)
118 }
119 }
120
121 pub fn vertex_bytes(&self) -> &[u8] {
122 bytemuck::cast_slice(&self.vertices)
123 }
124
125 pub fn index_bytes(&self) -> &[u8] {
126 bytemuck::cast_slice(&self.indices)
127 }
128}