cogl/auto/matrix.rs
1#![allow(
2 clippy::too_many_arguments,
3 clippy::let_and_return,
4 clippy::from_over_into
5)]
6
7use crate::{Euler, Quaternion};
8
9use glib::translate::*;
10use std::boxed::Box as Box_;
11use std::mem;
12
13glib_wrapper! {
14 #[derive(Debug, PartialOrd, Ord)] // Hash
15 pub struct Matrix(Boxed<ffi::CoglMatrix>);
16
17 match fn {
18 copy => |ptr| ffi::cogl_matrix_copy(mut_override(ptr)),
19 free => |ptr| ffi::cogl_matrix_free(ptr),
20 get_type => || ffi::cogl_matrix_get_gtype(),
21 }
22}
23
24impl Matrix {
25 /// Multiplies `self` by the given frustum perspective matrix.
26 /// ## `left`
27 /// X position of the left clipping plane where it
28 /// intersects the near clipping plane
29 /// ## `right`
30 /// X position of the right clipping plane where it
31 /// intersects the near clipping plane
32 /// ## `bottom`
33 /// Y position of the bottom clipping plane where it
34 /// intersects the near clipping plane
35 /// ## `top`
36 /// Y position of the top clipping plane where it intersects
37 /// the near clipping plane
38 /// ## `z_near`
39 /// The distance to the near clipping plane (Must be positive)
40 /// ## `z_far`
41 /// The distance to the far clipping plane (Must be positive)
42 pub fn frustum(
43 &mut self,
44 left: f32,
45 right: f32,
46 bottom: f32,
47 top: f32,
48 z_near: f32,
49 z_far: f32,
50 ) {
51 unsafe {
52 ffi::cogl_matrix_frustum(
53 self.to_glib_none_mut().0,
54 left,
55 right,
56 bottom,
57 top,
58 z_near,
59 z_far,
60 );
61 }
62 }
63
64 //TODO:
65 // /// Casts `self` to a float array which can be directly passed to OpenGL.
66 // ///
67 // /// # Returns
68 // ///
69 // /// a pointer to the float array
70 // pub fn get_array(&self) -> &[f32] {
71 // unsafe { ffi::cogl_matrix_get_array(self.to_glib_none().0) };
72 // }
73
74 /// Gets the inverse transform of a given matrix and uses it to initialize
75 /// a new `Matrix`.
76 ///
77 /// `<note>`Although the first parameter is annotated as const to indicate
78 /// that the transform it represents isn't modified this function may
79 /// technically save a copy of the inverse transform within the given
80 /// `Matrix` so that subsequent requests for the inverse transform may
81 /// avoid costly inversion calculations.`</note>`
82 /// ## `inverse`
83 /// The destination for a 4x4 inverse transformation matrix
84 ///
85 /// # Returns
86 ///
87 /// `true` if the inverse was successfully calculated or `false`
88 /// for degenerate transformations that can't be inverted (in this case the
89 /// `inverse` matrix will simply be initialized with the identity matrix)
90 pub fn get_inverse(&self) -> (bool, Matrix) {
91 unsafe {
92 let mut inverse = Matrix::uninitialized();
93 let ret =
94 ffi::cogl_matrix_get_inverse(self.to_glib_none().0, inverse.to_glib_none_mut().0);
95 (ret == crate::TRUE, inverse)
96 }
97 }
98
99 /// Initializes `self` with the contents of `array`
100 /// ## `array`
101 /// A linear array of 16 floats (column-major order)
102 pub fn init_from_array(&mut self, array: &[f32]) {
103 unsafe {
104 ffi::cogl_matrix_init_from_array(self.to_glib_none_mut().0, array.as_ptr());
105 }
106 }
107
108 /// Initializes `self` from a `Euler` rotation.
109 ///
110 /// ## `euler`
111 /// A `Euler`
112 pub fn init_from_euler(&mut self, euler: &Euler) {
113 unsafe {
114 ffi::cogl_matrix_init_from_euler(self.to_glib_none_mut().0, euler.to_glib_none().0);
115 }
116 }
117
118 /// Initializes `self` from a `Quaternion` rotation.
119 /// ## `quaternion`
120 /// A `Quaternion`
121 pub fn init_from_quaternion(&mut self, quaternion: &Quaternion) {
122 unsafe {
123 ffi::cogl_matrix_init_from_quaternion(
124 self.to_glib_none_mut().0,
125 quaternion.to_glib_none().0,
126 );
127 }
128 }
129
130 /// Resets matrix to the identity matrix:
131 ///
132 ///
133 /// ```text
134 /// .xx=1; .xy=0; .xz=0; .xw=0;
135 /// .yx=0; .yy=1; .yz=0; .yw=0;
136 /// .zx=0; .zy=0; .zz=1; .zw=0;
137 /// .wx=0; .wy=0; .wz=0; .ww=1;
138 /// ```
139 pub fn init_identity(&mut self) {
140 unsafe {
141 ffi::cogl_matrix_init_identity(self.to_glib_none_mut().0);
142 }
143 }
144
145 /// Resets matrix to the (tx, ty, tz) translation matrix:
146 ///
147 ///
148 /// ```text
149 /// .xx=1; .xy=0; .xz=0; .xw=tx;
150 /// .yx=0; .yy=1; .yz=0; .yw=ty;
151 /// .zx=0; .zy=0; .zz=1; .zw=tz;
152 /// .wx=0; .wy=0; .wz=0; .ww=1;
153 /// ```
154 ///
155 /// ## `tx`
156 /// x coordinate of the translation vector
157 /// ## `ty`
158 /// y coordinate of the translation vector
159 /// ## `tz`
160 /// z coordinate of the translation vector
161 pub fn init_translation(&mut self, tx: f32, ty: f32, tz: f32) {
162 unsafe {
163 ffi::cogl_matrix_init_translation(self.to_glib_none_mut().0, tx, ty, tz);
164 }
165 }
166
167 /// Determines if the given matrix is an identity matrix.
168 ///
169 /// # Returns
170 ///
171 /// `true` if `self` is an identity matrix else `false`
172 pub fn is_identity(&self) -> bool {
173 unsafe { ffi::cogl_matrix_is_identity(self.to_glib_none().0) == crate::TRUE }
174 }
175
176 /// Applies a view transform `self` that positions the camera at
177 /// the coordinate (`eye_position_x`, `eye_position_y`, `eye_position_z`)
178 /// looking towards an object at the coordinate (`object_x`, `object_y`,
179 /// `object_z`). The top of the camera is aligned to the given world up
180 /// vector, which is normally simply (0, 1, 0) to map up to the
181 /// positive direction of the y axis.
182 ///
183 /// Because there is a lot of missleading documentation online for
184 /// gluLookAt regarding the up vector we want to try and be a bit
185 /// clearer here.
186 ///
187 /// The up vector should simply be relative to your world coordinates
188 /// and does not need to change as you move the eye and object
189 /// positions. Many online sources may claim that the up vector needs
190 /// to be perpendicular to the vector between the eye and object
191 /// position (partly because the man page is somewhat missleading) but
192 /// that is not necessary for this function.
193 ///
194 /// `<note>`You should never look directly along the world-up
195 /// vector.`</note>`
196 ///
197 /// `<note>`It is assumed you are using a typical projection matrix where
198 /// your origin maps to the center of your viewport.`</note>`
199 ///
200 /// `<note>`Almost always when you use this function it should be the first
201 /// transform applied to a new modelview transform`</note>`
202 /// ## `eye_position_x`
203 /// The X coordinate to look from
204 /// ## `eye_position_y`
205 /// The Y coordinate to look from
206 /// ## `eye_position_z`
207 /// The Z coordinate to look from
208 /// ## `object_x`
209 /// The X coordinate of the object to look at
210 /// ## `object_y`
211 /// The Y coordinate of the object to look at
212 /// ## `object_z`
213 /// The Z coordinate of the object to look at
214 /// ## `world_up_x`
215 /// The X component of the world's up direction vector
216 /// ## `world_up_y`
217 /// The Y component of the world's up direction vector
218 /// ## `world_up_z`
219 /// The Z component of the world's up direction vector
220 pub fn look_at(
221 &mut self,
222 eye_position_x: f32,
223 eye_position_y: f32,
224 eye_position_z: f32,
225 object_x: f32,
226 object_y: f32,
227 object_z: f32,
228 world_up_x: f32,
229 world_up_y: f32,
230 world_up_z: f32,
231 ) {
232 unsafe {
233 ffi::cogl_matrix_look_at(
234 self.to_glib_none_mut().0,
235 eye_position_x,
236 eye_position_y,
237 eye_position_z,
238 object_x,
239 object_y,
240 object_z,
241 world_up_x,
242 world_up_y,
243 world_up_z,
244 );
245 }
246 }
247
248 /// Multiplies the two supplied matrices together and stores
249 /// the resulting matrix inside `self`.
250 ///
251 /// `<note>`It is possible to multiply the `a` matrix in-place, so
252 /// `self` can be equal to `a` but can't be equal to `b`.`</note>`
253 /// ## `a`
254 /// A 4x4 transformation matrix
255 /// ## `b`
256 /// A 4x4 transformation matrix
257 pub fn multiply(&mut self, a: &Matrix, b: &Matrix) {
258 unsafe {
259 ffi::cogl_matrix_multiply(
260 self.to_glib_none_mut().0,
261 a.to_glib_none().0,
262 b.to_glib_none().0,
263 );
264 }
265 }
266
267 /// Multiplies `self` by a parallel projection matrix.
268 /// ## `x_1`
269 /// The x coordinate for the first vertical clipping plane
270 /// ## `y_1`
271 /// The y coordinate for the first horizontal clipping plane
272 /// ## `x_2`
273 /// The x coordinate for the second vertical clipping plane
274 /// ## `y_2`
275 /// The y coordinate for the second horizontal clipping plane
276 /// ## `near`
277 /// The `<emphasis>`distance`</emphasis>` to the near clipping
278 /// plane (will be `<emphasis>`negative`</emphasis>` if the plane is
279 /// behind the viewer)
280 /// ## `far`
281 /// The `<emphasis>`distance`</emphasis>` to the far clipping
282 /// plane (will be `<emphasis>`negative`</emphasis>` if the plane is
283 /// behind the viewer)
284 pub fn orthographic(&mut self, x_1: f32, y_1: f32, x_2: f32, y_2: f32, near: f32, far: f32) {
285 unsafe {
286 ffi::cogl_matrix_orthographic(self.to_glib_none_mut().0, x_1, y_1, x_2, y_2, near, far);
287 }
288 }
289
290 /// Multiplies `self` by the described perspective matrix
291 ///
292 /// `<note>`You should be careful not to have to great a `z_far` / `z_near`
293 /// ratio since that will reduce the effectiveness of depth testing
294 /// since there wont be enough precision to identify the depth of
295 /// objects near to each other.`</note>`
296 /// ## `fov_y`
297 /// Vertical field of view angle in degrees.
298 /// ## `aspect`
299 /// The (width over height) aspect ratio for display
300 /// ## `z_near`
301 /// The distance to the near clipping plane (Must be positive,
302 /// and must not be 0)
303 /// ## `z_far`
304 /// The distance to the far clipping plane (Must be positive)
305 pub fn perspective(&mut self, fov_y: f32, aspect: f32, z_near: f32, z_far: f32) {
306 unsafe {
307 ffi::cogl_matrix_perspective(self.to_glib_none_mut().0, fov_y, aspect, z_near, z_far);
308 }
309 }
310
311 //pub fn project_points(&self, n_components: i32, stride_in: usize, points_in: /*Unimplemented*/Option<Fundamental: Pointer>, stride_out: usize, points_out: /*Unimplemented*/Option<Fundamental: Pointer>, n_points: i32) {
312 // unsafe { TODO: call cogl_sys:cogl_matrix_project_points() }
313 //}
314
315 /// Multiplies `self` with a rotation matrix that applies a rotation
316 /// of `angle` degrees around the specified 3D vector.
317 /// ## `angle`
318 /// The angle you want to rotate in degrees
319 /// ## `x`
320 /// X component of your rotation vector
321 /// ## `y`
322 /// Y component of your rotation vector
323 /// ## `z`
324 /// Z component of your rotation vector
325 pub fn rotate(&mut self, angle: f32, x: f32, y: f32, z: f32) {
326 unsafe {
327 ffi::cogl_matrix_rotate(self.to_glib_none_mut().0, angle, x, y, z);
328 }
329 }
330
331 /// Multiplies `self` with a rotation transformation described by the
332 /// given `Euler`.
333 ///
334 /// ## `euler`
335 /// A euler describing a rotation
336 pub fn rotate_euler(&mut self, euler: &Euler) {
337 unsafe {
338 ffi::cogl_matrix_rotate_euler(self.to_glib_none_mut().0, euler.to_glib_none().0);
339 }
340 }
341
342 /// Multiplies `self` with a rotation transformation described by the
343 /// given `Quaternion`.
344 ///
345 /// ## `quaternion`
346 /// A quaternion describing a rotation
347 pub fn rotate_quaternion(&mut self, quaternion: &Quaternion) {
348 unsafe {
349 ffi::cogl_matrix_rotate_quaternion(
350 self.to_glib_none_mut().0,
351 quaternion.to_glib_none().0,
352 );
353 }
354 }
355
356 /// Multiplies `self` with a transform matrix that scales along the X,
357 /// Y and Z axis.
358 /// ## `sx`
359 /// The X scale factor
360 /// ## `sy`
361 /// The Y scale factor
362 /// ## `sz`
363 /// The Z scale factor
364 pub fn scale(&mut self, sx: f32, sy: f32, sz: f32) {
365 unsafe {
366 ffi::cogl_matrix_scale(self.to_glib_none_mut().0, sx, sy, sz);
367 }
368 }
369
370 /// Transforms a point whos position is given and returned as four float
371 /// components.
372 /// ## `x`
373 /// The X component of your points position
374 /// ## `y`
375 /// The Y component of your points position
376 /// ## `z`
377 /// The Z component of your points position
378 /// ## `w`
379 /// The W component of your points position
380 pub fn transform_point(&self, x: &mut f32, y: &mut f32, z: &mut f32, w: &mut f32) {
381 unsafe {
382 ffi::cogl_matrix_transform_point(self.to_glib_none().0, x, y, z, w);
383 }
384 }
385
386 //pub fn transform_points(&self, n_components: i32, stride_in: usize, points_in: /*Unimplemented*/Option<Fundamental: Pointer>, stride_out: usize, points_out: /*Unimplemented*/Option<Fundamental: Pointer>, n_points: i32) {
387 // unsafe { TODO: call cogl_sys:cogl_matrix_transform_points() }
388 //}
389
390 /// Multiplies `self` with a transform matrix that translates along
391 /// the X, Y and Z axis.
392 /// ## `x`
393 /// The X translation you want to apply
394 /// ## `y`
395 /// The Y translation you want to apply
396 /// ## `z`
397 /// The Z translation you want to apply
398 pub fn translate(&mut self, x: f32, y: f32, z: f32) {
399 unsafe {
400 ffi::cogl_matrix_translate(self.to_glib_none_mut().0, x, y, z);
401 }
402 }
403
404 /// Replaces `self` with its transpose. Ie, every element (i,j) in the
405 /// new matrix is taken from element (j,i) in the old matrix.
406 pub fn transpose(&mut self) {
407 unsafe {
408 ffi::cogl_matrix_transpose(self.to_glib_none_mut().0);
409 }
410 }
411
412 /// Multiplies `self` by a view transform that maps the 2D coordinates
413 /// (0,0) top left and (`width_2d`,`height_2d`) bottom right the full viewport
414 /// size. Geometry at a depth of 0 will now lie on this 2D plane.
415 ///
416 /// Note: this doesn't multiply the matrix by any projection matrix,
417 /// but it assumes you have a perspective projection as defined by
418 /// passing the corresponding arguments to `Matrix::frustum`.
419 ///
420 /// Toolkits such as Clutter that mix 2D and 3D drawing can use this to
421 /// create a 2D coordinate system within a 3D perspective projected
422 /// view frustum.
423 /// ## `left`
424 /// coord of left vertical clipping plane
425 /// ## `right`
426 /// coord of right vertical clipping plane
427 /// ## `bottom`
428 /// coord of bottom horizontal clipping plane
429 /// ## `top`
430 /// coord of top horizontal clipping plane
431 /// ## `z_near`
432 /// The distance to the near clip plane. Never pass 0 and always pass
433 /// a positive number.
434 /// ## `z_2d`
435 /// The distance to the 2D plane. (Should always be positive and
436 /// be between `z_near` and the z_far value that was passed to
437 /// `Matrix::frustum`)
438 /// ## `width_2d`
439 /// The width of the 2D coordinate system
440 /// ## `height_2d`
441 /// The height of the 2D coordinate system
442 pub fn view_2d_in_frustum(
443 &mut self,
444 left: f32,
445 right: f32,
446 bottom: f32,
447 top: f32,
448 z_near: f32,
449 z_2d: f32,
450 width_2d: f32,
451 height_2d: f32,
452 ) {
453 unsafe {
454 ffi::cogl_matrix_view_2d_in_frustum(
455 self.to_glib_none_mut().0,
456 left,
457 right,
458 bottom,
459 top,
460 z_near,
461 z_2d,
462 width_2d,
463 height_2d,
464 );
465 }
466 }
467
468 /// Multiplies `self` by a view transform that maps the 2D coordinates
469 /// (0,0) top left and (`width_2d`,`height_2d`) bottom right the full viewport
470 /// size. Geometry at a depth of 0 will now lie on this 2D plane.
471 ///
472 /// Note: this doesn't multiply the matrix by any projection matrix,
473 /// but it assumes you have a perspective projection as defined by
474 /// passing the corresponding arguments to `Matrix::perspective`.
475 ///
476 /// Toolkits such as Clutter that mix 2D and 3D drawing can use this to
477 /// create a 2D coordinate system within a 3D perspective projected
478 /// view frustum.
479 /// ## `fov_y`
480 /// A field of view angle for the Y axis
481 /// ## `aspect`
482 /// The ratio of width to height determining the field of view angle
483 /// for the x axis.
484 /// ## `z_near`
485 /// The distance to the near clip plane. Never pass 0 and always pass
486 /// a positive number.
487 /// ## `z_2d`
488 /// The distance to the 2D plane. (Should always be positive and
489 /// be between `z_near` and the z_far value that was passed to
490 /// `Matrix::frustum`)
491 /// ## `width_2d`
492 /// The width of the 2D coordinate system
493 /// ## `height_2d`
494 /// The height of the 2D coordinate system
495 pub fn view_2d_in_perspective(
496 &mut self,
497 fov_y: f32,
498 aspect: f32,
499 z_near: f32,
500 z_2d: f32,
501 width_2d: f32,
502 height_2d: f32,
503 ) {
504 unsafe {
505 ffi::cogl_matrix_view_2d_in_perspective(
506 self.to_glib_none_mut().0,
507 fov_y,
508 aspect,
509 z_near,
510 z_2d,
511 width_2d,
512 height_2d,
513 );
514 }
515 }
516
517 fn equal(v1: &Self, v2: &Self) -> bool {
518 let a = Box_::into_raw(Box::new(v1)) as *mut _;
519 let b = Box_::into_raw(Box::new(v2)) as *mut _;
520 unsafe { ffi::cogl_matrix_equal(a, b) == crate::TRUE }
521 }
522}
523
524#[doc(hidden)]
525impl Uninitialized for Matrix {
526 #[inline]
527 unsafe fn uninitialized() -> Self {
528 mem::zeroed()
529 }
530}
531
532impl PartialEq for Matrix {
533 #[inline]
534 fn eq(&self, other: &Self) -> bool {
535 Matrix::equal(self, other)
536 }
537}
538
539impl Eq for Matrix {}