geng_draw2d/
polygon.rs

1use super::*;
2
3pub struct Polygon {
4    pub transform: mat3<f32>,
5    pub draw_mode: ugli::DrawMode,
6    pub vertices: Vec<ColoredVertex>,
7}
8
9impl Polygon {
10    pub fn new(vertices: Vec<vec2<f32>>, color: Rgba<f32>) -> Self {
11        Self::new_gradient(
12            vertices
13                .into_iter()
14                .map(|vertex| ColoredVertex {
15                    a_pos: vertex,
16                    a_color: color,
17                })
18                .collect(),
19        )
20    }
21    pub fn new_gradient(vertices: Vec<ColoredVertex>) -> Self {
22        let (transform, vertices) = Self::normalize(vertices);
23        Self {
24            transform,
25            vertices,
26            draw_mode: ugli::DrawMode::TriangleFan,
27        }
28    }
29    pub fn strip(vertices: Vec<vec2<f32>>, color: Rgba<f32>) -> Self {
30        Self::strip_gradient(
31            vertices
32                .into_iter()
33                .map(|vertex| ColoredVertex {
34                    a_pos: vertex,
35                    a_color: color,
36                })
37                .collect(),
38        )
39    }
40    pub fn strip_gradient(vertices: Vec<ColoredVertex>) -> Self {
41        let (transform, vertices) = Self::normalize(vertices);
42        Self {
43            transform,
44            vertices,
45            draw_mode: ugli::DrawMode::TriangleStrip,
46        }
47    }
48
49    pub(super) fn normalize(mut vertices: Vec<ColoredVertex>) -> (mat3<f32>, Vec<ColoredVertex>) {
50        let aabb = Aabb2::points_bounding_box(vertices.iter().map(|vertex| vertex.a_pos)).unwrap();
51        let transform = mat3::translate(aabb.center()) * mat3::scale(aabb.size() / 2.0);
52        let inverse = transform.inverse();
53        for vertex in &mut vertices {
54            vertex.a_pos = (inverse * vertex.a_pos.extend(1.0)).xy();
55        }
56        (transform, vertices)
57    }
58}
59
60impl Draw2d for Polygon {
61    fn draw2d_transformed(
62        &self,
63        helper: &Helper,
64        framebuffer: &mut ugli::Framebuffer,
65        camera: &dyn AbstractCamera2d,
66        transform: mat3<f32>,
67    ) {
68        let framebuffer_size = framebuffer.size();
69        ugli::draw(
70            framebuffer,
71            &helper.color_program,
72            self.draw_mode,
73            &ugli::VertexBuffer::new_dynamic(helper.ugli(), self.vertices.clone()),
74            (
75                ugli::uniforms! {
76                    u_color: Rgba::WHITE,
77                    u_framebuffer_size: framebuffer_size,
78                    u_model_matrix: transform * self.transform,
79                },
80                camera.uniforms(framebuffer_size.map(|x| x as f32)),
81            ),
82            ugli::DrawParameters {
83                blend_mode: Some(ugli::BlendMode::straight_alpha()),
84                ..Default::default()
85            },
86        );
87    }
88}
89
90impl Transform2d<f32> for Polygon {
91    fn bounding_quad(&self) -> batbox_lapp::Quad<f32> {
92        batbox_lapp::Quad {
93            transform: self.transform,
94        }
95    }
96    fn apply_transform(&mut self, transform: mat3<f32>) {
97        self.transform = transform * self.transform;
98    }
99}
100
101pub struct TexturedPolygon<T: std::borrow::Borrow<ugli::Texture>> {
102    transform: mat3<f32>,
103    texture: T,
104    draw_mode: ugli::DrawMode,
105    vertices: Vec<TexturedVertex>,
106}
107
108impl<T: std::borrow::Borrow<ugli::Texture>> TexturedPolygon<T> {
109    pub fn new(vertices: Vec<TexturedVertex>, texture: T) -> Self {
110        let (transform, vertices) = Self::normalize(vertices);
111        Self {
112            transform,
113            texture,
114            vertices,
115            draw_mode: ugli::DrawMode::TriangleFan,
116        }
117    }
118    pub fn with_mode(vertices: Vec<TexturedVertex>, texture: T, draw_mode: ugli::DrawMode) -> Self {
119        let (transform, vertices) = Self::normalize(vertices);
120        Self {
121            transform,
122            texture,
123            vertices,
124            draw_mode,
125        }
126    }
127    pub fn strip(vertices: Vec<TexturedVertex>, texture: T) -> Self {
128        let (transform, vertices) = Self::normalize(vertices);
129        Self {
130            transform,
131            texture,
132            vertices,
133            draw_mode: ugli::DrawMode::TriangleStrip,
134        }
135    }
136
137    pub(super) fn normalize(mut vertices: Vec<TexturedVertex>) -> (mat3<f32>, Vec<TexturedVertex>) {
138        let aabb = Aabb2::points_bounding_box(vertices.iter().map(|vertex| vertex.a_pos)).unwrap();
139        let transform = mat3::translate(aabb.center()) * mat3::scale(aabb.size() / 2.0);
140        let inverse = transform.inverse();
141        for vertex in &mut vertices {
142            vertex.a_pos = (inverse * vertex.a_pos.extend(1.0)).xy();
143        }
144        (transform, vertices)
145    }
146}
147
148impl<T: std::borrow::Borrow<ugli::Texture>> Draw2d for TexturedPolygon<T> {
149    fn draw2d_transformed(
150        &self,
151        helper: &Helper,
152        framebuffer: &mut ugli::Framebuffer,
153        camera: &dyn AbstractCamera2d,
154        transform: mat3<f32>,
155    ) {
156        let framebuffer_size = framebuffer.size();
157        ugli::draw(
158            framebuffer,
159            &helper.textured_program,
160            self.draw_mode,
161            &ugli::VertexBuffer::new_dynamic(helper.ugli(), self.vertices.clone()),
162            (
163                ugli::uniforms! {
164                    u_color: Rgba::WHITE,
165                    u_texture: self.texture.borrow(),
166                    u_framebuffer_size: framebuffer_size,
167                    u_model_matrix: transform * self.transform,
168                    u_texture_matrix: mat3::identity(),
169                },
170                camera.uniforms(framebuffer_size.map(|x| x as f32)),
171            ),
172            ugli::DrawParameters {
173                blend_mode: Some(ugli::BlendMode::straight_alpha()),
174                ..Default::default()
175            },
176        );
177    }
178}
179
180impl<T: std::borrow::Borrow<ugli::Texture>> Transform2d<f32> for TexturedPolygon<T> {
181    fn bounding_quad(&self) -> batbox_lapp::Quad<f32> {
182        batbox_lapp::Quad {
183            transform: self.transform,
184        }
185    }
186    fn apply_transform(&mut self, transform: mat3<f32>) {
187        self.transform = transform * self.transform;
188    }
189}