1use super::{Point3, Vector3};
2use std::ops::Mul;
3
4pub struct Mat4 {
5 elements: [f32; 16],
6}
7
8impl std::convert::From<[f32; 16]> for Mat4 {
9 fn from(elements: [f32; 16]) -> Self {
10 Mat4 { elements }
11 }
12}
13
14impl Mat4 {
15 pub fn new_perspective(aspect: f32, field_of_view_in_radians: f32, near: f32, far: f32) -> Self {
16 let f = 1.0 / (0.5 * field_of_view_in_radians).tan();
18 let range_inv = 1.0 / (near - far);
19
20 [ f / aspect, 0.0, 0.0, 0.0,
21 0.0, f, 0.0, 0.0,
22 0.0, 0.0, (near + far) * range_inv, -1.0,
23 0.0, 0.0, near * far * range_inv * 2.0, 0.0,
24 ].into()
25 }
26
27 pub fn as_slice(&self) -> &[f32] { &self.elements }
28
29 pub fn new_projection(width: f32, height: f32, depth: f32) -> Self {
30 [ 2.0 / width, 0.0, 0.0, 0.0,
32 0.0, -2.0 / height, 0.0, 0.0,
33 0.0, 0.0, 2.0 / depth, 0.0,
34 -1.0, 1.0, 0.0, 1.0,
35 ].into()
36 }
37
38 pub fn multiply(&self, other: &Mat4) -> Mat4 {
39 multiply(&self.elements, &other.elements).into()
40 }
41
42 pub fn new_translation(tx: f32, ty: f32, tz: f32) -> Mat4 {
43 [ 1.0, 0.0, 0.0, 0.0,
44 0.0, 1.0, 0.0, 0.0,
45 0.0, 0.0, 1.0, 0.0,
46 tx, ty, tz, 1.0,
47 ].into()
48 }
49
50 pub fn look_at_rh(camera_position: &Point3, target: &Point3, up: &Vector3) -> Mat4 {
51 let z_axis = (camera_position - target).normalize();
52 let x_axis = up.cross(&z_axis).normalize();
53 let y_axis = z_axis.cross(&x_axis).normalize();
54
55 inverse(&
56 [ x_axis.dx(), x_axis.dy(), x_axis.dz(), 0.0,
57 y_axis.dx(), y_axis.dy(), y_axis.dz(), 0.0,
58 z_axis.dx(), z_axis.dy(), z_axis.dz(), 0.0,
59 camera_position.x(),
60 camera_position.y(),
61 camera_position.z(),
62 1.0,
63 ]).into()
64 }
65
66 }
134
135impl Mul<&Mat4> for &Mat4 {
136 type Output = Mat4;
137 fn mul(self, other: &Mat4) -> Mat4 {
138 self.multiply(other)
139 }
140}
141
142
143fn multiply(a: &[f32; 16], b: &[f32; 16]) -> [f32; 16] {
144 let a00 = a[0 * 4 + 0];
145 let a01 = a[0 * 4 + 1];
146 let a02 = a[0 * 4 + 2];
147 let a03 = a[0 * 4 + 3];
148 let a10 = a[1 * 4 + 0];
149 let a11 = a[1 * 4 + 1];
150 let a12 = a[1 * 4 + 2];
151 let a13 = a[1 * 4 + 3];
152 let a20 = a[2 * 4 + 0];
153 let a21 = a[2 * 4 + 1];
154 let a22 = a[2 * 4 + 2];
155 let a23 = a[2 * 4 + 3];
156 let a30 = a[3 * 4 + 0];
157 let a31 = a[3 * 4 + 1];
158 let a32 = a[3 * 4 + 2];
159 let a33 = a[3 * 4 + 3];
160 let b00 = b[0 * 4 + 0];
161 let b01 = b[0 * 4 + 1];
162 let b02 = b[0 * 4 + 2];
163 let b03 = b[0 * 4 + 3];
164 let b10 = b[1 * 4 + 0];
165 let b11 = b[1 * 4 + 1];
166 let b12 = b[1 * 4 + 2];
167 let b13 = b[1 * 4 + 3];
168 let b20 = b[2 * 4 + 0];
169 let b21 = b[2 * 4 + 1];
170 let b22 = b[2 * 4 + 2];
171 let b23 = b[2 * 4 + 3];
172 let b30 = b[3 * 4 + 0];
173 let b31 = b[3 * 4 + 1];
174 let b32 = b[3 * 4 + 2];
175 let b33 = b[3 * 4 + 3];
176 [
177 b00 * a00 + b01 * a10 + b02 * a20 + b03 * a30,
178 b00 * a01 + b01 * a11 + b02 * a21 + b03 * a31,
179 b00 * a02 + b01 * a12 + b02 * a22 + b03 * a32,
180 b00 * a03 + b01 * a13 + b02 * a23 + b03 * a33,
181 b10 * a00 + b11 * a10 + b12 * a20 + b13 * a30,
182 b10 * a01 + b11 * a11 + b12 * a21 + b13 * a31,
183 b10 * a02 + b11 * a12 + b12 * a22 + b13 * a32,
184 b10 * a03 + b11 * a13 + b12 * a23 + b13 * a33,
185 b20 * a00 + b21 * a10 + b22 * a20 + b23 * a30,
186 b20 * a01 + b21 * a11 + b22 * a21 + b23 * a31,
187 b20 * a02 + b21 * a12 + b22 * a22 + b23 * a32,
188 b20 * a03 + b21 * a13 + b22 * a23 + b23 * a33,
189 b30 * a00 + b31 * a10 + b32 * a20 + b33 * a30,
190 b30 * a01 + b31 * a11 + b32 * a21 + b33 * a31,
191 b30 * a02 + b31 * a12 + b32 * a22 + b33 * a32,
192 b30 * a03 + b31 * a13 + b32 * a23 + b33 * a33,
193 ]
194}
195
196fn inverse(m: &[f32; 16]) -> [f32; 16] {
197 let m00 = m[0 * 4 + 0];
198 let m01 = m[0 * 4 + 1];
199 let m02 = m[0 * 4 + 2];
200 let m03 = m[0 * 4 + 3];
201 let m10 = m[1 * 4 + 0];
202 let m11 = m[1 * 4 + 1];
203 let m12 = m[1 * 4 + 2];
204 let m13 = m[1 * 4 + 3];
205 let m20 = m[2 * 4 + 0];
206 let m21 = m[2 * 4 + 1];
207 let m22 = m[2 * 4 + 2];
208 let m23 = m[2 * 4 + 3];
209 let m30 = m[3 * 4 + 0];
210 let m31 = m[3 * 4 + 1];
211 let m32 = m[3 * 4 + 2];
212 let m33 = m[3 * 4 + 3];
213 let tmp_0 = m22 * m33;
214 let tmp_1 = m32 * m23;
215 let tmp_2 = m12 * m33;
216 let tmp_3 = m32 * m13;
217 let tmp_4 = m12 * m23;
218 let tmp_5 = m22 * m13;
219 let tmp_6 = m02 * m33;
220 let tmp_7 = m32 * m03;
221 let tmp_8 = m02 * m23;
222 let tmp_9 = m22 * m03;
223 let tmp_10 = m02 * m13;
224 let tmp_11 = m12 * m03;
225 let tmp_12 = m20 * m31;
226 let tmp_13 = m30 * m21;
227 let tmp_14 = m10 * m31;
228 let tmp_15 = m30 * m11;
229 let tmp_16 = m10 * m21;
230 let tmp_17 = m20 * m11;
231 let tmp_18 = m00 * m31;
232 let tmp_19 = m30 * m01;
233 let tmp_20 = m00 * m21;
234 let tmp_21 = m20 * m01;
235 let tmp_22 = m00 * m11;
236 let tmp_23 = m10 * m01;
237
238 let t0 = (tmp_0 * m11 + tmp_3 * m21 + tmp_4 * m31) -
239 (tmp_1 * m11 + tmp_2 * m21 + tmp_5 * m31);
240 let t1 = (tmp_1 * m01 + tmp_6 * m21 + tmp_9 * m31) -
241 (tmp_0 * m01 + tmp_7 * m21 + tmp_8 * m31);
242 let t2 = (tmp_2 * m01 + tmp_7 * m11 + tmp_10 * m31) -
243 (tmp_3 * m01 + tmp_6 * m11 + tmp_11 * m31);
244 let t3 = (tmp_5 * m01 + tmp_8 * m11 + tmp_11 * m21) -
245 (tmp_4 * m01 + tmp_9 * m11 + tmp_10 * m21);
246
247 let d = 1.0 / (m00 * t0 + m10 * t1 + m20 * t2 + m30 * t3);
248
249 [
250 d * t0,
251 d * t1,
252 d * t2,
253 d * t3,
254 d * ((tmp_1 * m10 + tmp_2 * m20 + tmp_5 * m30) -
255 (tmp_0 * m10 + tmp_3 * m20 + tmp_4 * m30)),
256 d * ((tmp_0 * m00 + tmp_7 * m20 + tmp_8 * m30) -
257 (tmp_1 * m00 + tmp_6 * m20 + tmp_9 * m30)),
258 d * ((tmp_3 * m00 + tmp_6 * m10 + tmp_11 * m30) -
259 (tmp_2 * m00 + tmp_7 * m10 + tmp_10 * m30)),
260 d * ((tmp_4 * m00 + tmp_9 * m10 + tmp_10 * m20) -
261 (tmp_5 * m00 + tmp_8 * m10 + tmp_11 * m20)),
262 d * ((tmp_12 * m13 + tmp_15 * m23 + tmp_16 * m33) -
263 (tmp_13 * m13 + tmp_14 * m23 + tmp_17 * m33)),
264 d * ((tmp_13 * m03 + tmp_18 * m23 + tmp_21 * m33) -
265 (tmp_12 * m03 + tmp_19 * m23 + tmp_20 * m33)),
266 d * ((tmp_14 * m03 + tmp_19 * m13 + tmp_22 * m33) -
267 (tmp_15 * m03 + tmp_18 * m13 + tmp_23 * m33)),
268 d * ((tmp_17 * m03 + tmp_20 * m13 + tmp_23 * m23) -
269 (tmp_16 * m03 + tmp_21 * m13 + tmp_22 * m23)),
270 d * ((tmp_14 * m22 + tmp_17 * m32 + tmp_13 * m12) -
271 (tmp_16 * m32 + tmp_12 * m12 + tmp_15 * m22)),
272 d * ((tmp_20 * m32 + tmp_12 * m02 + tmp_19 * m22) -
273 (tmp_18 * m22 + tmp_21 * m32 + tmp_13 * m02)),
274 d * ((tmp_18 * m12 + tmp_23 * m32 + tmp_15 * m02) -
275 (tmp_22 * m32 + tmp_14 * m02 + tmp_19 * m12)),
276 d * ((tmp_22 * m22 + tmp_16 * m02 + tmp_21 * m12) -
277 (tmp_20 * m12 + tmp_23 * m22 + tmp_17 * m02)),
278 ]
279}