raylib/core/
math.rs

1/* raylib-rs
2   raymath.rs - Structs and functions for game-related math and linear algebra
3
4Copyright (c) 2018-2019 Paul Clement (@deltaphc)
5
6This software is provided "as-is", without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software.
7
8Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
9
10  1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
11
12  2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
13
14  3. This notice may not be removed or altered from any source distribution.
15*/
16
17use crate::ffi;
18use crate::misc::AsF32;
19use std::f32::consts::PI;
20use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Range, Sub, SubAssign};
21
22#[cfg(feature = "with_serde")]
23use serde::{Deserialize, Serialize};
24
25make_rslice!(RSliceVec4, Vector4, ffi::MemFree);
26
27macro_rules! optional_serde_struct {
28    ($def:item) => {
29        cfg_if::cfg_if! {
30            if #[cfg(feature = "with_serde")] {
31                #[repr(C)]
32                #[derive(Default, Debug, Copy, Clone, PartialEq, Serialize, Deserialize)]
33                $def
34            } else {
35                #[repr(C)]
36                #[derive(Default, Debug, Copy, Clone, PartialEq)]
37                $def
38            }
39        }
40    };
41}
42
43optional_serde_struct! {
44    pub struct Vector2 {
45        pub x: f32,
46        pub y: f32,
47    }
48}
49
50#[cfg(feature = "convert_mint")]
51impl From<mint::Vector2<f32>> for Vector2 {
52    fn from(v: mint::Vector2<f32>) -> Vector2 {
53        Vector2 { x: v.x, y: v.y }
54    }
55}
56
57#[cfg(feature = "convert_mint")]
58impl From<mint::Point2<f32>> for Vector2 {
59    fn from(v: mint::Point2<f32>) -> Vector2 {
60        Vector2 { x: v.x, y: v.y }
61    }
62}
63
64#[cfg(feature = "convert_mint")]
65impl From<Vector2> for mint::Vector2<f32> {
66    fn from(v: Vector2) -> Self {
67        Self { x: v.x, y: v.y }
68    }
69}
70
71impl From<ffi::Vector2> for Vector2 {
72    fn from(v: ffi::Vector2) -> Vector2 {
73        unsafe { std::mem::transmute(v) }
74    }
75}
76
77impl From<Vector2> for ffi::Vector2 {
78    fn from(v: Vector2) -> Self {
79        unsafe { std::mem::transmute(v) }
80    }
81}
82
83impl From<&Vector2> for ffi::Vector2 {
84    fn from(v: &Vector2) -> ffi::Vector2 {
85        ffi::Vector2 { x: v.x, y: v.y }
86    }
87}
88
89/// A convenience function for linearly interpolating an `f32`.
90#[inline]
91pub fn lerp(v0: f32, v1: f32, amount: f32) -> f32 {
92    v0 + amount * (v1 - v0)
93}
94
95/// A convenience function for making a new `Vector2`.
96#[inline]
97pub fn rvec2<T1: AsF32, T2: AsF32>(x: T1, y: T2) -> Vector2 {
98    Vector2::new(x.as_f32(), y.as_f32())
99}
100
101/// A convenience function for making a new `Vector3`.
102#[inline]
103pub fn rvec3<T1: AsF32, T2: AsF32, T3: AsF32>(x: T1, y: T2, z: T3) -> Vector3 {
104    Vector3::new(x.as_f32(), y.as_f32(), z.as_f32())
105}
106
107/// A convenience function for making a new `Quaternion`.
108#[inline]
109pub fn rquat<T1: AsF32, T2: AsF32, T3: AsF32, T4: AsF32>(x: T1, y: T2, z: T3, w: T4) -> Quaternion {
110    Quaternion::new(x.as_f32(), y.as_f32(), z.as_f32(), w.as_f32())
111}
112
113/// A convenience function for making a new `Rectangle`.
114#[inline]
115pub fn rrect<T1: AsF32, T2: AsF32, T3: AsF32, T4: AsF32>(
116    x: T1,
117    y: T2,
118    width: T3,
119    height: T4,
120) -> Rectangle {
121    Rectangle::new(x.as_f32(), y.as_f32(), width.as_f32(), height.as_f32())
122}
123
124impl Vector2 {
125    /// Constant `Vector2` with both components set to zero.
126    const ZERO: Vector2 = Vector2 { x: 0.0, y: 0.0 };
127
128    /// Constant `Vector2` with both components set to one.
129    const ONE: Vector2 = Vector2 { x: 1.0, y: 1.0 };
130
131    /// Returns a new `Vector2` with specified components.
132    pub const fn new(x: f32, y: f32) -> Vector2 {
133        Vector2 { x, y }
134    }
135
136    /// Returns a new `Vector2` with both components set to zero.
137    #[inline]
138    pub const fn zero() -> Vector2 {
139        Vector2 { x: 0.0, y: 0.0 }
140    }
141
142    /// Returns a new `Vector2` with both components set to one.
143    #[inline]
144    pub const fn one() -> Vector2 {
145        Vector2 { x: 1.0, y: 1.0 }
146    }
147
148    /// Calculates the vector length.
149    pub fn length(&self) -> f32 {
150        ((self.x * self.x) + (self.y * self.y)).sqrt()
151    }
152
153    /// Calculates the vector length square (**2);
154    pub fn length_sqr(&self) -> f32 {
155        (self.x * self.x) + (self.y * self.y)
156    }
157
158    /// Calculates the dot product with vector `v`.
159    pub fn dot(&self, v: Vector2) -> f32 {
160        self.x * v.x + self.y * v.y
161    }
162
163    /// Calculates the distance towards vector `v`.
164    pub fn distance_to(&self, v: Vector2) -> f32 {
165        ((self.x - v.x) * (self.x - v.x) + (self.y - v.y) * (self.y - v.y)).sqrt()
166    }
167
168    /// Calculates the angle towards vector `v` in radians.
169    pub fn angle_to(&self, v: Vector2) -> f32 {
170        let mut result = (v.y - self.y).atan2(v.x - self.x);
171        if result < 0.0 {
172            result += 2.0 * PI;
173        }
174        result
175    }
176
177    /// Scales the vector by multiplying both components by `scale`.
178    pub fn scale(&mut self, scale: f32) {
179        *self *= scale;
180    }
181
182    /// Returns a new `Vector2` with components scaled by `scale`.
183    pub fn scale_by(&self, scale: f32) -> Vector2 {
184        *self * scale
185    }
186
187    /// Normalizes the vector.
188    pub fn normalize(&mut self) {
189        *self = self.normalized();
190    }
191
192    /// Returns a new `Vector2` with normalized components from the current vector.
193    pub fn normalized(&self) -> Vector2 {
194        let length_sqr = self.length_sqr();
195        if length_sqr == 0.0 {
196            return *self;
197        }
198        *self / length_sqr.sqrt()
199    }
200
201    /// Rotates the vector by `angle` radians.
202    pub fn rotate(&mut self, angle: f32) {
203        let cos_res = angle.cos();
204        let sin_res = angle.sin();
205
206        let result = Vector2::new(
207            self.x * cos_res - self.y * sin_res,
208            self.x * sin_res + self.y * cos_res,
209        );
210
211        self.x = result.x;
212        self.y = result.y;
213    }
214
215    /// Returns a new `Vector2` rotated by `angle` radians.
216    pub fn rotated(&self, angle: f32) -> Vector2 {
217        let cos_res = angle.cos();
218        let sin_res = angle.sin();
219
220        Vector2::new(
221            self.x * cos_res - self.y * sin_res,
222            self.x * sin_res + self.y * cos_res,
223        )
224    }
225
226    /// Returns a new `Vector2` with componenets linearly interpolated by `amount` towards vector `v`.
227    pub fn lerp(&self, v: Vector2, amount: f32) -> Vector2 {
228        Vector2 {
229            x: self.x + amount * (v.x - self.x),
230            y: self.y + amount * (v.y - self.y),
231        }
232    }
233
234    /// Returns a new `Vector2` with componenets clamp to a certain interval.
235    pub fn clamp(&self, num: Range<f32>) -> Vector2 {
236        Vector2 {
237            x: self.x.clamp(num.start, num.end),
238            y: self.y.clamp(num.start, num.end),
239        }
240    }
241}
242
243impl From<(f32, f32)> for Vector2 {
244    #[inline]
245    fn from((x, y): (f32, f32)) -> Vector2 {
246        Vector2 { x, y }
247    }
248}
249
250impl Add for Vector2 {
251    type Output = Vector2;
252    fn add(self, v: Vector2) -> Self {
253        Vector2 {
254            x: self.x + v.x,
255            y: self.y + v.y,
256        }
257    }
258}
259
260impl Add<f32> for Vector2 {
261    type Output = Vector2;
262    fn add(self, value: f32) -> Self {
263        Vector2 {
264            x: self.x + value,
265            y: self.y + value,
266        }
267    }
268}
269
270impl AddAssign for Vector2 {
271    fn add_assign(&mut self, v: Vector2) {
272        *self = *self + v;
273    }
274}
275
276impl AddAssign<f32> for Vector2 {
277    fn add_assign(&mut self, value: f32) {
278        *self = *self + value;
279    }
280}
281
282impl Sub for Vector2 {
283    type Output = Vector2;
284    fn sub(self, v: Vector2) -> Self {
285        Vector2 {
286            x: self.x - v.x,
287            y: self.y - v.y,
288        }
289    }
290}
291
292impl Sub<f32> for Vector2 {
293    type Output = Vector2;
294    fn sub(self, value: f32) -> Self {
295        Vector2 {
296            x: self.x - value,
297            y: self.y - value,
298        }
299    }
300}
301
302impl SubAssign for Vector2 {
303    fn sub_assign(&mut self, v: Vector2) {
304        *self = *self - v;
305    }
306}
307
308impl SubAssign<f32> for Vector2 {
309    fn sub_assign(&mut self, value: f32) {
310        *self = *self - value;
311    }
312}
313
314impl Mul for Vector2 {
315    type Output = Vector2;
316    fn mul(self, v: Vector2) -> Self {
317        Vector2 {
318            x: self.x * v.x,
319            y: self.y * v.y,
320        }
321    }
322}
323
324impl Mul<f32> for Vector2 {
325    type Output = Vector2;
326    fn mul(self, value: f32) -> Self {
327        Vector2 {
328            x: self.x * value,
329            y: self.y * value,
330        }
331    }
332}
333
334impl MulAssign for Vector2 {
335    fn mul_assign(&mut self, v: Vector2) {
336        *self = *self * v;
337    }
338}
339
340impl MulAssign<f32> for Vector2 {
341    fn mul_assign(&mut self, value: f32) {
342        *self = *self * value;
343    }
344}
345
346impl Div for Vector2 {
347    type Output = Vector2;
348    fn div(self, v: Vector2) -> Self {
349        Vector2 {
350            x: self.x / v.x,
351            y: self.y / v.y,
352        }
353    }
354}
355
356impl Div<f32> for Vector2 {
357    type Output = Vector2;
358    fn div(self, value: f32) -> Self {
359        Vector2 {
360            x: self.x / value,
361            y: self.y / value,
362        }
363    }
364}
365
366impl DivAssign for Vector2 {
367    fn div_assign(&mut self, v: Vector2) {
368        *self = *self / v;
369    }
370}
371
372impl DivAssign<f32> for Vector2 {
373    fn div_assign(&mut self, value: f32) {
374        *self = *self / value;
375    }
376}
377
378impl Neg for Vector2 {
379    type Output = Vector2;
380    fn neg(self) -> Self {
381        Vector2 {
382            x: -self.x,
383            y: -self.y,
384        }
385    }
386}
387
388optional_serde_struct! {
389    pub struct Vector3 {
390        pub x: f32,
391        pub y: f32,
392        pub z: f32,
393    }
394}
395
396#[cfg(feature = "convert_mint")]
397impl From<mint::Vector3<f32>> for Vector3 {
398    fn from(v: mint::Vector3<f32>) -> Vector3 {
399        Vector3 {
400            x: v.x,
401            y: v.y,
402            z: v.z,
403        }
404    }
405}
406
407#[cfg(feature = "convert_mint")]
408impl From<mint::Point3<f32>> for Vector3 {
409    fn from(v: mint::Point3<f32>) -> Vector3 {
410        Vector3 {
411            x: v.x,
412            y: v.y,
413            z: v.z,
414        }
415    }
416}
417
418#[cfg(feature = "convert_mint")]
419impl From<Vector3> for mint::Vector3<f32> {
420    fn from(v: Vector3) -> Self {
421        Self {
422            x: v.x,
423            y: v.y,
424            z: v.z,
425        }
426    }
427}
428
429impl From<ffi::Vector3> for Vector3 {
430    fn from(v: ffi::Vector3) -> Vector3 {
431        unsafe { std::mem::transmute(v) }
432    }
433}
434
435impl From<Vector3> for ffi::Vector3 {
436    fn from(v: Vector3) -> Self {
437        unsafe { std::mem::transmute(v) }
438    }
439}
440
441impl From<&Vector3> for ffi::Vector3 {
442    fn from(v: &Vector3) -> ffi::Vector3 {
443        ffi::Vector3 {
444            x: v.x,
445            y: v.y,
446            z: v.z,
447        }
448    }
449}
450
451impl Vector3 {
452    /// Returns a new `Vector3` with specified components.
453    pub const fn new(x: f32, y: f32, z: f32) -> Vector3 {
454        Vector3 { x, y, z }
455    }
456
457    pub fn up() -> Vector3 {
458        Vector3::new(0.0, 1.0, 0.0)
459    }
460
461    pub fn forward() -> Vector3 {
462        Vector3::new(0.0, 0.0, 1.0)
463    }
464
465    pub fn right() -> Vector3 {
466        Vector3::new(1.0, 0.0, 0.0)
467    }
468
469    pub fn left() -> Vector3 {
470        Vector3::new(-1.0, 0.0, 0.0)
471    }
472
473    /// Returns a new `Vector3` with all components set to zero.
474    pub fn zero() -> Vector3 {
475        Vector3 {
476            x: 0.0,
477            y: 0.0,
478            z: 0.0,
479        }
480    }
481
482    /// Returns a new `Vector3` with all components set to one.
483    pub fn one() -> Vector3 {
484        Vector3 {
485            x: 1.0,
486            y: 1.0,
487            z: 1.0,
488        }
489    }
490
491    /// Returns a new `Vector3` containing the cross product between `self` and vector `v`.
492    pub fn cross(&self, v: Vector3) -> Vector3 {
493        Vector3 {
494            x: self.y * v.z - self.z * v.y,
495            y: self.z * v.x - self.x * v.z,
496            z: self.x * v.y - self.y * v.x,
497        }
498    }
499
500    /// Returns a new `Vector3` perpendicular to `self`.
501    pub fn perpendicular(&self) -> Vector3 {
502        let mut min = self.x.abs();
503        let mut cardinal_axis = Vector3 {
504            x: 1.0,
505            y: 0.0,
506            z: 0.0,
507        };
508
509        if self.y.abs() < min {
510            min = self.y.abs();
511            cardinal_axis = Vector3 {
512                x: 0.0,
513                y: 1.0,
514                z: 0.0,
515            };
516        }
517
518        if self.z.abs() < min {
519            cardinal_axis = Vector3 {
520                x: 0.0,
521                y: 0.0,
522                z: 1.0,
523            };
524        }
525
526        self.cross(cardinal_axis)
527    }
528
529    /// Calculates the vector length.
530    pub fn length(&self) -> f32 {
531        (self.x * self.x + self.y * self.y + self.z * self.z).sqrt()
532    }
533
534    /// Calculates the dot product with vector `v`.
535    pub fn dot(&self, v: Vector3) -> f32 {
536        self.x * v.x + self.y * v.y + self.z * v.z
537    }
538
539    /// Calculates the distance towards vector `v`.
540    pub fn distance_to(&self, v: Vector3) -> f32 {
541        let dx = v.x - self.x;
542        let dy = v.y - self.y;
543        let dz = v.z - self.z;
544        (dx * dx + dy * dy + dz * dz).sqrt()
545    }
546
547    /// Scales the vector by multiplying both components by `scale`.
548    pub fn scale(&mut self, scale: f32) {
549        *self *= scale;
550    }
551
552    /// Returns a new `Vector3` with components scaled by `scale`.
553    pub fn scale_by(&self, scale: f32) -> Vector3 {
554        *self * scale
555    }
556
557    /// Normalizes the current vector.
558    pub fn normalize(&mut self) {
559        *self = self.normalized();
560    }
561
562    /// Returns a new `Vector3` with normalized components from the current vector.
563    pub fn normalized(&self) -> Vector3 {
564        let mut length = self.length();
565        if length == 0.0 {
566            length = 1.0;
567        }
568        let ilength = 1.0 / length;
569
570        Vector3 {
571            x: self.x * ilength,
572            y: self.y * ilength,
573            z: self.z * ilength,
574        }
575    }
576
577    /// Normalizes and changes both `self` and `v` to be orthogonal to eachother.
578    pub fn ortho_normalize(&mut self, v: &mut Vector3) {
579        *self = self.normalized();
580        let vn = self.cross(*v).normalized();
581        *v = vn.cross(*self);
582    }
583
584    /// Transforms the current vector using Matrix `mat`.
585    pub fn transform(&mut self, mat: Matrix) {
586        *self = self.transform_with(mat);
587    }
588
589    /// Returns a new `Vector3` containing components transformed by Matrix `mat`.
590    pub fn transform_with(&self, mat: Matrix) -> Vector3 {
591        Vector3 {
592            x: mat.m0 * self.x + mat.m4 * self.y + mat.m8 * self.z + mat.m12,
593            y: mat.m1 * self.x + mat.m5 * self.y + mat.m9 * self.z + mat.m13,
594            z: mat.m2 * self.x + mat.m6 * self.y + mat.m10 * self.z + mat.m14,
595        }
596    }
597
598    /// Rotates the current vector using Quaternion `q`.
599    pub fn rotate(&mut self, q: Quaternion) {
600        *self = self.rotate_by(q);
601    }
602
603    /// Returns a new `Vector3` with components rotated by Quaternion `q`.
604    pub fn rotate_by(&self, q: Quaternion) -> Vector3 {
605        Vector3 {
606            x: self.x * (q.x * q.x + q.w * q.w - q.y * q.y - q.z * q.z)
607                + self.y * (2.0 * q.x * q.y - 2.0 * q.w * q.z)
608                + self.z * (2.0 * q.x * q.z + 2.0 * q.w * q.y),
609            y: self.x * (2.0 * q.w * q.z + 2.0 * q.x * q.y)
610                + self.y * (q.w * q.w - q.x * q.x + q.y * q.y - q.z * q.z)
611                + self.z * (-2.0 * q.w * q.x + 2.0 * q.y * q.z),
612            z: self.x * (-2.0 * q.w * q.y + 2.0 * q.x * q.z)
613                + self.y * (2.0 * q.w * q.x + 2.0 * q.y * q.z)
614                + self.z * (q.w * q.w - q.x * q.x - q.y * q.y + q.z * q.z),
615        }
616    }
617
618    /// Returns a new `Vector3` with componenets linearly interpolated by `amount` towards vector `v`.
619    pub fn lerp(&self, v: Vector3, amount: f32) -> Vector3 {
620        Vector3 {
621            x: self.x + amount * (v.x - self.x),
622            y: self.y + amount * (v.y - self.y),
623            z: self.z + amount * (v.z - self.z),
624        }
625    }
626
627    /// Reflects the current vector from `normal`.
628    pub fn reflect(&mut self, normal: Vector3) {
629        *self = self.reflect_from(normal);
630    }
631
632    /// Returns a new `Vector3` reflected from the current vector using `normal`.
633    pub fn reflect_from(&self, normal: Vector3) -> Vector3 {
634        let dot_product = self.dot(normal);
635        Vector3 {
636            x: self.x - (2.0 * normal.x) * dot_product,
637            y: self.y - (2.0 * normal.y) * dot_product,
638            z: self.z - (2.0 * normal.z) * dot_product,
639        }
640    }
641
642    /// Returns a new `Vector3` containing the minimum of each corresponding component.
643    pub fn min(&self, v: Vector3) -> Vector3 {
644        Vector3 {
645            x: self.x.min(v.x),
646            y: self.y.min(v.y),
647            z: self.z.min(v.z),
648        }
649    }
650
651    /// Returns a new `Vector3` containing the maximum of each corresponding component.
652    pub fn max(&self, v: Vector3) -> Vector3 {
653        Vector3 {
654            x: self.x.max(v.x),
655            y: self.y.max(v.y),
656            z: self.z.max(v.z),
657        }
658    }
659
660    /// Returns barycenter coordinates (u, v, w) from point p (current vector) with respect to triangle (`a`, `b`, `c`).
661    pub fn barycenter(&self, a: Vector3, b: Vector3, c: Vector3) -> Vector3 {
662        let v0 = b - a;
663        let v1 = c - a;
664        let v2 = *self - a;
665        let d00 = v0.dot(v0);
666        let d01 = v0.dot(v1);
667        let d11 = v1.dot(v1);
668        let d20 = v2.dot(v0);
669        let d21 = v2.dot(v1);
670        let denom = d00 * d11 - d01 * d01;
671
672        let y = (d11 * d20 - d01 * d21) / denom;
673        let z = (d00 * d21 - d01 * d20) / denom;
674        Vector3 {
675            x: 1.0 - (z + y),
676            y,
677            z,
678        }
679    }
680
681    /// Returns a 3-length `f32` array containing components `[x, y, z]` of the current vector.
682    pub fn to_array(&self) -> [f32; 3] {
683        [self.x, self.y, self.z]
684    }
685
686    /// Returns a new `Vector3` with componenets clamp to a certain interval.
687    pub fn clamp(&self, num: Range<f32>) -> Vector3 {
688        Vector3 {
689            x: self.x.clamp(num.start, num.end),
690            y: self.y.clamp(num.start, num.end),
691            z: self.z.clamp(num.start, num.end),
692        }
693    }
694}
695
696impl From<(f32, f32, f32)> for Vector3 {
697    #[inline]
698    fn from((x, y, z): (f32, f32, f32)) -> Vector3 {
699        Vector3 { x, y, z }
700    }
701}
702
703impl Add for Vector3 {
704    type Output = Vector3;
705    fn add(self, v: Vector3) -> Self {
706        Vector3 {
707            x: self.x + v.x,
708            y: self.y + v.y,
709            z: self.z + v.z,
710        }
711    }
712}
713
714impl Add<f32> for Vector3 {
715    type Output = Vector3;
716    fn add(self, value: f32) -> Self {
717        Vector3 {
718            x: self.x + value,
719            y: self.y + value,
720            z: self.z + value,
721        }
722    }
723}
724
725impl AddAssign for Vector3 {
726    fn add_assign(&mut self, v: Vector3) {
727        *self = *self + v;
728    }
729}
730
731impl AddAssign<f32> for Vector3 {
732    fn add_assign(&mut self, value: f32) {
733        *self = *self + value;
734    }
735}
736
737impl Sub for Vector3 {
738    type Output = Vector3;
739    fn sub(self, v: Vector3) -> Self {
740        Vector3 {
741            x: self.x - v.x,
742            y: self.y - v.y,
743            z: self.z - v.z,
744        }
745    }
746}
747
748impl Sub<f32> for Vector3 {
749    type Output = Vector3;
750    fn sub(self, value: f32) -> Self {
751        Vector3 {
752            x: self.x - value,
753            y: self.y - value,
754            z: self.z - value,
755        }
756    }
757}
758
759impl SubAssign for Vector3 {
760    fn sub_assign(&mut self, v: Vector3) {
761        *self = *self - v;
762    }
763}
764
765impl SubAssign<f32> for Vector3 {
766    fn sub_assign(&mut self, value: f32) {
767        *self = *self - value;
768    }
769}
770
771impl Mul for Vector3 {
772    type Output = Vector3;
773    fn mul(self, v: Vector3) -> Self {
774        Vector3 {
775            x: self.x * v.x,
776            y: self.y * v.y,
777            z: self.z * v.z,
778        }
779    }
780}
781
782impl Mul<f32> for Vector3 {
783    type Output = Vector3;
784    fn mul(self, value: f32) -> Self {
785        Vector3 {
786            x: self.x * value,
787            y: self.y * value,
788            z: self.z * value,
789        }
790    }
791}
792
793impl MulAssign for Vector3 {
794    fn mul_assign(&mut self, v: Vector3) {
795        *self = *self * v;
796    }
797}
798
799impl MulAssign<f32> for Vector3 {
800    fn mul_assign(&mut self, value: f32) {
801        *self = *self * value;
802    }
803}
804
805impl Div for Vector3 {
806    type Output = Vector3;
807    fn div(self, v: Vector3) -> Self {
808        Vector3 {
809            x: self.x / v.x,
810            y: self.y / v.y,
811            z: self.z / v.z,
812        }
813    }
814}
815
816impl Div<f32> for Vector3 {
817    type Output = Vector3;
818    fn div(self, value: f32) -> Self {
819        Vector3 {
820            x: self.x / value,
821            y: self.y / value,
822            z: self.z / value,
823        }
824    }
825}
826
827impl DivAssign for Vector3 {
828    fn div_assign(&mut self, v: Vector3) {
829        *self = *self / v;
830    }
831}
832
833impl DivAssign<f32> for Vector3 {
834    fn div_assign(&mut self, value: f32) {
835        *self = *self / value;
836    }
837}
838
839impl Neg for Vector3 {
840    type Output = Vector3;
841    fn neg(self) -> Self {
842        Vector3 {
843            x: -self.x,
844            y: -self.y,
845            z: -self.z,
846        }
847    }
848}
849
850optional_serde_struct! {
851    pub struct Vector4 {
852        pub x: f32,
853        pub y: f32,
854        pub z: f32,
855        pub w: f32,
856    }
857}
858
859pub type Quaternion = Vector4;
860
861#[cfg(feature = "convert_mint")]
862impl From<mint::Vector4<f32>> for Vector4 {
863    fn from(v: mint::Vector4<f32>) -> Vector4 {
864        Vector4 {
865            x: v.x,
866            y: v.y,
867            z: v.z,
868            w: v.w,
869        }
870    }
871}
872
873#[cfg(feature = "convert_mint")]
874impl From<Vector4> for mint::Vector4<f32> {
875    fn from(v: Vector4) -> Self {
876        mint::Vector4 {
877            x: v.x,
878            y: v.y,
879            z: v.z,
880            w: v.w,
881        }
882    }
883}
884
885impl From<ffi::Vector4> for Vector4 {
886    fn from(v: ffi::Vector4) -> Vector4 {
887        unsafe { std::mem::transmute(v) }
888    }
889}
890
891impl From<Vector4> for ffi::Vector4 {
892    fn from(v: Vector4) -> ffi::Vector4 {
893        unsafe { std::mem::transmute(v) }
894    }
895}
896
897impl From<&Vector4> for ffi::Vector4 {
898    fn from(v: &Vector4) -> ffi::Vector4 {
899        ffi::Vector4 {
900            x: v.x,
901            y: v.y,
902            z: v.z,
903            w: v.w,
904        }
905    }
906}
907
908impl Quaternion {
909    /// Returns a new `Quaternion` with specified components.
910    pub const fn new(x: f32, y: f32, z: f32, w: f32) -> Quaternion {
911        Quaternion { x, y, z, w }
912    }
913
914    /// Returns the identity quaternion.
915    pub fn identity() -> Quaternion {
916        Quaternion {
917            x: 0.0,
918            y: 0.0,
919            z: 0.0,
920            w: 1.0,
921        }
922    }
923
924    /// Returns quaternion based on the rotation from one vector to another.
925    pub fn from_vec3_pair(from: Vector3, to: Vector3) -> Quaternion {
926        let cross = from.cross(to);
927        Quaternion {
928            x: cross.x,
929            y: cross.y,
930            z: cross.z,
931            w: 1.0 + from.dot(to),
932        }
933        .normalized()
934    }
935
936    /// Returns a quaternion for a given rotation matrix.
937    pub fn from_matrix(mat: Matrix) -> Quaternion {
938        let trace = mat.trace();
939
940        if trace > 0.0 {
941            let s = (trace + 1.0).sqrt() * 2.0;
942            let inv_s = 1.0 / s;
943
944            Quaternion {
945                w: s * 0.25,
946                x: (mat.m6 - mat.m9) * inv_s,
947                y: (mat.m8 - mat.m2) * inv_s,
948                z: (mat.m1 - mat.m4) * inv_s,
949            }
950        } else {
951            let m00 = mat.m0;
952            let m11 = mat.m5;
953            let m22 = mat.m10;
954
955            if m00 > m11 && m00 > m22 {
956                let s = (1.0 + m00 - m11 - m22).sqrt() * 2.0;
957                let inv_s = 1.0 / s;
958
959                Quaternion {
960                    w: (mat.m6 - mat.m9) * inv_s,
961                    x: s * 0.25,
962                    y: (mat.m4 + mat.m1) * inv_s,
963                    z: (mat.m8 + mat.m2) * inv_s,
964                }
965            } else if m11 > m22 {
966                let s = (1.0 + m11 - m00 - m22).sqrt() * 2.0;
967                let inv_s = 1.0 / s;
968
969                Quaternion {
970                    w: (mat.m8 - mat.m2) * inv_s,
971                    x: (mat.m4 + mat.m1) * inv_s,
972                    y: s * 0.25,
973                    z: (mat.m9 + mat.m6) * inv_s,
974                }
975            } else {
976                let s = (1.0 + m22 - m00 - m11).sqrt() * 2.0;
977                let inv_s = 1.0 / s;
978
979                Quaternion {
980                    w: (mat.m1 - mat.m4) * inv_s,
981                    x: (mat.m8 + mat.m2) * inv_s,
982                    y: (mat.m9 + mat.m6) * inv_s,
983                    z: s * 0.25,
984                }
985            }
986        }
987    }
988
989    /// Returns a rotation matrix for the current quaternion.
990    pub fn to_matrix(&self) -> Matrix {
991        let x = self.x;
992        let y = self.y;
993        let z = self.z;
994        let w = self.w;
995
996        let x2 = x + x;
997        let y2 = y + y;
998        let z2 = z + z;
999
1000        let length = self.length();
1001        let length_squared = length * length;
1002
1003        let xx = x * x2 / length_squared;
1004        let xy = x * y2 / length_squared;
1005        let xz = x * z2 / length_squared;
1006
1007        let yy = y * y2 / length_squared;
1008        let yz = y * z2 / length_squared;
1009        let zz = z * z2 / length_squared;
1010
1011        let wx = w * x2 / length_squared;
1012        let wy = w * y2 / length_squared;
1013        let wz = w * z2 / length_squared;
1014
1015        Matrix {
1016            m0: 1.0 - (yy + zz),
1017            m1: xy - wz,
1018            m2: xz + wy,
1019            m3: 0.0,
1020            m4: xy + wz,
1021            m5: 1.0 - (xx + zz),
1022            m6: yz - wx,
1023            m7: 0.0,
1024            m8: xz - wy,
1025            m9: yz + wx,
1026            m10: 1.0 - (xx + yy),
1027            m11: 0.0,
1028            m12: 0.0,
1029            m13: 0.0,
1030            m14: 0.0,
1031            m15: 1.0,
1032        }
1033    }
1034
1035    /// Returns a quaternion equivalent to Euler angles.
1036    pub fn from_euler(pitch: f32, yaw: f32, roll: f32) -> Quaternion {
1037        let x0 = (pitch * 0.5).cos();
1038        let x1 = (pitch * 0.5).sin();
1039        let y0 = (yaw * 0.5).cos();
1040        let y1 = (yaw * 0.5).sin();
1041        let z0 = (roll * 0.5).cos();
1042        let z1 = (roll * 0.5).sin();
1043
1044        Quaternion {
1045            x: (x1 * y0 * z0) - (x0 * y1 * z1),
1046            y: (x0 * y1 * z0) + (x1 * y0 * z1),
1047            z: (x0 * y0 * z1) - (x1 * y1 * z0),
1048            w: (x0 * y0 * z0) + (x1 * y1 * z1),
1049        }
1050    }
1051
1052    /// Returns a vector containing Euler angles in radians (roll, pitch, yaw), based on the current quaternion.
1053    pub fn to_euler(&self) -> Vector3 {
1054        // roll (x-axis rotation)
1055        let x0 = 2.0 * (self.w * self.x + self.y * self.z);
1056        let x1 = 1.0 - 2.0 * (self.x * self.x + self.y * self.y);
1057
1058        // pitch (y-axis rotation)
1059        let mut y0 = 2.0 * (self.w * self.y - self.z * self.x);
1060        y0 = if y0 > 1.0 { 1.0 } else { y0 };
1061        y0 = if y0 < -1.0 { -1.0 } else { y0 };
1062
1063        // yaw (z-axis rotation)
1064        let z0 = 2.0 * (self.w * self.z + self.x * self.y);
1065        let z1 = 1.0 - 2.0 * (self.y * self.y + self.z * self.z);
1066
1067        Vector3 {
1068            x: x0.atan2(x1),
1069            y: y0.asin(),
1070            z: z0.atan2(z1),
1071        }
1072    }
1073
1074    /// Returns rotation quaternion for an `axis` and `angle` (in radians).
1075    pub fn from_axis_angle(axis: Vector3, angle: f32) -> Quaternion {
1076        let mut result = Quaternion::identity();
1077        let mut axis = axis;
1078        let mut angle = angle;
1079
1080        if axis.length() != 0.0 {
1081            angle *= 0.5;
1082        }
1083
1084        axis.normalize();
1085
1086        let sinres = angle.sin();
1087        let cosres = angle.cos();
1088
1089        result.x = axis.x * sinres;
1090        result.y = axis.y * sinres;
1091        result.z = axis.z * sinres;
1092        result.w = cosres;
1093        result.normalized()
1094    }
1095
1096    /// Returns a 2-tuple containing the axis (`Vector3`) and angle (`f32` in radians) for the current quaternion.
1097    pub fn to_axis_angle(&self) -> (Vector3, f32) {
1098        let mut q = *self;
1099        if q.w.abs() > 1.0 {
1100            q = q.normalized();
1101        }
1102
1103        let mut res_axis = Vector3::zero();
1104        let res_angle = 2.0 * q.w.acos();
1105        let den = (1.0 - q.w * q.w).sqrt();
1106
1107        if den > 0.0001 {
1108            res_axis.x = q.x / den;
1109            res_axis.y = q.y / den;
1110            res_axis.z = q.z / den;
1111        } else {
1112            // This occurs when the angle is zero.
1113            // Not a problem: just set an arbitrary normalized axis.
1114            res_axis.x = 1.0;
1115        }
1116
1117        (res_axis, res_angle)
1118    }
1119
1120    /// Computes the length of the current quaternion.
1121    pub fn length(&self) -> f32 {
1122        (self.x * self.x + self.y * self.y + self.z * self.z + self.w * self.w).sqrt()
1123    }
1124
1125    /// Returns a normalized version of the current quaternion.
1126    pub fn normalized(&self) -> Quaternion {
1127        let mut length = self.length();
1128        if length == 0.0 {
1129            length = 1.0;
1130        }
1131        let ilength = 1.0 / length;
1132
1133        Quaternion {
1134            x: self.x * ilength,
1135            y: self.y * ilength,
1136            z: self.z * ilength,
1137            w: self.w * ilength,
1138        }
1139    }
1140
1141    /// Returns an inverted version of the current quaternion.
1142    pub fn inverted(&self) -> Quaternion {
1143        let mut result = *self;
1144        let length = self.length();
1145        let length_sq = length * length;
1146
1147        if length_sq != 0.0 {
1148            let i = 1.0 / length_sq;
1149            result.x *= -i;
1150            result.y *= -i;
1151            result.z *= -i;
1152            result.w *= i;
1153        }
1154        result
1155    }
1156
1157    /// Calculates linear interpolation between current and `q` quaternions.
1158    pub fn lerp(&self, q: Quaternion, amount: f32) -> Quaternion {
1159        Quaternion {
1160            x: self.x + amount * (q.x - self.x),
1161            y: self.y + amount * (q.y - self.y),
1162            z: self.z + amount * (q.z - self.z),
1163            w: self.w + amount * (q.w - self.w),
1164        }
1165    }
1166
1167    /// Calculates slerp-optimized interpolation between current and `q` quaternions.
1168    pub fn nlerp(&self, q: Quaternion, amount: f32) -> Quaternion {
1169        self.lerp(q, amount).normalized()
1170    }
1171
1172    /// Calculates spherical linear interpolation between current and `q` quaternions.
1173    pub fn slerp(&self, q: Quaternion, amount: f32) -> Quaternion {
1174        let cos_half_theta = self.x * q.x + self.y * q.y + self.z * q.z + self.w * q.w;
1175
1176        if cos_half_theta.abs() >= 1.0 {
1177            *self
1178        } else if cos_half_theta > 0.95 {
1179            self.nlerp(q, amount)
1180        } else {
1181            let half_theta = cos_half_theta.acos();
1182            let sin_half_theta = (1.0 - cos_half_theta * cos_half_theta).sqrt();
1183
1184            if sin_half_theta.abs() < 0.001 {
1185                Quaternion {
1186                    x: (self.x * 0.5 + q.x * 0.5),
1187                    y: (self.y * 0.5 + q.y * 0.5),
1188                    z: (self.z * 0.5 + q.z * 0.5),
1189                    w: (self.w * 0.5 + q.w * 0.5),
1190                }
1191            } else {
1192                let ratio_a = ((1.0 - amount) * half_theta).sin() / sin_half_theta;
1193                let ratio_b = (amount * half_theta).sin() / sin_half_theta;
1194
1195                Quaternion {
1196                    x: (self.x * ratio_a + q.x * ratio_b),
1197                    y: (self.y * ratio_a + q.y * ratio_b),
1198                    z: (self.z * ratio_a + q.z * ratio_b),
1199                    w: (self.w * ratio_a + q.w * ratio_b),
1200                }
1201            }
1202        }
1203    }
1204
1205    /// Returns a transformed version of the current quaternion given a transformation matrix.
1206    pub fn transform(&self, mat: Matrix) -> Quaternion {
1207        Quaternion {
1208            x: mat.m0 * self.x + mat.m4 * self.y + mat.m8 * self.z + mat.m12 * self.w,
1209            y: mat.m1 * self.x + mat.m5 * self.y + mat.m9 * self.z + mat.m13 * self.w,
1210            z: mat.m2 * self.x + mat.m6 * self.y + mat.m10 * self.z + mat.m14 * self.w,
1211            w: mat.m3 * self.x + mat.m7 * self.y + mat.m11 * self.z + mat.m15 * self.w,
1212        }
1213    }
1214
1215    /// Returns a new `Quaternion` with componenets clamp to a certain interval.
1216    pub fn clamp(&self, num: Range<f32>) -> Quaternion {
1217        Quaternion {
1218            x: self.x.clamp(num.start, num.end),
1219            y: self.y.clamp(num.start, num.end),
1220            z: self.z.clamp(num.start, num.end),
1221            w: self.w.clamp(num.start, num.end),
1222        }
1223    }
1224}
1225
1226#[cfg(feature = "convert_mint")]
1227impl From<mint::Quaternion<f32>> for Quaternion {
1228    fn from(q: mint::Quaternion<f32>) -> Quaternion {
1229        Quaternion {
1230            x: q.v.x,
1231            y: q.v.y,
1232            z: q.v.z,
1233            w: q.s,
1234        }
1235    }
1236}
1237
1238#[cfg(feature = "convert_mint")]
1239impl From<Quaternion> for mint::Quaternion<f32> {
1240    fn from(q: Quaternion) -> Self {
1241        Self {
1242            v: mint::Vector3 {
1243                x: q.x,
1244                y: q.y,
1245                z: q.z,
1246            },
1247            s: q.w,
1248        }
1249    }
1250}
1251
1252impl From<(f32, f32, f32, f32)> for Quaternion {
1253    #[inline]
1254    fn from((x, y, z, w): (f32, f32, f32, f32)) -> Quaternion {
1255        Quaternion { x, y, z, w }
1256    }
1257}
1258
1259impl Mul for Quaternion {
1260    type Output = Quaternion;
1261    fn mul(self, q: Quaternion) -> Quaternion {
1262        let qax = self.x;
1263        let qay = self.y;
1264        let qaz = self.z;
1265        let qaw = self.w;
1266        let qbx = q.x;
1267        let qby = q.y;
1268        let qbz = q.z;
1269        let qbw = q.w;
1270
1271        Quaternion {
1272            x: (qax * qbw) + (qaw * qbx) + (qay * qbz) - (qaz * qby),
1273            y: (qay * qbw) + (qaw * qby) + (qaz * qbx) - (qax * qbz),
1274            z: (qaz * qbw) + (qaw * qbz) + (qax * qby) - (qay * qbx),
1275            w: (qaw * qbw) - (qax * qbx) - (qay * qby) - (qaz * qbz),
1276        }
1277    }
1278}
1279
1280impl MulAssign for Quaternion {
1281    fn mul_assign(&mut self, q: Quaternion) {
1282        *self = *self * q;
1283    }
1284}
1285
1286optional_serde_struct! {
1287    pub struct Matrix {
1288        pub m0: f32,
1289        pub m4: f32,
1290        pub m8: f32,
1291        pub m12: f32,
1292        pub m1: f32,
1293        pub m5: f32,
1294        pub m9: f32,
1295        pub m13: f32,
1296        pub m2: f32,
1297        pub m6: f32,
1298        pub m10: f32,
1299        pub m14: f32,
1300        pub m3: f32,
1301        pub m7: f32,
1302        pub m11: f32,
1303        pub m15: f32,
1304    }
1305}
1306
1307impl From<ffi::Matrix> for Matrix {
1308    fn from(r: ffi::Matrix) -> Matrix {
1309        unsafe { std::mem::transmute(r) }
1310    }
1311}
1312
1313impl From<Matrix> for ffi::Matrix {
1314    fn from(v: Matrix) -> Self {
1315        unsafe { std::mem::transmute(v) }
1316    }
1317}
1318
1319impl From<&Matrix> for ffi::Matrix {
1320    fn from(v: &Matrix) -> Self {
1321        ffi::Matrix {
1322            m0: v.m0,
1323            m4: v.m4,
1324            m8: v.m8,
1325            m12: v.m12,
1326            m1: v.m1,
1327            m5: v.m5,
1328            m9: v.m9,
1329            m13: v.m13,
1330            m2: v.m2,
1331            m6: v.m6,
1332            m10: v.m10,
1333            m14: v.m14,
1334            m3: v.m3,
1335            m7: v.m7,
1336            m11: v.m11,
1337            m15: v.m15,
1338        }
1339    }
1340}
1341
1342impl Matrix {
1343    /// Returns the identity matrix.
1344    pub fn identity() -> Matrix {
1345        Matrix {
1346            m0: 1.0,
1347            m4: 0.0,
1348            m8: 0.0,
1349            m12: 0.0,
1350            m1: 0.0,
1351            m5: 1.0,
1352            m9: 0.0,
1353            m13: 0.0,
1354            m2: 0.0,
1355            m6: 0.0,
1356            m10: 1.0,
1357            m14: 0.0,
1358            m3: 0.0,
1359            m7: 0.0,
1360            m11: 0.0,
1361            m15: 1.0,
1362        }
1363    }
1364
1365    /// Returns the zero matriz.
1366    pub fn zero() -> Matrix {
1367        Matrix {
1368            m0: 0.0,
1369            m4: 0.0,
1370            m8: 0.0,
1371            m12: 0.0,
1372            m1: 0.0,
1373            m5: 0.0,
1374            m9: 0.0,
1375            m13: 0.0,
1376            m2: 0.0,
1377            m6: 0.0,
1378            m10: 0.0,
1379            m14: 0.0,
1380            m3: 0.0,
1381            m7: 0.0,
1382            m11: 0.0,
1383            m15: 0.0,
1384        }
1385    }
1386
1387    /// Returns a translation matrix.
1388    pub fn translate(x: f32, y: f32, z: f32) -> Matrix {
1389        Matrix {
1390            m0: 1.0,
1391            m4: 0.0,
1392            m8: 0.0,
1393            m12: x,
1394            m1: 0.0,
1395            m5: 1.0,
1396            m9: 0.0,
1397            m13: y,
1398            m2: 0.0,
1399            m6: 0.0,
1400            m10: 1.0,
1401            m14: z,
1402            m3: 0.0,
1403            m7: 0.0,
1404            m11: 0.0,
1405            m15: 1.0,
1406        }
1407    }
1408
1409    /// Returns a rotation matrix.
1410    pub fn rotate(axis: Vector3, angle: f32) -> Matrix {
1411        let mut x = axis.x;
1412        let mut y = axis.y;
1413        let mut z = axis.z;
1414        let mut length = (x * x + y * y + z * z).sqrt();
1415
1416        if (length != 1.0) && (length != 0.0) {
1417            length = 1.0 / length;
1418            x *= length;
1419            y *= length;
1420            z *= length;
1421        }
1422
1423        let sinres = angle.sin();
1424        let cosres = angle.cos();
1425        let t = 1.0 - cosres;
1426
1427        Matrix {
1428            m0: (x * x * t) + cosres,
1429            m1: (y * x * t) + (z * sinres),
1430            m2: (z * x * t) - (y * sinres),
1431            m3: 0.0,
1432
1433            m4: (x * y * t) - (z * sinres),
1434            m5: (y * y * t) + cosres,
1435            m6: (z * y * t) + (x * sinres),
1436            m7: 0.0,
1437
1438            m8: (x * z * t) + (y * sinres),
1439            m9: (y * z * t) - (x * sinres),
1440            m10: (z * z * t) + cosres,
1441            m11: 0.0,
1442
1443            m12: 0.0,
1444            m13: 0.0,
1445            m14: 0.0,
1446            m15: 1.0,
1447        }
1448    }
1449
1450    /// Returns a translation matrix around the X axis.
1451    pub fn rotate_x(angle: f32) -> Matrix {
1452        let mut result = Matrix::identity();
1453
1454        let cosres = angle.cos();
1455        let sinres = angle.sin();
1456
1457        result.m5 = cosres;
1458        result.m6 = sinres;
1459        result.m9 = -sinres;
1460        result.m10 = cosres;
1461        result
1462    }
1463
1464    /// Returns a translation matrix around the Y axis.
1465    pub fn rotate_y(angle: f32) -> Matrix {
1466        let mut result = Matrix::identity();
1467
1468        let cosres = angle.cos();
1469        let sinres = angle.sin();
1470
1471        result.m0 = cosres;
1472        result.m2 = -sinres;
1473        result.m8 = sinres;
1474        result.m10 = cosres;
1475        result
1476    }
1477
1478    /// Returns a translation matrix around the Z axis.
1479    pub fn rotate_z(angle: f32) -> Matrix {
1480        let mut result = Matrix::identity();
1481
1482        let cosres = angle.cos();
1483        let sinres = angle.sin();
1484
1485        result.m0 = cosres;
1486        result.m1 = sinres;
1487        result.m4 = -sinres;
1488        result.m5 = cosres;
1489        result
1490    }
1491
1492    /// Returns xyz-rotation matrix (angles in radians)
1493    pub fn rotate_xyz(ang: Vector3) -> Self {
1494        let mut result = Self::identity();
1495
1496        let cosz = -ang.z.cos();
1497        let sinz = -ang.z.sin();
1498        let cosy = -ang.y.cos();
1499        let siny = -ang.y.sin();
1500        let cosx = -ang.x.cos();
1501        let sinx = -ang.x.sin();
1502
1503        result.m0 = cosz * cosy;
1504        result.m4 = (cosz * siny * sinx) - (sinz * cosx);
1505        result.m8 = (cosz * siny * cosx) + (sinz * sinx);
1506
1507        result.m1 = sinz * cosy;
1508        result.m5 = (sinz * siny * sinx) + (cosz * cosx);
1509        result.m9 = (sinz * siny * cosx) - (cosz * sinx);
1510
1511        result.m2 = -siny;
1512        result.m6 = cosy * sinx;
1513        result.m10 = cosy * cosx;
1514
1515        result
1516    }
1517
1518    /// Returns a scaling matrix.
1519    pub fn scale(x: f32, y: f32, z: f32) -> Matrix {
1520        Matrix {
1521            m0: x,
1522            m4: 0.0,
1523            m8: 0.0,
1524            m12: 0.0,
1525            m1: 0.0,
1526            m5: y,
1527            m9: 0.0,
1528            m13: 0.0,
1529            m2: 0.0,
1530            m6: 0.0,
1531            m10: z,
1532            m14: 0.0,
1533            m3: 0.0,
1534            m7: 0.0,
1535            m11: 0.0,
1536            m15: 1.0,
1537        }
1538    }
1539
1540    /// Returns perspective projection matrix based on frustum parameters.
1541    pub fn frustum(left: f32, right: f32, bottom: f32, top: f32, near: f32, far: f32) -> Matrix {
1542        let rl = right - left;
1543        let tb = top - bottom;
1544        let fne = far - near;
1545
1546        Matrix {
1547            m0: (near * 2.0) / rl,
1548            m1: 0.0,
1549            m2: 0.0,
1550            m3: 0.0,
1551
1552            m4: 0.0,
1553            m5: (near * 2.0) / tb,
1554            m6: 0.0,
1555            m7: 0.0,
1556
1557            m8: (right + left) / rl,
1558            m9: (top + bottom) / tb,
1559            m10: -(far + near) / fne,
1560            m11: -1.0,
1561
1562            m12: 0.0,
1563            m13: 0.0,
1564            m14: -(far * near * 2.0) / fne,
1565            m15: 0.0,
1566        }
1567    }
1568
1569    /// Returns perspective projection matrix.
1570    pub fn perspective(fovy: f32, aspect: f32, near: f32, far: f32) -> Matrix {
1571        let top = near * (fovy * 0.5).tan();
1572        let right = top * aspect;
1573        Matrix::frustum(-right, right, -top, top, near, far)
1574    }
1575
1576    /// Returns orthographic projection matrix.
1577    pub fn ortho(left: f32, right: f32, bottom: f32, top: f32, near: f32, far: f32) -> Matrix {
1578        let rl = right - left;
1579        let tb = top - bottom;
1580        let fne = far - near;
1581
1582        Matrix {
1583            m0: 2.0 / rl,
1584            m1: 0.0,
1585            m2: 0.0,
1586            m3: 0.0,
1587            m4: 0.0,
1588            m5: 2.0 / tb,
1589            m6: 0.0,
1590            m7: 0.0,
1591            m8: 0.0,
1592            m9: 0.0,
1593            m10: -2.0 / fne,
1594            m11: 0.0,
1595            m12: -(left + right) / rl,
1596            m13: -(top + bottom) / tb,
1597            m14: -(far + near) / fne,
1598            m15: 1.0,
1599        }
1600    }
1601
1602    /// Returns camera look-at matrix (view matrix).
1603    pub fn look_at(eye: Vector3, target: Vector3, up: Vector3) -> Matrix {
1604        let z = (eye - target).normalized();
1605        let x = up.cross(z).normalized();
1606        let y = z.cross(x).normalized();
1607
1608        Matrix {
1609            m0: x.x,
1610            m1: x.y,
1611            m2: x.z,
1612            m3: 0.0,
1613            m4: y.x,
1614            m5: y.y,
1615            m6: y.z,
1616            m7: 0.0,
1617            m8: z.x,
1618            m9: z.y,
1619            m10: z.z,
1620            m11: 0.0,
1621            m12: eye.x,
1622            m13: eye.y,
1623            m14: eye.z,
1624            m15: 1.0,
1625        }
1626        .inverted()
1627    }
1628
1629    /// Calculates the determinant of the current matrix.
1630    pub fn determinant(&self) -> f32 {
1631        let a00 = self.m0;
1632        let a01 = self.m1;
1633        let a02 = self.m2;
1634        let a03 = self.m3;
1635        let a10 = self.m4;
1636        let a11 = self.m5;
1637        let a12 = self.m6;
1638        let a13 = self.m7;
1639        let a20 = self.m8;
1640        let a21 = self.m9;
1641        let a22 = self.m10;
1642        let a23 = self.m11;
1643        let a30 = self.m12;
1644        let a31 = self.m13;
1645        let a32 = self.m14;
1646        let a33 = self.m15;
1647
1648        a30 * a21 * a12 * a03 - a20 * a31 * a12 * a03 - a30 * a11 * a22 * a03
1649            + a10 * a31 * a22 * a03
1650            + a20 * a11 * a32 * a03
1651            - a10 * a21 * a32 * a03
1652            - a30 * a21 * a02 * a13
1653            + a20 * a31 * a02 * a13
1654            + a30 * a01 * a22 * a13
1655            - a00 * a31 * a22 * a13
1656            - a20 * a01 * a32 * a13
1657            + a00 * a21 * a32 * a13
1658            + a30 * a11 * a02 * a23
1659            - a10 * a31 * a02 * a23
1660            - a30 * a01 * a12 * a23
1661            + a00 * a31 * a12 * a23
1662            + a10 * a01 * a32 * a23
1663            - a00 * a11 * a32 * a23
1664            - a20 * a11 * a02 * a33
1665            + a10 * a21 * a02 * a33
1666            + a20 * a01 * a12 * a33
1667            - a00 * a21 * a12 * a33
1668            - a10 * a01 * a22 * a33
1669            + a00 * a11 * a22 * a33
1670    }
1671
1672    /// Calculates the trace of the matrix (sum of the values along the diagonal).
1673    pub fn trace(&self) -> f32 {
1674        self.m0 + self.m5 + self.m10 + self.m15
1675    }
1676
1677    /// Returns a new `Matrix` transposed from the current one.
1678    pub fn transposed(&self) -> Matrix {
1679        Matrix {
1680            m0: self.m0,
1681            m1: self.m4,
1682            m2: self.m8,
1683            m3: self.m12,
1684            m4: self.m1,
1685            m5: self.m5,
1686            m6: self.m9,
1687            m7: self.m13,
1688            m8: self.m2,
1689            m9: self.m6,
1690            m10: self.m10,
1691            m11: self.m14,
1692            m12: self.m3,
1693            m13: self.m7,
1694            m14: self.m11,
1695            m15: self.m15,
1696        }
1697    }
1698
1699    /// Returns a new `Matrix` inverted from the current one.
1700    pub fn inverted(&self) -> Matrix {
1701        let a00 = self.m0;
1702        let a01 = self.m1;
1703        let a02 = self.m2;
1704        let a03 = self.m3;
1705        let a10 = self.m4;
1706        let a11 = self.m5;
1707        let a12 = self.m6;
1708        let a13 = self.m7;
1709        let a20 = self.m8;
1710        let a21 = self.m9;
1711        let a22 = self.m10;
1712        let a23 = self.m11;
1713        let a30 = self.m12;
1714        let a31 = self.m13;
1715        let a32 = self.m14;
1716        let a33 = self.m15;
1717
1718        let b00 = (a00 * a11) - (a01 * a10);
1719        let b01 = (a00 * a12) - (a02 * a10);
1720        let b02 = (a00 * a13) - (a03 * a10);
1721        let b03 = (a01 * a12) - (a02 * a11);
1722        let b04 = (a01 * a13) - (a03 * a11);
1723        let b05 = (a02 * a13) - (a03 * a12);
1724        let b06 = (a20 * a31) - (a21 * a30);
1725        let b07 = (a20 * a32) - (a22 * a30);
1726        let b08 = (a20 * a33) - (a23 * a30);
1727        let b09 = (a21 * a32) - (a22 * a31);
1728        let b10 = (a21 * a33) - (a23 * a31);
1729        let b11 = (a22 * a33) - (a23 * a32);
1730
1731        let inv_det = 1.0
1732            / ((b00 * b11) - (b01 * b10) + (b02 * b09) + (b03 * b08) - (b04 * b07) + (b05 * b06));
1733
1734        Matrix {
1735            m0: ((a11 * b11) - (a12 * b10) + (a13 * b09)) * inv_det,
1736            m1: ((-a01 * b11) + (a02 * b10) - (a03 * b09)) * inv_det,
1737            m2: ((a31 * b05) - (a32 * b04) + (a33 * b03)) * inv_det,
1738            m3: ((-a21 * b05) + (a22 * b04) - (a23 * b03)) * inv_det,
1739            m4: ((-a10 * b11) + (a12 * b08) - (a13 * b07)) * inv_det,
1740            m5: ((a00 * b11) - (a02 * b08) + (a03 * b07)) * inv_det,
1741            m6: ((-a30 * b05) + (a32 * b02) - (a33 * b01)) * inv_det,
1742            m7: ((a20 * b05) - (a22 * b02) + (a23 * b01)) * inv_det,
1743            m8: ((a10 * b10) - (a11 * b08) + (a13 * b06)) * inv_det,
1744            m9: ((-a00 * b10) + (a01 * b08) - (a03 * b06)) * inv_det,
1745            m10: ((a30 * b04) - (a31 * b02) + (a33 * b00)) * inv_det,
1746            m11: ((-a20 * b04) + (a21 * b02) - (a23 * b00)) * inv_det,
1747            m12: ((-a10 * b09) + (a11 * b07) - (a12 * b06)) * inv_det,
1748            m13: ((a00 * b09) - (a01 * b07) + (a02 * b06)) * inv_det,
1749            m14: ((-a30 * b03) + (a31 * b01) - (a32 * b00)) * inv_det,
1750            m15: ((a20 * b03) - (a21 * b01) + (a22 * b00)) * inv_det,
1751        }
1752    }
1753
1754    /// Returns a new `Matrix` normalized from the current one.
1755    pub fn normalized(&self) -> Matrix {
1756        let det = self.determinant();
1757        Matrix {
1758            m0: self.m0 / det,
1759            m1: self.m1 / det,
1760            m2: self.m2 / det,
1761            m3: self.m3 / det,
1762            m4: self.m4 / det,
1763            m5: self.m5 / det,
1764            m6: self.m6 / det,
1765            m7: self.m7 / det,
1766            m8: self.m8 / det,
1767            m9: self.m9 / det,
1768            m10: self.m10 / det,
1769            m11: self.m11 / det,
1770            m12: self.m12 / det,
1771            m13: self.m13 / det,
1772            m14: self.m14 / det,
1773            m15: self.m15 / det,
1774        }
1775    }
1776
1777    /// Returns a 16-length `f32` array containing the current matrix data.
1778    pub fn to_array(&self) -> [f32; 16] {
1779        [
1780            self.m0, self.m1, self.m2, self.m3, self.m4, self.m5, self.m6, self.m7, self.m8,
1781            self.m9, self.m10, self.m11, self.m12, self.m13, self.m14, self.m15,
1782        ]
1783    }
1784}
1785
1786impl Add for Matrix {
1787    type Output = Matrix;
1788    fn add(self, mat: Matrix) -> Matrix {
1789        Matrix {
1790            m0: self.m0 + mat.m0,
1791            m1: self.m1 + mat.m1,
1792            m2: self.m2 + mat.m2,
1793            m3: self.m3 + mat.m3,
1794            m4: self.m4 + mat.m4,
1795            m5: self.m5 + mat.m5,
1796            m6: self.m6 + mat.m6,
1797            m7: self.m7 + mat.m7,
1798            m8: self.m8 + mat.m8,
1799            m9: self.m9 + mat.m9,
1800            m10: self.m10 + mat.m10,
1801            m11: self.m11 + mat.m11,
1802            m12: self.m12 + mat.m12,
1803            m13: self.m13 + mat.m13,
1804            m14: self.m14 + mat.m14,
1805            m15: self.m15 + mat.m15,
1806        }
1807    }
1808}
1809
1810impl AddAssign for Matrix {
1811    fn add_assign(&mut self, mat: Matrix) {
1812        *self = *self + mat;
1813    }
1814}
1815
1816impl Sub for Matrix {
1817    type Output = Matrix;
1818    fn sub(self, mat: Matrix) -> Matrix {
1819        Matrix {
1820            m0: self.m0 - mat.m0,
1821            m1: self.m1 - mat.m1,
1822            m2: self.m2 - mat.m2,
1823            m3: self.m3 - mat.m3,
1824            m4: self.m4 - mat.m4,
1825            m5: self.m5 - mat.m5,
1826            m6: self.m6 - mat.m6,
1827            m7: self.m7 - mat.m7,
1828            m8: self.m8 - mat.m8,
1829            m9: self.m9 - mat.m9,
1830            m10: self.m10 - mat.m10,
1831            m11: self.m11 - mat.m11,
1832            m12: self.m12 - mat.m12,
1833            m13: self.m13 - mat.m13,
1834            m14: self.m14 - mat.m14,
1835            m15: self.m15 - mat.m15,
1836        }
1837    }
1838}
1839
1840impl SubAssign for Matrix {
1841    fn sub_assign(&mut self, mat: Matrix) {
1842        *self = *self - mat;
1843    }
1844}
1845
1846impl Mul for Matrix {
1847    type Output = Matrix;
1848    fn mul(self, mat: Matrix) -> Matrix {
1849        Matrix {
1850            m0: self.m0 * mat.m0 + self.m1 * mat.m4 + self.m2 * mat.m8 + self.m3 * mat.m12,
1851            m1: self.m0 * mat.m1 + self.m1 * mat.m5 + self.m2 * mat.m9 + self.m3 * mat.m13,
1852            m2: self.m0 * mat.m2 + self.m1 * mat.m6 + self.m2 * mat.m10 + self.m3 * mat.m14,
1853            m3: self.m0 * mat.m3 + self.m1 * mat.m7 + self.m2 * mat.m11 + self.m3 * mat.m15,
1854            m4: self.m4 * mat.m0 + self.m5 * mat.m4 + self.m6 * mat.m8 + self.m7 * mat.m12,
1855            m5: self.m4 * mat.m1 + self.m5 * mat.m5 + self.m6 * mat.m9 + self.m7 * mat.m13,
1856            m6: self.m4 * mat.m2 + self.m5 * mat.m6 + self.m6 * mat.m10 + self.m7 * mat.m14,
1857            m7: self.m4 * mat.m3 + self.m5 * mat.m7 + self.m6 * mat.m11 + self.m7 * mat.m15,
1858            m8: self.m8 * mat.m0 + self.m9 * mat.m4 + self.m10 * mat.m8 + self.m11 * mat.m12,
1859            m9: self.m8 * mat.m1 + self.m9 * mat.m5 + self.m10 * mat.m9 + self.m11 * mat.m13,
1860            m10: self.m8 * mat.m2 + self.m9 * mat.m6 + self.m10 * mat.m10 + self.m11 * mat.m14,
1861            m11: self.m8 * mat.m3 + self.m9 * mat.m7 + self.m10 * mat.m11 + self.m11 * mat.m15,
1862            m12: self.m12 * mat.m0 + self.m13 * mat.m4 + self.m14 * mat.m8 + self.m15 * mat.m12,
1863            m13: self.m12 * mat.m1 + self.m13 * mat.m5 + self.m14 * mat.m9 + self.m15 * mat.m13,
1864            m14: self.m12 * mat.m2 + self.m13 * mat.m6 + self.m14 * mat.m10 + self.m15 * mat.m14,
1865            m15: self.m12 * mat.m3 + self.m13 * mat.m7 + self.m14 * mat.m11 + self.m15 * mat.m15,
1866        }
1867    }
1868}
1869
1870impl MulAssign for Matrix {
1871    fn mul_assign(&mut self, mat: Matrix) {
1872        *self = *self * mat;
1873    }
1874}
1875
1876optional_serde_struct! {
1877    pub struct Ray {
1878        pub position: Vector3,
1879        pub direction: Vector3,
1880    }
1881}
1882
1883impl From<ffi::Ray> for Ray {
1884    fn from(r: ffi::Ray) -> Ray {
1885        unsafe { std::mem::transmute(r) }
1886    }
1887}
1888
1889impl From<Ray> for ffi::Ray {
1890    fn from(v: Ray) -> ffi::Ray {
1891        unsafe { std::mem::transmute(v) }
1892    }
1893}
1894
1895impl From<&Ray> for ffi::Ray {
1896    fn from(v: &Ray) -> ffi::Ray {
1897        ffi::Ray {
1898            position: v.position.into(),
1899            direction: v.direction.into(),
1900        }
1901    }
1902}
1903
1904impl Ray {
1905    pub const fn new(position: Vector3, direction: Vector3) -> Self {
1906        Self {
1907            position,
1908            direction,
1909        }
1910    }
1911}
1912
1913optional_serde_struct! {
1914    pub struct Rectangle {
1915        pub x: f32,
1916        pub y: f32,
1917        pub width: f32,
1918        pub height: f32,
1919    }
1920}
1921
1922impl From<ffi::Rectangle> for Rectangle {
1923    fn from(r: ffi::Rectangle) -> Rectangle {
1924        unsafe { std::mem::transmute(r) }
1925    }
1926}
1927
1928impl From<Rectangle> for ffi::Rectangle {
1929    fn from(v: Rectangle) -> ffi::Rectangle {
1930        unsafe { std::mem::transmute(v) }
1931    }
1932}
1933
1934impl From<&Rectangle> for ffi::Rectangle {
1935    fn from(v: &Rectangle) -> ffi::Rectangle {
1936        ffi::Rectangle {
1937            x: v.x,
1938            y: v.y,
1939            width: v.width,
1940            height: v.height,
1941        }
1942    }
1943}
1944
1945impl Rectangle {
1946    pub const EMPTY: Rectangle = Rectangle::new(0.0, 0.0, 0.0, 0.0);
1947    pub const fn new(x: f32, y: f32, width: f32, height: f32) -> Self {
1948        Self {
1949            x,
1950            y,
1951            width,
1952            height,
1953        }
1954    }
1955}
1956
1957optional_serde_struct! {
1958    pub struct BoundingBox {
1959        pub min: Vector3,
1960        pub max: Vector3,
1961    }
1962}
1963
1964impl BoundingBox {
1965    pub fn new(min: Vector3, max: Vector3) -> BoundingBox {
1966        BoundingBox { min, max }
1967    }
1968}
1969
1970impl From<ffi::BoundingBox> for BoundingBox {
1971    fn from(r: ffi::BoundingBox) -> BoundingBox {
1972        unsafe { std::mem::transmute(r) }
1973    }
1974}
1975
1976impl From<BoundingBox> for ffi::BoundingBox {
1977    fn from(v: BoundingBox) -> ffi::BoundingBox {
1978        unsafe { std::mem::transmute(v) }
1979    }
1980}
1981
1982impl From<&BoundingBox> for ffi::BoundingBox {
1983    fn from(v: &BoundingBox) -> ffi::BoundingBox {
1984        ffi::BoundingBox {
1985            min: v.min.into(),
1986            max: v.max.into(),
1987        }
1988    }
1989}
1990
1991optional_serde_struct! {
1992    pub struct RayCollision {
1993        pub hit: bool,
1994        pub distance: f32,
1995        pub point: Vector3,
1996        pub normal: Vector3,
1997    }
1998}
1999
2000impl From<ffi::RayCollision> for RayCollision {
2001    fn from(r: ffi::RayCollision) -> RayCollision {
2002        unsafe { std::mem::transmute(r) }
2003    }
2004}
2005
2006impl From<RayCollision> for ffi::RayCollision {
2007    fn from(v: RayCollision) -> ffi::RayCollision {
2008        unsafe { std::mem::transmute(v) }
2009    }
2010}
2011
2012impl From<&RayCollision> for ffi::RayCollision {
2013    fn from(v: &RayCollision) -> ffi::RayCollision {
2014        ffi::RayCollision {
2015            hit: v.hit,
2016            distance: v.distance,
2017            point: v.point.into(),
2018            normal: v.normal.into(),
2019        }
2020    }
2021}
2022
2023optional_serde_struct! {
2024    pub struct Transform {
2025        pub translation: Vector3,
2026        pub rotation: Quaternion,
2027        pub scale: Vector3,
2028    }
2029}
2030
2031impl From<ffi::Transform> for Transform {
2032    fn from(r: ffi::Transform) -> Transform {
2033        unsafe { std::mem::transmute(r) }
2034    }
2035}
2036
2037impl From<Transform> for ffi::Transform {
2038    fn from(v: Transform) -> ffi::Transform {
2039        unsafe { std::mem::transmute(v) }
2040    }
2041}
2042
2043impl From<&Transform> for ffi::Transform {
2044    fn from(v: &Transform) -> ffi::Transform {
2045        ffi::Transform {
2046            translation: v.translation.into(),
2047            rotation: v.rotation.into(),
2048            scale: v.scale.into(),
2049        }
2050    }
2051}
2052
2053#[cfg(test)]
2054mod math_test {
2055    use super::{Ray, Vector2, Vector3, Vector4};
2056    use crate::ffi;
2057
2058    #[test]
2059    fn test_into() {
2060        let v2: ffi::Vector2 = (Vector2 { x: 1.0, y: 2.0 }).into();
2061        assert!(v2.x == 1.0 && v2.y == 2.0, "bad memory transmutation");
2062
2063        let v3: ffi::Vector3 = (Vector3 {
2064            x: 1.0,
2065            y: 2.0,
2066            z: 3.0,
2067        })
2068        .into();
2069        assert!(
2070            v3.x == 1.0 && v3.y == 2.0 && v3.z == 3.0,
2071            "bad memory transmutation"
2072        );
2073
2074        let v4: ffi::Vector4 = (Vector4 {
2075            x: 1.0,
2076            y: 2.0,
2077            z: 3.0,
2078            w: 4.0,
2079        })
2080        .into();
2081        assert!(
2082            v4.x == 1.0 && v4.y == 2.0 && v4.z == 3.0 && v4.w == 4.0,
2083            "bad memory transmutation"
2084        );
2085
2086        let r: ffi::Ray = (Ray {
2087            position: v3.into(),
2088            direction: Vector3 {
2089                x: 3.0,
2090                y: 2.0,
2091                z: 1.0,
2092            },
2093        })
2094        .into();
2095        assert!(
2096            r.position.x == 1.0
2097                && r.position.y == 2.0
2098                && r.position.z == 3.0
2099                && r.direction.x == 3.0
2100                && r.direction.y == 2.0
2101                && r.direction.z == 1.0,
2102            "bad memory transmutation"
2103        )
2104    }
2105}