glium_types/matrices/
dmat2.rs

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