cogl/auto/
matrix_stack.rs

1use crate::{Context, Euler, Matrix, MatrixEntry, Object, Quaternion};
2
3use glib::translate::*;
4use std::fmt;
5
6glib_wrapper! {
7    pub struct MatrixStack(Object<ffi::CoglMatrixStack, MatrixStackClass>) @extends Object;
8
9    match fn {
10        get_type => || ffi::cogl_matrix_stack_get_gtype(),
11    }
12}
13
14impl MatrixStack {
15    /// Allocates a new `MatrixStack` that can be used to build up
16    /// transformations relating to objects in a scenegraph like hierarchy.
17    /// (See the description of `MatrixStack` and `MatrixEntry` for
18    /// more details of what a matrix stack is best suited for)
19    ///
20    /// When a `MatrixStack` is first allocated it is conceptually
21    /// positioned at the root of your scenegraph hierarchy. As you
22    /// traverse your scenegraph then you should call
23    /// `MatrixStack::push` whenever you move down a level and
24    /// `MatrixStack::pop` whenever you move back up a level towards
25    /// the root.
26    ///
27    /// Once you have allocated a `MatrixStack` you can get a reference
28    /// to the current transformation for the current position in the
29    /// hierarchy by calling `MatrixStack::get_entry`.
30    ///
31    /// Once you have allocated a `MatrixStack` you can apply operations
32    /// such as rotate, scale and translate to modify the current transform
33    /// for the current position in the hierarchy by calling
34    /// `MatrixStack::rotate`, `MatrixStack::scale` and
35    /// `MatrixStack::translate`.
36    /// ## `ctx`
37    /// A `Context`
38    ///
39    /// # Returns
40    ///
41    /// A newly allocated `MatrixStack`
42    pub fn new(ctx: &Context) -> MatrixStack {
43        unsafe { from_glib_full(ffi::cogl_matrix_stack_new(ctx.to_glib_none().0)) }
44    }
45
46    /// Replaces the current matrix with a perspective matrix for a given
47    /// viewing frustum defined by 4 side clip planes that all cross
48    /// through the origin and 2 near and far clip planes.
49    /// ## `left`
50    /// X position of the left clipping plane where it
51    ///  intersects the near clipping plane
52    /// ## `right`
53    /// X position of the right clipping plane where it
54    ///  intersects the near clipping plane
55    /// ## `bottom`
56    /// Y position of the bottom clipping plane where it
57    ///  intersects the near clipping plane
58    /// ## `top`
59    /// Y position of the top clipping plane where it intersects
60    ///  the near clipping plane
61    /// ## `z_near`
62    /// The distance to the near clipping plane (Must be positive)
63    /// ## `z_far`
64    /// The distance to the far clipping plane (Must be positive)
65    pub fn frustum(&self, left: f32, right: f32, bottom: f32, top: f32, z_near: f32, z_far: f32) {
66        unsafe {
67            ffi::cogl_matrix_stack_frustum(
68                self.to_glib_none().0,
69                left,
70                right,
71                bottom,
72                top,
73                z_near,
74                z_far,
75            );
76        }
77    }
78
79    /// Resolves the current `self` transform into a `Matrix` by
80    /// combining the operations that have been applied to build up the
81    /// current transform.
82    ///
83    /// There are two possible ways that this function may return its
84    /// result depending on whether the stack is able to directly point
85    /// to an internal `Matrix` or whether the result needs to be
86    /// composed of multiple operations.
87    ///
88    /// If an internal matrix contains the required result then this
89    /// function will directly return a pointer to that matrix, otherwise
90    /// if the function returns `None` then `matrix` will be initialized
91    /// to match the current transform of `self`.
92    ///
93    /// `<note>``matrix` will be left untouched if a direct pointer is
94    /// returned.`</note>`
95    /// ## `matrix`
96    /// The potential destination for the current matrix
97    ///
98    /// # Returns
99    ///
100    /// A direct pointer to the current transform or `None`
101    ///  and in that case `matrix` will be initialized with
102    ///  the value of the current transform.
103    pub fn get(&self) -> (Matrix, Matrix) {
104        unsafe {
105            let mut matrix = Matrix::uninitialized();
106            let ret = from_glib_full(ffi::cogl_matrix_stack_get(
107                self.to_glib_none().0,
108                matrix.to_glib_none_mut().0,
109            ));
110            (ret, matrix)
111        }
112    }
113
114    /// Gets a reference to the current transform represented by a
115    /// `MatrixEntry` pointer.
116    ///
117    /// `<note>`The transform represented by a `MatrixEntry` is
118    /// immutable.`</note>`
119    ///
120    /// `<note>``MatrixEntry`<!-- -->s are reference counted using
121    /// `MatrixEntry::ref` and `MatrixEntry::unref` and you
122    /// should call `MatrixEntry::unref` when you are finished with
123    /// and entry you get via `MatrixStack::get_entry`.`</note>`
124    ///
125    /// # Returns
126    ///
127    /// A pointer to the `MatrixEntry`
128    ///  representing the current matrix stack transform.
129    pub fn get_entry(&self) -> Option<MatrixEntry> {
130        unsafe { from_glib_none(ffi::cogl_matrix_stack_get_entry(self.to_glib_none().0)) }
131    }
132
133    /// Gets the inverse transform of the current matrix and uses it to
134    /// initialize a new `Matrix`.
135    /// ## `inverse`
136    /// The destination for a 4x4 inverse transformation matrix
137    ///
138    /// # Returns
139    ///
140    /// `true` if the inverse was successfully calculated or `false`
141    ///  for degenerate transformations that can't be inverted (in this case the
142    ///  `inverse` matrix will simply be initialized with the identity matrix)
143    pub fn get_inverse(&self) -> (bool, Matrix) {
144        unsafe {
145            let mut inverse = Matrix::uninitialized();
146            let ret = ffi::cogl_matrix_stack_get_inverse(
147                self.to_glib_none().0,
148                inverse.to_glib_none_mut().0,
149            );
150            (ret == crate::TRUE, inverse)
151        }
152    }
153
154    /// Resets the current matrix to the identity matrix.
155    pub fn load_identity(&self) {
156        unsafe {
157            ffi::cogl_matrix_stack_load_identity(self.to_glib_none().0);
158        }
159    }
160
161    /// Multiplies the current matrix by the given matrix.
162    /// ## `matrix`
163    /// the matrix to multiply with the current model-view
164    pub fn multiply(&self, matrix: &Matrix) {
165        unsafe {
166            ffi::cogl_matrix_stack_multiply(self.to_glib_none().0, matrix.to_glib_none().0);
167        }
168    }
169
170    /// Replaces the current matrix with an orthographic projection matrix.
171    /// ## `x_1`
172    /// The x coordinate for the first vertical clipping plane
173    /// ## `y_1`
174    /// The y coordinate for the first horizontal clipping plane
175    /// ## `x_2`
176    /// The x coordinate for the second vertical clipping plane
177    /// ## `y_2`
178    /// The y coordinate for the second horizontal clipping plane
179    /// ## `near`
180    /// The `<emphasis>`distance`</emphasis>` to the near clipping
181    ///  plane (will be `<emphasis>`negative`</emphasis>` if the plane is
182    ///  behind the viewer)
183    /// ## `far`
184    /// The `<emphasis>`distance`</emphasis>` to the far clipping
185    ///  plane (will be `<emphasis>`negative`</emphasis>` if the plane is
186    ///  behind the viewer)
187    pub fn orthographic(&self, x_1: f32, y_1: f32, x_2: f32, y_2: f32, near: f32, far: f32) {
188        unsafe {
189            ffi::cogl_matrix_stack_orthographic(
190                self.to_glib_none().0,
191                x_1,
192                y_1,
193                x_2,
194                y_2,
195                near,
196                far,
197            );
198        }
199    }
200
201    /// Replaces the current matrix with a perspective matrix based on the
202    /// provided values.
203    ///
204    /// `<note>`You should be careful not to have too great a `z_far` / `z_near`
205    /// ratio since that will reduce the effectiveness of depth testing
206    /// since there wont be enough precision to identify the depth of
207    /// objects near to each other.`</note>`
208    /// ## `fov_y`
209    /// Vertical field of view angle in degrees.
210    /// ## `aspect`
211    /// The (width over height) aspect ratio for display
212    /// ## `z_near`
213    /// The distance to the near clipping plane (Must be positive,
214    ///  and must not be 0)
215    /// ## `z_far`
216    /// The distance to the far clipping plane (Must be positive)
217    pub fn perspective(&self, fov_y: f32, aspect: f32, z_near: f32, z_far: f32) {
218        unsafe {
219            ffi::cogl_matrix_stack_perspective(self.to_glib_none().0, fov_y, aspect, z_near, z_far);
220        }
221    }
222
223    /// Restores the previous transform that was last saved by calling
224    /// `MatrixStack::push`.
225    ///
226    /// This is usually called while traversing a scenegraph whenever you
227    /// return up one level in the graph towards the root node.
228    pub fn pop(&self) {
229        unsafe {
230            ffi::cogl_matrix_stack_pop(self.to_glib_none().0);
231        }
232    }
233
234    /// Saves the current transform and starts a new transform that derives
235    /// from the current transform.
236    ///
237    /// This is usually called while traversing a scenegraph whenever you
238    /// traverse one level deeper. `MatrixStack::pop` can then be
239    /// called when going back up one layer to restore the previous
240    /// transform of an ancestor.
241    pub fn push(&self) {
242        unsafe {
243            ffi::cogl_matrix_stack_push(self.to_glib_none().0);
244        }
245    }
246
247    /// Multiplies the current matrix by one that rotates the around the
248    /// axis-vector specified by `x`, `y` and `z`. The rotation follows the
249    /// right-hand thumb rule so for example rotating by 10 degrees about
250    /// the axis-vector (0, 0, 1) causes a small counter-clockwise
251    /// rotation.
252    /// ## `angle`
253    /// Angle in degrees to rotate.
254    /// ## `x`
255    /// X-component of vertex to rotate around.
256    /// ## `y`
257    /// Y-component of vertex to rotate around.
258    /// ## `z`
259    /// Z-component of vertex to rotate around.
260    pub fn rotate(&self, angle: f32, x: f32, y: f32, z: f32) {
261        unsafe {
262            ffi::cogl_matrix_stack_rotate(self.to_glib_none().0, angle, x, y, z);
263        }
264    }
265
266    /// Multiplies the current matrix by one that rotates according to the
267    /// rotation described by `euler`.
268    ///
269    /// ## `euler`
270    /// A `Euler`
271    pub fn rotate_euler(&self, euler: &Euler) {
272        unsafe {
273            ffi::cogl_matrix_stack_rotate_euler(self.to_glib_none().0, euler.to_glib_none().0);
274        }
275    }
276
277    /// Multiplies the current matrix by one that rotates according to the
278    /// rotation described by `quaternion`.
279    /// ## `quaternion`
280    /// A `Quaternion`
281    pub fn rotate_quaternion(&self, quaternion: &Quaternion) {
282        unsafe {
283            ffi::cogl_matrix_stack_rotate_quaternion(
284                self.to_glib_none().0,
285                quaternion.to_glib_none().0,
286            );
287        }
288    }
289
290    /// Multiplies the current matrix by one that scales the x, y and z
291    /// axes by the given values.
292    /// ## `x`
293    /// Amount to scale along the x-axis
294    /// ## `y`
295    /// Amount to scale along the y-axis
296    /// ## `z`
297    /// Amount to scale along the z-axis
298    pub fn scale(&self, x: f32, y: f32, z: f32) {
299        unsafe {
300            ffi::cogl_matrix_stack_scale(self.to_glib_none().0, x, y, z);
301        }
302    }
303
304    /// Replaces the current `self` matrix value with the value of `matrix`.
305    /// This effectively discards any other operations that were applied
306    /// since the last time `MatrixStack::push` was called or since
307    /// the stack was initialized.
308    /// ## `matrix`
309    /// A `Matrix` replace the current matrix value with
310    pub fn set(&self, matrix: &Matrix) {
311        unsafe {
312            ffi::cogl_matrix_stack_set(self.to_glib_none().0, matrix.to_glib_none().0);
313        }
314    }
315
316    /// Multiplies the current matrix by one that translates along all
317    /// three axes according to the given values.
318    /// ## `x`
319    /// Distance to translate along the x-axis
320    /// ## `y`
321    /// Distance to translate along the y-axis
322    /// ## `z`
323    /// Distance to translate along the z-axis
324    pub fn translate(&self, x: f32, y: f32, z: f32) {
325        unsafe {
326            ffi::cogl_matrix_stack_translate(self.to_glib_none().0, x, y, z);
327        }
328    }
329}
330
331impl fmt::Display for MatrixStack {
332    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
333        write!(f, "MatrixStack")
334    }
335}