webgl_matrix/
mat4.rs

1use crate::matrix::Matrix;
2use crate::utils::EPSILON;
3use crate::vec4::Vec4;
4use std::f32;
5
6pub type Mat4 = [f32; 16];
7
8impl Matrix for Mat4 {
9    type MatrixType = Mat4;
10    type VectorType = Vec4;
11
12    fn zeros() -> Self {
13        [0.; 16]
14    }
15    fn ones() -> Self {
16        [1.; 16]
17    }
18    fn identity() -> Self {
19        [
20            1., 0., 0., 0., 0., 1., 0., 0., 0., 0., 1., 0., 0., 0., 0., 1.,
21        ]
22    }
23
24    fn copy_to(&self, dst: &mut Self) {
25        for i in 0..16 {
26            dst[i] = self[i];
27        }
28    }
29
30    fn transpose(&mut self) -> &mut Self {
31        let v01 = self[1];
32        let v02 = self[2];
33        let v03 = self[3];
34        let v12 = self[6];
35        let v13 = self[7];
36        let v23 = self[11];
37
38        self[1] = self[4];
39        self[2] = self[8];
40        self[3] = self[12];
41        self[4] = v01;
42        self[6] = self[9];
43        self[7] = self[13];
44        self[8] = v02;
45        self[9] = v12;
46        self[11] = self[14];
47        self[12] = v03;
48        self[13] = v13;
49        self[14] = v23;
50
51        self
52    }
53
54    fn mul(&mut self, rhs: &Self) -> &mut Self {
55        let r00 = rhs[0];
56        let r01 = rhs[1];
57        let r02 = rhs[2];
58        let r03 = rhs[3];
59        let r10 = rhs[4];
60        let r11 = rhs[5];
61        let r12 = rhs[6];
62        let r13 = rhs[7];
63        let r20 = rhs[8];
64        let r21 = rhs[9];
65        let r22 = rhs[10];
66        let r23 = rhs[11];
67        let r30 = rhs[12];
68        let r31 = rhs[13];
69        let r32 = rhs[14];
70        let r33 = rhs[15];
71
72        let mut v0 = self[0];
73        let mut v1 = self[1];
74        let mut v2 = self[2];
75        let mut v3 = self[3];
76        self[0] = v0 * r00 + v1 * r10 + v2 * r20 + v3 * r30;
77        self[1] = v0 * r01 + v1 * r11 + v2 * r21 + v3 * r31;
78        self[2] = v0 * r02 + v1 * r12 + v2 * r22 + v3 * r32;
79        self[3] = v0 * r03 + v1 * r13 + v2 * r23 + v3 * r33;
80
81        v0 = self[4];
82        v1 = self[5];
83        v2 = self[6];
84        v3 = self[7];
85        self[4] = v0 * r00 + v1 * r10 + v2 * r20 + v3 * r30;
86        self[5] = v0 * r01 + v1 * r11 + v2 * r21 + v3 * r31;
87        self[6] = v0 * r02 + v1 * r12 + v2 * r22 + v3 * r32;
88        self[7] = v0 * r03 + v1 * r13 + v2 * r23 + v3 * r33;
89
90        v0 = self[8];
91        v1 = self[9];
92        v2 = self[10];
93        v3 = self[11];
94        self[8] = v0 * r00 + v1 * r10 + v2 * r20 + v3 * r30;
95        self[9] = v0 * r01 + v1 * r11 + v2 * r21 + v3 * r31;
96        self[10] = v0 * r02 + v1 * r12 + v2 * r22 + v3 * r32;
97        self[11] = v0 * r03 + v1 * r13 + v2 * r23 + v3 * r33;
98
99        v0 = self[12];
100        v1 = self[13];
101        v2 = self[14];
102        v3 = self[15];
103        self[12] = v0 * r00 + v1 * r10 + v2 * r20 + v3 * r30;
104        self[13] = v0 * r01 + v1 * r11 + v2 * r21 + v3 * r31;
105        self[14] = v0 * r02 + v1 * r12 + v2 * r22 + v3 * r32;
106        self[15] = v0 * r03 + v1 * r13 + v2 * r23 + v3 * r33;
107
108        self
109    }
110    fn mul_vector(&self, rhs: &[f32]) -> Vec4 {
111        debug_assert!(rhs.len() >= 3);
112        let x = rhs[0];
113        let y = rhs[1];
114        let z = rhs[2];
115        let w = if rhs.len() > 3 { rhs[3] } else { 1. };
116
117        [
118            self[0] * x + self[1] * y + self[2] * z + self[3] * w,
119            self[4] * x + self[5] * y + self[6] * z + self[7] * w,
120            self[8] * x + self[9] * y + self[10] * z + self[11] * w,
121            self[12] * x + self[13] * y + self[14] * z + self[15] * w,
122        ]
123    }
124    fn mul_vector_left(&self, lhs: &[f32]) -> Vec4 {
125        debug_assert!(lhs.len() >= 3);
126        let x = lhs[0];
127        let y = lhs[1];
128        let z = lhs[2];
129        let w = if lhs.len() > 3 { lhs[3] } else { 1. };
130        [
131            self[0] * x + self[4] * y + self[8] * z + self[12] * w,
132            self[1] * x + self[5] * y + self[9] * z + self[13] * w,
133            self[2] * x + self[6] * y + self[10] * z + self[14] * w,
134            self[3] * x + self[7] * y + self[11] * z + self[15] * w,
135        ]
136    }
137    fn add(&mut self, rhs: &Self) -> &mut Self {
138        for i in 0..16 {
139            self[i] += rhs[i];
140        }
141
142        self
143    }
144    fn sub(&mut self, rhs: &Self) -> &mut Self {
145        for i in 0..16 {
146            self[i] -= rhs[i];
147        }
148
149        self
150    }
151
152    fn scale(&mut self, factor: f32) -> &mut Self {
153        for i in 0..16 {
154            self[i] *= factor;
155        }
156
157        self
158    }
159
160    fn inverse(&mut self) -> Option<&mut Self> {
161        let v00 = self[0];
162        let v01 = self[1];
163        let v02 = self[2];
164        let v03 = self[3];
165        let v10 = self[4];
166        let v11 = self[5];
167        let v12 = self[6];
168        let v13 = self[7];
169        let v20 = self[8];
170        let v21 = self[9];
171        let v22 = self[10];
172        let v23 = self[11];
173        let v30 = self[12];
174        let v31 = self[13];
175        let v32 = self[14];
176        let v33 = self[15];
177
178        let tmp00 = v00 * v11 - v01 * v10;
179        let tmp01 = v00 * v12 - v02 * v10;
180        let tmp02 = v00 * v13 - v03 * v10;
181        let tmp03 = v01 * v12 - v02 * v11;
182        let tmp04 = v01 * v13 - v03 * v11;
183        let tmp05 = v02 * v13 - v03 * v12;
184        let tmp06 = v20 * v31 - v21 * v30;
185        let tmp07 = v20 * v32 - v22 * v30;
186        let tmp08 = v20 * v33 - v23 * v30;
187        let tmp09 = v21 * v32 - v22 * v31;
188        let tmp10 = v21 * v33 - v23 * v31;
189        let tmp11 = v22 * v33 - v23 * v32;
190
191        let det = tmp00 * tmp11 - tmp01 * tmp10 + tmp02 * tmp09 + tmp03 * tmp08 - tmp04 * tmp07
192            + tmp05 * tmp06;
193
194        if det.abs() <= EPSILON {
195            return None;
196        }
197        let det_inv = 1.0 / det;
198
199        self[0] = (v11 * tmp11 - v12 * tmp10 + v13 * tmp09) * det_inv;
200        self[1] = (v02 * tmp10 - v01 * tmp11 - v03 * tmp09) * det_inv;
201        self[2] = (v31 * tmp05 - v32 * tmp04 + v33 * tmp03) * det_inv;
202        self[3] = (v22 * tmp04 - v21 * tmp05 - v23 * tmp03) * det_inv;
203        self[4] = (v12 * tmp08 - v10 * tmp11 - v13 * tmp07) * det_inv;
204        self[5] = (v00 * tmp11 - v02 * tmp08 + v03 * tmp07) * det_inv;
205        self[6] = (v32 * tmp02 - v30 * tmp05 - v33 * tmp01) * det_inv;
206        self[7] = (v20 * tmp05 - v22 * tmp02 + v23 * tmp01) * det_inv;
207        self[8] = (v10 * tmp10 - v11 * tmp08 + v13 * tmp06) * det_inv;
208        self[9] = (v01 * tmp08 - v00 * tmp10 - v03 * tmp06) * det_inv;
209        self[10] = (v30 * tmp04 - v31 * tmp02 + v33 * tmp00) * det_inv;
210        self[11] = (v21 * tmp02 - v20 * tmp04 - v23 * tmp00) * det_inv;
211        self[12] = (v11 * tmp07 - v10 * tmp09 - v12 * tmp06) * det_inv;
212        self[13] = (v00 * tmp09 - v01 * tmp07 + v02 * tmp06) * det_inv;
213        self[14] = (v31 * tmp01 - v30 * tmp03 - v32 * tmp00) * det_inv;
214        self[15] = (v20 * tmp03 - v21 * tmp01 + v22 * tmp00) * det_inv;
215
216        Some(self)
217    }
218
219    fn det(&self) -> f32 {
220        let v00 = self[0];
221        let v01 = self[1];
222        let v02 = self[2];
223        let v03 = self[3];
224        let v10 = self[4];
225        let v11 = self[5];
226        let v12 = self[6];
227        let v13 = self[7];
228        let v20 = self[8];
229        let v21 = self[9];
230        let v22 = self[10];
231        let v23 = self[11];
232        let v30 = self[12];
233        let v31 = self[13];
234        let v32 = self[14];
235        let v33 = self[15];
236
237        let tmp00 = v00 * v11 - v01 * v10;
238        let tmp01 = v00 * v12 - v02 * v10;
239        let tmp02 = v00 * v13 - v03 * v10;
240        let tmp03 = v01 * v12 - v02 * v11;
241        let tmp04 = v01 * v13 - v03 * v11;
242        let tmp05 = v02 * v13 - v03 * v12;
243        let tmp06 = v20 * v31 - v21 * v30;
244        let tmp07 = v20 * v32 - v22 * v30;
245        let tmp08 = v20 * v33 - v23 * v30;
246        let tmp09 = v21 * v32 - v22 * v31;
247        let tmp10 = v21 * v33 - v23 * v31;
248        let tmp11 = v22 * v33 - v23 * v32;
249
250        tmp00 * tmp11 - tmp01 * tmp10 + tmp02 * tmp09 + tmp03 * tmp08 - tmp04 * tmp07
251            + tmp05 * tmp06
252    }
253
254    fn adjugate(&mut self) -> &mut Self {
255        let v00 = self[0];
256        let v01 = self[1];
257        let v02 = self[2];
258        let v03 = self[3];
259        let v10 = self[4];
260        let v11 = self[5];
261        let v12 = self[6];
262        let v13 = self[7];
263        let v20 = self[8];
264        let v21 = self[9];
265        let v22 = self[10];
266        let v23 = self[11];
267        let v30 = self[12];
268        let v31 = self[13];
269        let v32 = self[14];
270        let v33 = self[15];
271
272        self[0] = v11 * (v22 * v33 - v23 * v32) - v21 * (v12 * v33 - v13 * v32)
273            + v31 * (v12 * v23 - v13 * v22);
274        self[1] = -(v01 * (v22 * v33 - v23 * v32) - v21 * (v02 * v33 - v03 * v32)
275            + v31 * (v02 * v23 - v03 * v22));
276        self[2] = v01 * (v12 * v33 - v13 * v32) - v11 * (v02 * v33 - v03 * v32)
277            + v31 * (v02 * v13 - v03 * v12);
278        self[3] = -(v01 * (v12 * v23 - v13 * v22) - v11 * (v02 * v23 - v03 * v22)
279            + v21 * (v02 * v13 - v03 * v12));
280        self[4] = -(v10 * (v22 * v33 - v23 * v32) - v20 * (v12 * v33 - v13 * v32)
281            + v30 * (v12 * v23 - v13 * v22));
282        self[5] = v00 * (v22 * v33 - v23 * v32) - v20 * (v02 * v33 - v03 * v32)
283            + v30 * (v02 * v23 - v03 * v22);
284        self[6] = -(v00 * (v12 * v33 - v13 * v32) - v10 * (v02 * v33 - v03 * v32)
285            + v30 * (v02 * v13 - v03 * v12));
286        self[7] = v00 * (v12 * v23 - v13 * v22) - v10 * (v02 * v23 - v03 * v22)
287            + v20 * (v02 * v13 - v03 * v12);
288        self[8] = v10 * (v21 * v33 - v23 * v31) - v20 * (v11 * v33 - v13 * v31)
289            + v30 * (v11 * v23 - v13 * v21);
290        self[9] = -(v00 * (v21 * v33 - v23 * v31) - v20 * (v01 * v33 - v03 * v31)
291            + v30 * (v01 * v23 - v03 * v21));
292        self[10] = v00 * (v11 * v33 - v13 * v31) - v10 * (v01 * v33 - v03 * v31)
293            + v30 * (v01 * v13 - v03 * v11);
294        self[11] = -(v00 * (v11 * v23 - v13 * v21) - v10 * (v01 * v23 - v03 * v21)
295            + v20 * (v01 * v13 - v03 * v11));
296        self[12] = -(v10 * (v21 * v32 - v22 * v31) - v20 * (v11 * v32 - v12 * v31)
297            + v30 * (v11 * v22 - v12 * v21));
298        self[13] = v00 * (v21 * v32 - v22 * v31) - v20 * (v01 * v32 - v02 * v31)
299            + v30 * (v01 * v22 - v02 * v21);
300        self[14] = -(v00 * (v11 * v32 - v12 * v31) - v10 * (v01 * v32 - v02 * v31)
301            + v30 * (v01 * v12 - v02 * v11));
302        self[15] = v00 * (v11 * v22 - v12 * v21) - v10 * (v01 * v22 - v02 * v21)
303            + v20 * (v01 * v12 - v02 * v11);
304
305        self
306    }
307
308    fn translate(&mut self, direction: &[f32]) -> &mut Self {
309        debug_assert!(direction.len() >= 3);
310
311        let mut x = direction[0];
312        let mut y = direction[1];
313        let mut z = direction[2];
314
315        if direction.len() > 3 {
316            x /= direction[3];
317            y /= direction[3];
318            z /= direction[3];
319        }
320
321        self[12] += self[0] * x + self[4] * y + self[8] * z;
322        self[13] += self[1] * x + self[5] * y + self[9] * z;
323        self[14] += self[2] * x + self[6] * y + self[10] * z;
324        self[15] += self[3] * x + self[7] * y + self[11] * z;
325
326        self
327    }
328
329    fn rotate(&mut self, angle: f32, axis: &[f32]) -> &mut Self {
330        debug_assert!(axis.len() >= 3);
331
332        let mut x = axis[0];
333        let mut y = axis[1];
334        let mut z = axis[2];
335
336        if axis.len() > 3 {
337            x /= axis[3];
338            y /= axis[3];
339            z /= axis[3];
340        }
341
342        let len = (x * x + y * y + z * z).sqrt();
343
344        // no rotation around nothing
345        if len.abs() <= EPSILON {
346            debug_assert!(len.abs() > EPSILON);
347            return self;
348        }
349
350        x /= len;
351        y /= len;
352        z /= len;
353
354        let (s, c) = angle.sin_cos();
355        let t = 1. - c;
356
357        let v00 = self[0];
358        let v01 = self[1];
359        let v02 = self[2];
360        let v03 = self[3];
361        let v10 = self[4];
362        let v11 = self[5];
363        let v12 = self[6];
364        let v13 = self[7];
365        let v20 = self[8];
366        let v21 = self[9];
367        let v22 = self[10];
368        let v23 = self[11];
369
370        let rot00 = x * x * t + c;
371        let rot01 = y * x * t + z * s;
372        let rot02 = z * x * t - y * s;
373
374        let rot10 = x * y * t - z * s;
375        let rot11 = y * y * t + c;
376        let rot12 = z * y * t + x * s;
377
378        let rot20 = x * z * t + y * s;
379        let rot21 = y * z * t - x * s;
380        let rot22 = z * z * t + c;
381
382        self[0] = v00 * rot00 + v10 * rot01 + v20 * rot02;
383        self[1] = v01 * rot00 + v11 * rot01 + v21 * rot02;
384        self[2] = v02 * rot00 + v12 * rot01 + v22 * rot02;
385        self[3] = v03 * rot00 + v13 * rot01 + v23 * rot02;
386        self[4] = v00 * rot10 + v10 * rot11 + v20 * rot12;
387        self[5] = v01 * rot10 + v11 * rot11 + v21 * rot12;
388        self[6] = v02 * rot10 + v12 * rot11 + v22 * rot12;
389        self[7] = v03 * rot10 + v13 * rot11 + v23 * rot12;
390        self[8] = v00 * rot20 + v10 * rot21 + v20 * rot22;
391        self[9] = v01 * rot20 + v11 * rot21 + v21 * rot22;
392        self[10] = v02 * rot20 + v12 * rot21 + v22 * rot22;
393        self[11] = v03 * rot20 + v13 * rot21 + v23 * rot22;
394
395        self
396    }
397}
398
399pub trait ProjectionMatrix {
400    fn create_perspective(fov_y: f32, aspect_ratio: f32, near: f32, far: f32) -> Mat4;
401    fn create_perspective_from_viewport(
402        vp_left: f32,
403        vp_right: f32,
404        vp_bot: f32,
405        vp_top: f32,
406        near: f32,
407        far: f32,
408    ) -> Mat4;
409
410    fn create_orthogonal_from_viewport(
411        vp_left: f32,
412        vp_right: f32,
413        vp_bot: f32,
414        vp_top: f32,
415        near: f32,
416        far: f32,
417    ) -> Mat4;
418}
419
420impl ProjectionMatrix for Mat4 {
421    fn create_perspective(fov_y: f32, aspect_ratio: f32, near: f32, far: f32) -> Self {
422        let f = 1. / (fov_y / 2.).tan();
423        let nf = 1. / (near - far);
424        [
425            f / aspect_ratio,
426            0.,
427            0.,
428            0.,
429            0.,
430            f,
431            0.,
432            0.,
433            0.,
434            0.,
435            (far + near) * nf,
436            -1.,
437            0.,
438            0.,
439            2. * far * near * nf,
440            0.,
441        ]
442    }
443    fn create_perspective_from_viewport(
444        vp_left: f32,
445        vp_right: f32,
446        vp_bot: f32,
447        vp_top: f32,
448        near: f32,
449        far: f32,
450    ) -> Self {
451        let wi = 1. / (vp_right - vp_left);
452        let hi = 1. / (vp_top - vp_bot);
453        let nf = 1. / (near - far);
454
455        [
456            near * 2. * wi,
457            0.,
458            0.,
459            0.,
460            0.,
461            near * 2. * hi,
462            0.,
463            0.,
464            (vp_right + vp_left) * wi,
465            (vp_top + vp_bot) * hi,
466            (far + near) * nf,
467            -1.,
468            0.,
469            0.,
470            far * near * 2. * nf,
471            0.,
472        ]
473    }
474
475    fn create_orthogonal_from_viewport(
476        vp_left: f32,
477        vp_right: f32,
478        vp_bot: f32,
479        vp_top: f32,
480        near: f32,
481        far: f32,
482    ) -> Self {
483        let wi = 1. / (vp_right - vp_left);
484        let hi = 1. / (vp_top - vp_bot);
485        let nf = 1. / (near - far);
486
487        [
488            2. * wi,
489            0.,
490            0.,
491            0.,
492            0.,
493            2. * hi,
494            0.,
495            0.,
496            0.,
497            0.,
498            2. * nf,
499            0.,
500            -(vp_left + vp_right) * wi,
501            -(vp_top + vp_bot) * hi,
502            (far + near) * nf,
503            1.,
504        ]
505    }
506}
507
508#[cfg(test)]
509mod tests {
510    use super::*;
511    use crate::utils::almost_eq;
512
513    #[test]
514    fn mat4_zeros() {
515        let zeros = Mat4::zeros();
516        assert!(zeros.iter().all(|&x| x == 0.0));
517    }
518
519    #[test]
520    fn mat4_ones() {
521        let zeros = Mat4::ones();
522        assert!(zeros.iter().all(|&x| x == 1.0));
523    }
524
525    #[test]
526    fn mat4_identity() {
527        let i = Mat4::identity();
528        assert_eq!(i[0], 1.0);
529        assert_eq!(i[1], 0.0);
530        assert_eq!(i[2], 0.0);
531        assert_eq!(i[3], 0.0);
532
533        assert_eq!(i[4], 0.0);
534        assert_eq!(i[5], 1.0);
535        assert_eq!(i[6], 0.0);
536        assert_eq!(i[7], 0.0);
537
538        assert_eq!(i[8], 0.0);
539        assert_eq!(i[9], 0.0);
540        assert_eq!(i[10], 1.0);
541        assert_eq!(i[11], 0.0);
542
543        assert_eq!(i[12], 0.0);
544        assert_eq!(i[13], 0.0);
545        assert_eq!(i[14], 0.0);
546        assert_eq!(i[15], 1.0);
547    }
548
549    #[test]
550    fn mat4_copy_to() {
551        let mut a = Mat4::zeros();
552        let b = Mat4::ones();
553
554        b.copy_to(&mut a);
555        assert!(a.iter().all(|&x| x == 1.0));
556    }
557
558    #[test]
559    fn mat4_transpose() {
560        //  1  2  3  4
561        //  5  6  7  8
562        //  9 10 11 12
563        // 13 14 15 16
564        //
565        // --->
566        //
567        //  1  5  9 13
568        //  2  6 10 14
569        //  3  7 11 15
570        //  4  8 12 16
571        let mut a = [
572            1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12., 13., 14., 15., 16.,
573        ];
574        a.transpose();
575        let b = [
576            1., 5., 9., 13., 2., 6., 10., 14., 3., 7., 11., 15., 4., 8., 12., 16.,
577        ];
578
579        assert_eq!(a, b);
580    }
581
582    #[test]
583    fn mat4_mul() {
584        let mut a = [
585            1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12., 13., 14., 15., 16.,
586        ];
587        let b = [
588            11., 12., 13., 14., 15., 16., 17., 18., 19., 20., 21., 22., 23., 24., 25., 26.,
589        ];
590
591        let c = [
592            190., 200., 210., 220., 462., 488., 514., 540., 734., 776., 818., 860., 1006., 1064.,
593            1122., 1180.,
594        ];
595
596        assert_eq!(a.mul(&b), &c);
597    }
598
599    #[test]
600    fn mat4_mul_identity() {
601        let a = [
602            1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12., 13., 14., 15., 16.,
603        ];
604        let mut b = Mat4::identity();
605
606        assert_eq!(b.mul(&a), &a);
607    }
608
609    #[test]
610    fn mat4_add() {
611        let mut a = [
612            1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12., 13., 14., 15., 16.,
613        ];
614        let b = [
615            11., 12., 13., 14., 15., 16., 17., 18., 19., 20., 21., 22., 23., 24., 25., 26.,
616        ];
617
618        let c = [
619            12., 14., 16., 18., 20., 22., 24., 26., 28., 30., 32., 34., 36., 38., 40., 42.,
620        ];
621
622        assert_eq!(a.add(&b), &c);
623    }
624
625    #[test]
626    fn mat4_sub() {
627        let mut a = [
628            16., 15., 14., 13., 12., 11., 10., 9., 8., 7., 6., 5., 4., 3., 2., 1.,
629        ];
630        let b = [
631            11., 12., 13., 14., 15., 16., 17., 18., 19., 20., 21., 22., 23., 24., 25., 26.,
632        ];
633
634        let c = [
635            5., 3., 1., -1., -3., -5., -7., -9., -11., -13., -15., -17., -19., -21., -23., -25.,
636        ];
637
638        assert_eq!(a.sub(&b), &c);
639    }
640
641    #[test]
642    fn mat4_scale() {
643        let mut a = [
644            16., 15., 14., 13., 12., 11., 10., 9., 8., 7., 6., 5., 4., 3., 2., 1.,
645        ];
646        let b = [
647            32., 30., 28., 26., 24., 22., 20., 18., 16., 14., 12., 10., 8., 6., 4., 2.,
648        ];
649
650        assert_eq!(a.scale(2.0), &b);
651    }
652
653    #[test]
654    fn mat4_inverse_valid() {
655        let mut a = [
656            3., 4., 1., 2., 3., 6., 10., 12., 2., 7., 3., 14., 16., 4., 8., 18.,
657        ];
658        let b = a.clone();
659
660        a.inverse().expect("Inverse should exist");
661
662        let inv = [
663            0.0976342, -0.0401802, -0.0548254, 0.0585805, 0.2482163, 0.0093879, 0.0221555,
664            -0.0510702, -0.0168982, 0.1415697, -0.1058956, -0.0101389, -0.1344348, -0.0292903,
665            0.0908750, 0.0193391,
666        ];
667
668        assert!(almost_eq(&inv, &a));
669
670        assert!(almost_eq(a.mul(&b), &Mat4::identity()));
671    }
672
673    #[test]
674    fn mat4_inverse_invalid() {
675        let mut a = [
676            1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12., 13., 14., 15., 16.,
677        ];
678        assert_eq!(a.inverse(), None);
679    }
680
681    #[test]
682    fn mat4_det() {
683        let a = [
684            3., 4., 1., 2., 3., 6., 10., 12., 2., 7., 3., 14., 16., 4., 8., 18.,
685        ];
686        assert_eq!(a.det(), -5326.0);
687    }
688
689    #[test]
690    fn mat4_adjugate() {
691        let mut a = [
692            3., 4., 1., 2., 3., 6., 10., 12., 2., 7., 3., 14., 16., 4., 8., 18.,
693        ];
694        let b = [
695            -520., 214., 292., -312., -1322., -50., -118., 272., 90., -754., 564., 54., 716., 156.,
696            -484., -103.,
697        ];
698        assert_eq!(a.adjugate(), &b);
699    }
700
701    #[test]
702    fn mat4_mul_vector() {
703        let a = [
704            1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12., 13., 14., 15., 16.,
705        ];
706        let b = [17., 18., 19., 20.];
707
708        let c = a.mul_vector(&b);
709        assert_eq!(c, [190., 486., 782., 1078.]);
710    }
711
712    #[test]
713    fn mat4_mul_vector_left() {
714        let a = [
715            1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12., 13., 14., 15., 16.,
716        ];
717        let b = [17., 18., 19., 20.];
718
719        let c = a.mul_vector_left(&b);
720        assert_eq!(c, [538., 612., 686., 760.]);
721    }
722
723    #[test]
724    fn mat4_translate() {
725        let d = [3., -5., 7., 1.];
726        let mut m = Mat4::identity();
727        m.translate(&d);
728
729        let a = [-3., 5., -7., 1.];
730        assert_eq!(m.mul_vector_left(&a), [0., 0., 0., 1.]);
731    }
732
733    #[test]
734    fn mat4_rotate_x() {
735        let mut m = Mat4::identity();
736        m.rotate(f32::consts::FRAC_PI_2, &[1., 0., 0., 1.]);
737        let v = [-1., 3., 5., 1.];
738
739        let r = m.mul_vector_left(&v);
740        assert!(almost_eq(&r, &[-1., -5., 3., 1.]));
741    }
742
743    #[test]
744    fn mat4_rotate_y() {
745        let mut m = Mat4::identity();
746        m.rotate(f32::consts::FRAC_PI_2, &[0., 1., 0., 1.]);
747        let v = [-1., 3., 5., 1.];
748
749        let r = m.mul_vector_left(&v);
750        assert!(almost_eq(&r, &[5., 3., 1., 1.]));
751    }
752
753    #[test]
754    fn mat4_rotate_z() {
755        let mut m = Mat4::identity();
756        m.rotate(f32::consts::FRAC_PI_2, &[0., 0., 1., 1.]);
757        let v = [-1., 3., 5., 1.];
758
759        let r = m.mul_vector_left(&v);
760        assert!(almost_eq(&r, &[-3., -1., 5., 1.]));
761    }
762}