j_webgl/algebra/
matrix4.rs

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 = (std::f32::consts::PI * 0.5 - 0.5 * field_of_view_in_radians).tan();
17      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      // Note: This matrix flips the Y axis so 0 is at the top.
31      [  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  /*
67    xRotation: function(angleInRadians) {
68      var c = Math.cos(angleInRadians);
69      var s = Math.sin(angleInRadians);
70  
71      return [
72        1, 0, 0, 0,
73        0, c, s, 0,
74        0, -s, c, 0,
75        0, 0, 0, 1,
76      ];
77    },
78  
79    yRotation: function(angleInRadians) {
80      var c = Math.cos(angleInRadians);
81      var s = Math.sin(angleInRadians);
82  
83      return [
84        c, 0, -s, 0,
85        0, 1, 0, 0,
86        s, 0, c, 0,
87        0, 0, 0, 1,
88      ];
89    },
90  
91    zRotation: function(angleInRadians) {
92      var c = Math.cos(angleInRadians);
93      var s = Math.sin(angleInRadians);
94  
95      return [
96         c, s, 0, 0,
97        -s, c, 0, 0,
98         0, 0, 1, 0,
99         0, 0, 0, 1,
100      ];
101    },
102  
103    scaling: function(sx, sy, sz) {
104      return [
105        sx, 0,  0,  0,
106        0, sy,  0,  0,
107        0,  0, sz,  0,
108        0,  0,  0,  1,
109      ];
110    },
111  
112    translate: function(m, tx, ty, tz) {
113      return m4.multiply(m, m4.translation(tx, ty, tz));
114    },
115  
116    xRotate: function(m, angleInRadians) {
117      return m4.multiply(m, m4.xRotation(angleInRadians));
118    },
119  
120    yRotate: function(m, angleInRadians) {
121      return m4.multiply(m, m4.yRotation(angleInRadians));
122    },
123  
124    zRotate: function(m, angleInRadians) {
125      return m4.multiply(m, m4.zRotation(angleInRadians));
126    },
127  
128    scale: function(m, sx, sy, sz) {
129      return m4.multiply(m, m4.scaling(sx, sy, sz));
130    },
131  
132    */
133}
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}