glam/f32/sse2/
quat.rs

1// Generated from quat.rs.tera template. Edit the template, not the generated file.
2
3use crate::{
4    euler::{EulerRot, FromEuler, ToEuler},
5    f32::math,
6    sse2::*,
7    DQuat, Mat3, Mat3A, Mat4, Vec2, Vec3, Vec3A, Vec4,
8};
9
10#[cfg(target_arch = "x86")]
11use core::arch::x86::*;
12#[cfg(target_arch = "x86_64")]
13use core::arch::x86_64::*;
14
15use core::fmt;
16use core::iter::{Product, Sum};
17use core::ops::{
18    Add, AddAssign, Deref, DerefMut, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign,
19};
20
21#[repr(C)]
22union UnionCast {
23    a: [f32; 4],
24    v: Quat,
25}
26
27/// Creates a quaternion from `x`, `y`, `z` and `w` values.
28///
29/// This should generally not be called manually unless you know what you are doing. Use
30/// one of the other constructors instead such as `identity` or `from_axis_angle`.
31#[inline]
32#[must_use]
33pub const fn quat(x: f32, y: f32, z: f32, w: f32) -> Quat {
34    Quat::from_xyzw(x, y, z, w)
35}
36
37/// A quaternion representing an orientation.
38///
39/// This quaternion is intended to be of unit length but may denormalize due to
40/// floating point "error creep" which can occur when successive quaternion
41/// operations are applied.
42///
43/// SIMD vector types are used for storage on supported platforms.
44///
45/// This type is 16 byte aligned.
46#[derive(Clone, Copy)]
47#[cfg_attr(feature = "bytemuck", derive(bytemuck::Pod, bytemuck::Zeroable))]
48#[repr(transparent)]
49pub struct Quat(pub(crate) __m128);
50
51impl Quat {
52    /// All zeros.
53    const ZERO: Self = Self::from_array([0.0; 4]);
54
55    /// The identity quaternion. Corresponds to no rotation.
56    pub const IDENTITY: Self = Self::from_xyzw(0.0, 0.0, 0.0, 1.0);
57
58    /// All NANs.
59    pub const NAN: Self = Self::from_array([f32::NAN; 4]);
60
61    /// Creates a new rotation quaternion.
62    ///
63    /// This should generally not be called manually unless you know what you are doing.
64    /// Use one of the other constructors instead such as `identity` or `from_axis_angle`.
65    ///
66    /// `from_xyzw` is mostly used by unit tests and `serde` deserialization.
67    ///
68    /// # Preconditions
69    ///
70    /// This function does not check if the input is normalized, it is up to the user to
71    /// provide normalized input or to normalized the resulting quaternion.
72    #[inline(always)]
73    #[must_use]
74    pub const fn from_xyzw(x: f32, y: f32, z: f32, w: f32) -> Self {
75        unsafe { UnionCast { a: [x, y, z, w] }.v }
76    }
77
78    /// Creates a rotation quaternion from an array.
79    ///
80    /// # Preconditions
81    ///
82    /// This function does not check if the input is normalized, it is up to the user to
83    /// provide normalized input or to normalized the resulting quaternion.
84    #[inline]
85    #[must_use]
86    pub const fn from_array(a: [f32; 4]) -> Self {
87        Self::from_xyzw(a[0], a[1], a[2], a[3])
88    }
89
90    /// Creates a new rotation quaternion from a 4D vector.
91    ///
92    /// # Preconditions
93    ///
94    /// This function does not check if the input is normalized, it is up to the user to
95    /// provide normalized input or to normalized the resulting quaternion.
96    #[inline]
97    #[must_use]
98    pub const fn from_vec4(v: Vec4) -> Self {
99        Self(v.0)
100    }
101
102    /// Creates a rotation quaternion from a slice.
103    ///
104    /// # Preconditions
105    ///
106    /// This function does not check if the input is normalized, it is up to the user to
107    /// provide normalized input or to normalized the resulting quaternion.
108    ///
109    /// # Panics
110    ///
111    /// Panics if `slice` length is less than 4.
112    #[inline]
113    #[must_use]
114    pub fn from_slice(slice: &[f32]) -> Self {
115        assert!(slice.len() >= 4);
116        Self(unsafe { _mm_loadu_ps(slice.as_ptr()) })
117    }
118
119    /// Writes the quaternion to an unaligned slice.
120    ///
121    /// # Panics
122    ///
123    /// Panics if `slice` length is less than 4.
124    #[inline]
125    pub fn write_to_slice(self, slice: &mut [f32]) {
126        assert!(slice.len() >= 4);
127        unsafe { _mm_storeu_ps(slice.as_mut_ptr(), self.0) }
128    }
129
130    /// Create a quaternion for a normalized rotation `axis` and `angle` (in radians).
131    ///
132    /// The axis must be a unit vector.
133    ///
134    /// # Panics
135    ///
136    /// Will panic if `axis` is not normalized when `glam_assert` is enabled.
137    #[inline]
138    #[must_use]
139    pub fn from_axis_angle(axis: Vec3, angle: f32) -> Self {
140        glam_assert!(axis.is_normalized());
141        let (s, c) = math::sin_cos(angle * 0.5);
142        let v = axis * s;
143        Self::from_xyzw(v.x, v.y, v.z, c)
144    }
145
146    /// Create a quaternion that rotates `v.length()` radians around `v.normalize()`.
147    ///
148    /// `from_scaled_axis(Vec3::ZERO)` results in the identity quaternion.
149    #[inline]
150    #[must_use]
151    pub fn from_scaled_axis(v: Vec3) -> Self {
152        let length = v.length();
153        if length == 0.0 {
154            Self::IDENTITY
155        } else {
156            Self::from_axis_angle(v / length, length)
157        }
158    }
159
160    /// Creates a quaternion from the `angle` (in radians) around the x axis.
161    #[inline]
162    #[must_use]
163    pub fn from_rotation_x(angle: f32) -> Self {
164        let (s, c) = math::sin_cos(angle * 0.5);
165        Self::from_xyzw(s, 0.0, 0.0, c)
166    }
167
168    /// Creates a quaternion from the `angle` (in radians) around the y axis.
169    #[inline]
170    #[must_use]
171    pub fn from_rotation_y(angle: f32) -> Self {
172        let (s, c) = math::sin_cos(angle * 0.5);
173        Self::from_xyzw(0.0, s, 0.0, c)
174    }
175
176    /// Creates a quaternion from the `angle` (in radians) around the z axis.
177    #[inline]
178    #[must_use]
179    pub fn from_rotation_z(angle: f32) -> Self {
180        let (s, c) = math::sin_cos(angle * 0.5);
181        Self::from_xyzw(0.0, 0.0, s, c)
182    }
183
184    /// Creates a quaternion from the given Euler rotation sequence and the angles (in radians).
185    #[inline]
186    #[must_use]
187    pub fn from_euler(euler: EulerRot, a: f32, b: f32, c: f32) -> Self {
188        Self::from_euler_angles(euler, a, b, c)
189    }
190
191    /// From the columns of a 3x3 rotation matrix.
192    ///
193    /// Note if the input axes contain scales, shears, or other non-rotation transformations then
194    /// the output of this function is ill-defined.
195    ///
196    /// # Panics
197    ///
198    /// Will panic if any axis is not normalized when `glam_assert` is enabled.
199    #[inline]
200    #[must_use]
201    pub(crate) fn from_rotation_axes(x_axis: Vec3, y_axis: Vec3, z_axis: Vec3) -> Self {
202        glam_assert!(x_axis.is_normalized() && y_axis.is_normalized() && z_axis.is_normalized());
203        // Based on https://github.com/microsoft/DirectXMath `XMQuaternionRotationMatrix`
204        let (m00, m01, m02) = x_axis.into();
205        let (m10, m11, m12) = y_axis.into();
206        let (m20, m21, m22) = z_axis.into();
207        if m22 <= 0.0 {
208            // x^2 + y^2 >= z^2 + w^2
209            let dif10 = m11 - m00;
210            let omm22 = 1.0 - m22;
211            if dif10 <= 0.0 {
212                // x^2 >= y^2
213                let four_xsq = omm22 - dif10;
214                let inv4x = 0.5 / math::sqrt(four_xsq);
215                Self::from_xyzw(
216                    four_xsq * inv4x,
217                    (m01 + m10) * inv4x,
218                    (m02 + m20) * inv4x,
219                    (m12 - m21) * inv4x,
220                )
221            } else {
222                // y^2 >= x^2
223                let four_ysq = omm22 + dif10;
224                let inv4y = 0.5 / math::sqrt(four_ysq);
225                Self::from_xyzw(
226                    (m01 + m10) * inv4y,
227                    four_ysq * inv4y,
228                    (m12 + m21) * inv4y,
229                    (m20 - m02) * inv4y,
230                )
231            }
232        } else {
233            // z^2 + w^2 >= x^2 + y^2
234            let sum10 = m11 + m00;
235            let opm22 = 1.0 + m22;
236            if sum10 <= 0.0 {
237                // z^2 >= w^2
238                let four_zsq = opm22 - sum10;
239                let inv4z = 0.5 / math::sqrt(four_zsq);
240                Self::from_xyzw(
241                    (m02 + m20) * inv4z,
242                    (m12 + m21) * inv4z,
243                    four_zsq * inv4z,
244                    (m01 - m10) * inv4z,
245                )
246            } else {
247                // w^2 >= z^2
248                let four_wsq = opm22 + sum10;
249                let inv4w = 0.5 / math::sqrt(four_wsq);
250                Self::from_xyzw(
251                    (m12 - m21) * inv4w,
252                    (m20 - m02) * inv4w,
253                    (m01 - m10) * inv4w,
254                    four_wsq * inv4w,
255                )
256            }
257        }
258    }
259
260    /// Creates a quaternion from a 3x3 rotation matrix.
261    ///
262    /// Note if the input matrix contain scales, shears, or other non-rotation transformations then
263    /// the resulting quaternion will be ill-defined.
264    ///
265    /// # Panics
266    ///
267    /// Will panic if any input matrix column is not normalized when `glam_assert` is enabled.
268    #[inline]
269    #[must_use]
270    pub fn from_mat3(mat: &Mat3) -> Self {
271        Self::from_rotation_axes(mat.x_axis, mat.y_axis, mat.z_axis)
272    }
273
274    /// Creates a quaternion from a 3x3 SIMD aligned rotation matrix.
275    ///
276    /// Note if the input matrix contain scales, shears, or other non-rotation transformations then
277    /// the resulting quaternion will be ill-defined.
278    ///
279    /// # Panics
280    ///
281    /// Will panic if any input matrix column is not normalized when `glam_assert` is enabled.
282    #[inline]
283    #[must_use]
284    pub fn from_mat3a(mat: &Mat3A) -> Self {
285        Self::from_rotation_axes(mat.x_axis.into(), mat.y_axis.into(), mat.z_axis.into())
286    }
287
288    /// Creates a quaternion from the upper 3x3 rotation matrix inside a homogeneous 4x4 matrix.
289    ///
290    /// Note if the upper 3x3 matrix contain scales, shears, or other non-rotation transformations
291    /// then the resulting quaternion will be ill-defined.
292    ///
293    /// # Panics
294    ///
295    /// Will panic if any column of the upper 3x3 rotation matrix is not normalized when
296    /// `glam_assert` is enabled.
297    #[inline]
298    #[must_use]
299    pub fn from_mat4(mat: &Mat4) -> Self {
300        Self::from_rotation_axes(
301            mat.x_axis.truncate(),
302            mat.y_axis.truncate(),
303            mat.z_axis.truncate(),
304        )
305    }
306
307    /// Gets the minimal rotation for transforming `from` to `to`.  The rotation is in the
308    /// plane spanned by the two vectors.  Will rotate at most 180 degrees.
309    ///
310    /// The inputs must be unit vectors.
311    ///
312    /// `from_rotation_arc(from, to) * from ≈ to`.
313    ///
314    /// For near-singular cases (from≈to and from≈-to) the current implementation
315    /// is only accurate to about 0.001 (for `f32`).
316    ///
317    /// # Panics
318    ///
319    /// Will panic if `from` or `to` are not normalized when `glam_assert` is enabled.
320    #[must_use]
321    pub fn from_rotation_arc(from: Vec3, to: Vec3) -> Self {
322        glam_assert!(from.is_normalized());
323        glam_assert!(to.is_normalized());
324
325        const ONE_MINUS_EPS: f32 = 1.0 - 2.0 * f32::EPSILON;
326        let dot = from.dot(to);
327        if dot > ONE_MINUS_EPS {
328            // 0° singularity: from ≈ to
329            Self::IDENTITY
330        } else if dot < -ONE_MINUS_EPS {
331            // 180° singularity: from ≈ -to
332            use core::f32::consts::PI; // half a turn = 𝛕/2 = 180°
333            Self::from_axis_angle(from.any_orthonormal_vector(), PI)
334        } else {
335            let c = from.cross(to);
336            Self::from_xyzw(c.x, c.y, c.z, 1.0 + dot).normalize()
337        }
338    }
339
340    /// Gets the minimal rotation for transforming `from` to either `to` or `-to`.  This means
341    /// that the resulting quaternion will rotate `from` so that it is colinear with `to`.
342    ///
343    /// The rotation is in the plane spanned by the two vectors.  Will rotate at most 90
344    /// degrees.
345    ///
346    /// The inputs must be unit vectors.
347    ///
348    /// `to.dot(from_rotation_arc_colinear(from, to) * from).abs() ≈ 1`.
349    ///
350    /// # Panics
351    ///
352    /// Will panic if `from` or `to` are not normalized when `glam_assert` is enabled.
353    #[inline]
354    #[must_use]
355    pub fn from_rotation_arc_colinear(from: Vec3, to: Vec3) -> Self {
356        if from.dot(to) < 0.0 {
357            Self::from_rotation_arc(from, -to)
358        } else {
359            Self::from_rotation_arc(from, to)
360        }
361    }
362
363    /// Gets the minimal rotation for transforming `from` to `to`.  The resulting rotation is
364    /// around the z axis. Will rotate at most 180 degrees.
365    ///
366    /// The inputs must be unit vectors.
367    ///
368    /// `from_rotation_arc_2d(from, to) * from ≈ to`.
369    ///
370    /// For near-singular cases (from≈to and from≈-to) the current implementation
371    /// is only accurate to about 0.001 (for `f32`).
372    ///
373    /// # Panics
374    ///
375    /// Will panic if `from` or `to` are not normalized when `glam_assert` is enabled.
376    #[must_use]
377    pub fn from_rotation_arc_2d(from: Vec2, to: Vec2) -> Self {
378        glam_assert!(from.is_normalized());
379        glam_assert!(to.is_normalized());
380
381        const ONE_MINUS_EPSILON: f32 = 1.0 - 2.0 * f32::EPSILON;
382        let dot = from.dot(to);
383        if dot > ONE_MINUS_EPSILON {
384            // 0° singularity: from ≈ to
385            Self::IDENTITY
386        } else if dot < -ONE_MINUS_EPSILON {
387            // 180° singularity: from ≈ -to
388            const COS_FRAC_PI_2: f32 = 0.0;
389            const SIN_FRAC_PI_2: f32 = 1.0;
390            // rotation around z by PI radians
391            Self::from_xyzw(0.0, 0.0, SIN_FRAC_PI_2, COS_FRAC_PI_2)
392        } else {
393            // vector3 cross where z=0
394            let z = from.x * to.y - to.x * from.y;
395            let w = 1.0 + dot;
396            // calculate length with x=0 and y=0 to normalize
397            let len_rcp = 1.0 / math::sqrt(z * z + w * w);
398            Self::from_xyzw(0.0, 0.0, z * len_rcp, w * len_rcp)
399        }
400    }
401
402    /// Creates a quaterion rotation from a facing direction and an up direction.
403    ///
404    /// For a left-handed view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`.
405    ///
406    /// # Panics
407    ///
408    /// Will panic if `up` is not normalized when `glam_assert` is enabled.
409    #[inline]
410    #[must_use]
411    pub fn look_to_lh(dir: Vec3, up: Vec3) -> Self {
412        Self::look_to_rh(-dir, up)
413    }
414
415    /// Creates a quaterion rotation from facing direction and an up direction.
416    ///
417    /// For a right-handed view coordinate system with `+X=right`, `+Y=up` and `+Z=back`.
418    ///
419    /// # Panics
420    ///
421    /// Will panic if `dir` and `up` are not normalized when `glam_assert` is enabled.
422    #[inline]
423    #[must_use]
424    pub fn look_to_rh(dir: Vec3, up: Vec3) -> Self {
425        glam_assert!(dir.is_normalized());
426        glam_assert!(up.is_normalized());
427        let f = dir;
428        let s = f.cross(up).normalize();
429        let u = s.cross(f);
430
431        Self::from_rotation_axes(
432            Vec3::new(s.x, u.x, -f.x),
433            Vec3::new(s.y, u.y, -f.y),
434            Vec3::new(s.z, u.z, -f.z),
435        )
436    }
437
438    /// Creates a left-handed view matrix using a camera position, a focal point, and an up
439    /// direction.
440    ///
441    /// For a left-handed view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`.
442    ///
443    /// # Panics
444    ///
445    /// Will panic if `up` is not normalized when `glam_assert` is enabled.
446    #[inline]
447    #[must_use]
448    pub fn look_at_lh(eye: Vec3, center: Vec3, up: Vec3) -> Self {
449        Self::look_to_lh(center.sub(eye).normalize(), up)
450    }
451
452    /// Creates a right-handed view matrix using a camera position, an up direction, and a focal
453    /// point.
454    ///
455    /// For a right-handed view coordinate system with `+X=right`, `+Y=up` and `+Z=back`.
456    ///
457    /// # Panics
458    ///
459    /// Will panic if `up` is not normalized when `glam_assert` is enabled.
460    #[inline]
461    #[must_use]
462    pub fn look_at_rh(eye: Vec3, center: Vec3, up: Vec3) -> Self {
463        Self::look_to_rh(center.sub(eye).normalize(), up)
464    }
465
466    /// Returns the rotation axis (normalized) and angle (in radians) of `self`.
467    #[inline]
468    #[must_use]
469    pub fn to_axis_angle(self) -> (Vec3, f32) {
470        const EPSILON: f32 = 1.0e-8;
471        let v = Vec3::new(self.x, self.y, self.z);
472        let length = v.length();
473        if length >= EPSILON {
474            let angle = 2.0 * math::atan2(length, self.w);
475            let axis = v / length;
476            (axis, angle)
477        } else {
478            (Vec3::X, 0.0)
479        }
480    }
481
482    /// Returns the rotation axis scaled by the rotation in radians.
483    #[inline]
484    #[must_use]
485    pub fn to_scaled_axis(self) -> Vec3 {
486        let (axis, angle) = self.to_axis_angle();
487        axis * angle
488    }
489
490    /// Returns the rotation angles for the given euler rotation sequence.
491    #[inline]
492    #[must_use]
493    pub fn to_euler(self, order: EulerRot) -> (f32, f32, f32) {
494        self.to_euler_angles(order)
495    }
496
497    /// `[x, y, z, w]`
498    #[inline]
499    #[must_use]
500    pub fn to_array(&self) -> [f32; 4] {
501        [self.x, self.y, self.z, self.w]
502    }
503
504    /// Returns the vector part of the quaternion.
505    #[inline]
506    #[must_use]
507    pub fn xyz(self) -> Vec3 {
508        Vec3::new(self.x, self.y, self.z)
509    }
510
511    /// Returns the quaternion conjugate of `self`. For a unit quaternion the
512    /// conjugate is also the inverse.
513    #[inline]
514    #[must_use]
515    pub fn conjugate(self) -> Self {
516        const SIGN: __m128 = m128_from_f32x4([-0.0, -0.0, -0.0, 0.0]);
517        Self(unsafe { _mm_xor_ps(self.0, SIGN) })
518    }
519
520    /// Returns the inverse of a normalized quaternion.
521    ///
522    /// Typically quaternion inverse returns the conjugate of a normalized quaternion.
523    /// Because `self` is assumed to already be unit length this method *does not* normalize
524    /// before returning the conjugate.
525    ///
526    /// # Panics
527    ///
528    /// Will panic if `self` is not normalized when `glam_assert` is enabled.
529    #[inline]
530    #[must_use]
531    pub fn inverse(self) -> Self {
532        glam_assert!(self.is_normalized());
533        self.conjugate()
534    }
535
536    /// Computes the dot product of `self` and `rhs`. The dot product is
537    /// equal to the cosine of the angle between two quaternion rotations.
538    #[inline]
539    #[must_use]
540    pub fn dot(self, rhs: Self) -> f32 {
541        Vec4::from(self).dot(Vec4::from(rhs))
542    }
543
544    /// Computes the length of `self`.
545    #[doc(alias = "magnitude")]
546    #[inline]
547    #[must_use]
548    pub fn length(self) -> f32 {
549        Vec4::from(self).length()
550    }
551
552    /// Computes the squared length of `self`.
553    ///
554    /// This is generally faster than `length()` as it avoids a square
555    /// root operation.
556    #[doc(alias = "magnitude2")]
557    #[inline]
558    #[must_use]
559    pub fn length_squared(self) -> f32 {
560        Vec4::from(self).length_squared()
561    }
562
563    /// Computes `1.0 / length()`.
564    ///
565    /// For valid results, `self` must _not_ be of length zero.
566    #[inline]
567    #[must_use]
568    pub fn length_recip(self) -> f32 {
569        Vec4::from(self).length_recip()
570    }
571
572    /// Returns `self` normalized to length 1.0.
573    ///
574    /// For valid results, `self` must _not_ be of length zero.
575    ///
576    /// Panics
577    ///
578    /// Will panic if `self` is zero length when `glam_assert` is enabled.
579    #[inline]
580    #[must_use]
581    pub fn normalize(self) -> Self {
582        Self::from_vec4(Vec4::from(self).normalize())
583    }
584
585    /// Returns `true` if, and only if, all elements are finite.
586    /// If any element is either `NaN`, positive or negative infinity, this will return `false`.
587    #[inline]
588    #[must_use]
589    pub fn is_finite(self) -> bool {
590        Vec4::from(self).is_finite()
591    }
592
593    /// Returns `true` if any elements are `NAN`.
594    #[inline]
595    #[must_use]
596    pub fn is_nan(self) -> bool {
597        Vec4::from(self).is_nan()
598    }
599
600    /// Returns whether `self` of length `1.0` or not.
601    ///
602    /// Uses a precision threshold of `1e-6`.
603    #[inline]
604    #[must_use]
605    pub fn is_normalized(self) -> bool {
606        Vec4::from(self).is_normalized()
607    }
608
609    #[inline]
610    #[must_use]
611    pub fn is_near_identity(self) -> bool {
612        // Based on https://github.com/nfrechette/rtm `rtm::quat_near_identity`
613        let threshold_angle = 0.002_847_144_6;
614        // Because of floating point precision, we cannot represent very small rotations.
615        // The closest f32 to 1.0 that is not 1.0 itself yields:
616        // 0.99999994.acos() * 2.0  = 0.000690533954 rad
617        //
618        // An error threshold of 1.e-6 is used by default.
619        // (1.0 - 1.e-6).acos() * 2.0 = 0.00284714461 rad
620        // (1.0 - 1.e-7).acos() * 2.0 = 0.00097656250 rad
621        //
622        // We don't really care about the angle value itself, only if it's close to 0.
623        // This will happen whenever quat.w is close to 1.0.
624        // If the quat.w is close to -1.0, the angle will be near 2*PI which is close to
625        // a negative 0 rotation. By forcing quat.w to be positive, we'll end up with
626        // the shortest path.
627        let positive_w_angle = math::acos_approx(math::abs(self.w)) * 2.0;
628        positive_w_angle < threshold_angle
629    }
630
631    /// Returns the angle (in radians) for the minimal rotation
632    /// for transforming this quaternion into another.
633    ///
634    /// Both quaternions must be normalized.
635    ///
636    /// # Panics
637    ///
638    /// Will panic if `self` or `rhs` are not normalized when `glam_assert` is enabled.
639    #[inline]
640    #[must_use]
641    pub fn angle_between(self, rhs: Self) -> f32 {
642        glam_assert!(self.is_normalized() && rhs.is_normalized());
643        math::acos_approx(math::abs(self.dot(rhs))) * 2.0
644    }
645
646    /// Rotates towards `rhs` up to `max_angle` (in radians).
647    ///
648    /// When `max_angle` is `0.0`, the result will be equal to `self`. When `max_angle` is equal to
649    /// `self.angle_between(rhs)`, the result will be equal to `rhs`. If `max_angle` is negative,
650    /// rotates towards the exact opposite of `rhs`. Will not go past the target.
651    ///
652    /// Both quaternions must be normalized.
653    ///
654    /// # Panics
655    ///
656    /// Will panic if `self` or `rhs` are not normalized when `glam_assert` is enabled.
657    #[inline]
658    #[must_use]
659    pub fn rotate_towards(&self, rhs: Self, max_angle: f32) -> Self {
660        glam_assert!(self.is_normalized() && rhs.is_normalized());
661        let angle = self.angle_between(rhs);
662        if angle <= 1e-4 {
663            return rhs;
664        }
665        let s = (max_angle / angle).clamp(-1.0, 1.0);
666        self.slerp(rhs, s)
667    }
668
669    /// Returns true if the absolute difference of all elements between `self` and `rhs`
670    /// is less than or equal to `max_abs_diff`.
671    ///
672    /// This can be used to compare if two quaternions contain similar elements. It works
673    /// best when comparing with a known value. The `max_abs_diff` that should be used used
674    /// depends on the values being compared against.
675    ///
676    /// For more see
677    /// [comparing floating point numbers](https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/).
678    #[inline]
679    #[must_use]
680    pub fn abs_diff_eq(self, rhs: Self, max_abs_diff: f32) -> bool {
681        Vec4::from(self).abs_diff_eq(Vec4::from(rhs), max_abs_diff)
682    }
683
684    #[inline(always)]
685    #[must_use]
686    fn lerp_impl(self, end: Self, s: f32) -> Self {
687        (self * (1.0 - s) + end * s).normalize()
688    }
689
690    /// Performs a linear interpolation between `self` and `rhs` based on
691    /// the value `s`.
692    ///
693    /// When `s` is `0.0`, the result will be equal to `self`.  When `s`
694    /// is `1.0`, the result will be equal to `rhs`.
695    ///
696    /// # Panics
697    ///
698    /// Will panic if `self` or `end` are not normalized when `glam_assert` is enabled.
699    #[doc(alias = "mix")]
700    #[inline]
701    #[must_use]
702    pub fn lerp(self, end: Self, s: f32) -> Self {
703        glam_assert!(self.is_normalized());
704        glam_assert!(end.is_normalized());
705
706        const NEG_ZERO: __m128 = m128_from_f32x4([-0.0; 4]);
707        unsafe {
708            let dot = dot4_into_m128(self.0, end.0);
709            // Calculate the bias, if the dot product is positive or zero, there is no bias
710            // but if it is negative, we want to flip the 'end' rotation XYZW components
711            let bias = _mm_and_ps(dot, NEG_ZERO);
712            self.lerp_impl(Self(_mm_xor_ps(end.0, bias)), s)
713        }
714    }
715
716    /// Performs a spherical linear interpolation between `self` and `end`
717    /// based on the value `s`.
718    ///
719    /// When `s` is `0.0`, the result will be equal to `self`.  When `s`
720    /// is `1.0`, the result will be equal to `end`.
721    ///
722    /// # Panics
723    ///
724    /// Will panic if `self` or `end` are not normalized when `glam_assert` is enabled.
725    #[inline]
726    #[must_use]
727    pub fn slerp(self, mut end: Self, s: f32) -> Self {
728        // http://number-none.com/product/Understanding%20Slerp,%20Then%20Not%20Using%20It/
729        glam_assert!(self.is_normalized());
730        glam_assert!(end.is_normalized());
731
732        // Note that a rotation can be represented by two quaternions: `q` and
733        // `-q`. The slerp path between `q` and `end` will be different from the
734        // path between `-q` and `end`. One path will take the long way around and
735        // one will take the short way. In order to correct for this, the `dot`
736        // product between `self` and `end` should be positive. If the `dot`
737        // product is negative, slerp between `self` and `-end`.
738        let mut dot = self.dot(end);
739        if dot < 0.0 {
740            end = -end;
741            dot = -dot;
742        }
743
744        const DOT_THRESHOLD: f32 = 1.0 - f32::EPSILON;
745        if dot > DOT_THRESHOLD {
746            // if above threshold perform linear interpolation to avoid divide by zero
747            self.lerp_impl(end, s)
748        } else {
749            let theta = math::acos_approx(dot);
750
751            let x = 1.0 - s;
752            let y = s;
753            let z = 1.0;
754
755            unsafe {
756                let tmp = _mm_mul_ps(_mm_set_ps1(theta), _mm_set_ps(0.0, z, y, x));
757                let tmp = m128_sin(tmp);
758
759                let scale1 = _mm_shuffle_ps(tmp, tmp, 0b00_00_00_00);
760                let scale2 = _mm_shuffle_ps(tmp, tmp, 0b01_01_01_01);
761                let theta_sin = _mm_shuffle_ps(tmp, tmp, 0b10_10_10_10);
762
763                Self(_mm_div_ps(
764                    _mm_add_ps(_mm_mul_ps(self.0, scale1), _mm_mul_ps(end.0, scale2)),
765                    theta_sin,
766                ))
767            }
768        }
769    }
770
771    /// Multiplies a quaternion and a 3D vector, returning the rotated vector.
772    ///
773    /// # Panics
774    ///
775    /// Will panic if `self` is not normalized when `glam_assert` is enabled.
776    #[inline]
777    #[must_use]
778    pub fn mul_vec3(self, rhs: Vec3) -> Vec3 {
779        glam_assert!(self.is_normalized());
780
781        self.mul_vec3a(rhs.into()).into()
782    }
783
784    /// Multiplies two quaternions. If they each represent a rotation, the result will
785    /// represent the combined rotation.
786    ///
787    /// Note that due to floating point rounding the result may not be perfectly normalized.
788    ///
789    /// # Panics
790    ///
791    /// Will panic if `self` or `rhs` are not normalized when `glam_assert` is enabled.
792    #[inline]
793    #[must_use]
794    pub fn mul_quat(self, rhs: Self) -> Self {
795        // Based on https://github.com/nfrechette/rtm `rtm::quat_mul`
796        const CONTROL_WZYX: __m128 = m128_from_f32x4([1.0, -1.0, 1.0, -1.0]);
797        const CONTROL_ZWXY: __m128 = m128_from_f32x4([1.0, 1.0, -1.0, -1.0]);
798        const CONTROL_YXWZ: __m128 = m128_from_f32x4([-1.0, 1.0, 1.0, -1.0]);
799
800        let lhs = self.0;
801        let rhs = rhs.0;
802
803        unsafe {
804            let r_xxxx = _mm_shuffle_ps(lhs, lhs, 0b00_00_00_00);
805            let r_yyyy = _mm_shuffle_ps(lhs, lhs, 0b01_01_01_01);
806            let r_zzzz = _mm_shuffle_ps(lhs, lhs, 0b10_10_10_10);
807            let r_wwww = _mm_shuffle_ps(lhs, lhs, 0b11_11_11_11);
808
809            let lxrw_lyrw_lzrw_lwrw = _mm_mul_ps(r_wwww, rhs);
810            let l_wzyx = _mm_shuffle_ps(rhs, rhs, 0b00_01_10_11);
811
812            let lwrx_lzrx_lyrx_lxrx = _mm_mul_ps(r_xxxx, l_wzyx);
813            let l_zwxy = _mm_shuffle_ps(l_wzyx, l_wzyx, 0b10_11_00_01);
814
815            let lwrx_nlzrx_lyrx_nlxrx = _mm_mul_ps(lwrx_lzrx_lyrx_lxrx, CONTROL_WZYX);
816
817            let lzry_lwry_lxry_lyry = _mm_mul_ps(r_yyyy, l_zwxy);
818            let l_yxwz = _mm_shuffle_ps(l_zwxy, l_zwxy, 0b00_01_10_11);
819
820            let lzry_lwry_nlxry_nlyry = _mm_mul_ps(lzry_lwry_lxry_lyry, CONTROL_ZWXY);
821
822            let lyrz_lxrz_lwrz_lzrz = _mm_mul_ps(r_zzzz, l_yxwz);
823            let result0 = _mm_add_ps(lxrw_lyrw_lzrw_lwrw, lwrx_nlzrx_lyrx_nlxrx);
824
825            let nlyrz_lxrz_lwrz_wlzrz = _mm_mul_ps(lyrz_lxrz_lwrz_lzrz, CONTROL_YXWZ);
826            let result1 = _mm_add_ps(lzry_lwry_nlxry_nlyry, nlyrz_lxrz_lwrz_wlzrz);
827
828            Self(_mm_add_ps(result0, result1))
829        }
830    }
831
832    /// Creates a quaternion from a 3x3 rotation matrix inside a 3D affine transform.
833    ///
834    /// Note if the input affine matrix contain scales, shears, or other non-rotation
835    /// transformations then the resulting quaternion will be ill-defined.
836    ///
837    /// # Panics
838    ///
839    /// Will panic if any input affine matrix column is not normalized when `glam_assert` is
840    /// enabled.
841    #[inline]
842    #[must_use]
843    pub fn from_affine3(a: &crate::Affine3A) -> Self {
844        #[allow(clippy::useless_conversion)]
845        Self::from_rotation_axes(
846            a.matrix3.x_axis.into(),
847            a.matrix3.y_axis.into(),
848            a.matrix3.z_axis.into(),
849        )
850    }
851
852    /// Multiplies a quaternion and a 3D vector, returning the rotated vector.
853    #[inline]
854    #[must_use]
855    pub fn mul_vec3a(self, rhs: Vec3A) -> Vec3A {
856        unsafe {
857            const TWO: __m128 = m128_from_f32x4([2.0; 4]);
858            let w = _mm_shuffle_ps(self.0, self.0, 0b11_11_11_11);
859            let b = self.0;
860            let b2 = dot3_into_m128(b, b);
861            Vec3A(_mm_add_ps(
862                _mm_add_ps(
863                    _mm_mul_ps(rhs.0, _mm_sub_ps(_mm_mul_ps(w, w), b2)),
864                    _mm_mul_ps(b, _mm_mul_ps(dot3_into_m128(rhs.0, b), TWO)),
865                ),
866                _mm_mul_ps(Vec3A(b).cross(rhs).into(), _mm_mul_ps(w, TWO)),
867            ))
868        }
869    }
870
871    #[inline]
872    #[must_use]
873    pub fn as_dquat(self) -> DQuat {
874        DQuat::from_xyzw(self.x as f64, self.y as f64, self.z as f64, self.w as f64)
875    }
876}
877
878impl fmt::Debug for Quat {
879    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
880        fmt.debug_tuple(stringify!(Quat))
881            .field(&self.x)
882            .field(&self.y)
883            .field(&self.z)
884            .field(&self.w)
885            .finish()
886    }
887}
888
889impl fmt::Display for Quat {
890    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
891        if let Some(p) = f.precision() {
892            write!(
893                f,
894                "[{:.*}, {:.*}, {:.*}, {:.*}]",
895                p, self.x, p, self.y, p, self.z, p, self.w
896            )
897        } else {
898            write!(f, "[{}, {}, {}, {}]", self.x, self.y, self.z, self.w)
899        }
900    }
901}
902
903impl Add for Quat {
904    type Output = Self;
905    /// Adds two quaternions.
906    ///
907    /// The sum is not guaranteed to be normalized.
908    ///
909    /// Note that addition is not the same as combining the rotations represented by the
910    /// two quaternions! That corresponds to multiplication.
911    #[inline]
912    fn add(self, rhs: Self) -> Self {
913        Self::from_vec4(Vec4::from(self) + Vec4::from(rhs))
914    }
915}
916
917impl Add<&Self> for Quat {
918    type Output = Self;
919    #[inline]
920    fn add(self, rhs: &Self) -> Self {
921        self.add(*rhs)
922    }
923}
924
925impl Add<&Quat> for &Quat {
926    type Output = Quat;
927    #[inline]
928    fn add(self, rhs: &Quat) -> Quat {
929        (*self).add(*rhs)
930    }
931}
932
933impl Add<Quat> for &Quat {
934    type Output = Quat;
935    #[inline]
936    fn add(self, rhs: Quat) -> Quat {
937        (*self).add(rhs)
938    }
939}
940
941impl AddAssign for Quat {
942    #[inline]
943    fn add_assign(&mut self, rhs: Self) {
944        *self = self.add(rhs);
945    }
946}
947
948impl AddAssign<&Self> for Quat {
949    #[inline]
950    fn add_assign(&mut self, rhs: &Self) {
951        self.add_assign(*rhs);
952    }
953}
954
955impl Sub for Quat {
956    type Output = Self;
957    /// Subtracts the `rhs` quaternion from `self`.
958    ///
959    /// The difference is not guaranteed to be normalized.
960    #[inline]
961    fn sub(self, rhs: Self) -> Self {
962        Self::from_vec4(Vec4::from(self) - Vec4::from(rhs))
963    }
964}
965
966impl Sub<&Self> for Quat {
967    type Output = Self;
968    #[inline]
969    fn sub(self, rhs: &Self) -> Self {
970        self.sub(*rhs)
971    }
972}
973
974impl Sub<&Quat> for &Quat {
975    type Output = Quat;
976    #[inline]
977    fn sub(self, rhs: &Quat) -> Quat {
978        (*self).sub(*rhs)
979    }
980}
981
982impl Sub<Quat> for &Quat {
983    type Output = Quat;
984    #[inline]
985    fn sub(self, rhs: Quat) -> Quat {
986        (*self).sub(rhs)
987    }
988}
989
990impl SubAssign for Quat {
991    #[inline]
992    fn sub_assign(&mut self, rhs: Self) {
993        *self = self.sub(rhs);
994    }
995}
996
997impl SubAssign<&Self> for Quat {
998    #[inline]
999    fn sub_assign(&mut self, rhs: &Self) {
1000        self.sub_assign(*rhs);
1001    }
1002}
1003
1004impl Mul<f32> for Quat {
1005    type Output = Self;
1006    /// Multiplies a quaternion by a scalar value.
1007    ///
1008    /// The product is not guaranteed to be normalized.
1009    #[inline]
1010    fn mul(self, rhs: f32) -> Self {
1011        Self::from_vec4(Vec4::from(self) * rhs)
1012    }
1013}
1014
1015impl Mul<&f32> for Quat {
1016    type Output = Self;
1017    #[inline]
1018    fn mul(self, rhs: &f32) -> Self {
1019        self.mul(*rhs)
1020    }
1021}
1022
1023impl Mul<&f32> for &Quat {
1024    type Output = Quat;
1025    #[inline]
1026    fn mul(self, rhs: &f32) -> Quat {
1027        (*self).mul(*rhs)
1028    }
1029}
1030
1031impl Mul<f32> for &Quat {
1032    type Output = Quat;
1033    #[inline]
1034    fn mul(self, rhs: f32) -> Quat {
1035        (*self).mul(rhs)
1036    }
1037}
1038
1039impl MulAssign<f32> for Quat {
1040    #[inline]
1041    fn mul_assign(&mut self, rhs: f32) {
1042        *self = self.mul(rhs);
1043    }
1044}
1045
1046impl MulAssign<&f32> for Quat {
1047    #[inline]
1048    fn mul_assign(&mut self, rhs: &f32) {
1049        self.mul_assign(*rhs);
1050    }
1051}
1052
1053impl Div<f32> for Quat {
1054    type Output = Self;
1055    /// Divides a quaternion by a scalar value.
1056    /// The quotient is not guaranteed to be normalized.
1057    #[inline]
1058    fn div(self, rhs: f32) -> Self {
1059        Self::from_vec4(Vec4::from(self) / rhs)
1060    }
1061}
1062
1063impl Div<&f32> for Quat {
1064    type Output = Self;
1065    #[inline]
1066    fn div(self, rhs: &f32) -> Self {
1067        self.div(*rhs)
1068    }
1069}
1070
1071impl Div<&f32> for &Quat {
1072    type Output = Quat;
1073    #[inline]
1074    fn div(self, rhs: &f32) -> Quat {
1075        (*self).div(*rhs)
1076    }
1077}
1078
1079impl Div<f32> for &Quat {
1080    type Output = Quat;
1081    #[inline]
1082    fn div(self, rhs: f32) -> Quat {
1083        (*self).div(rhs)
1084    }
1085}
1086
1087impl DivAssign<f32> for Quat {
1088    #[inline]
1089    fn div_assign(&mut self, rhs: f32) {
1090        *self = self.div(rhs);
1091    }
1092}
1093
1094impl DivAssign<&f32> for Quat {
1095    #[inline]
1096    fn div_assign(&mut self, rhs: &f32) {
1097        self.div_assign(*rhs);
1098    }
1099}
1100
1101impl Mul for Quat {
1102    type Output = Self;
1103    /// Multiplies two quaternions. If they each represent a rotation, the result will
1104    /// represent the combined rotation.
1105    ///
1106    /// Note that due to floating point rounding the result may not be perfectly
1107    /// normalized.
1108    ///
1109    /// # Panics
1110    ///
1111    /// Will panic if `self` or `rhs` are not normalized when `glam_assert` is enabled.
1112    #[inline]
1113    fn mul(self, rhs: Self) -> Self {
1114        self.mul_quat(rhs)
1115    }
1116}
1117
1118impl Mul<&Self> for Quat {
1119    type Output = Self;
1120    #[inline]
1121    fn mul(self, rhs: &Self) -> Self {
1122        self.mul(*rhs)
1123    }
1124}
1125
1126impl Mul<&Quat> for &Quat {
1127    type Output = Quat;
1128    #[inline]
1129    fn mul(self, rhs: &Quat) -> Quat {
1130        (*self).mul(*rhs)
1131    }
1132}
1133
1134impl Mul<Quat> for &Quat {
1135    type Output = Quat;
1136    #[inline]
1137    fn mul(self, rhs: Quat) -> Quat {
1138        (*self).mul(rhs)
1139    }
1140}
1141
1142impl MulAssign for Quat {
1143    #[inline]
1144    fn mul_assign(&mut self, rhs: Self) {
1145        *self = self.mul(rhs);
1146    }
1147}
1148
1149impl MulAssign<&Self> for Quat {
1150    #[inline]
1151    fn mul_assign(&mut self, rhs: &Self) {
1152        self.mul_assign(*rhs);
1153    }
1154}
1155
1156impl Mul<Vec3> for Quat {
1157    type Output = Vec3;
1158    /// Multiplies a quaternion and a 3D vector, returning the rotated vector.
1159    ///
1160    /// # Panics
1161    ///
1162    /// Will panic if `self` is not normalized when `glam_assert` is enabled.
1163    #[inline]
1164    fn mul(self, rhs: Vec3) -> Self::Output {
1165        self.mul_vec3(rhs)
1166    }
1167}
1168
1169impl Mul<&Vec3> for Quat {
1170    type Output = Vec3;
1171    #[inline]
1172    fn mul(self, rhs: &Vec3) -> Vec3 {
1173        self.mul(*rhs)
1174    }
1175}
1176
1177impl Mul<&Vec3> for &Quat {
1178    type Output = Vec3;
1179    #[inline]
1180    fn mul(self, rhs: &Vec3) -> Vec3 {
1181        (*self).mul(*rhs)
1182    }
1183}
1184
1185impl Mul<Vec3> for &Quat {
1186    type Output = Vec3;
1187    #[inline]
1188    fn mul(self, rhs: Vec3) -> Vec3 {
1189        (*self).mul(rhs)
1190    }
1191}
1192
1193impl Mul<Vec3A> for Quat {
1194    type Output = Vec3A;
1195    #[inline]
1196    fn mul(self, rhs: Vec3A) -> Self::Output {
1197        self.mul_vec3a(rhs)
1198    }
1199}
1200
1201impl Mul<&Vec3A> for Quat {
1202    type Output = Vec3A;
1203    #[inline]
1204    fn mul(self, rhs: &Vec3A) -> Vec3A {
1205        self.mul(*rhs)
1206    }
1207}
1208
1209impl Mul<&Vec3A> for &Quat {
1210    type Output = Vec3A;
1211    #[inline]
1212    fn mul(self, rhs: &Vec3A) -> Vec3A {
1213        (*self).mul(*rhs)
1214    }
1215}
1216
1217impl Mul<Vec3A> for &Quat {
1218    type Output = Vec3A;
1219    #[inline]
1220    fn mul(self, rhs: Vec3A) -> Vec3A {
1221        (*self).mul(rhs)
1222    }
1223}
1224
1225impl Neg for Quat {
1226    type Output = Self;
1227    #[inline]
1228    fn neg(self) -> Self {
1229        self * -1.0
1230    }
1231}
1232
1233impl Neg for &Quat {
1234    type Output = Quat;
1235    #[inline]
1236    fn neg(self) -> Quat {
1237        (*self).neg()
1238    }
1239}
1240
1241impl Default for Quat {
1242    #[inline]
1243    fn default() -> Self {
1244        Self::IDENTITY
1245    }
1246}
1247
1248impl PartialEq for Quat {
1249    #[inline]
1250    fn eq(&self, rhs: &Self) -> bool {
1251        Vec4::from(*self).eq(&Vec4::from(*rhs))
1252    }
1253}
1254
1255impl AsRef<[f32; 4]> for Quat {
1256    #[inline]
1257    fn as_ref(&self) -> &[f32; 4] {
1258        unsafe { &*(self as *const Self as *const [f32; 4]) }
1259    }
1260}
1261
1262impl Sum<Self> for Quat {
1263    fn sum<I>(iter: I) -> Self
1264    where
1265        I: Iterator<Item = Self>,
1266    {
1267        iter.fold(Self::ZERO, Self::add)
1268    }
1269}
1270
1271impl<'a> Sum<&'a Self> for Quat {
1272    fn sum<I>(iter: I) -> Self
1273    where
1274        I: Iterator<Item = &'a Self>,
1275    {
1276        iter.fold(Self::ZERO, |a, &b| Self::add(a, b))
1277    }
1278}
1279
1280impl Product for Quat {
1281    fn product<I>(iter: I) -> Self
1282    where
1283        I: Iterator<Item = Self>,
1284    {
1285        iter.fold(Self::IDENTITY, Self::mul)
1286    }
1287}
1288
1289impl<'a> Product<&'a Self> for Quat {
1290    fn product<I>(iter: I) -> Self
1291    where
1292        I: Iterator<Item = &'a Self>,
1293    {
1294        iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b))
1295    }
1296}
1297
1298impl From<Quat> for Vec4 {
1299    #[inline]
1300    fn from(q: Quat) -> Self {
1301        Self(q.0)
1302    }
1303}
1304
1305impl From<Quat> for (f32, f32, f32, f32) {
1306    #[inline]
1307    fn from(q: Quat) -> Self {
1308        Vec4::from(q).into()
1309    }
1310}
1311
1312impl From<Quat> for [f32; 4] {
1313    #[inline]
1314    fn from(q: Quat) -> Self {
1315        Vec4::from(q).into()
1316    }
1317}
1318
1319impl From<Quat> for __m128 {
1320    #[inline]
1321    fn from(q: Quat) -> Self {
1322        q.0
1323    }
1324}
1325
1326impl Deref for Quat {
1327    type Target = crate::deref::Vec4<f32>;
1328    #[inline]
1329    fn deref(&self) -> &Self::Target {
1330        unsafe { &*(self as *const Self).cast() }
1331    }
1332}
1333
1334impl DerefMut for Quat {
1335    #[inline]
1336    fn deref_mut(&mut self) -> &mut Self::Target {
1337        unsafe { &mut *(self as *mut Self).cast() }
1338    }
1339}