1use nalgebra_glm as glm;
2
3use crate::sys::{Rect, Rectui, Transform};
4
5pub struct TupleVector(f32, f32, f32);
6pub const UP_VECTOR: TupleVector = TupleVector(0., 1., 0.);
7pub const FORWARD_VECTOR: TupleVector = TupleVector(0., 0., 1.);
8
9impl From<TupleVector> for glm::Vec3 {
10 fn from(t: TupleVector) -> Self { glm::vec3(t.0, t.1, t.2) }
11}
12
13
14#[repr(C)] #[derive(Copy, Clone, Default)] pub struct Vert2DPosition { pub x: f32, pub y: f32, pub z: f32 }
15#[repr(C)] #[derive(Copy, Clone, Default)] pub struct Vert2DTextureCoord { pub u: f32, pub v: f32 }
16#[repr(C)] #[derive(Copy, Clone, Default)] pub struct Vert2DColor { pub r: f32, pub g: f32, pub b: f32, pub a: f32 }
17#[repr(C)] #[derive(Copy, Clone, Default)] pub struct Vertex2D {
18 pub position: Vert2DPosition,
19 pub text_coord: Vert2DTextureCoord,
20 pub color: Vert2DColor
21}
22
23impl From<&glm::Vec4> for Vert2DColor {
24 fn from(v: &glm::Vec4) -> Self {
25 Vert2DColor {
26 r: v.x, g: v.y, b: v.z, a: v.w
27 }
28 }
29}
30
31impl From<glm::Vec4> for Vert2DPosition {
32 fn from(v: glm::Vec4) -> Self {
33 Vert2DPosition {
34 x: v.x, y: v.y, z: v.z
35 }
36 }
37}
38
39impl From<glm::Vec2> for Vert2DTextureCoord {
40 fn from(v: glm::Vec2) -> Self {
41 Vert2DTextureCoord {
42 u: v.x, v: v.y
43 }
44 }
45}
46
47impl From<Vert2DPosition> for glm::Vec4 {
48 fn from(p: Vert2DPosition) -> Self {
49 glm::vec4(p.x, p.y, p.z, 1.)
50 }
51}
52
53pub trait Vertex2DSliceOps<'a> {
54 fn set_color(&mut self, color: &glm::Vec4);
55 fn translate(&mut self, xform: &Transform);
56 fn calc_texture_coords(&mut self, texture_rect: &Rectui);
57 fn flip_texture_coords_vert(&mut self, min: f32, max: f32);
62
63 fn normalize_texture_coords(&mut self, bounds: glm::Vec2);
64}
65
66trait Vertex2DAsRaw<'a> { fn as_raw(&self) -> &'a [f32]; }
67
68impl<'a> Vertex2DAsRaw<'a> for std::slice::Iter<'_, Vertex2D> {
69 fn as_raw(&self) -> &'a [f32] {
70 unsafe { std::mem::transmute(self.as_slice()) }
71 }
72}
73
74
75impl<'a> Vertex2DSliceOps<'a> for std::slice::IterMut<'_, Vertex2D> {
76
77 fn set_color(&mut self, color: &glm::Vec4) {
78 for v in self { v.color = color.into() }
79 }
80
81 fn translate(&mut self, xform: &Transform) {
82 for v in self {
83 let position: glm::Vec4 = v.position.into();
84 v.position = (xform.model() * position).into();
85 }
86 }
87
88 fn flip_texture_coords_vert(&mut self, min: f32, max: f32) {
89 for v in self { v.text_coord.v = min + (max - v.text_coord.v) }
90 }
91
92 fn normalize_texture_coords(&mut self, bounds: glm::Vec2) {
93 for v in self {
94 v.text_coord.u /= bounds.x;
95 v.text_coord.v = 1.0 - (v.text_coord.v / bounds.y);
96 }
97 }
98
99 fn calc_texture_coords(&mut self, texture_rect: &Rect<u32>) {
100 let rect_size = glm::vec2(texture_rect.w as f32, texture_rect.h as f32);
101 let uv_offset = glm::vec2(texture_rect.x as f32, texture_rect.y as f32);
102
103 for v in self {
104 let flipped = glm::vec2(v.text_coord.u, 1. - v.text_coord.v);
105 let text_dim = glm::vec2(rect_size.x * flipped.x, rect_size.y * (1. - v.text_coord.v));
107 v.text_coord = (text_dim + uv_offset).into();
109 }
112 }
113}
114
115impl Vertex2D {
116 pub const fn new() -> Self {
117
118 Vertex2D { position: Vert2DPosition { x: 0., y: 0., z: 0. }, text_coord: Vert2DTextureCoord { u: 0., v: 0. }, color: Vert2DColor { r: 0., g: 0., b: 0., a: 0. } }
119 }
120
121 pub fn as_slice(&self) -> &[f32; 9] {
122 unsafe { std::mem::transmute(self) }
123 }
124
125 pub fn as_mut_slice(&mut self) -> &mut [f32; 9] {
126 unsafe { std::mem::transmute(self) }
127 }
128}
129
130impl Vert2DColor {
131 pub const fn white() -> Self {
132 Vert2DColor { r: 1., g: 1., b: 1., a: 1. }
133 }
134}