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 {}