grassmann/core/
matrix4.rs

1use std::{
2    fmt,
3    fmt::{
4        Display, 
5        Formatter
6    }, 
7    ops::{
8        Add, 
9        AddAssign, 
10        Index, 
11        IndexMut,
12        Sub,
13        SubAssign,
14        Mul,
15        MulAssign,
16        Div,
17        Neg
18    }
19};
20use crate::{Float, matrix3, matrix3::Matrix3, vec4, vector4::Vector4, vector3::Vector3};
21extern crate wasm_bindgen;
22use std::f64::consts::PI;
23use wasm_bindgen::prelude::*;
24use super::matrix::Matrix;
25
26
27
28#[macro_export]
29macro_rules! matrix4 {
30    (
31        $x1:expr, $y1:expr, $z1:expr, $t1:expr,
32        $x2:expr, $y2:expr, $z2:expr, $t2:expr,
33        $x3:expr, $y3:expr, $z3:expr, $t3:expr,
34        $x4:expr, $y4:expr, $z4:expr, $t4:expr
35    ) => {
36        {
37            Matrix4::new([
38                $x1, $y1, $z1, $t1,
39                $x2, $y2, $z2, $t2,
40                $x3, $y3, $z3, $t3,
41                $x4, $y4, $z4, $t4
42            ])
43        }
44    };
45}
46
47
48
49#[macro_export]
50macro_rules! compose_basis4 {
51    (
52        $x:expr, 
53        $y:expr, 
54        $z:expr, 
55        $t:expr
56    ) => {
57        {
58            Matrix4::new([
59                $x[0], $y[0], $z[0], $t[0],
60                $x[1], $y[1], $z[1], $t[1],
61                $x[2], $y[2], $z[2], $t[2],
62                $x[3], $y[3], $z[3], $t[3]
63            ])
64        }
65    };
66}
67
68
69
70#[wasm_bindgen]
71extern "C" {
72    #[wasm_bindgen(js_namespace = console)]
73    fn log(s: &str);
74}
75
76
77
78#[macro_export]
79macro_rules! compose_m4 {
80    ($v:expr) => { $v };
81    ($v:expr, $($x:expr),+) => {
82
83        &( $v ) * &( compose_m4!($($x),*) )
84
85    }
86}
87
88
89
90#[derive(Clone, Debug)]
91pub struct Matrix4 {
92    pub data: [Float; 16]
93}
94
95
96
97impl Display for Matrix4 {
98    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
99        write!(f, 
100            "\n [{}, {}, {}, {}] \n [{}, {}, {}, {}] \n [{}, {}, {}, {}] \n [{}, {}, {}, {}] \n", 
101            self[0], self[1], self[2], self[3],
102            self[4], self[5], self[6], self[7],
103            self[8], self[9], self[10], self[11],
104            self[12], self[13], self[14], self[15]
105        )
106    }
107}
108
109
110
111impl Index<usize> for Matrix4 {
112    type Output = Float;
113
114    fn index(&self, idx:usize) -> &Float {
115        &self.data[idx]
116    }
117}
118
119
120
121impl IndexMut<usize> for Matrix4 {
122    fn index_mut(&mut self, idx:usize) -> &mut Float {
123        &mut self.data[idx]
124    }
125}
126
127
128
129impl Index<[usize;2]> for Matrix4 {
130    type Output = Float;
131
132    fn index(&self, idx:[usize;2]) -> &Float {
133        &self.data[idx[0] * 4 + idx[1]]
134    }
135}
136
137
138
139impl IndexMut<[usize;2]> for Matrix4 {
140    fn index_mut(&mut self, idx:[usize;2]) -> &mut Float {
141        &mut self.data[idx[0] * 4 + idx[1]]
142    }
143}
144
145
146
147impl Matrix4 {
148
149    pub fn new(data: [Float; 16]) -> Matrix4 {
150        Matrix4 {
151            data
152        }
153    }
154
155
156
157    pub fn id() -> Matrix4 {
158        Matrix4::new([
159            1., 0., 0., 0.,
160            0., 1., 0., 0.,
161            0., 0., 1., 0., 
162            0., 0., 0., 1. 
163        ])
164    }
165
166
167    
168    pub fn transpose(&self) -> Matrix4 {
169        Matrix4::new([
170            self[0], self[4], self[8],  self[12],
171            self[1], self[5], self[9],  self[13],
172            self[2], self[6], self[10], self[14],
173            self[3], self[7], self[11], self[15]
174        ])
175    }
176
177
178
179    pub fn det(&self) -> Float {
180        let a = matrix3![
181            self[5], self[6], self[7],
182            self[9], self[10], self[11],
183            self[13], self[14], self[15]
184        ];
185        let b = matrix3![
186            self[4], self[6], self[7],
187            self[8], self[10], self[11],
188            self[12], self[14], self[15]
189        ];
190        let c = matrix3![
191            self[4], self[5], self[7],
192            self[8], self[9], self[11],
193            self[12], self[13], self[15]
194        ];
195        let d = matrix3![
196            self[4], self[5], self[6],
197            self[8], self[9], self[10],
198            self[12], self[13], self[14]
199        ];
200        
201        self[0] * a.det() - self[1] * b.det() + self[2] * c.det() - self[3] * d.det()
202    }
203
204
205
206    pub fn inv(&self) -> Option<Matrix4> {
207        let s = self.det();
208        
209        if s==0. {
210            return None;
211        }
212
213        let x1 = matrix3![
214            self[5],  self[6],  self[7],
215            self[9],  self[10], self[11],
216            self[13], self[14], self[15]
217        ];
218        let y1 = matrix3![
219            self[4],  self[6],  self[7],
220            self[8],  self[10], self[11],
221            self[12], self[14], self[15]
222        ];
223        let z1 = matrix3![
224            self[4],  self[5],  self[7],
225            self[8],  self[9], self[11],
226            self[12], self[13], self[15]
227        ];
228        let t1 = matrix3![
229            self[4],  self[5],  self[6],
230            self[8],  self[9],  self[10],
231            self[12], self[13], self[14]
232        ];
233
234        let x2 = matrix3![
235            self[1],  self[2],  self[3],
236            self[9],  self[10], self[11],
237            self[13], self[14], self[15]
238        ];
239        let y2 = matrix3![
240            self[0],  self[2],  self[3],
241            self[8],  self[10], self[11],
242            self[12], self[14], self[15]
243        ];
244        let z2 = matrix3![
245            self[0],  self[1],  self[3],
246            self[8],  self[9], self[11],
247            self[12], self[13], self[15]
248        ];
249        let t2 = matrix3![
250            self[0],  self[1],  self[2],
251            self[8],  self[9],  self[10],
252            self[12], self[13], self[14]
253        ];
254
255        let x3 = matrix3![
256            self[1],  self[2],  self[3],
257            self[5],  self[6], self[7],
258            self[13], self[14], self[15]
259        ];
260        let y3 = matrix3![
261            self[0],  self[2],  self[3],
262            self[4],  self[6], self[7],
263            self[12], self[14], self[15]
264        ];
265        let z3 = matrix3![
266            self[0],  self[1],  self[3],
267            self[4],  self[5],  self[7],
268            self[12], self[13], self[15]
269        ];
270        let t3 = matrix3![
271            self[0],  self[1],  self[2],
272            self[4],  self[5],  self[6],
273            self[12], self[13], self[14]
274        ];
275
276        let x4 = matrix3![
277            self[1],  self[2],  self[3],
278            self[5],  self[6],  self[7],
279            self[9],  self[10], self[11]
280        ];
281        let y4 = matrix3![
282            self[0],  self[2],  self[3],
283            self[4],  self[6],  self[7],
284            self[8],  self[10], self[11]
285        ];
286        let z4 = matrix3![
287            self[0],  self[1],  self[3],
288            self[4],  self[5],  self[7],
289            self[8],  self[9],  self[11]
290        ];
291        let t4 = matrix3![
292            self[0],  self[1],  self[2],
293            self[4],  self[5],  self[6],
294            self[8],  self[9],  self[10]
295        ];
296
297        let mut m = matrix4![
298            x1.det(), -y1.det(), z1.det(), -t1.det(),
299            -x2.det(), y2.det(), -z2.det(), t2.det(),
300            x3.det(), -y3.det(), z3.det(), -t3.det(),
301            -x4.det(), y4.det(), -z4.det(), t4.det()
302        ];
303
304        m = m.transpose();
305
306        m = m * (1./s);
307
308        Some(m)
309    }
310
311
312
313    pub fn rot_x(x_rad: f64) -> Matrix4 {
314
315        let x = matrix4![
316            1., 0.,          0.,          0.,
317            0., x_rad.cos(),-x_rad.sin(), 0.,
318            0., x_rad.sin(), x_rad.cos(), 0.,
319            0., 0.,          0.,          1.
320        ];
321
322        x
323    }
324
325
326
327    pub fn rot_y(y_rad: f64) -> Matrix4 {
328
329        let y = matrix4![
330            y_rad.cos(),  0., y_rad.sin(), 0.,
331            0.,           1., 0.,          0.,
332           -y_rad.sin(),  0., y_rad.cos(), 0.,
333            0.,           0., 0.,          1.
334        ];
335
336        y
337    }
338
339
340
341    pub fn rot_z(z_rad: f64) -> Matrix4 {
342
343        let z = matrix4![
344            z_rad.cos(),-z_rad.sin(), 0., 0.,
345            z_rad.sin(), z_rad.cos(), 0., 0.,
346            0.,          0.,          1., 0.,
347            0.,          0.,          0., 1.
348        ];
349
350        z
351    }
352
353
354
355    pub fn rotation(x_rad: f64, y_rad: f64, z_rad: f64) -> Matrix4 {
356
357        let x = Matrix4::rot_x(x_rad);
358        let y = Matrix4::rot_y(y_rad);
359        let z = Matrix4::rot_z(z_rad);
360
361        x * y * z
362    }
363
364
365
366    pub fn scale(s: f64) -> Matrix4 {
367        matrix4![
368            s,  0., 0., 0.,
369            0., s,  0., 0.,
370            0., 0., s,  0.,
371            0., 0., 0., 1.
372        ]
373    }
374
375    
376
377    pub fn translate(x: f64, y: f64, z:f64, t:f64) -> Matrix4 {
378        matrix4![
379            1., 0., 0., x,
380            0., 1., 0., y,
381            0., 0., 1., z,
382            0., 0., 0., t
383        ]
384    }
385
386
387
388    pub fn sheer_x(y: f64, z: f64) -> Matrix4 {
389        matrix4![
390            1., 0., 0., 0.,
391            y,  1., 0., 0.,
392            z,  0., 1., 0.,
393            0., 0., 0., 1.
394        ]
395    }
396
397
398
399    pub fn sheer_y(x: f64, z: f64) -> Matrix4 {
400        matrix4![
401            1., x,  0., 0.,
402            0., 1., 0., 0.,
403            0., z,  1., 0.,
404            0., 0., 0., 1.
405        ]
406    }
407
408
409
410    pub fn sheer_z(x: f64, y: f64) -> Matrix4 {
411        matrix4![
412            1., 0., x,  0.,
413            0., 1., y,  0.,
414            0., 0., 1., 0.,
415            0., 0., 0., 1.
416        ]
417    }
418    
419
420
421    pub fn sheer(
422        xy:f64, xz:f64,
423        yx:f64, yz:f64,
424        zx:f64, zy:f64
425    ) -> Matrix4 {
426        matrix4![
427            1., yx, zx, 0.,
428            xy, 1., zy, 0.,
429            xz, yz, 1., 0.,
430            0., 0., 0., 1.
431        ]
432    }
433
434
435
436    pub fn from_basis(
437        x: Vector4,
438        y: Vector4,
439        z: Vector4,
440        t: Vector4
441    ) -> Matrix4 {
442        let r = compose_basis4![
443            &x,
444            &y,
445            &z,
446            &t
447        ];
448
449        r
450    }
451
452
453
454    pub fn into_basis(&self) -> [Vector4; 4] {
455        let x = vec4![self[0], self[4], self[8],  self[12]];
456        let y = vec4![self[1], self[5], self[9],  self[13]];
457        let z = vec4![self[2], self[6], self[10], self[14]];
458        let t = vec4![self[3], self[7], self[11], self[15]];
459
460        [x,y,z,t]
461    }
462
463
464    
465    pub fn orthographic(left: f64, right: f64, top: f64, bottom: f64, near: f64, far: f64) -> Matrix4 {
466        let xx = 2.0 / ( right - left );
467        let yy = 2.0 / ( top - bottom );
468        let zz = -2.0 / ( far - near );
469        
470        let x = ( right + left ) * xx / 2.;
471		let y = ( top + bottom ) * yy / 2.;
472		let z = ( far + near ) * -zz / 2.;
473
474        matrix4![
475            xx, 0., 0., -x,
476            0., yy, 0., -y,
477            0., 0., zz, -z,
478            0., 0., 0.,  1.
479        ]
480    }
481
482
483
484    //what it does to a shape/space
485    //how it diverges from identity
486    //play with each parameter
487    //what is the purpose of the matrix
488    //action per component
489    pub fn perspective(fov: f64, aspect: f64, near:f64, far:f64) -> Matrix4 {
490        let f = (PI / 2. - fov / 2.).tan();
491        let r = 1.0 / (near - far);
492
493        let xx = f / aspect;
494        let yy = f;
495        let zz = (near + far) * r;
496        let zt = near * far * r * 2.;
497        let tz = -1.;
498
499        matrix4![
500            xx, 0., 0., 0.,
501            0., yy, 0., 0.,
502            0., 0., zz, tz,
503            0., 0., zt, 1.
504        ]
505    }
506
507
508
509    pub fn into_gl(&self) -> [f32; 16] {
510        [
511            self[0] as f32, self[1] as f32, self[2] as f32, self[3] as f32,
512            self[4] as f32, self[5] as f32, self[6] as f32, self[7] as f32,
513            self[8] as f32, self[9] as f32, self[10] as f32, self[11] as f32,
514            self[12] as f32, self[13] as f32, self[14] as f32, self[15] as f32
515        ]
516    }
517
518
519
520    pub fn apply(&mut self, f: fn(f64) -> f64) {
521        self[0] = f(self[0]);
522        self[1] = f(self[1]);
523        self[2] = f(self[2]); 
524        self[3] = f(self[3]);
525        self[4] = f(self[4]);
526        self[5] = f(self[5]);
527        self[6] = f(self[6]); 
528        self[7] = f(self[7]);
529        self[8] = f(self[8]);
530        self[9]  = f(self[9]);
531        self[10] = f(self[10]);
532        self[11] = f(self[11]); 
533        self[12] = f(self[12]);
534        self[13] = f(self[13]);
535        self[14] = f(self[14]);
536        self[15] = f(self[15]);
537    }
538}
539
540
541
542impl Add for &Matrix4 {
543    type Output = Matrix4;
544
545    fn add(self, b:&Matrix4) -> Matrix4 {
546        Matrix4::new([
547            self[0] + b[0], self[1] + b[1], self[2] + b[2], self[3] + b[3],
548            self[4] + b[4], self[5] + b[5], self[6] + b[6], self[7] + b[7],
549            self[8] + b[8], self[9] + b[9], self[10] + b[10], self[11] + b[11],
550            self[12] + b[12], self[13] + b[13], self[14] + b[14], self[15] + b[15]
551        ])
552    }
553}
554
555
556
557impl AddAssign for Matrix4 {
558    fn add_assign(&mut self, b:Matrix4) {
559        self[0] += b[0];
560        self[1] += b[1];
561        self[2] += b[2];
562        self[3] += b[3];
563        self[4] += b[4];
564        self[5] += b[5];
565        self[6] += b[6];
566        self[7] += b[7];
567        self[8] += b[8];
568        self[9]  += b[9];
569        self[10] += b[10];
570        self[11] += b[11]; 
571        self[12] += b[12];
572        self[13] += b[13];
573        self[14] += b[14];
574        self[15] += b[15];
575    }
576}
577
578
579
580impl Sub for &Matrix4 {
581    type Output = Matrix4;
582
583    fn sub(self, b:&Matrix4) -> Matrix4 {
584        Matrix4::new([
585            self[0] - b[0], self[1] - b[1], self[2] - b[2], self[3] - b[3],
586            self[4] - b[4], self[5] - b[5], self[6] - b[6], self[7] - b[7],
587            self[8] - b[8], self[9] - b[9], self[10] - b[10], self[11] - b[11],
588            self[12] - b[12], self[13] - b[13], self[14] - b[14], self[15] - b[15]
589        ])
590    }
591}
592
593
594
595impl SubAssign for Matrix4 {
596    fn sub_assign(&mut self, b:Matrix4) {
597        self[0] -= b[0];
598        self[1] -= b[1];
599        self[2] -= b[2];
600        self[3] -= b[3];
601        self[4] -= b[4];
602        self[5] -= b[5];
603        self[6] -= b[6];
604        self[7] -= b[7];
605        self[8] -= b[8];
606        self[9]  -= b[9];
607        self[10] -= b[10];
608        self[11] -= b[11]; 
609        self[12] -= b[12];
610        self[13] -= b[13];
611        self[14] -= b[14];
612        self[15] -= b[15];
613    }
614}
615
616
617
618impl Mul for Matrix4 {
619    type Output = Matrix4;
620
621    fn mul(self, b: Matrix4) -> Matrix4 {
622        Matrix4::new([
623            self[0] * b[0] + self[1] * b[4] + self[2] * b[8] + self[3] * b[12],
624            self[0] * b[1] + self[1] * b[5] + self[2] * b[9] + self[3] * b[13], 
625            self[0] * b[2] + self[1] * b[6] + self[2] * b[10] + self[3] * b[14], 
626            self[0] * b[3] + self[1] * b[7] + self[2] * b[11] + self[3] * b[15], 
627
628            self[4] * b[0] + self[5] * b[4] + self[6] * b[8] + self[7] * b[12],
629            self[4] * b[1] + self[5] * b[5] + self[6] * b[9] + self[7] * b[13], 
630            self[4] * b[2] + self[5] * b[6] + self[6] * b[10] + self[7] * b[14], 
631            self[4] * b[3] + self[5] * b[7] + self[6] * b[11] + self[7] * b[15], 
632            
633            self[8] * b[0] + self[9] * b[4] + self[10] * b[8] + self[11] * b[12],
634            self[8] * b[1] + self[9] * b[5] + self[10] * b[9] + self[11] * b[13], 
635            self[8] * b[2] + self[9] * b[6] + self[10] * b[10] + self[11] * b[14], 
636            self[8] * b[3] + self[9] * b[7] + self[10] * b[11] + self[11] * b[15], 
637
638            self[12] * b[0] + self[13] * b[4] + self[14] * b[8] + self[15] * b[12],
639            self[12] * b[1] + self[13] * b[5] + self[14] * b[9] + self[15] * b[13], 
640            self[12] * b[2] + self[13] * b[6] + self[14] * b[10] + self[15] * b[14], 
641            self[12] * b[3] + self[13] * b[7] + self[14] * b[11] + self[15] * b[15]
642        ])
643    }
644}
645
646
647
648impl Mul for &Matrix4 {
649    type Output = Matrix4;
650
651    fn mul(self, b: &Matrix4) -> Matrix4 {
652        Matrix4::new([
653            self[0] * b[0] + self[1] * b[4] + self[2] * b[8] + self[3] * b[12],
654            self[0] * b[1] + self[1] * b[5] + self[2] * b[9] + self[3] * b[13], 
655            self[0] * b[2] + self[1] * b[6] + self[2] * b[10] + self[3] * b[14], 
656            self[0] * b[3] + self[1] * b[7] + self[2] * b[11] + self[3] * b[15], 
657
658            self[4] * b[0] + self[5] * b[4] + self[6] * b[8] + self[7] * b[12],
659            self[4] * b[1] + self[5] * b[5] + self[6] * b[9] + self[7] * b[13], 
660            self[4] * b[2] + self[5] * b[6] + self[6] * b[10] + self[7] * b[14], 
661            self[4] * b[3] + self[5] * b[7] + self[6] * b[11] + self[7] * b[15], 
662            
663            self[8] * b[0] + self[9] * b[4] + self[10] * b[8] + self[11] * b[12],
664            self[8] * b[1] + self[9] * b[5] + self[10] * b[9] + self[11] * b[13], 
665            self[8] * b[2] + self[9] * b[6] + self[10] * b[10] + self[11] * b[14], 
666            self[8] * b[3] + self[9] * b[7] + self[10] * b[11] + self[11] * b[15], 
667
668            self[12] * b[0] + self[13] * b[4] + self[14] * b[8] + self[15] * b[12],
669            self[12] * b[1] + self[13] * b[5] + self[14] * b[9] + self[15] * b[13], 
670            self[12] * b[2] + self[13] * b[6] + self[14] * b[10] + self[15] * b[14], 
671            self[12] * b[3] + self[13] * b[7] + self[14] * b[11] + self[15] * b[15]
672        ])
673    }
674}
675
676
677
678impl Mul <Float> for Matrix4 {
679    type Output = Matrix4;
680
681    fn mul(mut self, s:f64) -> Matrix4 {
682        self[0] *= s;
683        self[1] *= s;
684        self[2] *= s;
685        self[3] *= s;
686        self[4] *= s;
687        self[5] *= s;
688        self[6] *= s;
689        self[7] *= s;
690        self[8] *= s;
691        self[9] *= s;
692        self[10] *= s;
693        self[11] *= s;
694        self[12] *= s;
695        self[13] *= s;
696        self[14] *= s;
697        self[15] *= s;
698        self
699    }
700}
701
702
703
704impl Mul <Vector4> for &Matrix4 {
705    type Output = Vector4;
706
707    fn mul(self, v:Vector4) -> Vector4 {
708        vec4![
709            self[0] * v[0] + self[1] * v[1] + self[2] * v[2] + self[3] * v[3],
710            self[4] * v[0] + self[5] * v[1] + self[6] * v[2] + self[7] * v[3],
711            self[8] * v[0] + self[9] * v[1] + self[10] * v[2] + self[11] * v[3],
712            self[12] * v[0] + self[13] * v[1] + self[14] * v[2] + self[15] * v[3]
713        ]
714    }
715}
716
717
718
719impl Mul <Vector4> for Matrix4 {
720    type Output = Vector4;
721
722    fn mul(self, v:Vector4) -> Vector4 {
723        vec4![
724            self[0] * v[0] + self[1] * v[1] + self[2] * v[2] + self[3] * v[3],
725            self[4] * v[0] + self[5] * v[1] + self[6] * v[2] + self[7] * v[3],
726            self[8] * v[0] + self[9] * v[1] + self[10] * v[2] + self[11] * v[3],
727            self[12] * v[0] + self[13] * v[1] + self[14] * v[2] + self[15] * v[3]
728        ]
729    }
730}
731
732
733
734impl Div <Float> for Matrix4 {
735    type Output = Matrix4;
736    
737    fn div(mut self, s:f64) -> Matrix4 {
738        self[0] /= s;
739        self[1] /= s;
740        self[2] /= s;
741        self[3] /= s;
742        self[4] /= s;
743        self[5] /= s;
744        self[6] /= s;
745        self[7] /= s;
746        self[8] /= s;
747        self[9] /= s;
748        self[10] /= s;
749        self[11] /= s;
750        self[12] /= s;
751        self[13] /= s;
752        self[14] /= s;
753        self[15] /= s;
754        self
755    }
756}
757
758
759
760fn eq(a: &Matrix4, b: &Matrix4) -> bool {
761    //f64::EPSILON
762    a[0] == b[0] &&
763    a[1] == b[1] &&
764    a[2] == b[2] &&
765    a[3] == b[3] &&
766    a[4] == b[4] &&
767    a[5] == b[5] &&
768    a[6] == b[6] &&
769    a[7] == b[7] &&
770    a[8] == b[8] &&
771    a[9] == b[8] &&
772    a[10] == b[10] &&
773    a[11] == b[11] &&
774    a[12] == b[12] &&
775    a[13] == b[13] &&
776    a[14] == b[14] &&
777    a[15] == b[15]
778}
779
780
781
782fn almost_eq(a: &Matrix4, b: &Matrix4) -> bool {
783    
784    fn eq(a: Float, b: Float) -> bool {
785        (a - b).abs() < f32::EPSILON as f64
786    }
787
788    eq(a[0], b[0]) &&
789    eq(a[1], b[1]) &&
790    eq(a[2], b[2]) &&
791    eq(a[3], b[3]) &&
792    eq(a[4], b[4]) &&
793    eq(a[5], b[5]) &&
794    eq(a[6], b[6]) &&
795    eq(a[7], b[7]) &&
796    eq(a[8], b[8]) &&
797    eq(a[9], b[9]) &&
798    eq(a[10], b[10]) &&
799    eq(a[11], b[11]) &&
800    eq(a[12], b[12]) &&
801    eq(a[13], b[13]) &&
802    eq(a[14], b[14]) &&
803    eq(a[15], b[15])
804}
805
806
807
808impl PartialEq for Matrix4 {
809    fn eq(&self, b: &Matrix4) -> bool {
810        //eq(self, b)
811        almost_eq(self, b)
812    }
813}
814
815
816
817impl Eq for Matrix4 {}
818
819
820
821impl Neg for Matrix4 {
822
823    type Output = Matrix4;
824    
825    fn neg(mut self) -> Self {
826        self[0] *= -1.;
827        self[1] *= -1.;
828        self[2] *= -1.;
829        self[3] *= -1.;
830        self[4] *= -1.;
831        self[5] *= -1.;
832        self[6] *= -1.;
833        self[7] *= -1.;
834        self[8] *= -1.;
835        self[9] *= -1.;
836        self[10] *= -1.;
837        self[11] *= -1.;
838        self[12] *= -1.;
839        self[13] *= -1.;
840        self[14] *= -1.;
841        self[15] *= -1.;
842        self
843    }
844}
845
846
847
848impl From<Matrix<f64>> for Matrix4 {
849    fn from(m: Matrix<f64>) -> Matrix4 {
850        matrix4![
851            m[[0,0]], m[[0,1]], m[[0,2]], m[[0,3]],
852            m[[1,0]], m[[1,1]], m[[1,2]], m[[1,3]],
853            m[[2,0]], m[[2,1]], m[[2,2]], m[[2,3]],
854            m[[3,0]], m[[3,1]], m[[3,2]], m[[3,3]]
855        ]
856    }
857}
858
859
860
861impl From<&Matrix<f64>> for Matrix4 {
862    fn from(m: &Matrix<f64>) -> Matrix4 {
863        matrix4![
864            m[[0,0]], m[[0,1]], m[[0,2]], m[[0,3]],
865            m[[1,0]], m[[1,1]], m[[1,2]], m[[1,3]],
866            m[[2,0]], m[[2,1]], m[[2,2]], m[[2,3]],
867            m[[3,0]], m[[3,1]], m[[3,2]], m[[3,3]]
868        ]
869    }
870}
871
872
873
874impl From<Matrix3> for Matrix4 {
875    fn from(m: Matrix3) -> Matrix4 {
876        matrix4![
877            m[0], m[1], m[2], 0.,
878            m[3], m[4], m[5], 0.,
879            m[6], m[7], m[8], 0.,
880            0.,   0.,   0.,   1.
881        ]
882    }
883}
884
885
886
887mod tests {
888    use std::{f32::EPSILON, f64::consts::PI};
889    use crate::{ vec3 };
890    use super::{
891        Vector3,
892        Matrix3,
893        Matrix4,
894        Matrix
895    };
896
897    //TODO!
898    #[test]
899    fn gimbal_lock() {
900        
901        let basis = Matrix3::id().into_basis();
902        let v = vec3![2., 3., 4.];
903
904        let x_rad = PI / 10.;
905        let y_rad = PI / 5.; //PI / 2.;
906        let z_rad = PI / 10.;
907        
908        let r1: Matrix3 = Matrix4::rotation(x_rad, y_rad, z_rad).into();
909        
910        let x_rad2 = PI / 10.;
911        let y_rad2 = PI / 10.;
912        let z_rad2 = PI / 10.;
913
914        let r2: Matrix3 = Matrix4::rotation(x_rad2, y_rad2, z_rad2).into();
915        let r1v = &r1 * &v;
916        let r2v = &r2 * &v;
917        
918        let r3: Matrix3 = Matrix4::rotation(x_rad + x_rad2, y_rad + y_rad2, z_rad + z_rad2).into();
919        let r2r1: Matrix3 = &r2 * &r1;
920        
921        let r3v = &r3 * &v;
922        let r2r1v = &r2r1 * &v;
923        
924        println!("\n r1 is {} \n r2 is {} \n r3 is {} \n r2r1 is {} \n", r1, r2, r3, r2r1);
925
926        println!("\n r3v is {} \n r2r1v {} \n", r3v, r2r1v);
927
928        let x = basis[0];
929        let y = basis[1];
930        let z = basis[2];
931
932        let r3v_x = r3v.angle(&x);
933        let r3v_y = r3v.angle(&y);
934        let r3v_z = r3v.angle(&z);
935
936        let r2r1v_x = r2r1v.angle(&x);
937        let r2r1v_y = r2r1v.angle(&y);
938        let r2r1v_z = r2r1v.angle(&z);
939
940        println!("\n r3v_x is {} \n r3v_y is {} \n r3v_z is {} \n", r3v_x, r3v_y, r3v_z);
941
942        println!("\n r2r1v_x is {} \n r2r1v_y is {} \n r2r1v_z is {} \n", r2r1v_x, r2r1v_y, r2r1v_z);
943    }
944    
945    #[test]
946    fn perspective() {
947        
948        const fov: f32 = 45. * std::f32::consts::PI / 180.;
949        const far: f32 = 100.;
950        const near: f32 = 0.1;
951        const aspect: f32 = 1.; //-2.414213;
952       
953        //apply to cube
954        let p = Matrix4::perspective(fov as f64, aspect as f64, near as f64, far as f64);
955        
956        //assert_eq!(1.,0., "perspective {}", p);
957    }
958}