1//! Draw triangles!
2use crate::color;
3use crate::core::{Rectangle, Transformation};
4use crate::gradient;
56use bytemuck::{Pod, Zeroable};
78/// A low-level primitive to render a mesh of triangles.
9#[derive(Debug, Clone, PartialEq)]
10pub enum Mesh {
11/// A mesh with a solid color.
12Solid {
13/// The vertices and indices of the mesh.
14buffers: Indexed<SolidVertex2D>,
1516/// The [`Transformation`] for the vertices of the [`Mesh`].
17transformation: Transformation,
1819/// The clip bounds of the [`Mesh`].
20clip_bounds: Rectangle,
21 },
22/// A mesh with a gradient.
23Gradient {
24/// The vertices and indices of the mesh.
25buffers: Indexed<GradientVertex2D>,
2627/// The [`Transformation`] for the vertices of the [`Mesh`].
28transformation: Transformation,
2930/// The clip bounds of the [`Mesh`].
31clip_bounds: Rectangle,
32 },
33}
3435impl Mesh {
36/// Returns the indices of the [`Mesh`].
37pub fn indices(&self) -> &[u32] {
38match self {
39Self::Solid { buffers, .. } => &buffers.indices,
40Self::Gradient { buffers, .. } => &buffers.indices,
41 }
42 }
4344/// Returns the [`Transformation`] of the [`Mesh`].
45pub fn transformation(&self) -> Transformation {
46match self {
47Self::Solid { transformation, .. }
48 | Self::Gradient { transformation, .. } => *transformation,
49 }
50 }
5152/// Returns the clip bounds of the [`Mesh`].
53pub fn clip_bounds(&self) -> Rectangle {
54match self {
55Self::Solid {
56 clip_bounds,
57 transformation,
58 ..
59 }
60 | Self::Gradient {
61 clip_bounds,
62 transformation,
63 ..
64 } => *clip_bounds * *transformation,
65 }
66 }
67}
6869/// A set of vertices and indices representing a list of triangles.
70#[derive(Clone, Debug, PartialEq, Eq)]
71pub struct Indexed<T> {
72/// The vertices of the mesh
73pub vertices: Vec<T>,
7475/// The list of vertex indices that defines the triangles of the mesh.
76 ///
77 /// Therefore, this list should always have a length that is a multiple of 3.
78pub indices: Vec<u32>,
79}
8081/// A two-dimensional vertex with a color.
82#[derive(Copy, Clone, Debug, PartialEq, Zeroable, Pod)]
83#[repr(C)]
84pub struct SolidVertex2D {
85/// The vertex position in 2D space.
86pub position: [f32; 2],
8788/// The color of the vertex in __linear__ RGBA.
89pub color: color::Packed,
90}
9192/// A vertex which contains 2D position & packed gradient data.
93#[derive(Copy, Clone, Debug, PartialEq, Zeroable, Pod)]
94#[repr(C)]
95pub struct GradientVertex2D {
96/// The vertex position in 2D space.
97pub position: [f32; 2],
9899/// The packed vertex data of the gradient.
100pub gradient: gradient::Packed,
101}
102103/// The result of counting the attributes of a set of meshes.
104#[derive(Debug, Clone, Copy, Default)]
105pub struct AttributeCount {
106/// The total amount of solid vertices.
107pub solid_vertices: usize,
108109/// The total amount of solid meshes.
110pub solids: usize,
111112/// The total amount of gradient vertices.
113pub gradient_vertices: usize,
114115/// The total amount of gradient meshes.
116pub gradients: usize,
117118/// The total amount of indices.
119pub indices: usize,
120}
121122/// Returns the number of total vertices & total indices of all [`Mesh`]es.
123pub fn attribute_count_of(meshes: &[Mesh]) -> AttributeCount {
124 meshes
125 .iter()
126 .fold(AttributeCount::default(), |mut count, mesh| {
127match mesh {
128 Mesh::Solid { buffers, .. } => {
129 count.solids += 1;
130 count.solid_vertices += buffers.vertices.len();
131 count.indices += buffers.indices.len();
132 }
133 Mesh::Gradient { buffers, .. } => {
134 count.gradients += 1;
135 count.gradient_vertices += buffers.vertices.len();
136 count.indices += buffers.indices.len();
137 }
138 }
139140 count
141 })
142}
143144/// A renderer capable of drawing a [`Mesh`].
145pub trait Renderer {
146/// Draws the given [`Mesh`].
147fn draw_mesh(&mut self, mesh: Mesh);
148}