graphene/
quaternion.rs

1// Take a look at the license at the top of the repository in the LICENSE file.
2
3use std::{fmt, ops};
4
5use glib::translate::*;
6
7use crate::{ffi, Euler, Matrix, Quaternion, Vec3, Vec4};
8
9impl Quaternion {
10    /// Initializes a [`Quaternion`][crate::Quaternion] using the given four values.
11    /// ## `x`
12    /// the first component of the quaternion
13    /// ## `y`
14    /// the second component of the quaternion
15    /// ## `z`
16    /// the third component of the quaternion
17    /// ## `w`
18    /// the fourth component of the quaternion
19    ///
20    /// # Returns
21    ///
22    /// the initialized quaternion
23    #[doc(alias = "graphene_quaternion_init")]
24    pub fn new(x: f32, y: f32, z: f32, w: f32) -> Self {
25        assert_initialized_main_thread!();
26        unsafe {
27            let mut quat = Self::uninitialized();
28            ffi::graphene_quaternion_init(quat.to_glib_none_mut().0, x, y, z, w);
29            quat
30        }
31    }
32
33    /// Initializes a [`Quaternion`][crate::Quaternion] using an `angle` on a
34    /// specific `axis`.
35    /// ## `angle`
36    /// the rotation on a given axis, in degrees
37    /// ## `axis`
38    /// the axis of rotation, expressed as a vector
39    ///
40    /// # Returns
41    ///
42    /// the initialized quaternion
43    #[doc(alias = "graphene_quaternion_init_from_angle_vec3")]
44    #[doc(alias = "init_from_angle_vec3")]
45    pub fn from_angle_vec3(angle: f32, axis: &Vec3) -> Self {
46        assert_initialized_main_thread!();
47        unsafe {
48            let mut quat = Self::uninitialized();
49            ffi::graphene_quaternion_init_from_angle_vec3(
50                quat.to_glib_none_mut().0,
51                angle,
52                axis.to_glib_none().0,
53            );
54            quat
55        }
56    }
57
58    /// Initializes a [`Quaternion`][crate::Quaternion] using the values of
59    /// the [Euler angles](http://en.wikipedia.org/wiki/Euler_angles)
60    /// on each axis.
61    ///
62    /// See also: [`from_euler()`][Self::from_euler()]
63    /// ## `deg_x`
64    /// rotation angle on the X axis (yaw), in degrees
65    /// ## `deg_y`
66    /// rotation angle on the Y axis (pitch), in degrees
67    /// ## `deg_z`
68    /// rotation angle on the Z axis (roll), in degrees
69    ///
70    /// # Returns
71    ///
72    /// the initialized quaternion
73    #[doc(alias = "graphene_quaternion_init_from_angles")]
74    #[doc(alias = "init_from_angles")]
75    pub fn from_angles(deg_x: f32, deg_y: f32, deg_z: f32) -> Self {
76        assert_initialized_main_thread!();
77        unsafe {
78            let mut quat = Self::uninitialized();
79            ffi::graphene_quaternion_init_from_angles(
80                quat.to_glib_none_mut().0,
81                deg_x,
82                deg_y,
83                deg_z,
84            );
85            quat
86        }
87    }
88
89    /// Initializes a [`Quaternion`][crate::Quaternion] using the given [`Euler`][crate::Euler].
90    /// ## `e`
91    /// a [`Euler`][crate::Euler]
92    ///
93    /// # Returns
94    ///
95    /// the initialized [`Quaternion`][crate::Quaternion]
96    #[doc(alias = "graphene_quaternion_init_from_euler")]
97    #[doc(alias = "init_from_euler")]
98    pub fn from_euler(e: &Euler) -> Self {
99        assert_initialized_main_thread!();
100        unsafe {
101            let mut quat = Self::uninitialized();
102            ffi::graphene_quaternion_init_from_euler(quat.to_glib_none_mut().0, e.to_glib_none().0);
103            quat
104        }
105    }
106
107    /// Initializes a [`Quaternion`][crate::Quaternion] using the rotation components
108    /// of a transformation matrix.
109    /// ## `m`
110    /// a [`Matrix`][crate::Matrix]
111    ///
112    /// # Returns
113    ///
114    /// the initialized quaternion
115    #[doc(alias = "graphene_quaternion_init_from_matrix")]
116    #[doc(alias = "init_from_matrix")]
117    pub fn from_matrix(m: &Matrix) -> Self {
118        assert_initialized_main_thread!();
119        unsafe {
120            let mut quat = Self::uninitialized();
121            ffi::graphene_quaternion_init_from_matrix(
122                quat.to_glib_none_mut().0,
123                m.to_glib_none().0,
124            );
125            quat
126        }
127    }
128
129    /// Initializes a [`Quaternion`][crate::Quaternion] using the values of
130    /// the [Euler angles](http://en.wikipedia.org/wiki/Euler_angles)
131    /// on each axis.
132    ///
133    /// See also: [`from_euler()`][Self::from_euler()]
134    /// ## `rad_x`
135    /// rotation angle on the X axis (yaw), in radians
136    /// ## `rad_y`
137    /// rotation angle on the Y axis (pitch), in radians
138    /// ## `rad_z`
139    /// rotation angle on the Z axis (roll), in radians
140    ///
141    /// # Returns
142    ///
143    /// the initialized quaternion
144    #[doc(alias = "graphene_quaternion_init_from_radians")]
145    #[doc(alias = "init_from_radians")]
146    pub fn from_radians(rad_x: f32, rad_y: f32, rad_z: f32) -> Self {
147        assert_initialized_main_thread!();
148        unsafe {
149            let mut quat = Self::uninitialized();
150            ffi::graphene_quaternion_init_from_radians(
151                quat.to_glib_none_mut().0,
152                rad_x,
153                rad_y,
154                rad_z,
155            );
156            quat
157        }
158    }
159
160    /// Initializes a [`Quaternion`][crate::Quaternion] with the values from `src`.
161    /// ## `src`
162    /// a [`Vec4`][crate::Vec4]
163    ///
164    /// # Returns
165    ///
166    /// the initialized quaternion
167    #[doc(alias = "graphene_quaternion_init_from_vec4")]
168    #[doc(alias = "init_from_vec4")]
169    pub fn from_vec4(src: &Vec4) -> Self {
170        assert_initialized_main_thread!();
171        unsafe {
172            let mut quat = Self::uninitialized();
173            ffi::graphene_quaternion_init_from_vec4(
174                quat.to_glib_none_mut().0,
175                src.to_glib_none().0,
176            );
177            quat
178        }
179    }
180
181    /// Initializes a [`Quaternion`][crate::Quaternion] using the identity
182    /// transformation.
183    ///
184    /// # Returns
185    ///
186    /// the initialized quaternion
187    #[doc(alias = "graphene_quaternion_init_identity")]
188    #[doc(alias = "init_identity")]
189    pub fn new_identity() -> Self {
190        assert_initialized_main_thread!();
191        unsafe {
192            let mut quat = Self::uninitialized();
193            ffi::graphene_quaternion_init_identity(quat.to_glib_none_mut().0);
194            quat
195        }
196    }
197
198    #[inline]
199    pub fn x(&self) -> f32 {
200        self.inner.x
201    }
202
203    #[inline]
204    pub fn y(&self) -> f32 {
205        self.inner.y
206    }
207
208    #[inline]
209    pub fn z(&self) -> f32 {
210        self.inner.z
211    }
212
213    #[inline]
214    pub fn w(&self) -> f32 {
215        self.inner.w
216    }
217}
218
219impl fmt::Debug for Quaternion {
220    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
221        f.debug_struct("Quaternion")
222            .field("x", &self.x())
223            .field("y", &self.y())
224            .field("z", &self.z())
225            .field("w", &self.w())
226            .finish()
227    }
228}
229
230impl ops::Add<Quaternion> for Quaternion {
231    type Output = Quaternion;
232
233    fn add(self, rhs: Quaternion) -> Self::Output {
234        Quaternion::add(&self, &rhs)
235    }
236}
237
238impl ops::AddAssign<Quaternion> for Quaternion {
239    fn add_assign(&mut self, rhs: Quaternion) {
240        *self = *self + rhs;
241    }
242}
243
244impl ops::Mul<Quaternion> for Quaternion {
245    type Output = Quaternion;
246
247    fn mul(self, rhs: Quaternion) -> Self::Output {
248        Quaternion::multiply(&self, &rhs)
249    }
250}
251
252impl ops::MulAssign<Quaternion> for Quaternion {
253    fn mul_assign(&mut self, rhs: Quaternion) {
254        *self = *self * rhs;
255    }
256}