glium_types/matrices/
mat2.rs

1use glium::uniforms::AsUniformValue;
2use crate::prelude::Vec2;
3use super::{Mat3, Mat4};
4
5#[derive(Clone, Copy, PartialEq, Debug)]
6///a matrix often used for transformations in glium.
7pub struct Mat2 {
8    matrix: [[f32; 2]; 2]
9}
10impl Mat2{
11    pub const IDENTITY: Self = Mat2::from_values(
12        1.0, 0.0,
13        0.0, 1.0,
14    );
15    pub const fn from_column_major_array(array: [[f32; 2]; 2]) -> Self { Self { matrix: array } }
16    pub const fn into_column_major_array(self) -> [[f32; 2]; 2] { self.matrix }
17    pub const fn from_row_major_array(array: [[f32; 2]; 2]) -> Self { Self { matrix: array }.transpose() }
18    pub const fn into_row_major_array(self) -> [[f32; 2]; 2] { self.transpose().matrix }
19    pub const fn from_scale(scale: Vec2) -> Self{
20        Mat2::from_values(
21            scale.x, 0.0,
22            0.0, scale.y
23        )
24    }
25    pub fn from_transform(scale: Vec2, rot: f32) -> Self{
26        Self::from_values(
27            rot.cos()*scale.x, -rot.sin()*scale.y,
28            rot.sin()*scale.x, rot.cos()*scale.y
29        )
30    }
31    pub fn from_rot(rot: f32) -> Self{
32        Self::from_values(
33            rot.cos(), -rot.sin(),
34            rot.sin(), rot.cos()
35        )
36    }
37    ///creates a matrix with the following values.
38    /// ```
39    /// use glium_types::matrices::Mat2;
40    /// let new_matrix = Mat2::from_values(
41    ///     1.0, 0.0, 
42    ///     0.0, 1.0
43    /// );
44    /// assert!(new_matrix == Mat2::IDENTITY);
45    /// ```
46    pub const fn from_values(
47        a: f32, b: f32,
48        c: f32, d: f32
49        ) -> Self{
50        Self{
51            // opengl uses a diffent matrix format to the input. this is why the order is shifted.
52            matrix: [
53                [a, c],
54                [b, d]
55            ]
56        }
57    }
58    pub fn scale(&self, scalar: f32) -> Mat2 {
59        let Mat2 { matrix: [
60            [a, c],
61            [b, d]
62        ]} = self;
63        Self::from_values(
64            a * scalar, b * scalar,
65            c * scalar, d * scalar
66        )
67    }
68    pub const fn transpose(self) -> Self {
69        let Mat2 { matrix: [
70            [a, c],
71            [b, d]
72        ] } = self;
73        Mat2::from_values(
74            a, c,
75            b, d
76        )
77    }
78    pub fn determinant(&self) -> f32 {
79        let Mat2 { matrix: [
80            [a, c],
81            [b, d]
82        ]} = self;
83        a*d - b*c
84    }
85    pub fn inverse(&self) -> Mat2 {
86        let Mat2 { matrix: [
87            [a, c],
88            [b, d]
89        ]} = self;
90        
91        let scalar = 1.0/self.determinant();
92        Self::from_values(
93            *d, -b,
94            -c, *a
95        ).scale(scalar)
96    }
97    pub const fn column(&self, pos: usize) -> [f32; 2] {
98        self.matrix[pos]
99    }
100    pub const fn row(&self, pos: usize) -> [f32; 2] {
101        let matrix = self.matrix;
102        [matrix[0][pos], matrix[1][pos]]
103    }
104}
105impl Default for Mat2 {
106    fn default() -> Self {
107        Self { matrix: [
108            [1.0, 0.0],
109            [0.0, 1.0],
110        ] }
111    }
112}
113impl std::ops::Mul<Vec2> for Mat2 {
114    fn mul(self, rhs: Vec2) -> Self::Output { rhs.transform(self) }
115    type Output = Vec2;
116}
117impl std::ops::Mul<f32> for Mat2 {
118    fn mul(self, rhs: f32) -> Self::Output { self.scale(rhs) }
119    type Output = Self;
120}
121impl std::ops::MulAssign<f32> for Mat2 {
122    fn mul_assign(&mut self, rhs: f32) { *self = *self * rhs }
123}
124impl std::ops::Mul<Mat2> for f32 {
125    fn mul(self, rhs: Mat2) -> Self::Output { rhs * self }
126    type Output = Mat2;
127}
128impl std::ops::Div<f32> for Mat2 {
129    fn div(self, rhs: f32) -> Self::Output { self.scale(1.0/rhs) }
130    type Output = Self;
131}
132impl std::ops::DivAssign<f32> for Mat2 {
133    fn div_assign(&mut self, rhs: f32) { *self = *self / rhs }
134}
135impl std::ops::Div<Mat2> for f32 {
136    fn div(self, rhs: Mat2) -> Self::Output {
137        let Mat2 { matrix: [
138            [a, c],
139            [b, d]
140        ] } = rhs;
141        Mat2::from_values(
142            self/a, self/b,
143            self/c, self/d
144        )
145    }
146    type Output = Mat2;
147}
148impl std::ops::Rem<f32> for Mat2 {
149    fn rem(self, rhs: f32) -> Self::Output {
150        let Mat2 { matrix: [
151            [a, c],
152            [b, d]
153        ] } = self;
154        Mat2::from_values(
155            a%rhs, b%rhs,
156            c%rhs, d%rhs
157        )
158    }
159    type Output = Self;
160}
161impl std::ops::RemAssign<f32> for Mat2 {
162    fn rem_assign(&mut self, rhs: f32) { *self = *self % rhs }
163}
164impl std::ops::Rem<Mat2> for f32 {
165    fn rem(self, rhs: Mat2) -> Self::Output {
166        let Mat2 { matrix: [
167            [a, c],
168            [b, d]
169        ] } = rhs;
170        Mat2::from_values(
171            self%a, self%b,
172            self%c, self%d
173        )
174    }
175    type Output = Mat2;
176}
177#[allow(clippy::needless_range_loop)]
178impl std::ops::Mul for Mat2 {
179    fn mul(self, rhs: Self) -> Self::Output {
180        let mut matrix = [[0.0; 2]; 2];
181        for x in 0..2 {
182            for y in 0..2 {
183                matrix[x][y] = Vec2::dot(self.row(y).into(), rhs.column(x).into());
184            }
185        }
186        Self {
187            matrix
188        }
189    }
190    type Output = Self;
191}
192impl std::ops::MulAssign for Mat2 {
193    fn mul_assign(&mut self, rhs: Self) { *self = *self * rhs }
194}
195#[allow(clippy::suspicious_arithmetic_impl)]
196impl std::ops::Div for Mat2 {
197    fn div(self, rhs: Self) -> Self::Output { self * rhs.inverse() }
198    type Output = Self;
199}
200impl std::ops::DivAssign for Mat2 {
201    fn div_assign(&mut self, rhs: Self) { *self = *self / rhs }
202}
203impl AsUniformValue for Mat2 {
204    fn as_uniform_value(&self) -> glium::uniforms::UniformValue<'_> {
205        glium::uniforms::UniformValue::Mat2(self.matrix)
206    }
207}
208impl From<Mat3> for Mat2 {
209    fn from(value: Mat3) -> Self {
210        Self::from_values(
211            value[0][0], value[0][1],
212            value[1][0], value[1][1]
213        )
214    }
215}
216impl From<Mat4> for Mat2 {
217    fn from(value: Mat4) -> Self {
218        Self::from_values(
219            value[0][0], value[0][1],
220            value[1][0], value[1][1]
221        )
222    }
223}
224impl std::ops::Index<usize> for Mat2 {
225    fn index(&self, index: usize) -> &Self::Output {
226        &self.matrix[index]
227    }
228    
229    type Output = [f32; 2];
230}
231impl std::ops::IndexMut<usize> for Mat2 {
232    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
233        &mut self.matrix[index]
234    }
235}
236#[test]
237fn test_inverse() {
238    let mut a = Mat2::from_values(
239        4.0, 0.0,
240        1.0, 3.0
241    );
242    a = a.inverse() * a;
243    assert!(a == Mat2::IDENTITY)
244}
245#[test]
246fn addition() {
247    let a = Mat2::IDENTITY;
248    assert_eq!(a + a, Mat2::from_values(
249        2.0, 0.0,
250        0.0, 2.0
251    ))
252}
253
254impl std::ops::Add for Mat2{
255    fn add(self, rhs: Self) -> Self::Output {
256        let a = self.matrix;
257        let b = rhs.matrix;
258        Self{
259            matrix:[
260                [a[0][0] + b[0][0], a[0][1] + b[0][1]],
261                [a[1][0] + b[1][0], a[1][1] + b[1][1]]
262            ]
263        }
264    }
265    type Output = Self;
266}
267impl std::ops::AddAssign for Mat2{
268    fn add_assign(&mut self, rhs: Self) {
269        let a = self.matrix;
270        let b = rhs.matrix;
271        *self = Self{
272            matrix:[
273                [a[0][0] + b[0][0], a[0][1] + b[0][1]],
274                [a[1][0] + b[1][0], a[1][1] + b[1][1]]
275            ]
276        };
277    }
278}
279impl std::ops::Sub for Mat2{
280    fn sub(self, rhs: Self) -> Self::Output {
281        let a = self.matrix;
282        let b = rhs.matrix;
283        Self{
284            matrix:[
285                [a[0][0] - b[0][0], a[0][1] - b[0][1]],
286                [a[1][0] - b[1][0], a[1][1] - b[1][1]]
287            ]
288        }
289    }
290    type Output = Self;
291}
292impl std::ops::SubAssign for Mat2{
293    fn sub_assign(&mut self, rhs: Self) {
294        *self = *self - rhs
295    }
296}