1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148
//! Draw triangles!
use crate::color;
use crate::core::{Rectangle, Transformation};
use crate::gradient;
use bytemuck::{Pod, Zeroable};
/// A low-level primitive to render a mesh of triangles.
#[derive(Debug, Clone, PartialEq)]
pub enum Mesh {
/// A mesh with a solid color.
Solid {
/// The vertices and indices of the mesh.
buffers: Indexed<SolidVertex2D>,
/// The [`Transformation`] for the vertices of the [`Mesh`].
transformation: Transformation,
/// The clip bounds of the [`Mesh`].
clip_bounds: Rectangle,
},
/// A mesh with a gradient.
Gradient {
/// The vertices and indices of the mesh.
buffers: Indexed<GradientVertex2D>,
/// The [`Transformation`] for the vertices of the [`Mesh`].
transformation: Transformation,
/// The clip bounds of the [`Mesh`].
clip_bounds: Rectangle,
},
}
impl Mesh {
/// Returns the indices of the [`Mesh`].
pub fn indices(&self) -> &[u32] {
match self {
Self::Solid { buffers, .. } => &buffers.indices,
Self::Gradient { buffers, .. } => &buffers.indices,
}
}
/// Returns the [`Transformation`] of the [`Mesh`].
pub fn transformation(&self) -> Transformation {
match self {
Self::Solid { transformation, .. }
| Self::Gradient { transformation, .. } => *transformation,
}
}
/// Returns the clip bounds of the [`Mesh`].
pub fn clip_bounds(&self) -> Rectangle {
match self {
Self::Solid {
clip_bounds,
transformation,
..
}
| Self::Gradient {
clip_bounds,
transformation,
..
} => *clip_bounds * *transformation,
}
}
}
/// A set of vertices and indices representing a list of triangles.
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Indexed<T> {
/// The vertices of the mesh
pub vertices: Vec<T>,
/// The list of vertex indices that defines the triangles of the mesh.
///
/// Therefore, this list should always have a length that is a multiple of 3.
pub indices: Vec<u32>,
}
/// A two-dimensional vertex with a color.
#[derive(Copy, Clone, Debug, PartialEq, Zeroable, Pod)]
#[repr(C)]
pub struct SolidVertex2D {
/// The vertex position in 2D space.
pub position: [f32; 2],
/// The color of the vertex in __linear__ RGBA.
pub color: color::Packed,
}
/// A vertex which contains 2D position & packed gradient data.
#[derive(Copy, Clone, Debug, PartialEq, Zeroable, Pod)]
#[repr(C)]
pub struct GradientVertex2D {
/// The vertex position in 2D space.
pub position: [f32; 2],
/// The packed vertex data of the gradient.
pub gradient: gradient::Packed,
}
/// The result of counting the attributes of a set of meshes.
#[derive(Debug, Clone, Copy, Default)]
pub struct AttributeCount {
/// The total amount of solid vertices.
pub solid_vertices: usize,
/// The total amount of solid meshes.
pub solids: usize,
/// The total amount of gradient vertices.
pub gradient_vertices: usize,
/// The total amount of gradient meshes.
pub gradients: usize,
/// The total amount of indices.
pub indices: usize,
}
/// Returns the number of total vertices & total indices of all [`Mesh`]es.
pub fn attribute_count_of(meshes: &[Mesh]) -> AttributeCount {
meshes
.iter()
.fold(AttributeCount::default(), |mut count, mesh| {
match mesh {
Mesh::Solid { buffers, .. } => {
count.solids += 1;
count.solid_vertices += buffers.vertices.len();
count.indices += buffers.indices.len();
}
Mesh::Gradient { buffers, .. } => {
count.gradients += 1;
count.gradient_vertices += buffers.vertices.len();
count.indices += buffers.indices.len();
}
}
count
})
}
/// A renderer capable of drawing a [`Mesh`].
pub trait Renderer {
/// Draws the given [`Mesh`].
fn draw_mesh(&mut self, mesh: Mesh);
}