glium_types/matrices/
dmat3.rs

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