dbsdk_rs/
math.rs

1use std::{mem::size_of, convert::TryInto, ops};
2
3use field_offset::FieldOffset;
4
5use crate::db_internal::{mat4_loadSIMD, mat4_storeSIMD, mat4_mulSIMD, mat4_transformSIMD};
6
7#[repr(C)]
8#[derive(Clone, Copy, Debug, Default)]
9pub struct Vector2 {
10    pub x: f32,
11    pub y: f32,
12}
13
14impl Vector2 {
15    pub const fn new(x: f32, y: f32) -> Vector2 {
16        return Vector2 { x: x, y: y };
17    }
18
19    pub const fn zero() -> Vector2 {
20        return Vector2 { x: 0.0, y: 0.0 };
21    }
22
23    pub const fn unit_x() -> Vector2 {
24        return Vector2 { x: 1.0, y: 0.0 };
25    }
26    
27    pub const fn unit_y() -> Vector2 {
28        return Vector2 { x: 0.0, y: 1.0 };
29    }
30
31    /// Compute the squared distance between two vectors
32    pub fn distance_sq(lhs: &Vector2, rhs: &Vector2) -> f32 {
33        let dx = lhs.x - rhs.x;
34        let dy = lhs.y - rhs.y;
35        return (dx * dx) + (dy * dy);
36    }
37
38    /// Compute the distance between two vectors
39    pub fn distance(lhs: &Vector2, rhs: &Vector2) -> f32 {
40        let dx = lhs.x - rhs.x;
41        let dy = lhs.y - rhs.y;
42        return ((dx * dx) + (dy * dy)).sqrt();
43    }
44
45    /// Compute the squared length of the vector
46    pub fn length_sq(self) -> f32 {
47        return (self.x * self.x) + (self.y * self.y);
48    }
49
50    /// Compute the length of the vector
51    pub fn length(self) -> f32 {
52        return ((self.x * self.x) + (self.y * self.y)).sqrt();
53    }
54
55    /// Normalize the vector
56    pub fn normalize(&mut self) {
57        let mag = 1.0 / (self.x * self.x + self.y * self.y).sqrt();
58        self.x *= mag;
59        self.y *= mag;
60    }
61
62    /// Produce a normalized copy of the vector
63    pub fn normalized(&self) -> Vector2 {
64        let mag = 1.0 / (self.x * self.x + self.y * self.y).sqrt();
65        return Vector2 { x: self.x * mag, y: self.y * mag };
66    }
67
68    /// Compute the dot product of two vectors
69    pub fn dot(lhs: &Vector2, rhs: &Vector2) -> f32 {
70        return (lhs.x * rhs.x) + (lhs.y * rhs.y);
71    }
72}
73
74impl ops::Add<Vector2> for Vector2 {
75    type Output = Vector2;
76
77    fn add(self, rhs: Vector2) -> Vector2 {
78        return Vector2 { x: self.x + rhs.x, y: self.y + rhs.y };
79    }
80}
81
82impl ops::Sub<Vector2> for Vector2 {
83    type Output = Vector2;
84
85    fn sub(self, rhs: Vector2) -> Vector2 {
86        return Vector2 { x: self.x - rhs.x, y: self.y - rhs.y };
87    }
88}
89
90impl ops::Mul<Vector2> for Vector2 {
91    type Output = Vector2;
92
93    fn mul(self, rhs: Vector2) -> Vector2 {
94        return Vector2 { x: self.x * rhs.x, y: self.y * rhs.y };
95    }
96}
97
98impl ops::Mul<f32> for Vector2 {
99    type Output = Vector2;
100
101    fn mul(self, rhs: f32) -> Vector2 {
102        return Vector2 { x: self.x * rhs, y: self.y * rhs };
103    }
104}
105
106impl ops::Mul<Vector2> for f32 {
107    type Output = Vector2;
108
109    fn mul(self, rhs: Vector2) -> Vector2 {
110        return Vector2 { x: self * rhs.x, y: self * rhs.y };
111    }
112}
113
114impl ops::Div<Vector2> for Vector2 {
115    type Output = Vector2;
116
117    fn div(self, rhs: Vector2) -> Vector2 {
118        return Vector2 { x: self.x / rhs.x, y: self.y / rhs.y };
119    }
120}
121
122impl ops::Div<f32> for Vector2 {
123    type Output = Vector2;
124
125    fn div(self, rhs: f32) -> Vector2 {
126        return Vector2 { x: self.x / rhs, y: self.y / rhs };
127    }
128}
129
130impl ops::Div<Vector2> for f32 {
131    type Output = Vector2;
132
133    fn div(self, rhs: Vector2) -> Vector2 {
134        return Vector2 { x: self / rhs.x, y: self / rhs.y };
135    }
136}
137
138#[repr(C)]
139#[derive(Clone, Copy, Debug, Default)]
140pub struct Vector3 {
141    pub x: f32,
142    pub y: f32,
143    pub z: f32,
144}
145
146impl Vector3 {
147    pub const fn new(x: f32, y: f32, z: f32) -> Vector3 {
148        return Vector3 { x: x, y: y, z: z };
149    }
150
151    pub const fn zero() -> Vector3 {
152        return Vector3 { x: 0.0, y: 0.0, z: 0.0 };
153    }
154
155    pub const fn unit_x() -> Vector3 {
156        return Vector3 { x: 1.0, y: 0.0, z: 0.0 };
157    }
158
159    pub const fn unit_y() -> Vector3 {
160        return Vector3 { x: 0.0, y: 1.0, z: 0.0 };
161    }
162
163    pub const fn unit_z() -> Vector3 {
164        return Vector3 { x: 0.0, y: 0.0, z: 1.0 };
165    }
166
167    /// Compute the squared distance between two vectors
168    pub fn distance_sq(lhs: &Vector3, rhs: &Vector3) -> f32 {
169        let dx = lhs.x - rhs.x;
170        let dy = lhs.y - rhs.y;
171        let dz = lhs.z - rhs.z;
172        return (dx * dx) + (dy * dy) + (dz * dz);
173    }
174
175    /// Compute the distance between two vectors
176    pub fn distance(lhs: &Vector3, rhs: &Vector3) -> f32 {
177        let dx = lhs.x - rhs.x;
178        let dy = lhs.y - rhs.y;
179        let dz = lhs.z - rhs.z;
180        return ((dx * dx) + (dy * dy) + (dz * dz)).sqrt();
181    }
182
183    /// Compute the squared length of the vector
184    pub fn length_sq(self) -> f32 {
185        return (self.x * self.x) + (self.y * self.y) + (self.z * self.z);
186    }
187
188    /// Compute the length of the vector
189    pub fn length(self) -> f32 {
190        return ((self.x * self.x) + (self.y * self.y) + (self.z * self.z)).sqrt();
191    }
192
193    /// Normalize the vector
194    pub fn normalize(&mut self) {
195        let mag = 1.0 / (self.x * self.x + self.y * self.y + self.z * self.z).sqrt();
196        self.x *= mag;
197        self.y *= mag;
198        self.z *= mag;
199    }
200
201    /// Produce a normalized copy of the vector
202    pub fn normalized(&self) -> Vector3 {
203        let mag = 1.0 / (self.x * self.x + self.y * self.y + self.z * self.z).sqrt();
204        return Vector3 { x: self.x * mag, y: self.y * mag, z: self.z * mag };
205    }
206
207    /// Compute the dot product of two vectors
208    pub fn dot(lhs: &Vector3, rhs: &Vector3) -> f32 {
209        return (lhs.x * rhs.x) + (lhs.y * rhs.y) + (lhs.z * rhs.z);
210    }
211
212    /// Compute the cross product of two vectors
213    pub fn cross(lhs: &Vector3, rhs: &Vector3) -> Vector3 {
214        return Vector3 {
215            x: lhs.y * rhs.z - lhs.z * rhs.y,
216            y: -(lhs.x * rhs.z - lhs.z * rhs.x),
217            z: lhs.x * rhs.y - lhs.y * rhs.x
218        };
219    }
220}
221
222impl ops::Add<Vector3> for Vector3 {
223    type Output = Vector3;
224
225    fn add(self, rhs: Vector3) -> Vector3 {
226        return Vector3 { x: self.x + rhs.x, y: self.y + rhs.y, z: self.z + rhs.z };
227    }
228}
229
230impl ops::Sub<Vector3> for Vector3 {
231    type Output = Vector3;
232
233    fn sub(self, rhs: Vector3) -> Vector3 {
234        return Vector3 { x: self.x - rhs.x, y: self.y - rhs.y, z: self.z - rhs.z };
235    }
236}
237
238impl ops::Mul<Vector3> for Vector3 {
239    type Output = Vector3;
240
241    fn mul(self, rhs: Vector3) -> Vector3 {
242        return Vector3 { x: self.x * rhs.x, y: self.y * rhs.y, z: self.z * rhs.z };
243    }
244}
245
246impl ops::Mul<f32> for Vector3 {
247    type Output = Vector3;
248
249    fn mul(self, rhs: f32) -> Vector3 {
250        return Vector3 { x: self.x * rhs, y: self.y * rhs, z: self.z * rhs };
251    }
252}
253
254impl ops::Mul<Vector3> for f32 {
255    type Output = Vector3;
256
257    fn mul(self, rhs: Vector3) -> Vector3 {
258        return Vector3 { x: self * rhs.x, y: self * rhs.y, z: self * rhs.z };
259    }
260}
261
262impl ops::Div<Vector3> for Vector3 {
263    type Output = Vector3;
264
265    fn div(self, rhs: Vector3) -> Vector3 {
266        return Vector3 { x: self.x / rhs.x, y: self.y / rhs.y, z: self.z / rhs.z };
267    }
268}
269
270impl ops::Div<f32> for Vector3 {
271    type Output = Vector3;
272
273    fn div(self, rhs: f32) -> Vector3 {
274        return Vector3 { x: self.x / rhs, y: self.y / rhs, z: self.z / rhs };
275    }
276}
277
278impl ops::Div<Vector3> for f32 {
279    type Output = Vector3;
280
281    fn div(self, rhs: Vector3) -> Vector3 {
282        return Vector3 { x: self / rhs.x, y: self / rhs.y, z: self / rhs.z };
283    }
284}
285
286#[repr(C)]
287#[derive(Clone, Copy, Debug, Default)]
288pub struct Vector4 {
289    pub x: f32,
290    pub y: f32,
291    pub z: f32,
292    pub w: f32,
293}
294
295impl Vector4 {
296    pub const fn new(x: f32, y: f32, z: f32, w: f32) -> Vector4 {
297        return Vector4 { x: x, y: y, z: z, w: w };
298    }
299
300    pub const fn zero() -> Vector4 {
301        return Vector4 { x: 0.0, y: 0.0, z: 0.0, w: 0.0 };
302    }
303
304    pub const fn unit_x() -> Vector4 {
305        return Vector4 { x: 1.0, y: 0.0, z: 0.0, w: 0.0 };
306    }
307
308    pub const fn unit_y() -> Vector4 {
309        return Vector4 { x: 0.0, y: 1.0, z: 0.0, w: 0.0 };
310    }
311
312    pub const fn unit_z() -> Vector4 {
313        return Vector4 { x: 0.0, y: 0.0, z: 1.0, w: 0.0 };
314    }
315
316    pub const fn unit_w() -> Vector4 {
317        return Vector4 { x: 0.0, y: 0.0, z: 0.0, w: 1.0 };
318    }
319
320    /// Compute the squared distance between two vectors
321    pub fn distance_sq(lhs: &Vector4, rhs: &Vector4) -> f32 {
322        let dx = lhs.x - rhs.x;
323        let dy = lhs.y - rhs.y;
324        let dz = lhs.z - rhs.z;
325        let dw = lhs.w - rhs.w;
326        return (dx * dx) + (dy * dy) + (dz * dz) + (dw * dw);
327    }
328
329    /// Compute the distance between two vectors
330    pub fn distance(lhs: &Vector4, rhs: &Vector4) -> f32 {
331        let dx = lhs.x - rhs.x;
332        let dy = lhs.y - rhs.y;
333        let dz = lhs.z - rhs.z;
334        let dw = lhs.w - rhs.w;
335        return ((dx * dx) + (dy * dy) + (dz * dz) + (dw * dw)).sqrt();
336    }
337
338    /// Compute the squared length of the vector
339    pub fn length_sq(self) -> f32 {
340        return (self.x * self.x) + (self.y * self.y) + (self.z * self.z) + (self.w * self.w);
341    }
342
343    /// Compute the length of the vector
344    pub fn length(self) -> f32 {
345        return ((self.x * self.x) + (self.y * self.y) + (self.z * self.z) + (self.w * self.w)).sqrt();
346    }
347
348    /// Normalize the vector
349    pub fn normalize(&mut self) {
350        let mag = 1.0 / (self.x * self.x + self.y * self.y + self.z * self.z + self.w * self.w).sqrt();
351        self.x *= mag;
352        self.y *= mag;
353        self.z *= mag;
354        self.w *= mag;
355    }
356
357    /// Produce a normalized copy of the vector
358    pub fn normalized(&self) -> Vector4 {
359        let mag = 1.0 / (self.x * self.x + self.y * self.y + self.z * self.z + self.w * self.w).sqrt();
360        return Vector4 { x: self.x * mag, y: self.y * mag, z: self.z * mag, w: self.w * mag };
361    }
362
363    /// Compute the dot product of two vectors
364    pub fn dot(lhs: &Vector4, rhs: &Vector4) -> f32 {
365        return (lhs.x * rhs.x) + (lhs.y * rhs.y) + (lhs.z * rhs.z) + (lhs.w * rhs.w);
366    }
367}
368
369impl ops::Add<Vector4> for Vector4 {
370    type Output = Vector4;
371
372    fn add(self, rhs: Vector4) -> Vector4 {
373        return Vector4 { x: self.x + rhs.x, y: self.y + rhs.y, z: self.z + rhs.z, w: self.w + rhs.w };
374    }
375}
376
377impl ops::Sub<Vector4> for Vector4 {
378    type Output = Vector4;
379
380    fn sub(self, rhs: Vector4) -> Vector4 {
381        return Vector4 { x: self.x - rhs.x, y: self.y - rhs.y, z: self.z - rhs.z, w: self.w - rhs.w };
382    }
383}
384
385impl ops::Mul<Vector4> for Vector4 {
386    type Output = Vector4;
387
388    fn mul(self, rhs: Vector4) -> Vector4 {
389        return Vector4 { x: self.x * rhs.x, y: self.y * rhs.y, z: self.z * rhs.z, w: self.w * rhs.w };
390    }
391}
392
393impl ops::Mul<f32> for Vector4 {
394    type Output = Vector4;
395
396    fn mul(self, rhs: f32) -> Vector4 {
397        return Vector4 { x: self.x * rhs, y: self.y * rhs, z: self.z * rhs, w: self.w * rhs };
398    }
399}
400
401impl ops::Mul<Vector4> for f32 {
402    type Output = Vector4;
403
404    fn mul(self, rhs: Vector4) -> Vector4 {
405        return Vector4 { x: self * rhs.x, y: self * rhs.y, z: self * rhs.z, w: self * rhs.w };
406    }
407}
408
409impl ops::Div<Vector4> for Vector4 {
410    type Output = Vector4;
411
412    fn div(self, rhs: Vector4) -> Vector4 {
413        return Vector4 { x: self.x / rhs.x, y: self.y / rhs.y, z: self.z / rhs.z, w: self.w / rhs.w };
414    }
415}
416
417impl ops::Div<f32> for Vector4 {
418    type Output = Vector4;
419
420    fn div(self, rhs: f32) -> Vector4 {
421        return Vector4 { x: self.x / rhs, y: self.y / rhs, z: self.z / rhs, w: self.w / rhs };
422    }
423}
424
425impl ops::Div<Vector4> for f32 {
426    type Output = Vector4;
427
428    fn div(self, rhs: Vector4) -> Vector4 {
429        return Vector4 { x: self / rhs.x, y: self / rhs.y, z: self / rhs.z, w: self / rhs.w };
430    }
431}
432
433#[repr(C)]
434#[derive(Clone, Copy, Debug)]
435pub struct Quaternion {
436    pub x: f32,
437    pub y: f32,
438    pub z: f32,
439    pub w: f32,
440}
441
442impl Quaternion {
443    pub const fn new(x: f32, y: f32, z: f32, w: f32) -> Quaternion {
444        return Quaternion { x: x, y: y, z: z, w: w };
445    }
446
447    pub const fn identity() -> Quaternion {
448        return Quaternion { x: 0.0, y: 0.0, z: 0.0, w: 1.0 };
449    }
450
451    /// Construct a new quaternion from the given rotations about each axis
452    pub fn from_euler(euler_angles: Vector3) -> Quaternion {
453        let cx = (euler_angles.x * 0.5).cos();
454        let sx = (euler_angles.x * 0.5).sin();
455        let cy = (euler_angles.y * 0.5).cos();
456        let sy = (euler_angles.y * 0.5).sin();
457        let cz = (euler_angles.z * 0.5).cos();
458        let sz = (euler_angles.z * 0.5).sin();
459
460        return Quaternion {
461            x: sx * cy * cz - cx * sy * sz,
462            y: cx * sy * cz + sx * cy * sz,
463            z: cx * cy * sz - sx * sy * cz,
464            w: cx * cy * cz + sx * sy * sz,
465        };
466    }
467
468    /// Normalize the quaternion
469    pub fn normalize(&mut self) {
470        let mag = 1.0 / (self.x * self.x + self.y * self.y + self.z * self.z + self.w * self.w).sqrt();
471        self.x *= mag;
472        self.y *= mag;
473        self.z *= mag;
474        self.w *= mag;
475    }
476
477    /// Produce a normalized copy of the quaternion
478    pub fn normalized(&self) -> Quaternion {
479        let mag = 1.0 / (self.x * self.x + self.y * self.y + self.z * self.z + self.w * self.w).sqrt();
480        return Quaternion { x: self.x * mag, y: self.y * mag, z: self.z * mag, w: self.w * mag };
481    }
482
483    /// Invert the quaternion
484    pub fn invert(&mut self) {
485        let n = 1.0 / (self.x * self.x + self.y * self.y + self.z * self.z + self.w * self.w);
486        self.x *= -n;
487        self.y *= -n;
488        self.z *= -n;
489        self.w *= n;
490    }
491}
492
493impl ops::Mul<Quaternion> for Quaternion {
494    type Output = Quaternion;
495
496    fn mul(self, rhs: Quaternion) -> Quaternion {
497        let x = self.x * rhs.w + self.y * rhs.z - self.z * rhs.y + self.w * rhs.x;
498        let y = -self.x * rhs.z + self.y * rhs.w + self.z * rhs.x + self.w * rhs.y;
499        let z = self.x * rhs.y - self.y * rhs.x + self.z * rhs.w + self.w * rhs.z;
500        let w = -self.x * rhs.x - self.y * rhs.y - self.z * rhs.z + self.w * rhs.w;
501        return Quaternion { x: x, y: y, z: z, w: w };
502    }
503}
504
505impl ops::Mul<Vector3> for Quaternion {
506    type Output = Vector3;
507
508    fn mul(self, rhs: Vector3) -> Vector3 {
509        let x = 2.0 * (self.y * rhs.z - self.z * rhs.y);
510        let y = 2.0 * (self.z * rhs.x - self.x * rhs.z);
511        let z = 2.0 * (self.x * rhs.y - self.y * rhs.x);
512
513        let rx = rhs.x + x * self.w + (self.y * z - self.z * y);
514        let ry = rhs.y + y * self.w + (self.z * x - self.x * z);
515        let rz = rhs.z + z * self.w + (self.x * y - self.y * x);
516
517        return Vector3 { x: rx, y: ry, z: rz };
518    }
519}
520
521#[repr(C)]
522#[derive(Clone, Copy, Debug)]
523pub struct Matrix4x4 {
524    pub m: [[f32;4];4],
525}
526
527impl Matrix4x4 {
528    pub const fn identity() -> Matrix4x4 {
529        return Matrix4x4 { m: [
530            [1.0, 0.0, 0.0, 0.0],
531            [0.0, 1.0, 0.0, 0.0],
532            [0.0, 0.0, 1.0, 0.0],
533            [0.0, 0.0, 0.0, 1.0],
534        ] };
535    }
536
537    /// Return the given row of the matrix as a vector
538    pub fn get_row(self: &Matrix4x4, index: usize) -> Vector4 {
539        Vector4::new(self.m[0][index], self.m[1][index], self.m[2][index], self.m[3][index])
540    }
541
542    /// Return the given column of the matrix as a vector
543    pub fn get_column(self: &Matrix4x4, index: usize) -> Vector4 {
544        Vector4::new(self.m[index][0], self.m[index][1], self.m[index][2], self.m[index][3])
545    }
546
547    /// Transpose the rows and columns of the matrix
548    pub fn transpose(self: &mut Matrix4x4) {
549        let c0 = self.m[0];
550        let c1 = self.m[1];
551        let c2 = self.m[2];
552        let c3 = self.m[3];
553
554        self.m[0] = [c0[0], c1[0], c2[0], c3[0]];
555        self.m[1] = [c0[1], c1[1], c2[1], c3[1]];
556        self.m[2] = [c0[2], c1[2], c2[2], c3[2]];
557        self.m[3] = [c0[3], c1[3], c2[3], c3[3]];
558    }
559
560    /// Returns a transposed version of the matrix
561    pub fn transposed(self: &Matrix4x4) -> Matrix4x4 {
562        let mut ret = *self;
563        ret.transpose();
564
565        return ret;
566    }
567
568    /// Construct a translation matrix
569    pub fn translation(translation: Vector3) -> Matrix4x4 {
570        return Matrix4x4 { m: [
571            [1.0, 0.0, 0.0, 0.0],
572            [0.0, 1.0, 0.0, 0.0],
573            [0.0, 0.0, 1.0, 0.0],
574            [translation.x, translation.y, translation.z, 1.0],
575        ] };
576    }
577
578    /// Construct a scale matrix
579    pub fn scale(scale: Vector3) -> Matrix4x4 {
580        return Matrix4x4 { m: [
581            [scale.x, 0.0, 0.0, 0.0],
582            [0.0, scale.y, 0.0, 0.0],
583            [0.0, 0.0, scale.z, 0.0],
584            [0.0, 0.0, 0.0, 1.0],
585        ] };
586    }
587
588    /// Construct a rotation matrix
589    pub fn rotation(rotation: Quaternion) -> Matrix4x4 {
590        let num9 = rotation.x * rotation.x;
591        let num8 = rotation.y * rotation.y;
592        let num7 = rotation.z * rotation.z;
593        let num6 = rotation.x * rotation.y;
594        let num5 = rotation.z * rotation.w;
595        let num4 = rotation.z * rotation.x;
596        let num3 = rotation.y * rotation.w;
597        let num2 = rotation.y * rotation.z;
598        let num = rotation.x * rotation.w;
599        
600        let mut result = Matrix4x4::identity();
601        result.m[0][0] = 1.0 - (2.0 * (num8 + num7));
602        result.m[0][1] = 2.0 * (num6 + num5);
603        result.m[0][2] = 2.0 * (num4 - num3);
604        result.m[0][3] = 0.0;
605        result.m[1][0] = 2.0 * (num6 - num5);
606        result.m[1][1] = 1.0 - (2.0 * (num7 + num9));
607        result.m[1][2] = 2.0 * (num2 + num);
608        result.m[1][3] = 0.0;
609        result.m[2][0] = 2.0 * (num4 + num3);
610        result.m[2][1] = 2.0 * (num2 - num);
611        result.m[2][2] = 1.0 - (2.0 * (num8 + num9));
612        result.m[2][3] = 0.0;
613        result.m[3][0] = 0.0;
614        result.m[3][1] = 0.0;
615        result.m[3][2] = 0.0;
616        result.m[3][3] = 1.0;
617
618        return result;
619    }
620
621    /// Construct a new off-center orthographic projection matrix
622    pub fn projection_ortho(left: f32, right: f32, top: f32, bottom: f32, near: f32, far: f32) -> Matrix4x4 {
623        let scale_x = 2.0 / (right - left);
624        let scale_y = 2.0 / (top - bottom);
625        let scale_z = 1.0 / (near - far);
626
627        let mut mat = Matrix4x4::identity();
628
629        mat.m[0][0] = scale_x;
630        mat.m[1][1] = scale_y;
631        mat.m[2][2] = scale_z;
632
633        mat.m[3][0] = (left + right) / (left - right);
634        mat.m[3][1] = (top + bottom) / (bottom - top);
635        mat.m[3][2] = near / (near - far);
636
637        return mat;
638    }
639
640    /// Construct a new orthographic projection matrix using the given aspect ratio, scale, and near/far plane clip distances
641    pub fn projection_ortho_aspect(aspect_ratio: f32, scale: f32, near: f32, far: f32) -> Matrix4x4 {
642        let extent_x = scale * aspect_ratio * 0.5;
643        let extent_y = scale * 0.5;
644
645        return Matrix4x4::projection_ortho(-extent_x, extent_x, extent_y, -extent_y, near, far);
646    }
647
648    /// Construct a new perspective projection matrix using the given aspect ratio, field of view, and near/far plane clip distances
649    pub fn projection_perspective(aspect_ratio: f32, field_of_view: f32, near: f32, far: f32) -> Matrix4x4 {
650        let top = (field_of_view * 0.5).tan() * near;
651        let bottom = -top;
652        let right = top * aspect_ratio;
653        let left = -right;
654
655        let height = top - bottom;
656        let width = right - left;
657
658        let two_n = 2.0 * near;
659
660        let mut mat = Matrix4x4 {m: [
661            [ 0.0, 0.0, 0.0, 0.0 ],
662            [ 0.0, 0.0, 0.0, 0.0 ],
663            [ 0.0, 0.0, 0.0, 0.0 ],
664            [ 0.0, 0.0, 0.0, 0.0 ],
665        ]};
666
667        mat.m[0][0] = two_n / width;
668        mat.m[1][1] = two_n / height;
669        mat.m[2][2] = far / (near - far);
670        mat.m[2][3] = -1.0;
671        mat.m[3][2] = (near * far) /
672                    (near - far);
673
674        return mat;
675    }
676
677    /// Load an identity matrix into the SIMD register
678    #[deprecated(since = "0.1.16", note = "Dreambox v2.x now directly supports compiling with SIMD intrinsics")]
679    #[allow(deprecated)]
680    pub fn load_identity_simd() {
681        let m = Matrix4x4::identity();
682        Matrix4x4::load_simd(&m);
683    }
684
685    /// Load a matrix into the SIMD register
686    #[deprecated(since = "0.1.16", note = "Dreambox v2.x now directly supports compiling with WASM SIMD intrinsics")]
687    pub fn load_simd(matrix: &Matrix4x4) {
688        unsafe { mat4_loadSIMD(matrix) };
689    }
690
691    /// Store the current value of the SIMD register to the given matrix
692    #[deprecated(since = "0.1.16", note = "Dreambox v2.x now directly supports compiling with WASM SIMD intrinsics")]
693    pub fn store_simd(matrix: &mut Matrix4x4) {
694        unsafe { mat4_storeSIMD(matrix) };
695    }
696
697    /// Multiply the matrix in the SIMD register by the given matrix
698    #[deprecated(since = "0.1.16", note = "Dreambox v2.x now directly supports compiling with WASM SIMD intrinsics")]
699    pub fn mul_simd(matrix: &Matrix4x4) {
700        unsafe { mat4_mulSIMD(matrix) };
701    }
702
703    /// Transform an array of vectors using the SIMD matrix register
704    #[deprecated(since = "0.1.16", note = "Dreambox v2.x now directly supports compiling with WASM SIMD intrinsics")]
705    pub fn transform_vector_simd(data: &mut [Vector4]) {
706        unsafe {
707            let ptr = data.as_mut_ptr();
708            let stride = size_of::<Vector4>();
709            mat4_transformSIMD(ptr, ptr, data.len().try_into().unwrap(), stride.try_into().unwrap());
710        }
711    }
712
713    /// Transform a field of an array of input vertex structs using the SIMD matrix register
714    #[deprecated(since = "0.1.16", note = "Dreambox v2.x now directly supports compiling with WASM SIMD intrinsics")]
715    pub fn transform_vertex_simd<T>(data: &mut [T], field: FieldOffset<T,Vector4>) {
716        unsafe {
717            let fieldref = field.apply_ptr_mut(data.as_mut_ptr());
718            let stride = size_of::<T>();
719            mat4_transformSIMD(fieldref, fieldref, data.len().try_into().unwrap(), stride.try_into().unwrap());
720        }
721    }
722}
723
724impl ops::Mul<Vector4> for Matrix4x4 {
725    type Output = Vector4;
726
727    fn mul(self, rhs: Vector4) -> Vector4 {
728        let x = (rhs.x * self.m[0][0]) + (rhs.y * self.m[1][0]) + (rhs.z * self.m[2][0]) + (rhs.w * self.m[3][0]);
729        let y = (rhs.x * self.m[0][1]) + (rhs.y * self.m[1][1]) + (rhs.z * self.m[2][1]) + (rhs.w * self.m[3][1]);
730        let z = (rhs.x * self.m[0][2]) + (rhs.y * self.m[1][2]) + (rhs.z * self.m[2][2]) + (rhs.w * self.m[3][2]);
731        let w = (rhs.x * self.m[0][3]) + (rhs.y * self.m[1][3]) + (rhs.z * self.m[2][3]) + (rhs.w * self.m[3][3]);
732
733        return Vector4 { x, y, z, w };
734    }
735}
736
737impl ops::Mul<f32> for Matrix4x4 {
738    type Output = Matrix4x4;
739
740    fn mul(self, rhs: f32) -> Matrix4x4 {
741        let m00 = self.m[0][0] * rhs;
742        let m10 = self.m[1][0] * rhs;
743        let m20 = self.m[2][0] * rhs;
744        let m30 = self.m[3][0] * rhs;
745        
746        let m01 = self.m[0][1] * rhs;
747        let m11 = self.m[1][1] * rhs;
748        let m21 = self.m[2][1] * rhs;
749        let m31 = self.m[3][1] * rhs;
750        
751        let m02 = self.m[0][2] * rhs;
752        let m12 = self.m[1][2] * rhs;
753        let m22 = self.m[2][2] * rhs;
754        let m32 = self.m[3][2] * rhs;
755        
756        let m03 = self.m[0][3] * rhs;
757        let m13 = self.m[1][3] * rhs;
758        let m23 = self.m[2][3] * rhs;
759        let m33 = self.m[3][3] * rhs;
760
761        return Matrix4x4 { m: [
762            [m00, m10, m20, m30],
763            [m01, m11, m21, m31],
764            [m02, m12, m22, m32],
765            [m03, m13, m23, m33],
766        ] };
767    }
768}
769
770impl ops::Mul<Matrix4x4> for Matrix4x4 {
771    type Output = Matrix4x4;
772
773    fn mul(self, rhs: Matrix4x4) -> Matrix4x4 {
774        let m00 = (self.m[0][0] * rhs.m[0][0]) + (self.m[0][1] * rhs.m[1][0]) + (self.m[0][2] * rhs.m[2][0]) + (self.m[0][3] * rhs.m[3][0]);
775        let m10 = (self.m[0][0] * rhs.m[0][1]) + (self.m[0][1] * rhs.m[1][1]) + (self.m[0][2] * rhs.m[2][1]) + (self.m[0][3] * rhs.m[3][1]);
776        let m20 = (self.m[0][0] * rhs.m[0][2]) + (self.m[0][1] * rhs.m[1][2]) + (self.m[0][2] * rhs.m[2][2]) + (self.m[0][3] * rhs.m[3][2]);
777        let m30 = (self.m[0][0] * rhs.m[0][3]) + (self.m[0][1] * rhs.m[1][3]) + (self.m[0][2] * rhs.m[2][3]) + (self.m[0][3] * rhs.m[3][3]);
778
779        let m01 = (self.m[1][0] * rhs.m[0][0]) + (self.m[1][1] * rhs.m[1][0]) + (self.m[1][2] * rhs.m[2][0]) + (self.m[1][3] * rhs.m[3][0]);
780        let m11 = (self.m[1][0] * rhs.m[0][1]) + (self.m[1][1] * rhs.m[1][1]) + (self.m[1][2] * rhs.m[2][1]) + (self.m[1][3] * rhs.m[3][1]);
781        let m21 = (self.m[1][0] * rhs.m[0][2]) + (self.m[1][1] * rhs.m[1][2]) + (self.m[1][2] * rhs.m[2][2]) + (self.m[1][3] * rhs.m[3][2]);
782        let m31 = (self.m[1][0] * rhs.m[0][3]) + (self.m[1][1] * rhs.m[1][3]) + (self.m[1][2] * rhs.m[2][3]) + (self.m[1][3] * rhs.m[3][3]);
783
784        let m02 = (self.m[2][0] * rhs.m[0][0]) + (self.m[2][1] * rhs.m[1][0]) + (self.m[2][2] * rhs.m[2][0]) + (self.m[2][3] * rhs.m[3][0]);
785        let m12 = (self.m[2][0] * rhs.m[0][1]) + (self.m[2][1] * rhs.m[1][1]) + (self.m[2][2] * rhs.m[2][1]) + (self.m[2][3] * rhs.m[3][1]);
786        let m22 = (self.m[2][0] * rhs.m[0][2]) + (self.m[2][1] * rhs.m[1][2]) + (self.m[2][2] * rhs.m[2][2]) + (self.m[2][3] * rhs.m[3][2]);
787        let m32 = (self.m[2][0] * rhs.m[0][3]) + (self.m[2][1] * rhs.m[1][3]) + (self.m[2][2] * rhs.m[2][3]) + (self.m[2][3] * rhs.m[3][3]);
788
789        let m03 = (self.m[3][0] * rhs.m[0][0]) + (self.m[3][1] * rhs.m[1][0]) + (self.m[3][2] * rhs.m[2][0]) + (self.m[3][3] * rhs.m[3][0]);
790        let m13 = (self.m[3][0] * rhs.m[0][1]) + (self.m[3][1] * rhs.m[1][1]) + (self.m[3][2] * rhs.m[2][1]) + (self.m[3][3] * rhs.m[3][1]);
791        let m23 = (self.m[3][0] * rhs.m[0][2]) + (self.m[3][1] * rhs.m[1][2]) + (self.m[3][2] * rhs.m[2][2]) + (self.m[3][3] * rhs.m[3][2]);
792        let m33 = (self.m[3][0] * rhs.m[0][3]) + (self.m[3][1] * rhs.m[1][3]) + (self.m[3][2] * rhs.m[2][3]) + (self.m[3][3] * rhs.m[3][3]);
793
794        return Matrix4x4 { m: [
795            [m00, m10, m20, m30],
796            [m01, m11, m21, m31],
797            [m02, m12, m22, m32],
798            [m03, m13, m23, m33],
799        ] };
800    }
801}
802
803impl ops::Add<Matrix4x4> for Matrix4x4 {
804    type Output = Matrix4x4;
805
806    fn add(self, rhs: Matrix4x4) -> Matrix4x4 {
807        let m00 = self.m[0][0] + rhs.m[0][0];
808        let m10 = self.m[1][0] + rhs.m[1][0];
809        let m20 = self.m[2][0] + rhs.m[2][0];
810        let m30 = self.m[3][0] + rhs.m[3][0];
811        
812        let m01 = self.m[0][1] + rhs.m[0][1];
813        let m11 = self.m[1][1] + rhs.m[1][1];
814        let m21 = self.m[2][1] + rhs.m[2][1];
815        let m31 = self.m[3][1] + rhs.m[3][1];
816        
817        let m02 = self.m[0][2] + rhs.m[0][2];
818        let m12 = self.m[1][2] + rhs.m[1][2];
819        let m22 = self.m[2][2] + rhs.m[2][2];
820        let m32 = self.m[3][2] + rhs.m[3][2];
821        
822        let m03 = self.m[0][3] + rhs.m[0][3];
823        let m13 = self.m[1][3] + rhs.m[1][3];
824        let m23 = self.m[2][3] + rhs.m[2][3];
825        let m33 = self.m[3][3] + rhs.m[3][3];
826
827        return Matrix4x4 { m: [
828            [m00, m10, m20, m30],
829            [m01, m11, m21, m31],
830            [m02, m12, m22, m32],
831            [m03, m13, m23, m33],
832        ] };
833    }
834}
835
836impl ops::Sub<Matrix4x4> for Matrix4x4 {
837    type Output = Matrix4x4;
838
839    fn sub(self, rhs: Matrix4x4) -> Matrix4x4 {
840        let m00 = self.m[0][0] - rhs.m[0][0];
841        let m10 = self.m[1][0] - rhs.m[1][0];
842        let m20 = self.m[2][0] - rhs.m[2][0];
843        let m30 = self.m[3][0] - rhs.m[3][0];
844        
845        let m01 = self.m[0][1] - rhs.m[0][1];
846        let m11 = self.m[1][1] - rhs.m[1][1];
847        let m21 = self.m[2][1] - rhs.m[2][1];
848        let m31 = self.m[3][1] - rhs.m[3][1];
849        
850        let m02 = self.m[0][2] - rhs.m[0][2];
851        let m12 = self.m[1][2] - rhs.m[1][2];
852        let m22 = self.m[2][2] - rhs.m[2][2];
853        let m32 = self.m[3][2] - rhs.m[3][2];
854        
855        let m03 = self.m[0][3] - rhs.m[0][3];
856        let m13 = self.m[1][3] - rhs.m[1][3];
857        let m23 = self.m[2][3] - rhs.m[2][3];
858        let m33 = self.m[3][3] - rhs.m[3][3];
859
860        return Matrix4x4 { m: [
861            [m00, m10, m20, m30],
862            [m01, m11, m21, m31],
863            [m02, m12, m22, m32],
864            [m03, m13, m23, m33],
865        ] };
866    }
867}