ellipsoid/graphics/
shape.rs1use 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 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 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}