1use std::ops::Mul;
26
27use crate::*;
28
29#[derive(Debug, PartialEq, PartialOrd, Clone)]
32pub struct Matrix4 {
34 pub data: [[f64; 4]; 4],
35}
36
37impl Matrix4 {
38 pub fn identity() -> Matrix4 {
40 Matrix4 {
41 data: [
42 [1.0, 0.0, 0.0, 0.0],
43 [0.0, 1.0, 0.0, 0.0],
44 [0.0, 0.0, 1.0, 0.0],
45 [0.0, 0.0, 0.0, 1.0],
46 ],
47 }
48 }
49 pub fn zeroes() -> Matrix4 {
51 Matrix4 {
52 data: [
53 [0.0, 0.0, 0.0, 0.0],
54 [0.0, 0.0, 0.0, 0.0],
55 [0.0, 0.0, 0.0, 0.0],
56 [0.0, 0.0, 0.0, 0.0],
57 ],
58 }
59 }
60 pub fn translation(x: f64, y: f64, z: f64) -> Matrix4 {
62 Matrix4 {
63 data: [
64 [1.0, 0.0, 0.0, x],
65 [0.0, 1.0, 0.0, y],
66 [0.0, 0.0, 1.0, z],
67 [0.0, 0.0, 0.0, 1.0],
68 ],
69 }
70 }
71 pub fn scale(x: f64, y: f64, z: f64) -> Matrix4 {
73 Matrix4 {
74 data: [
75 [x, 0.0, 0.0, 0.0],
76 [0.0, y, 0.0, 0.0],
77 [0.0, 0.0, z, 0.0],
78 [0.0, 0.0, 0.0, 1.0],
79 ],
80 }
81 }
82 pub fn rotation(x: Rad, y: Rad, z: Rad) -> Matrix4 {
84 let (mut mx, mut my, mut mz) = (Matrix4::default(), Matrix4::default(), Matrix4::default());
85 let (rad_x, rad_y, rad_z) = (x.val, y.val, z.val);
86
87 mx.data[0][0] = 1.0;
88 mx.data[0][1] = 0.0;
89 mx.data[0][2] = 0.0;
90 mx.data[0][3] = 0.0;
91 mx.data[1][0] = 0.0;
92 mx.data[1][1] = rad_x.cos();
93 mx.data[1][2] = -rad_x.sin();
94 mx.data[1][3] = 0.0;
95 mx.data[2][0] = 0.0;
96 mx.data[2][1] = rad_x.sin();
97 mx.data[2][2] = rad_x.cos();
98 mx.data[2][3] = 0.0;
99 mx.data[3][0] = 0.0;
100 mx.data[3][1] = 0.0;
101 mx.data[3][2] = 0.0;
102 mx.data[3][3] = 1.0;
103
104 my.data[0][0] = rad_y.cos();
105 my.data[0][1] = 0.0;
106 my.data[0][2] = rad_y.sin();
107 my.data[0][3] = 0.0;
108 my.data[1][0] = 0.0;
109 my.data[1][1] = 1.0;
110 my.data[1][2] = 0.0;
111 my.data[1][3] = 0.0;
112 my.data[2][0] = -rad_y.sin();
113 my.data[2][1] = 0.0;
114 my.data[2][2] = rad_y.cos();
115 my.data[2][3] = 0.0;
116 my.data[3][0] = 0.0;
117 my.data[3][1] = 0.0;
118 my.data[3][2] = 0.0;
119 my.data[3][3] = 1.0;
120
121 mz.data[0][0] = rad_z.cos();
122 mz.data[0][1] = -rad_z.sin();
123 mz.data[0][2] = 0.0;
124 mz.data[0][3] = 0.0;
125 mz.data[1][0] = rad_z.sin();
126 mz.data[1][1] = rad_z.cos();
127 mz.data[1][2] = 0.0;
128 mz.data[1][3] = 0.0;
129 mz.data[2][0] = 0.0;
130 mz.data[2][1] = 0.0;
131 mz.data[2][2] = 1.0;
132 mz.data[2][3] = 0.0;
133 mz.data[3][0] = 0.0;
134 mz.data[3][1] = 0.0;
135 mz.data[3][2] = 0.0;
136 mz.data[3][3] = 1.0;
137
138 mx * my * mz
139 }
140 pub fn rotation_axis<N>(axis: &N, r: Rad) -> Matrix4
142 where
143 N: IsNormalized3D,
144 {
145 let rad = r.val;
146 let ref u = axis;
147 let mut result = Matrix4::default();
148 result.data[0][0] = rad.cos() + u.x() * u.x() * (1.0 - rad.cos());
149 result.data[0][1] = u.x() * u.y() * (1.0 - rad.cos()) - u.z() * rad.sin();
150 result.data[0][2] = u.x() * u.z() * (1.0 - rad.cos()) + u.y() * rad.sin();
151 result.data[0][3] = 0.0;
152 result.data[1][0] = u.y() * u.x() * (1.0 - rad.cos()) + u.z() * rad.sin();
153 result.data[1][1] = rad.cos() + u.y() * u.y() * (1.0 - rad.cos());
154 result.data[1][2] = u.y() * u.z() * (1.0 - rad.cos()) - u.x() * rad.sin();
155 result.data[1][3] = 0.0;
156 result.data[2][0] = u.z() * u.x() * (1.0 - rad.cos()) - u.y() * rad.sin();
157 result.data[2][1] = u.z() * u.y() * (1.0 - rad.cos()) + u.x() * rad.sin();
158 result.data[2][2] = rad.cos() + u.z() * u.z() * (1.0 - rad.cos());
159 result.data[2][3] = 0.0;
160 result.data[3][0] = 0.0;
161 result.data[3][1] = 0.0;
162 result.data[3][2] = 0.0;
163 result.data[3][3] = 1.0;
164 result
165 }
166 pub fn perspective(close: f64, away: f64, fov: Rad) -> Matrix4 {
168 let fov_rad = fov.val;
169 let range = close - away;
170 let tan_fov_half = (fov_rad / 2.0).tan();
171
172 let mut result = Matrix4::default();
173 result.data[0][0] = 1.0 / (tan_fov_half * away);
174 result.data[0][1] = 0.0;
175 result.data[0][2] = 0.0;
176 result.data[0][3] = 0.0;
177 result.data[1][0] = 0.0;
178 result.data[1][1] = 1.0 / tan_fov_half;
179 result.data[1][2] = 0.0;
180 result.data[1][3] = 0.0;
181 result.data[2][0] = 0.0;
182 result.data[2][1] = 0.0;
183 result.data[2][2] = (-close - away) / range;
184 result.data[2][3] = 2.0 * away * close / range;
185 result.data[3][0] = 0.0;
186 result.data[3][1] = 0.0;
187 result.data[3][2] = 1.0;
188 result.data[3][3] = 1.0;
189 result
190 }
191 pub fn look_at<P, N>(target: &P, up: &N) -> Result<Matrix4>
193 where
194 P: IsBuildable3D,
195 N: IsNormalized3D,
196 {
197 let n = target.normalized()?;
198 let u = cross(&*up, target);
199 let v = cross(&n, &u);
200
201 let mut result = Matrix4::default();
202 result.data[0][0] = u.x();
203 result.data[0][1] = u.y();
204 result.data[0][2] = u.z();
205 result.data[0][3] = 0.0;
206 result.data[1][0] = v.x();
207 result.data[1][1] = v.y();
208 result.data[1][2] = v.z();
209 result.data[1][3] = 0.0;
210 result.data[2][0] = n.x();
211 result.data[2][1] = n.y();
212 result.data[2][2] = n.z();
213 result.data[2][3] = 0.0;
214 result.data[3][0] = 0.0;
215 result.data[3][1] = 0.0;
216 result.data[3][2] = 0.0;
217 result.data[3][3] = 1.0;
218 Ok(result)
219 }
220}
221
222impl Default for Matrix4 {
225 fn default() -> Self {
226 Self::identity()
227 }
228}
229
230impl Mul for Matrix4 {
231 type Output = Self;
232
233 fn mul(self, other: Self) -> Self {
234 let mut result = Matrix4::default();
235 for i in 0..4 {
236 for j in 0..4 {
237 result.data[i][j] = self.data[i][0] * other.data[0][j]
238 + self.data[i][1] * other.data[1][j]
239 + self.data[i][2] * other.data[2][j]
240 + self.data[i][3] * other.data[3][j];
241 }
242 }
243 result
244 }
245}
246
247impl Mul<&Matrix4> for Matrix4 {
248 type Output = Self;
249
250 fn mul(self, other: &Self) -> Self {
251 let mut result = Matrix4::default();
252 for i in 0..4 {
253 for j in 0..4 {
254 result.data[i][j] = self.data[i][0] * other.data[0][j]
255 + self.data[i][1] * other.data[1][j]
256 + self.data[i][2] * other.data[2][j]
257 + self.data[i][3] * other.data[3][j];
258 }
259 }
260 result
261 }
262}
263
264impl Mul for &Matrix4 {
265 type Output = Matrix4;
266
267 fn mul(self, other: Self) -> Matrix4 {
268 let mut result = Matrix4::default();
269 for i in 0..4 {
270 for j in 0..4 {
271 result.data[i][j] = self.data[i][0] * other.data[0][j]
272 + self.data[i][1] * other.data[1][j]
273 + self.data[i][2] * other.data[2][j]
274 + self.data[i][3] * other.data[3][j];
275 }
276 }
277 result
278 }
279}
280
281impl Mul<f64> for Matrix4 {
282 type Output = Self;
283
284 fn mul(self, other: f64) -> Self {
285 let mut result = Matrix4::default();
286 for i in 0..4 {
287 for j in 0..4 {
288 result.data[i][j] = other * self.data[i][j];
289 }
290 }
291 result
292 }
293}
294
295impl Mul<f64> for &Matrix4 {
296 type Output = Matrix4;
297
298 fn mul(self, other: f64) -> Matrix4 {
299 let mut result = Matrix4::default();
300 for i in 0..4 {
301 for j in 0..4 {
302 result.data[i][j] = other * self.data[i][j];
303 }
304 }
305 result
306 }
307}