rootvg_mesh/
primitive.rs

1//! Draw triangles!
2use rootvg_core::math::{Angle, Point, Transform, Vector};
3
4mod solid;
5pub use solid::*;
6
7#[cfg(feature = "gradient")]
8mod gradient;
9#[cfg(feature = "gradient")]
10pub use gradient::*;
11
12/// A set of vertices and indices representing a list of triangles.
13#[derive(Clone, Debug, PartialEq, Eq)]
14pub struct Indexed<T> {
15    /// The vertices of the mesh
16    pub vertices: Vec<T>,
17
18    /// The list of vertex indices that defines the triangles of the mesh.
19    ///
20    /// Therefore, this list should always have a length that is a multiple of 3.
21    pub indices: Vec<u32>,
22}
23
24impl<T> Indexed<T> {
25    pub fn new() -> Self {
26        Self {
27            vertices: Vec::new(),
28            indices: Vec::new(),
29        }
30    }
31}
32
33#[repr(C)]
34#[derive(Debug, Clone, Copy, PartialEq, bytemuck::Pod, bytemuck::Zeroable)]
35pub struct MeshUniforms {
36    /// The offset in logical points.
37    pub offset: [f32; 2],
38
39    /// A 2d transform represented by a column-major 3 by 3 matrix, compressed down
40    /// to 3 by 2.
41    ///
42    /// Note that `size` is not included in the `transform`.
43    pub transform: [f32; 6],
44
45    /// Whether or not to apply the `transform` matrix. This is used to optimize
46    /// meshes with no transformations.
47    ///
48    /// Note that `size` is not included in the `transform`.
49    ///
50    /// By default this is set to `0` (false).
51    pub has_transform: u32,
52}
53
54impl MeshUniforms {
55    pub fn new(offset: Point, transform: Option<Transform>) -> Self {
56        let (transform, has_transform) = if let Some(transform) = transform {
57            (transform.to_array(), 1)
58        } else {
59            ([0.0; 6], 0)
60        };
61
62        Self {
63            offset: offset.into(),
64            transform,
65            has_transform,
66        }
67    }
68}
69
70impl Default for MeshUniforms {
71    fn default() -> Self {
72        Self {
73            offset: [0.0; 2],
74            transform: [0.0; 6],
75            has_transform: 0,
76        }
77    }
78}
79
80#[derive(Debug, Clone, PartialEq)]
81pub enum MeshPrimitive {
82    Solid(SolidMeshPrimitive),
83    #[cfg(feature = "gradient")]
84    Gradient(GradientMeshPrimitive),
85}
86
87impl MeshPrimitive {
88    pub fn set_offset(&mut self, offset: Point) {
89        match self {
90            MeshPrimitive::Solid(mesh) => mesh.uniform.offset = offset.into(),
91            #[cfg(feature = "gradient")]
92            MeshPrimitive::Gradient(mesh) => mesh.uniform.offset = offset.into(),
93        }
94    }
95
96    pub fn set_rotation(&mut self, angle: Angle, rotation_origin: Point) {
97        let transform = Transform::translation(-rotation_origin.x, -rotation_origin.y)
98            .then_rotate(angle)
99            .then_translate(Vector::new(rotation_origin.x, rotation_origin.y));
100
101        self.set_transform(transform);
102    }
103
104    pub fn set_transform(&mut self, transform: Transform) {
105        match self {
106            MeshPrimitive::Solid(mesh) => {
107                mesh.uniform.transform = transform.to_array();
108                mesh.uniform.has_transform = 1;
109            }
110            #[cfg(feature = "gradient")]
111            MeshPrimitive::Gradient(mesh) => {
112                mesh.uniform.transform = transform.to_array();
113                mesh.uniform.has_transform = 1;
114            }
115        }
116    }
117}