Skip to main content

ruckus/
vertex.rs

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    /** 
58     * Flips given verts tex coordinates along vertical (y) axis. Assumes
59     * coordinates are NDC
60    */
61    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            // Flip texture coordinates
106            let text_dim = glm::vec2(rect_size.x * flipped.x, rect_size.y * (1. - v.text_coord.v));
107            // get texture coordinate relative to top-left
108            v.text_coord = (text_dim + uv_offset).into();
109            // NOTE :: Only need to normalize if we are using a sprite sheet, so we will
110            // have user normalize coordinates manually with normalize_coords
111        }
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}