1use super::*;
2
3impl<T: Copy> mat4<T> {
4 pub fn transpose(self) -> Self {
18 let mut result = self;
19 for i in 0..4 {
20 for j in 0..4 {
21 result[(i, j)] = self[(j, i)];
22 }
23 }
24 result
25 }
26}
27
28impl<T: Num> mat4<T> {
29 pub fn from_orts(x: vec3<T>, y: vec3<T>, z: vec3<T>) -> Self {
45 mat4::new([
46 [x.x, y.x, z.x, T::ZERO],
47 [x.y, y.y, z.y, T::ZERO],
48 [x.z, y.z, z.z, T::ZERO],
49 [T::ZERO, T::ZERO, T::ZERO, T::ONE],
50 ])
51 }
52}
53
54impl<T: Float> mat4<T> {
55 pub fn inverse(self) -> Self {
70 let b00 = self[(0, 0)] * self[(1, 1)] - self[(1, 0)] * self[(0, 1)];
71 let b01 = self[(0, 0)] * self[(2, 1)] - self[(2, 0)] * self[(0, 1)];
72 let b02 = self[(0, 0)] * self[(3, 1)] - self[(3, 0)] * self[(0, 1)];
73 let b03 = self[(1, 0)] * self[(2, 1)] - self[(2, 0)] * self[(1, 1)];
74 let b04 = self[(1, 0)] * self[(3, 1)] - self[(3, 0)] * self[(1, 1)];
75 let b05 = self[(2, 0)] * self[(3, 1)] - self[(3, 0)] * self[(2, 1)];
76 let b06 = self[(0, 2)] * self[(1, 3)] - self[(1, 2)] * self[(0, 3)];
77 let b07 = self[(0, 2)] * self[(2, 3)] - self[(2, 2)] * self[(0, 3)];
78 let b08 = self[(0, 2)] * self[(3, 3)] - self[(3, 2)] * self[(0, 3)];
79 let b09 = self[(1, 2)] * self[(2, 3)] - self[(2, 2)] * self[(1, 3)];
80 let b10 = self[(1, 2)] * self[(3, 3)] - self[(3, 2)] * self[(1, 3)];
81 let b11 = self[(2, 2)] * self[(3, 3)] - self[(3, 2)] * self[(2, 3)];
82
83 let det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;
84
85 if det == T::ZERO {
86 Self::identity()
87 } else {
88 mat4::new([
89 [
90 self[(1, 1)] * b11 - self[(2, 1)] * b10 + self[(3, 1)] * b09,
91 self[(2, 1)] * b08 - self[(0, 1)] * b11 - self[(3, 1)] * b07,
92 self[(0, 1)] * b10 - self[(1, 1)] * b08 + self[(3, 1)] * b06,
93 self[(1, 1)] * b07 - self[(0, 1)] * b09 - self[(2, 1)] * b06,
94 ],
95 [
96 self[(2, 0)] * b10 - self[(1, 0)] * b11 - self[(3, 0)] * b09,
97 self[(0, 0)] * b11 - self[(2, 0)] * b08 + self[(3, 0)] * b07,
98 self[(1, 0)] * b08 - self[(0, 0)] * b10 - self[(3, 0)] * b06,
99 self[(0, 0)] * b09 - self[(1, 0)] * b07 + self[(2, 0)] * b06,
100 ],
101 [
102 self[(1, 3)] * b05 - self[(2, 3)] * b04 + self[(3, 3)] * b03,
103 self[(2, 3)] * b02 - self[(0, 3)] * b05 - self[(3, 3)] * b01,
104 self[(0, 3)] * b04 - self[(1, 3)] * b02 + self[(3, 3)] * b00,
105 self[(1, 3)] * b01 - self[(0, 3)] * b03 - self[(2, 3)] * b00,
106 ],
107 [
108 self[(2, 2)] * b04 - self[(1, 2)] * b05 - self[(3, 2)] * b03,
109 self[(0, 2)] * b05 - self[(2, 2)] * b02 + self[(3, 2)] * b01,
110 self[(1, 2)] * b02 - self[(0, 2)] * b04 - self[(3, 2)] * b00,
111 self[(0, 2)] * b03 - self[(1, 2)] * b01 + self[(2, 2)] * b00,
112 ],
113 ]) / det
114 }
115 }
116}
117
118#[test]
119fn test_mat_inverse_random() {
120 fn check(m: mat4<f64>) {
121 let m_inv = m.inverse();
122 let mul = m * m_inv;
123 assert!(mul.approx_eq(&mat4::identity()));
124 }
125 check(mat4::new([
127 [8.7, 3.6, 6.5, 6.5],
128 [7.4, 5.8, 8.6, 2.6],
129 [1.8, 8.3, 6.6, 4.9],
130 [2.1, 3.4, 3.5, 8.8],
131 ]));
132 check(mat4::new([
133 [9.6, 0.6, 5.4, 3.2],
134 [0.5, 0.1, 5.4, 6.6],
135 [2.0, 3.8, 0.0, 1.4],
136 [6.6, 2.9, 4.3, 9.3],
137 ]));
138 check(mat4::new([
139 [6.1, 1.7, 2.7, 3.6],
140 [1.8, 2.5, 7.8, 7.1],
141 [2.6, 9.5, 1.5, 8.0],
142 [6.5, 6.5, 5.9, 7.2],
143 ]));
144 check(mat4::new([
145 [8.4, 1.0, 6.4, 0.0],
146 [1.6, 1.1, 1.5, 4.0],
147 [5.5, 1.2, 0.6, 8.3],
148 [9.1, 9.7, 8.7, 0.8],
149 ]));
150 check(mat4::new([
151 [0.6, 5.7, 0.2, 7.1],
152 [3.5, 1.7, 6.4, 1.6],
153 [2.0, 3.4, 4.1, 5.0],
154 [7.3, 5.9, 8.9, 3.0],
155 ]));
156 check(mat4::new([
157 [1.9, 1.4, 4.0, 3.7],
158 [7.8, 8.2, 9.1, 1.3],
159 [3.2, 4.4, 3.9, 2.5],
160 [7.1, 7.3, 3.5, 5.0],
161 ]));
162 check(mat4::new([
163 [6.0, 7.0, 4.0, 0.6],
164 [0.9, 8.7, 6.2, 6.0],
165 [0.2, 4.6, 3.7, 0.2],
166 [8.4, 6.2, 7.6, 2.8],
167 ]));
168 check(mat4::new([
169 [5.1, 9.6, 4.6, 4.5],
170 [1.5, 9.2, 2.3, 9.4],
171 [5.6, 7.6, 0.4, 2.9],
172 [0.6, 0.5, 4.3, 4.6],
173 ]));
174 check(mat4::new([
175 [3.0, 5.7, 8.6, 2.1],
176 [6.2, 7.2, 0.1, 6.7],
177 [5.3, 5.9, 5.8, 2.1],
178 [9.4, 9.9, 9.8, 5.8],
179 ]));
180 check(mat4::new([
181 [4.3, 8.4, 2.0, 6.2],
182 [2.3, 9.0, 4.6, 5.8],
183 [5.5, 1.2, 8.8, 1.6],
184 [4.5, 9.3, 4.8, 1.5],
185 ]));
186}