Skip to main content

loam_shape/
visualizable.rs

1//! Mesh colors are linear RGBA; widths and point radii are in screen pixels.
2
3use serde::{Deserialize, Serialize};
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq)]
6pub enum NotVisualizable {
7    Unbounded,
8
9    WrongDimension,
10
11    Degenerate,
12}
13
14pub trait Visualizable<const N: usize> {
15    fn to_lines(&self) -> Result<LineMesh<N>, NotVisualizable>;
16
17    fn to_triangles(&self) -> Result<TriangleMesh<N>, NotVisualizable>;
18
19    fn to_points(&self) -> Result<PointMesh<N>, NotVisualizable>;
20}
21
22#[derive(Clone, Debug, Default, Serialize, Deserialize)]
23#[serde(bound(
24    serialize = "[f32; N]: Serialize",
25    deserialize = "[f32; N]: Deserialize<'de>"
26))]
27pub struct LineMesh<const N: usize> {
28    pub segments: Vec<([f32; N], [f32; N])>,
29    /// `(start_color, end_color)`; `colors.len() == segments.len()`.
30    pub colors: Vec<([f32; 4], [f32; 4])>,
31    /// Pixels. `widths.len() == segments.len()`.
32    pub widths: Vec<f32>,
33}
34
35#[derive(Clone, Debug, Default, Serialize, Deserialize)]
36#[serde(bound(
37    serialize = "[f32; N]: Serialize",
38    deserialize = "[f32; N]: Deserialize<'de>"
39))]
40pub struct TriangleMesh<const N: usize> {
41    pub vertices: Vec<[f32; N]>,
42    /// Counter-clockwise winding, looking down the normal.
43    pub indices: Vec<[u32; 3]>,
44    /// `colors.len() == vertices.len()`.
45    pub colors: Vec<[f32; 4]>,
46}
47
48#[derive(Clone, Debug, Default, Serialize, Deserialize)]
49#[serde(bound(
50    serialize = "[f32; N]: Serialize",
51    deserialize = "[f32; N]: Deserialize<'de>"
52))]
53pub struct PointMesh<const N: usize> {
54    pub positions: Vec<[f32; N]>,
55    /// `colors.len() == positions.len()`.
56    pub colors: Vec<[f32; 4]>,
57    pub sizes: Vec<f32>,
58}