ellipsoid/graphics/
shape.rs

1use glam::{vec2, vec3};
2
3use super::*;
4
5#[derive(Clone, Debug)]
6pub struct Shape<T: Textures> {
7    pub points: Vec<(Vec2, Vec2)>,
8    texture: T,
9    color: Color,
10    z: f32,
11}
12
13impl<T: Textures> Shape<T> {
14    pub fn new(points: Vec<Vec2>) -> Self {
15        Self {
16            points: points.into_iter().map(|p| (p, Vec2::ZERO)).collect(),
17            texture: Default::default(),
18            color: Color::WHITE,
19            z: 0.,
20        }
21        .update_texture_coords()
22    }
23
24    pub fn from_circle(segments: usize) -> Self {
25        let mut points = Vec::with_capacity(segments);
26        for i in 0..segments {
27            let angle = (i as f32 / segments as f32) * 2. * std::f32::consts::PI;
28            points.push(Vec2::new(angle.cos(), angle.sin()));
29        }
30        Self::new(points)
31    }
32    pub fn from_square() -> Self {
33        Self::new(vec![
34            Vec2::new(0., 0.),
35            Vec2::new(1., 0.),
36            Vec2::new(1., 1.),
37            Vec2::new(0., 1.),
38        ])
39    }
40    pub fn from_square_centered() -> Self {
41        Self::new(vec![
42            Vec2::new(-0.5, -0.5),
43            Vec2::new(0.5, -0.5),
44            Vec2::new(0.5, 0.5),
45            Vec2::new(-0.5, 0.5),
46        ])
47    }
48    pub fn from_triangle() -> Self {
49        Self::new(vec![vec2(0., 0.5), vec2(-0.5, -0.5), vec2(0.5, -0.5)])
50    }
51    pub fn from_line(length: f32, thickness: f32) -> Self {
52        let square = Self::from_square();
53        // length += thickness;
54
55        let gtransform = GTransform::from_translation(-Vec2::Y / 2. * thickness)
56            .stretch(vec2(length, thickness));
57
58        square.apply(gtransform)
59    }
60    pub fn from_polygon(sides: usize) -> Self {
61        let mut points = Vec::with_capacity(sides);
62        for i in 0..sides {
63            let angle = (i as f32 / sides as f32) * 2. * std::f32::consts::PI;
64            points.push(Vec2::new(angle.cos(), angle.sin()));
65        }
66        Self::new(points)
67    }
68
69    /// Rotation is after scale
70    pub fn apply(mut self, gtransform: GTransform) -> Shape<T> {
71        for (point, _) in &mut self.points {
72            *point = gtransform.transform(*point);
73        }
74        self
75    }
76
77    pub fn update_texture_coords(mut self) -> Self {
78        let mut left_lower_point = Vec2::new(std::f32::MAX, std::f32::MAX);
79        let mut right_upper_point = Vec2::new(std::f32::MIN, std::f32::MIN);
80
81        for (point, _) in &self.points {
82            left_lower_point = left_lower_point.min(*point);
83            right_upper_point = right_upper_point.max(*point);
84        }
85
86        for (point, tex_coord) in &mut self.points {
87            *tex_coord = (*point - left_lower_point) / (right_upper_point - left_lower_point);
88        }
89
90        self
91    }
92
93    pub fn set_texture(mut self, t: T) -> Self {
94        self.texture = t;
95        self
96    }
97    
98    pub fn reset_texture(mut self) -> Self {
99        self.texture = T::default();
100        self
101    }
102
103    pub fn set_color(mut self, c: Color) -> Self {
104        self.color = c;
105        self
106    }
107
108    pub fn set_z(mut self, z: f32) -> Self {
109        self.z = z;
110        self
111    }
112}
113
114impl<T: Textures> Into<(Vec<Vertex<T>>, Vec<u32>)> for Shape<T> {
115    fn into(self) -> (Vec<Vertex<T>>, Vec<u32>) {
116        let points = self
117            .points
118            .into_iter()
119            .map(|(p, tc)| (vec3(p.x, p.y, self.z), tc))
120            .collect::<Vec<_>>();
121        let mut vertices: Vec<Vertex<T>> = vec![points[0].into(), points[1].into()];
122        let mut indices = vec![];
123
124        for i in 2..points.len() {
125            vertices.push(points[i].into());
126            indices.push(0);
127            indices.push(i as u32 - 1);
128            indices.push(i as u32);
129        }
130
131        for vertex in &mut vertices {
132            vertex.texture = self.texture;
133            vertex.color = self.color;
134        }
135
136        (vertices, indices)
137    }
138}