1use crate::{enums::Axis, error, vector::Vector};
2
3#[derive(Debug, Clone)]
4pub struct Matrix {
5 m: Vec<f64>,
6}
7
8impl Matrix {
9 pub fn default() -> Matrix {
10 Matrix {
11 m: vec![
12 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
13 ],
14 }
15 }
16
17 pub fn identity() -> Matrix {
18 Matrix {
19 m: vec![
20 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0,
21 ],
22 }
23 }
24
25 pub fn new_with_fill(f: f64) -> Matrix {
26 Matrix {
27 m: vec![f, f, f, f, f, f, f, f, f, f, f, f, f, f, f, f],
28 }
29 }
30
31 pub fn new_from_vec(m: &Vec<f64>) -> error::Result<Matrix> {
32 if m.len() == 16 {
33 Ok(Matrix { m: m.clone() })
34 } else {
35 panic!("Array size mismatch");
36 }
37 }
38
39 pub fn new_from_array(m: &[f64; 12]) -> Matrix {
40 Matrix { m: m.to_vec() }
41 }
42
43 pub fn new_with_values(
44 v00: f64,
45 v01: f64,
46 v02: f64,
47 v03: f64,
48 v10: f64,
49 v11: f64,
50 v12: f64,
51 v13: f64,
52 v20: f64,
53 v21: f64,
54 v22: f64,
55 v23: f64,
56 v30: f64,
57 v31: f64,
58 v32: f64,
59 v33: f64,
60 ) -> Matrix {
61 Matrix {
62 m: vec![
63 v00, v01, v02, v03, v10, v11, v12, v13, v20, v21, v22, v23, v30, v31, v32, v33,
64 ],
65 }
66 }
67
68 fn index(&self, x: usize, y: usize) -> usize {
69 y * 4 + x
70 }
71
72 pub fn set(&mut self, x: usize, y: usize, v: f64) {
73 let i = self.index(x, y);
74 if i < 16 {
75 self.m[i] = v;
76 } else {
77 panic!("Invalid pixel coordinates");
78 }
79 }
80
81 pub fn get(&self, x: usize, y: usize) -> f64 {
82 let i = self.index(x, y);
83 if i < 16 {
84 self.m[i]
85 } else {
86 panic!("Invalid pixel coordinates");
87 }
88 }
89
90 pub fn matmul4(a: &Matrix, b: &Matrix) -> Matrix {
91 let mut product = vec![
92 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
93 ];
94
95 for row in 0..3 {
96 let ai0 = a.m[(0 << 2) + row];
97 let ai1 = a.m[(1 << 2) + row];
98 let ai2 = a.m[(2 << 2) + row];
99 let ai3 = a.m[(3 << 2) + row];
100
101 product[(0 << 2) + row] = ai0 * b.m[(0 << 2)]
102 + ai1 * b.m[(0 << 2) + 1]
103 + ai2 * b.m[(0 << 2) + 2]
104 + ai3 * b.m[(0 << 2) + 3];
105 product[(1 << 2) + row] = ai0 * b.m[(1 << 2)]
106 + ai1 * b.m[(1 << 2) + 1]
107 + ai2 * b.m[(1 << 2) + 2]
108 + ai3 * b.m[(1 << 2) + 3];
109 product[(2 << 2) + row] = ai0 * b.m[(2 << 2)]
110 + ai1 * b.m[(2 << 2) + 1]
111 + ai2 * b.m[(2 << 2) + 2]
112 + ai3 * b.m[(2 << 2) + 3];
113 product[(3 << 2) + row] = ai0 * b.m[(3 << 2)]
114 + ai1 * b.m[(3 << 2) + 1]
115 + ai2 * b.m[(3 << 2) + 2]
116 + ai3 * b.m[(3 << 2) + 3];
117 }
118
119 Matrix::new_from_vec(&product).unwrap()
120 }
121
122 pub fn multiply(&self, other: &Matrix) -> Matrix {
123 Matrix::matmul4(self, other)
124 }
125
126 pub fn multiply_vector(&self, other: &Vector) -> Vector {
127 let x = other.x * self.m[0] + other.y * self.m[4 + 0] + other.z * self.m[2 * 4 + 0];
128 let y = other.x * self.m[1] + other.y * self.m[4 + 1] + other.z * self.m[2 * 4 + 1];
129 let z = other.x * self.m[2] + other.y * self.m[4 + 2] + other.z * self.m[2 * 4 + 2];
130 Vector::new(x, y, z)
131 }
132
133 pub fn scale(&self, x: f64, y: f64, z: f64) -> Matrix {
134 Matrix {
135 m: vec![
136 self.m[0] * x,
137 self.m[1] * x,
138 self.m[2] * x,
139 self.m[4] * y,
140 self.m[5] * y,
141 self.m[6] * y,
142 self.m[8] * z,
143 self.m[9] * z,
144 self.m[10] * z,
145 ],
146 }
147 }
148
149 pub fn transpose_rotation(&self) -> Matrix {
150 let mut t = self.clone();
151 t.m[1] = self.m[4];
152 t.m[4] = self.m[1];
153
154 t.m[2] = self.m[8];
155 t.m[8] = self.m[2];
156
157 t.m[6] = self.m[9];
158 t.m[9] = self.m[6];
159
160 t
161 }
162
163 pub fn rotate(angle: f64, axis: Axis) -> Matrix {
164 let mut m = Matrix::identity();
165
166 let _a = if axis != Axis::YAxis {
167 angle
168 } else {
169 angle * -1.0
170 };
171
172 let c = _a.cos();
173 let s = _a.sin();
174
175 match axis {
176 Axis::XAxis => {
177 m.set(1, 1, c);
178 m.set(2, 2, c);
179 m.set(2, 1, -s);
180 m.set(1, 2, s);
181 }
182 Axis::YAxis => {
183 m.set(0, 0, c);
184 m.set(2, 2, c);
185 m.set(2, 0, s);
186 m.set(0, 2, -s);
187 }
188 Axis::ZAxis => {
189 m.set(0, 0, c);
190 m.set(1, 1, c);
191 m.set(0, 1, s);
192 m.set(1, 0, -s);
193 }
194 }
195
196 m
197 }
198}