iced_graphics/
mesh.rs

1//! Draw triangles!
2use crate::color;
3use crate::core::{Rectangle, Transformation};
4use crate::gradient;
5
6use bytemuck::{Pod, Zeroable};
7
8use std::sync::atomic::{self, AtomicU64};
9use std::sync::{Arc, Weak};
10
11/// A low-level primitive to render a mesh of triangles.
12#[derive(Debug, Clone, PartialEq)]
13pub enum Mesh {
14    /// A mesh with a solid color.
15    Solid {
16        /// The vertices and indices of the mesh.
17        buffers: Indexed<SolidVertex2D>,
18
19        /// The [`Transformation`] for the vertices of the [`Mesh`].
20        transformation: Transformation,
21
22        /// The clip bounds of the [`Mesh`].
23        clip_bounds: Rectangle,
24    },
25    /// A mesh with a gradient.
26    Gradient {
27        /// The vertices and indices of the mesh.
28        buffers: Indexed<GradientVertex2D>,
29
30        /// The [`Transformation`] for the vertices of the [`Mesh`].
31        transformation: Transformation,
32
33        /// The clip bounds of the [`Mesh`].
34        clip_bounds: Rectangle,
35    },
36}
37
38impl Mesh {
39    /// Returns the indices of the [`Mesh`].
40    pub fn indices(&self) -> &[u32] {
41        match self {
42            Self::Solid { buffers, .. } => &buffers.indices,
43            Self::Gradient { buffers, .. } => &buffers.indices,
44        }
45    }
46
47    /// Returns the [`Transformation`] of the [`Mesh`].
48    pub fn transformation(&self) -> Transformation {
49        match self {
50            Self::Solid { transformation, .. } | Self::Gradient { transformation, .. } => {
51                *transformation
52            }
53        }
54    }
55
56    /// Returns the clip bounds of the [`Mesh`].
57    pub fn clip_bounds(&self) -> Rectangle {
58        match self {
59            Self::Solid {
60                clip_bounds,
61                transformation,
62                ..
63            }
64            | Self::Gradient {
65                clip_bounds,
66                transformation,
67                ..
68            } => *clip_bounds * *transformation,
69        }
70    }
71}
72
73/// A set of vertices and indices representing a list of triangles.
74#[derive(Clone, Debug, PartialEq, Eq)]
75pub struct Indexed<T> {
76    /// The vertices of the mesh
77    pub vertices: Vec<T>,
78
79    /// The list of vertex indices that defines the triangles of the mesh.
80    ///
81    /// Therefore, this list should always have a length that is a multiple of 3.
82    pub indices: Vec<u32>,
83}
84
85/// A two-dimensional vertex with a color.
86#[derive(Copy, Clone, Debug, PartialEq, Zeroable, Pod)]
87#[repr(C)]
88pub struct SolidVertex2D {
89    /// The vertex position in 2D space.
90    pub position: [f32; 2],
91
92    /// The color of the vertex in __linear__ RGBA.
93    pub color: color::Packed,
94}
95
96/// A vertex which contains 2D position & packed gradient data.
97#[derive(Copy, Clone, Debug, PartialEq, Zeroable, Pod)]
98#[repr(C)]
99pub struct GradientVertex2D {
100    /// The vertex position in 2D space.
101    pub position: [f32; 2],
102
103    /// The packed vertex data of the gradient.
104    pub gradient: gradient::Packed,
105}
106
107/// The result of counting the attributes of a set of meshes.
108#[derive(Debug, Clone, Copy, Default)]
109pub struct AttributeCount {
110    /// The total amount of solid vertices.
111    pub solid_vertices: usize,
112
113    /// The total amount of solid meshes.
114    pub solids: usize,
115
116    /// The total amount of gradient vertices.
117    pub gradient_vertices: usize,
118
119    /// The total amount of gradient meshes.
120    pub gradients: usize,
121
122    /// The total amount of indices.
123    pub indices: usize,
124}
125
126/// Returns the number of total vertices & total indices of all [`Mesh`]es.
127pub fn attribute_count_of(meshes: &[Mesh]) -> AttributeCount {
128    meshes
129        .iter()
130        .fold(AttributeCount::default(), |mut count, mesh| {
131            match mesh {
132                Mesh::Solid { buffers, .. } => {
133                    count.solids += 1;
134                    count.solid_vertices += buffers.vertices.len();
135                    count.indices += buffers.indices.len();
136                }
137                Mesh::Gradient { buffers, .. } => {
138                    count.gradients += 1;
139                    count.gradient_vertices += buffers.vertices.len();
140                    count.indices += buffers.indices.len();
141                }
142            }
143
144            count
145        })
146}
147
148/// A cache of multiple meshes.
149#[derive(Debug, Clone)]
150pub struct Cache {
151    id: Id,
152    batch: Arc<[Mesh]>,
153    version: usize,
154}
155
156/// The unique id of a [`Cache`].
157#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
158pub struct Id(u64);
159
160impl Cache {
161    /// Creates a new [`Cache`] for the given meshes.
162    pub fn new(meshes: Arc<[Mesh]>) -> Self {
163        static NEXT_ID: AtomicU64 = AtomicU64::new(0);
164
165        Self {
166            id: Id(NEXT_ID.fetch_add(1, atomic::Ordering::Relaxed)),
167            batch: meshes,
168            version: 0,
169        }
170    }
171
172    /// Returns the [`Id`] of the [`Cache`].
173    pub fn id(&self) -> Id {
174        self.id
175    }
176
177    /// Returns the current version of the [`Cache`].
178    pub fn version(&self) -> usize {
179        self.version
180    }
181
182    /// Returns the batch of meshes in the [`Cache`].
183    pub fn batch(&self) -> &[Mesh] {
184        &self.batch
185    }
186
187    /// Returns a [`Weak`] reference to the contents of the [`Cache`].
188    pub fn downgrade(&self) -> Weak<[Mesh]> {
189        Arc::downgrade(&self.batch)
190    }
191
192    /// Returns true if the [`Cache`] is empty.
193    pub fn is_empty(&self) -> bool {
194        self.batch.is_empty()
195    }
196
197    /// Updates the [`Cache`] with the given meshes.
198    pub fn update(&mut self, meshes: Arc<[Mesh]>) {
199        self.batch = meshes;
200        self.version += 1;
201    }
202}
203
204/// A renderer capable of drawing a [`Mesh`].
205pub trait Renderer {
206    /// Draws the given [`Mesh`].
207    fn draw_mesh(&mut self, mesh: Mesh);
208
209    /// Draws the given [`Cache`].
210    fn draw_mesh_cache(&mut self, cache: Cache);
211}