ori_graphics/
mesh.rs

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}