radiant_rs/core/
math.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
use prelude::*;
use core::{AsUniform, Uniform};

/// A 4x4 matrix.
pub type Mat4<T = f32> = [ [ T; 4 ]; 4 ];

pub trait Mat4Trait<T> {
    fn identity() -> Mat4<T>;
    fn viewport(width: T, height: T) -> Mat4<T>;
    fn set(self: &mut Self, other: &Mat4<T>);
}

impl Mat4Trait<f32> for Mat4<f32> {
    fn identity() -> Mat4<f32> {
        [
            [ 1., 0., 0., 0. ],
            [ 0., 1., 0., 0. ],
            [ 0., 0., 1., 0. ],
            [ 0., 0., 0., 1. ],
        ]
    }
    fn viewport(width: f32, height: f32) -> Mat4<f32> {
        [
            [ 2. / width, 0., 0., 0. ],
            [ 0., -2. / height, 0., 0. ],
            [ 0., 0., 1., 0. ],
            [ -1., 1., 0., 1. ],
        ]
    }
    fn set(self: &mut Self, other: &Mat4<f32>) {
        *self = *other;
    }
}

impl AsUniform for Mat4<f32> {
    fn as_uniform(&self) -> Uniform {
        let a = &self;
        Uniform::Mat4([
            [ a[0][0], a[0][1], a[0][2], a[0][3] ],
            [ a[1][0], a[1][1], a[1][2], a[1][3] ],
            [ a[2][0], a[2][1], a[2][2], a[2][3] ],
            [ a[3][0], a[3][1], a[3][2], a[3][3] ],
        ])
    }
}

impl AsUniform for Mat4<f64> {
    fn as_uniform(&self) -> Uniform {
        let a = &self;
        Uniform::DoubleMat4([
            [ a[0][0], a[0][1], a[0][2], a[0][3] ],
            [ a[1][0], a[1][1], a[1][2], a[1][3] ],
            [ a[2][0], a[2][1], a[2][2], a[2][3] ],
            [ a[3][0], a[3][1], a[3][2], a[3][3] ],
        ])
    }
}

/// A stack of 4x4 matrices.
#[derive(Debug)]
pub struct Mat4Stack<T = f32> (Vec<Mat4<T>>);

impl<T> Mat4Stack<T> where T: Copy {

    /// Creates a new matrix stack.
    pub fn new(matrix: Mat4<T>) -> Mat4Stack<T> {
        Mat4Stack(vec![ matrix ])
    }

    /// Pushes a copy of the current matrix on the stack and returns a reference to it.
    pub fn push(self: &mut Self) -> &mut Mat4<T> {
        let last = *self.0.last().unwrap();
        self.0.push(last);
        self.0.last_mut().unwrap()
    }

    /// Removes the top matrix from the stack and replaces the current matrix with it.
    pub fn pop(self: &mut Self) -> &mut Mat4<T> {
        self.0.pop().unwrap();
        self.0.last_mut().unwrap()
    }
}

impl<T> Deref for Mat4Stack<T> where T: Copy {
    type Target = Mat4<T>;

    fn deref(&self) -> &Mat4<T> {
        self.0.last().unwrap()
    }
}

impl<T> DerefMut for Mat4Stack<T> where T: Copy {
    fn deref_mut(&mut self) -> &mut Mat4<T> {
        self.0.last_mut().unwrap()
    }
}

impl<T> From<Mat4<T>> for Mat4Stack<T> where T: Copy {
    fn from(source: Mat4<T>) -> Self {
        Mat4Stack::new(source)
    }
}

/// A point in 2d space.
pub type Point2<T = f32> = (T, T);

pub trait Point2Trait<T> {
    fn x(self: &Self) -> T;
    fn y(self: &Self) -> T;
    fn as_array(self: &Self) -> [ T; 2 ];
}

impl<T> Point2Trait<T> for Point2<T> where T: Copy {
    #[inline]
    fn x(self: &Self) -> T {
        self.0
    }
    #[inline]
    fn y(self: &Self) -> T {
        self.1
    }
    #[inline]
    fn as_array(self: &Self) -> [ T; 2 ] {
        [ self.0, self.1 ]
    }
}

/// A rectangle.
pub type Rect<T = f32> = (Point2<T>, Point2<T>);

pub trait RectTrait<T> {
    fn top_left(self: &Self) -> Point2<T>;
    fn top_right(self: &Self) -> Point2<T>;
    fn bottom_left(self: &Self) -> Point2<T>;
    fn bottom_right(self: &Self) -> Point2<T>;
    fn as_array(self: &Self) -> [ T; 4 ];
}

impl<T> RectTrait<T> for Rect<T> where T: Copy {
    #[inline]
    fn top_left(self: &Self) -> Point2<T> {
        ((self.0).0, (self.0).1)
    }
    #[inline]
    fn top_right(self: &Self) -> Point2<T> {
        ((self.1).0, (self.0).1)
    }
    #[inline]
    fn bottom_left(self: &Self) -> Point2<T> {
        ((self.0).0, (self.1).1)
    }
    #[inline]
    fn bottom_right(self: &Self) -> Point2<T> {
        ((self.1).0, (self.1).1)
    }
    #[inline]
    fn as_array(self: &Self) -> [ T; 4 ] {
        [ (self.0).0, (self.0).1, (self.1).0, (self.1).1 ]
    }
}