1use std::{fmt, ops};
4
5use glib::translate::*;
6
7use crate::{ffi, Matrix, Point, Point3D, Vec3, Vec4};
8
9impl Matrix {
10 #[doc(alias = "graphene_matrix_init_from_2d")]
11 #[doc(alias = "init_from_2d")]
12 pub fn from_2d(xx: f64, yx: f64, xy: f64, yy: f64, x_0: f64, y_0: f64) -> Self {
13 assert_initialized_main_thread!();
14 unsafe {
15 let mut mat = Self::uninitialized();
16 ffi::graphene_matrix_init_from_2d(mat.to_glib_none_mut().0, xx, yx, xy, yy, x_0, y_0);
17 mat
18 }
19 }
20
21 #[doc(alias = "graphene_matrix_init_from_float")]
22 #[doc(alias = "init_from_float")]
23 pub fn from_float(v: [f32; 16]) -> Self {
24 assert_initialized_main_thread!();
25 unsafe {
26 let mut mat = Self::uninitialized();
27 ffi::graphene_matrix_init_from_float(mat.to_glib_none_mut().0, v.as_ptr() as *const _);
28 mat
29 }
30 }
31
32 #[doc(alias = "graphene_matrix_init_from_vec4")]
33 #[doc(alias = "init_from_vec4")]
34 pub fn from_vec4(v0: &Vec4, v1: &Vec4, v2: &Vec4, v3: &Vec4) -> Self {
35 assert_initialized_main_thread!();
36 unsafe {
37 let mut mat = Self::uninitialized();
38 ffi::graphene_matrix_init_from_vec4(
39 mat.to_glib_none_mut().0,
40 v0.to_glib_none().0,
41 v1.to_glib_none().0,
42 v2.to_glib_none().0,
43 v3.to_glib_none().0,
44 );
45 mat
46 }
47 }
48
49 #[doc(alias = "graphene_matrix_init_frustum")]
50 #[doc(alias = "init_frustum")]
51 pub fn new_frustum(
52 left: f32,
53 right: f32,
54 bottom: f32,
55 top: f32,
56 z_near: f32,
57 z_far: f32,
58 ) -> Self {
59 assert_initialized_main_thread!();
60 unsafe {
61 let mut mat = Self::uninitialized();
62 ffi::graphene_matrix_init_frustum(
63 mat.to_glib_none_mut().0,
64 left,
65 right,
66 bottom,
67 top,
68 z_near,
69 z_far,
70 );
71 mat
72 }
73 }
74
75 #[doc(alias = "graphene_matrix_init_identity")]
76 #[doc(alias = "init_identity")]
77 pub fn new_identity() -> Self {
78 assert_initialized_main_thread!();
79 unsafe {
80 let mut mat = Self::uninitialized();
81 ffi::graphene_matrix_init_identity(mat.to_glib_none_mut().0);
82 mat
83 }
84 }
85
86 #[doc(alias = "graphene_matrix_init_look_at")]
87 #[doc(alias = "init_look_at")]
88 pub fn new_look_at(eye: &Vec3, center: &Vec3, up: &Vec3) -> Self {
89 assert_initialized_main_thread!();
90 unsafe {
91 let mut mat = Self::uninitialized();
92 ffi::graphene_matrix_init_look_at(
93 mat.to_glib_none_mut().0,
94 eye.to_glib_none().0,
95 center.to_glib_none().0,
96 up.to_glib_none().0,
97 );
98 mat
99 }
100 }
101
102 #[doc(alias = "graphene_matrix_init_ortho")]
103 #[doc(alias = "init_ortho")]
104 pub fn new_ortho(
105 left: f32,
106 right: f32,
107 top: f32,
108 bottom: f32,
109 z_near: f32,
110 z_far: f32,
111 ) -> Self {
112 assert_initialized_main_thread!();
113 unsafe {
114 let mut mat = Self::uninitialized();
115 ffi::graphene_matrix_init_ortho(
116 mat.to_glib_none_mut().0,
117 left,
118 right,
119 top,
120 bottom,
121 z_near,
122 z_far,
123 );
124 mat
125 }
126 }
127
128 #[doc(alias = "graphene_matrix_init_perspective")]
129 #[doc(alias = "init_perspective")]
130 pub fn new_perspective(fovy: f32, aspect: f32, z_near: f32, z_far: f32) -> Self {
131 assert_initialized_main_thread!();
132 unsafe {
133 let mut mat = Self::uninitialized();
134 ffi::graphene_matrix_init_perspective(
135 mat.to_glib_none_mut().0,
136 fovy,
137 aspect,
138 z_near,
139 z_far,
140 );
141 mat
142 }
143 }
144
145 #[doc(alias = "graphene_matrix_init_rotate")]
146 #[doc(alias = "init_rotate")]
147 pub fn new_rotate(angle: f32, axis: &Vec3) -> Self {
148 assert_initialized_main_thread!();
149 unsafe {
150 let mut mat = Self::uninitialized();
151 ffi::graphene_matrix_init_rotate(
152 mat.to_glib_none_mut().0,
153 angle,
154 axis.to_glib_none().0,
155 );
156 mat
157 }
158 }
159
160 #[doc(alias = "graphene_matrix_init_scale")]
161 #[doc(alias = "init_scale")]
162 pub fn new_scale(x: f32, y: f32, z: f32) -> Self {
163 assert_initialized_main_thread!();
164 unsafe {
165 let mut mat = Self::uninitialized();
166 ffi::graphene_matrix_init_scale(mat.to_glib_none_mut().0, x, y, z);
167 mat
168 }
169 }
170
171 #[doc(alias = "graphene_matrix_init_skew")]
172 #[doc(alias = "init_skew")]
173 pub fn new_skew(x_skew: f32, y_skew: f32) -> Self {
174 assert_initialized_main_thread!();
175 unsafe {
176 let mut mat = Self::uninitialized();
177 ffi::graphene_matrix_init_skew(mat.to_glib_none_mut().0, x_skew, y_skew);
178 mat
179 }
180 }
181
182 #[doc(alias = "graphene_matrix_init_translate")]
183 #[doc(alias = "init_translate")]
184 pub fn new_translate(p: &Point3D) -> Self {
185 assert_initialized_main_thread!();
186 unsafe {
187 let mut mat = Self::uninitialized();
188 ffi::graphene_matrix_init_translate(mat.to_glib_none_mut().0, p.to_glib_none().0);
189 mat
190 }
191 }
192
193 #[doc(alias = "graphene_matrix_to_float")]
194 pub fn to_float(&self) -> [f32; 16] {
195 unsafe {
196 let mut out = std::mem::MaybeUninit::uninit();
197 ffi::graphene_matrix_to_float(self.to_glib_none().0, out.as_mut_ptr());
198 out.assume_init()
199 }
200 }
201
202 #[inline]
203 pub fn values(&self) -> &[[f32; 4]; 4] {
204 unsafe { &*(&self.inner.value as *const ffi::graphene_simd4x4f_t as *const [[f32; 4]; 4]) }
205 }
206}
207
208impl fmt::Debug for Matrix {
209 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
210 f.debug_struct("Matrix")
211 .field("values", &self.values())
212 .finish()
213 }
214}
215
216impl Default for Matrix {
217 fn default() -> Self {
218 Self::new_identity()
219 }
220}
221
222impl ops::Mul<Matrix> for f32 {
224 type Output = Matrix;
225
226 fn mul(self, mut rhs: Matrix) -> Self::Output {
227 rhs.scale(self, self, self);
228 rhs
229 }
230}
231
232impl ops::Mul<Matrix> for Matrix {
234 type Output = Matrix;
235
236 fn mul(self, rhs: Matrix) -> Self::Output {
237 Matrix::multiply(&self, &rhs)
238 }
239}
240impl ops::MulAssign<Matrix> for Matrix {
241 fn mul_assign(&mut self, rhs: Matrix) {
242 *self = *self * rhs;
243 }
244}
245
246impl ops::Mul<Vec4> for Matrix {
247 type Output = Vec4;
248
249 fn mul(self, rhs: Vec4) -> Self::Output {
252 Matrix::transform_vec4(&self, &rhs)
253 }
254}
255
256impl ops::Mul<Vec3> for Matrix {
257 type Output = Vec3;
258
259 fn mul(self, rhs: Vec3) -> Self::Output {
262 Matrix::transform_vec3(&self, &rhs)
263 }
264}
265
266impl ops::Mul<Point> for Matrix {
267 type Output = Point;
268
269 fn mul(self, rhs: Point) -> Self::Output {
270 Matrix::transform_point(&self, &rhs)
271 }
272}
273
274impl ops::Mul<Point3D> for Matrix {
275 type Output = Point3D;
276
277 fn mul(self, rhs: Point3D) -> Self::Output {
280 Matrix::transform_point3d(&self, &rhs)
281 }
282}
283
284#[cfg(test)]
285mod tests {
286 use super::Matrix;
287 #[test]
288 fn test_matrix_values() {
289 let matrix = Matrix::new_identity();
290 assert_eq!(
291 matrix.values(),
292 &[
293 [1.0, 0.0, 0.0, 0.0],
294 [0.0, 1.0, 0.0, 0.0],
295 [0.0, 0.0, 1.0, 0.0],
296 [0.0, 0.0, 0.0, 1.0]
297 ],
298 );
299 }
300}