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