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}