cogl/auto/
quaternion.rs

1#![allow(
2    clippy::too_many_arguments,
3    clippy::let_and_return,
4    clippy::from_over_into
5)]
6
7use crate::{Euler, Matrix};
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 Quaternion(Boxed<ffi::CoglQuaternion>);
16
17    match fn {
18        copy => |ptr| ffi::cogl_quaternion_copy(mut_override(ptr)),
19        free => |ptr| ffi::cogl_quaternion_free(ptr),
20        get_type => || ffi::cogl_quaternion_get_gtype(),
21    }
22}
23
24impl Quaternion {
25    ///
26    /// ## `b`
27    /// A `Quaternion`
28    pub fn dot_product(&self, b: &Quaternion) -> f32 {
29        unsafe { ffi::cogl_quaternion_dot_product(self.to_glib_none().0, b.to_glib_none().0) }
30    }
31
32    ///
33    pub fn get_rotation_angle(&self) -> f32 {
34        unsafe { ffi::cogl_quaternion_get_rotation_angle(self.to_glib_none().0) }
35    }
36
37    ///
38    /// ## `vector3`
39    /// an allocated 3-float array
40    pub fn get_rotation_axis(&self) -> f32 {
41        unsafe {
42            let mut vector3 = mem::MaybeUninit::uninit();
43            ffi::cogl_quaternion_get_rotation_axis(self.to_glib_none().0, vector3.as_mut_ptr());
44            vector3.assume_init()
45        }
46    }
47
48    /// Initializes a quaternion that rotates `angle` degrees around the
49    /// axis vector (`x`, `y`, `z`). The axis vector does not need to be
50    /// normalized.
51    ///
52    /// ## `angle`
53    /// The angle you want to rotate around the given axis
54    /// ## `x`
55    /// The x component of your axis vector about which you want to
56    /// rotate.
57    /// ## `y`
58    /// The y component of your axis vector about which you want to
59    /// rotate.
60    /// ## `z`
61    /// The z component of your axis vector about which you want to
62    /// rotate.
63    pub fn init(&mut self, angle: f32, x: f32, y: f32, z: f32) {
64        unsafe {
65            ffi::cogl_quaternion_init(self.to_glib_none_mut().0, angle, x, y, z);
66        }
67    }
68
69    /// Initializes a quaternion that rotates `angle` degrees around the
70    /// given `axis` vector. The axis vector does not need to be
71    /// normalized.
72    ///
73    /// ## `angle`
74    /// The angle to rotate around `axis3f`
75    /// ## `axis3f`
76    /// your 3 component axis vector about which you want to rotate.
77    pub fn init_from_angle_vector(&mut self, angle: f32, axis3f: &[f32; 3]) {
78        unsafe {
79            ffi::cogl_quaternion_init_from_angle_vector(
80                self.to_glib_none_mut().0,
81                angle,
82                axis3f.to_glib_none().0,
83            );
84        }
85    }
86
87    /// Initializes a [w (x, y,z)] quaternion directly from an array of 4
88    /// floats: [w,x,y,z].
89    ///
90    /// ## `array`
91    /// An array of 4 floats w,(x,y,z)
92    pub fn init_from_array(&mut self, array: &[f32]) {
93        unsafe {
94            ffi::cogl_quaternion_init_from_array(self.to_glib_none_mut().0, array.as_ptr());
95        }
96    }
97
98    ///
99    /// ## `euler`
100    /// A `Euler` with which to initialize the quaternion
101    pub fn init_from_euler(&mut self, euler: &Euler) {
102        unsafe {
103            ffi::cogl_quaternion_init_from_euler(self.to_glib_none_mut().0, euler.to_glib_none().0);
104        }
105    }
106
107    /// Initializes a quaternion from a rotation matrix.
108    /// ## `matrix`
109    /// A rotation matrix with which to initialize the quaternion
110    pub fn init_from_matrix(&mut self, matrix: &Matrix) {
111        unsafe {
112            ffi::cogl_quaternion_init_from_matrix(
113                self.to_glib_none_mut().0,
114                matrix.to_glib_none().0,
115            );
116        }
117    }
118
119    ///
120    /// ## `src`
121    /// A `Quaternion` with which to initialize `self`
122    pub fn init_from_quaternion(&mut self, src: &mut Quaternion) {
123        unsafe {
124            ffi::cogl_quaternion_init_from_quaternion(
125                self.to_glib_none_mut().0,
126                src.to_glib_none_mut().0,
127            );
128        }
129    }
130
131    /// XXX: check which direction this rotates
132    ///
133    /// ## `angle`
134    /// The angle to rotate around the x axis
135    pub fn init_from_x_rotation(&mut self, angle: f32) {
136        unsafe {
137            ffi::cogl_quaternion_init_from_x_rotation(self.to_glib_none_mut().0, angle);
138        }
139    }
140
141    ///
142    /// ## `angle`
143    /// The angle to rotate around the y axis
144    pub fn init_from_y_rotation(&mut self, angle: f32) {
145        unsafe {
146            ffi::cogl_quaternion_init_from_y_rotation(self.to_glib_none_mut().0, angle);
147        }
148    }
149
150    ///
151    /// ## `angle`
152    /// The angle to rotate around the z axis
153    pub fn init_from_z_rotation(&mut self, angle: f32) {
154        unsafe {
155            ffi::cogl_quaternion_init_from_z_rotation(self.to_glib_none_mut().0, angle);
156        }
157    }
158
159    /// Initializes the quaternion with the canonical quaternion identity
160    /// [1 (0, 0, 0)] which represents no rotation. Multiplying a
161    /// quaternion with this identity leaves the quaternion unchanged.
162    ///
163    /// You might also want to consider using
164    /// `cogl_get_static_identity_quaternion`.
165    ///
166    pub fn init_identity(&mut self) {
167        unsafe {
168            ffi::cogl_quaternion_init_identity(self.to_glib_none_mut().0);
169        }
170    }
171
172    ///
173    pub fn invert(&mut self) {
174        unsafe {
175            ffi::cogl_quaternion_invert(self.to_glib_none_mut().0);
176        }
177    }
178
179    /// This combines the rotations of two quaternions into `self`. The
180    /// operation is not commutative so the order is important because AxB
181    /// != BxA. Cogl follows the standard convention for quaternions here
182    /// so the rotations are applied `right` to `left`. This is similar to the
183    /// combining of matrices.
184    ///
185    /// `<note>`It is possible to multiply the `a` quaternion in-place, so
186    /// `self` can be equal to `a` but can't be equal to `b`.`</note>`
187    ///
188    /// ## `left`
189    /// The second `Quaternion` rotation to apply
190    /// ## `right`
191    /// The first `Quaternion` rotation to apply
192    pub fn multiply(&mut self, left: &Quaternion, right: &Quaternion) {
193        unsafe {
194            ffi::cogl_quaternion_multiply(
195                self.to_glib_none_mut().0,
196                left.to_glib_none().0,
197                right.to_glib_none().0,
198            );
199        }
200    }
201
202    /// Performs a normalized linear interpolation between two quaternions.
203    /// That is it does a linear interpolation of the quaternion components
204    /// and then normalizes the result. This will follow the shortest arc
205    /// between the two orientations (just like the `slerp` function) but
206    /// will not progress at a constant speed. Unlike `slerp` nlerp is
207    /// commutative which is useful if you are blending animations
208    /// together. (I.e. nlerp (tmp, a, b) followed by nlerp (result, tmp,
209    /// d) is the same as nlerp (tmp, a, d) followed by nlerp (result, tmp,
210    /// b)). Finally nlerp is cheaper than slerp so it can be a good choice
211    /// if you don't need the constant speed property of the `slerp` function.
212    ///
213    /// Notable properties:
214    /// `<itemizedlist>`
215    /// `<listitem>`
216    /// commutative: Yes
217    /// `</listitem>`
218    /// `<listitem>`
219    /// constant velocity: No
220    /// `</listitem>`
221    /// `<listitem>`
222    /// torque minimal (travels along the surface of the 4-sphere): Yes
223    /// `</listitem>`
224    /// `<listitem>`
225    /// faster than `Quaternion::slerp`
226    /// `</listitem>`
227    /// `</itemizedlist>`
228    /// ## `a`
229    /// The first `Quaternion`
230    /// ## `b`
231    /// The second `Quaternion`
232    /// ## `t`
233    /// The factor in the range [0,1] used to interpolate between
234    /// quaterion `a` and `b`.
235    pub fn nlerp(&mut self, a: &Quaternion, b: &Quaternion, t: f32) {
236        unsafe {
237            ffi::cogl_quaternion_nlerp(
238                self.to_glib_none_mut().0,
239                a.to_glib_none().0,
240                b.to_glib_none().0,
241                t,
242            );
243        }
244    }
245
246    ///
247    pub fn normalize(&mut self) {
248        unsafe {
249            ffi::cogl_quaternion_normalize(self.to_glib_none_mut().0);
250        }
251    }
252
253    ///
254    /// ## `exponent`
255    /// the exponent
256    pub fn pow(&mut self, exponent: f32) {
257        unsafe {
258            ffi::cogl_quaternion_pow(self.to_glib_none_mut().0, exponent);
259        }
260    }
261
262    /// Performs a spherical linear interpolation between two quaternions.
263    ///
264    /// Noteable properties:
265    /// `<itemizedlist>`
266    /// `<listitem>`
267    /// commutative: No
268    /// `</listitem>`
269    /// `<listitem>`
270    /// constant velocity: Yes
271    /// `</listitem>`
272    /// `<listitem>`
273    /// torque minimal (travels along the surface of the 4-sphere): Yes
274    /// `</listitem>`
275    /// `<listitem>`
276    /// more expensive than `Quaternion::nlerp`
277    /// `</listitem>`
278    /// `</itemizedlist>`
279    /// ## `a`
280    /// The first `Quaternion`
281    /// ## `b`
282    /// The second `Quaternion`
283    /// ## `t`
284    /// The factor in the range [0,1] used to interpolate between
285    /// quaternion `a` and `b`.
286    pub fn slerp(&mut self, a: &Quaternion, b: &Quaternion, t: f32) {
287        unsafe {
288            ffi::cogl_quaternion_slerp(
289                self.to_glib_none_mut().0,
290                a.to_glib_none().0,
291                b.to_glib_none().0,
292                t,
293            );
294        }
295    }
296
297    ///
298    /// ## `prev`
299    /// A `Quaternion` used before `a`
300    /// ## `a`
301    /// The first `Quaternion`
302    /// ## `b`
303    /// The second `Quaternion`
304    /// ## `next`
305    /// A `Quaternion` that will be used after `b`
306    /// ## `t`
307    /// The factor in the range [0,1] used to interpolate between
308    /// quaternion `a` and `b`.
309    pub fn squad(
310        &mut self,
311        prev: &Quaternion,
312        a: &Quaternion,
313        b: &Quaternion,
314        next: &Quaternion,
315        t: f32,
316    ) {
317        unsafe {
318            ffi::cogl_quaternion_squad(
319                self.to_glib_none_mut().0,
320                prev.to_glib_none().0,
321                a.to_glib_none().0,
322                b.to_glib_none().0,
323                next.to_glib_none().0,
324                t,
325            );
326        }
327    }
328
329    fn equal(v1: &Self, v2: &Self) -> bool {
330        let a = Box_::into_raw(Box::new(v1)) as *mut _;
331        let b = Box_::into_raw(Box::new(v2)) as *mut _;
332        unsafe { ffi::cogl_quaternion_equal(a, b) == crate::TRUE }
333    }
334}
335
336impl PartialEq for Quaternion {
337    #[inline]
338    fn eq(&self, other: &Self) -> bool {
339        Quaternion::equal(self, other)
340    }
341}
342
343impl Eq for Quaternion {}