radiant_utils/math/
matrix.rs1use prelude::*;
2use super::{Vec3, Vector};
3
4pub type Mat4<T = f32> = [ [ T; 4 ]; 4 ];
6
7pub trait Matrix<T> where T: Copy {
9 fn set<M>(self: &mut Self, other: M) -> &mut Self where Mat4<T>: From<M>;
11 fn translate<V>(self: &mut Self, translation_vector: V) -> &mut Self where V: Vector<T>;
13 fn scale<V>(self: &mut Self, scaling_vector: V) -> &mut Self where V: Vector<T>;
15 fn scale_at<P, V>(self: &mut Self, position: P, scaling_vector: V) -> &mut Self where P: Vector<T>, V: Vector<T>;
17 fn rotate(self: &mut Self, radians: T) -> &mut Self;
19 fn rotate_at<P>(self: &mut Self, position: P, radians: T) -> &mut Self where P: Vector<T>;
21 fn rotate_axis<V>(self: &mut Self, radians: T, axis: V) -> &mut Self where Vec3<T>: From<V>;
23 fn rotate_axis_at<P, V>(self: &mut Self, position: P, radians: T, axis: V) -> &mut Self where P: Vector<T>, Vec3<T>: From<V>;
25 fn get_rotation(self: &Self) -> Self;
27 fn get_translation(self: &Self) -> Vec3<T>;
29 fn get_scale(self: &Self) -> Vec3<T>;
31 fn get_euler(self: &Self) -> Vec3<T>;
33}
34
35impl<T> Matrix<T> for Mat4<T> where T: Float {
36 fn set<M>(self: &mut Self, other: M) -> &mut Self where Mat4<T>: From<M> {
37 *self = other.into();
38 self
39 }
40 fn translate<V>(self: &mut Self, translation_vector: V) -> &mut Self where V: Vector<T> {
41 let Vec3::<T>(x, y, z) = translation_vector.as_vec3(T::zero());
42 self[3][0] = self[0][0]* x + self[1][0] * y + self[2][0] * z + self[3][0];
43 self[3][1] = self[0][1]* x + self[1][1] * y + self[2][1] * z + self[3][1];
44 self[3][2] = self[0][2]* x + self[1][2] * y + self[2][2] * z + self[3][2];
45 self[3][3] = self[0][3]* x + self[1][3] * y + self[2][3] * z + self[3][3];
46 self
47 }
48 fn scale<V>(self: &mut Self, scaling_vector: V) -> &mut Self where V: Vector<T> {
49 let Vec3::<T>(x, y, z) = scaling_vector.as_vec3(T::one());
50 self[0][0] = self[0][0] * x;
51 self[0][1] = self[0][1] * x;
52 self[0][2] = self[0][2] * x;
53 self[0][3] = self[0][3] * x;
54 self[1][0] = self[1][0] * y;
55 self[1][1] = self[1][1] * y;
56 self[1][2] = self[1][2] * y;
57 self[1][3] = self[1][3] * y;
58 self[2][0] = self[2][0] * z;
59 self[2][1] = self[2][1] * z;
60 self[2][2] = self[2][2] * z;
61 self[2][3] = self[2][3] * z;
62 self
63 }
64 fn scale_at<P, V>(self: &mut Self, position: P, scaling_vector: V) -> &mut Self where P: Vector<T>, V: Vector<T> {
65 let position = position.as_vec3(T::zero());
66 self.translate(position)
67 .scale(scaling_vector)
68 .translate(-position)
69 }
70 fn rotate(self: &mut Self, radians: T) -> &mut Self {
71 let s = radians.sin();
72 let c = radians.cos();
73 let a00 = self[0][0];
74 let a01 = self[0][1];
75 let a02 = self[0][2];
76 let a03 = self[0][3];
77 let a10 = self[1][0];
78 let a11 = self[1][1];
79 let a12 = self[1][2];
80 let a13 = self[1][3];
81 self[0][0] = a00 * c + a10 * s;
82 self[0][1] = a01 * c + a11 * s;
83 self[0][2] = a02 * c + a12 * s;
84 self[0][3] = a03 * c + a13 * s;
85 self[1][0] = a10 * c - a00 * s;
86 self[1][1] = a11 * c - a01 * s;
87 self[1][2] = a12 * c - a02 * s;
88 self[1][3] = a13 * c - a03 * s;
89 self
90 }
91 fn rotate_at<P>(self: &mut Self, position: P, radians: T) -> &mut Self where P: Vector<T> {
92 let position = position.as_vec3(T::zero());
93 self.translate(position)
94 .rotate(radians)
95 .translate(-position)
96 }
97 fn rotate_axis<V>(self: &mut Self, radians: T, axis: V) -> &mut Self where Vec3<T>: From<V> {
98
99 let Vec3::<T>(mut x, mut y, mut z) = axis.into();
100 let mut len: T = (x * x + y * y + z * z).sqrt();
101
102 if len == T::zero() || len.is_normal() == false {
103 return self;
104 }
105
106 len = T::one() / len;
107 x = x * len;
108 y = y * len;
109 z = z * len;
110
111 let s: T = radians.sin();
112 let c: T = radians.cos();
113 let t: T = T::one() - c;
114
115 let a00 = self[0][0];
116 let a01 = self[0][1];
117 let a02 = self[0][2];
118 let a03 = self[0][3];
119 let a10 = self[1][0];
120 let a11 = self[1][1];
121 let a12 = self[1][2];
122 let a13 = self[1][3];
123 let a20 = self[2][0];
124 let a21 = self[2][1];
125 let a22 = self[2][2];
126 let a23 = self[2][3];
127
128 let b00 = x * x * t + c;
130 let b01 = y * x * t + z * s;
131 let b02 = z * x * t - y * s;
132 let b10 = x * y * t - z * s;
133 let b11 = y * y * t + c;
134 let b12 = z * y * t + x * s;
135 let b20 = x * z * t + y * s;
136 let b21 = y * z * t - x * s;
137 let b22 = z * z * t + c;
138
139 self[0][0] = a00 * b00 + a10 * b01 + a20 * b02;
141 self[0][1] = a01 * b00 + a11 * b01 + a21 * b02;
142 self[0][2] = a02 * b00 + a12 * b01 + a22 * b02;
143 self[0][3] = a03 * b00 + a13 * b01 + a23 * b02;
144 self[1][0] = a00 * b10 + a10 * b11 + a20 * b12;
145 self[1][1] = a01 * b10 + a11 * b11 + a21 * b12;
146 self[1][2] = a02 * b10 + a12 * b11 + a22 * b12;
147 self[1][3] = a03 * b10 + a13 * b11 + a23 * b12;
148 self[2][0] = a00 * b20 + a10 * b21 + a20 * b22;
149 self[2][1] = a01 * b20 + a11 * b21 + a21 * b22;
150 self[2][2] = a02 * b20 + a12 * b21 + a22 * b22;
151 self[2][3] = a03 * b20 + a13 * b21 + a23 * b22;
152
153 self
154 }
155 fn rotate_axis_at<P, V>(self: &mut Self, position: P, radians: T, axis: V) -> &mut Self where P: Vector<T>, Vec3<T>: From<V> {
156 let position = position.as_vec3(T::zero());
157 self.translate(position)
158 .rotate_axis(radians, axis)
159 .translate(-position)
160 }
161 fn get_rotation(self: &Self) -> Self {
162 let Vec3(x, y, z) = self.get_scale();
163 let a = self;
164 [
165 [ a[0][0] / x, a[0][1] / x, a[0][2] / x, T::zero() ],
166 [ a[1][0] / y, a[1][1] / y, a[1][2] / y, T::zero(), ],
167 [ a[2][0] / z, a[2][1] / z, a[2][2] / z, T::zero(), ],
168 [ T::zero(), T::zero(), T::zero(), T::one(), ],
169 ]
170 }
171 fn get_translation(self: &Self) -> Vec3<T> {
172 let a = self;
173 Vec3(a[3][0], a[3][1], a[3][2])
174 }
175 fn get_scale(self: &Self) -> Vec3<T> {
176 let a = self;
177 let x = Vec3(a[0][0], a[0][1], a[0][2]);
178 let y = Vec3(a[1][0], a[1][1], a[1][2]);
179 let z = Vec3(a[2][0], a[2][1], a[2][2]);
180 Vec3(x.len(), y.len(), z.len())
181 }
182 #[allow(non_snake_case)]
183 fn get_euler(self: &Self) -> Vec3<T> {
184 let a = self;
185 let y: T;
186 let z: T;
187 let x: T;
188
189 let half_PI = NumCast::from(f64::consts::PI / 2.0).unwrap();
190
191 if a[0][1] > NumCast::from(0.998).unwrap() { y = a[2][0].atan2(a[2][2]);
193 z = half_PI;
194 x = T::zero();
195 } else if a[0][1] < NumCast::from(-0.998).unwrap() { y = a[2][0].atan2(a[2][2]);
197 z = -half_PI;
198 x = T::zero();
199 } else {
200 y = (-a[0][2]).atan2(a[0][0]);
201 x = (-a[2][1]).atan2(a[1][1]);
202 z = a[0][1].asin();
203 }
204
205 Vec3(x, y, z)
206 }
207}