glam/f32/sse2/
quat.rs

1// Generated from quat.rs.tera template. Edit the template, not the generated file.
2
3use crate::{
4    euler::{EulerFromQuaternion, EulerRot, EulerToQuaternion},
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
15#[cfg(not(target_arch = "spirv"))]
16use core::fmt;
17use core::iter::{Product, Sum};
18use core::ops::{Add, Deref, DerefMut, Div, Mul, MulAssign, Neg, Sub};
19
20#[repr(C)]
21union UnionCast {
22    a: [f32; 4],
23    v: Quat,
24}
25
26/// Creates a quaternion from `x`, `y`, `z` and `w` values.
27///
28/// This should generally not be called manually unless you know what you are doing. Use
29/// one of the other constructors instead such as `identity` or `from_axis_angle`.
30#[inline]
31#[must_use]
32pub const fn quat(x: f32, y: f32, z: f32, w: f32) -> Quat {
33    Quat::from_xyzw(x, y, z, w)
34}
35
36/// A quaternion representing an orientation.
37///
38/// This quaternion is intended to be of unit length but may denormalize due to
39/// floating point "error creep" which can occur when successive quaternion
40/// operations are applied.
41///
42/// SIMD vector types are used for storage on supported platforms.
43///
44/// This type is 16 byte aligned.
45#[derive(Clone, Copy)]
46#[repr(transparent)]
47pub struct Quat(pub(crate) __m128);
48
49impl Quat {
50    /// All zeros.
51    const ZERO: Self = Self::from_array([0.0; 4]);
52
53    /// The identity quaternion. Corresponds to no rotation.
54    pub const IDENTITY: Self = Self::from_xyzw(0.0, 0.0, 0.0, 1.0);
55
56    /// All NANs.
57    pub const NAN: Self = Self::from_array([f32::NAN; 4]);
58
59    /// Creates a new rotation quaternion.
60    ///
61    /// This should generally not be called manually unless you know what you are doing.
62    /// Use one of the other constructors instead such as `identity` or `from_axis_angle`.
63    ///
64    /// `from_xyzw` is mostly used by unit tests and `serde` deserialization.
65    ///
66    /// # Preconditions
67    ///
68    /// This function does not check if the input is normalized, it is up to the user to
69    /// provide normalized input or to normalized the resulting quaternion.
70    #[inline(always)]
71    #[must_use]
72    pub const fn from_xyzw(x: f32, y: f32, z: f32, w: f32) -> Self {
73        unsafe { UnionCast { a: [x, y, z, w] }.v }
74    }
75
76    /// Creates a rotation quaternion from an array.
77    ///
78    /// # Preconditions
79    ///
80    /// This function does not check if the input is normalized, it is up to the user to
81    /// provide normalized input or to normalized the resulting quaternion.
82    #[inline]
83    #[must_use]
84    pub const fn from_array(a: [f32; 4]) -> Self {
85        Self::from_xyzw(a[0], a[1], a[2], a[3])
86    }
87
88    /// Creates a new rotation quaternion from a 4D vector.
89    ///
90    /// # Preconditions
91    ///
92    /// This function does not check if the input is normalized, it is up to the user to
93    /// provide normalized input or to normalized the resulting quaternion.
94    #[inline]
95    #[must_use]
96    pub const fn from_vec4(v: Vec4) -> Self {
97        Self(v.0)
98    }
99
100    /// Creates a rotation quaternion from a slice.
101    ///
102    /// # Preconditions
103    ///
104    /// This function does not check if the input is normalized, it is up to the user to
105    /// provide normalized input or to normalized the resulting quaternion.
106    ///
107    /// # Panics
108    ///
109    /// Panics if `slice` length is less than 4.
110    #[inline]
111    #[must_use]
112    pub fn from_slice(slice: &[f32]) -> Self {
113        assert!(slice.len() >= 4);
114        Self(unsafe { _mm_loadu_ps(slice.as_ptr()) })
115    }
116
117    /// Writes the quaternion to an unaligned slice.
118    ///
119    /// # Panics
120    ///
121    /// Panics if `slice` length is less than 4.
122    #[inline]
123    pub fn write_to_slice(self, slice: &mut [f32]) {
124        assert!(slice.len() >= 4);
125        unsafe { _mm_storeu_ps(slice.as_mut_ptr(), self.0) }
126    }
127
128    /// Create a quaternion for a normalized rotation `axis` and `angle` (in radians).
129    ///
130    /// The axis must be a unit vector.
131    ///
132    /// # Panics
133    ///
134    /// Will panic if `axis` is not normalized when `glam_assert` is enabled.
135    #[inline]
136    #[must_use]
137    pub fn from_axis_angle(axis: Vec3, angle: f32) -> Self {
138        glam_assert!(axis.is_normalized());
139        let (s, c) = math::sin_cos(angle * 0.5);
140        let v = axis * s;
141        Self::from_xyzw(v.x, v.y, v.z, c)
142    }
143
144    /// Create a quaternion that rotates `v.length()` radians around `v.normalize()`.
145    ///
146    /// `from_scaled_axis(Vec3::ZERO)` results in the identity quaternion.
147    #[inline]
148    #[must_use]
149    pub fn from_scaled_axis(v: Vec3) -> Self {
150        let length = v.length();
151        if length == 0.0 {
152            Self::IDENTITY
153        } else {
154            Self::from_axis_angle(v / length, length)
155        }
156    }
157
158    /// Creates a quaternion from the `angle` (in radians) around the x axis.
159    #[inline]
160    #[must_use]
161    pub fn from_rotation_x(angle: f32) -> Self {
162        let (s, c) = math::sin_cos(angle * 0.5);
163        Self::from_xyzw(s, 0.0, 0.0, c)
164    }
165
166    /// Creates a quaternion from the `angle` (in radians) around the y axis.
167    #[inline]
168    #[must_use]
169    pub fn from_rotation_y(angle: f32) -> Self {
170        let (s, c) = math::sin_cos(angle * 0.5);
171        Self::from_xyzw(0.0, s, 0.0, c)
172    }
173
174    /// Creates a quaternion from the `angle` (in radians) around the z axis.
175    #[inline]
176    #[must_use]
177    pub fn from_rotation_z(angle: f32) -> Self {
178        let (s, c) = math::sin_cos(angle * 0.5);
179        Self::from_xyzw(0.0, 0.0, s, c)
180    }
181
182    /// Creates a quaternion from the given Euler rotation sequence and the angles (in radians).
183    #[inline]
184    #[must_use]
185    pub fn from_euler(euler: EulerRot, a: f32, b: f32, c: f32) -> Self {
186        euler.new_quat(a, b, c)
187    }
188
189    /// From the columns of a 3x3 rotation matrix.
190    #[inline]
191    #[must_use]
192    pub(crate) fn from_rotation_axes(x_axis: Vec3, y_axis: Vec3, z_axis: Vec3) -> Self {
193        // Based on https://github.com/microsoft/DirectXMath `XM$quaternionRotationMatrix`
194        let (m00, m01, m02) = x_axis.into();
195        let (m10, m11, m12) = y_axis.into();
196        let (m20, m21, m22) = z_axis.into();
197        if m22 <= 0.0 {
198            // x^2 + y^2 >= z^2 + w^2
199            let dif10 = m11 - m00;
200            let omm22 = 1.0 - m22;
201            if dif10 <= 0.0 {
202                // x^2 >= y^2
203                let four_xsq = omm22 - dif10;
204                let inv4x = 0.5 / math::sqrt(four_xsq);
205                Self::from_xyzw(
206                    four_xsq * inv4x,
207                    (m01 + m10) * inv4x,
208                    (m02 + m20) * inv4x,
209                    (m12 - m21) * inv4x,
210                )
211            } else {
212                // y^2 >= x^2
213                let four_ysq = omm22 + dif10;
214                let inv4y = 0.5 / math::sqrt(four_ysq);
215                Self::from_xyzw(
216                    (m01 + m10) * inv4y,
217                    four_ysq * inv4y,
218                    (m12 + m21) * inv4y,
219                    (m20 - m02) * inv4y,
220                )
221            }
222        } else {
223            // z^2 + w^2 >= x^2 + y^2
224            let sum10 = m11 + m00;
225            let opm22 = 1.0 + m22;
226            if sum10 <= 0.0 {
227                // z^2 >= w^2
228                let four_zsq = opm22 - sum10;
229                let inv4z = 0.5 / math::sqrt(four_zsq);
230                Self::from_xyzw(
231                    (m02 + m20) * inv4z,
232                    (m12 + m21) * inv4z,
233                    four_zsq * inv4z,
234                    (m01 - m10) * inv4z,
235                )
236            } else {
237                // w^2 >= z^2
238                let four_wsq = opm22 + sum10;
239                let inv4w = 0.5 / math::sqrt(four_wsq);
240                Self::from_xyzw(
241                    (m12 - m21) * inv4w,
242                    (m20 - m02) * inv4w,
243                    (m01 - m10) * inv4w,
244                    four_wsq * inv4w,
245                )
246            }
247        }
248    }
249
250    /// Creates a quaternion from a 3x3 rotation matrix.
251    #[inline]
252    #[must_use]
253    pub fn from_mat3(mat: &Mat3) -> Self {
254        Self::from_rotation_axes(mat.x_axis, mat.y_axis, mat.z_axis)
255    }
256
257    /// Creates a quaternion from a 3x3 SIMD aligned rotation matrix.
258    #[inline]
259    #[must_use]
260    pub fn from_mat3a(mat: &Mat3A) -> Self {
261        Self::from_rotation_axes(mat.x_axis.into(), mat.y_axis.into(), mat.z_axis.into())
262    }
263
264    /// Creates a quaternion from a 3x3 rotation matrix inside a homogeneous 4x4 matrix.
265    #[inline]
266    #[must_use]
267    pub fn from_mat4(mat: &Mat4) -> Self {
268        Self::from_rotation_axes(
269            mat.x_axis.truncate(),
270            mat.y_axis.truncate(),
271            mat.z_axis.truncate(),
272        )
273    }
274
275    /// Gets the minimal rotation for transforming `from` to `to`.  The rotation is in the
276    /// plane spanned by the two vectors.  Will rotate at most 180 degrees.
277    ///
278    /// The inputs must be unit vectors.
279    ///
280    /// `from_rotation_arc(from, to) * from ≈ to`.
281    ///
282    /// For near-singular cases (from≈to and from≈-to) the current implementation
283    /// is only accurate to about 0.001 (for `f32`).
284    ///
285    /// # Panics
286    ///
287    /// Will panic if `from` or `to` are not normalized when `glam_assert` is enabled.
288    #[must_use]
289    pub fn from_rotation_arc(from: Vec3, to: Vec3) -> Self {
290        glam_assert!(from.is_normalized());
291        glam_assert!(to.is_normalized());
292
293        const ONE_MINUS_EPS: f32 = 1.0 - 2.0 * core::f32::EPSILON;
294        let dot = from.dot(to);
295        if dot > ONE_MINUS_EPS {
296            // 0° singulary: from ≈ to
297            Self::IDENTITY
298        } else if dot < -ONE_MINUS_EPS {
299            // 180° singulary: from ≈ -to
300            use core::f32::consts::PI; // half a turn = 𝛕/2 = 180°
301            Self::from_axis_angle(from.any_orthonormal_vector(), PI)
302        } else {
303            let c = from.cross(to);
304            Self::from_xyzw(c.x, c.y, c.z, 1.0 + dot).normalize()
305        }
306    }
307
308    /// Gets the minimal rotation for transforming `from` to either `to` or `-to`.  This means
309    /// that the resulting quaternion will rotate `from` so that it is colinear with `to`.
310    ///
311    /// The rotation is in the plane spanned by the two vectors.  Will rotate at most 90
312    /// degrees.
313    ///
314    /// The inputs must be unit vectors.
315    ///
316    /// `to.dot(from_rotation_arc_colinear(from, to) * from).abs() ≈ 1`.
317    ///
318    /// # Panics
319    ///
320    /// Will panic if `from` or `to` are not normalized when `glam_assert` is enabled.
321    #[inline]
322    #[must_use]
323    pub fn from_rotation_arc_colinear(from: Vec3, to: Vec3) -> Self {
324        if from.dot(to) < 0.0 {
325            Self::from_rotation_arc(from, -to)
326        } else {
327            Self::from_rotation_arc(from, to)
328        }
329    }
330
331    /// Gets the minimal rotation for transforming `from` to `to`.  The resulting rotation is
332    /// around the z axis. Will rotate at most 180 degrees.
333    ///
334    /// The inputs must be unit vectors.
335    ///
336    /// `from_rotation_arc_2d(from, to) * from ≈ to`.
337    ///
338    /// For near-singular cases (from≈to and from≈-to) the current implementation
339    /// is only accurate to about 0.001 (for `f32`).
340    ///
341    /// # Panics
342    ///
343    /// Will panic if `from` or `to` are not normalized when `glam_assert` is enabled.
344    #[must_use]
345    pub fn from_rotation_arc_2d(from: Vec2, to: Vec2) -> Self {
346        glam_assert!(from.is_normalized());
347        glam_assert!(to.is_normalized());
348
349        const ONE_MINUS_EPSILON: f32 = 1.0 - 2.0 * core::f32::EPSILON;
350        let dot = from.dot(to);
351        if dot > ONE_MINUS_EPSILON {
352            // 0° singulary: from ≈ to
353            Self::IDENTITY
354        } else if dot < -ONE_MINUS_EPSILON {
355            // 180° singulary: from ≈ -to
356            const COS_FRAC_PI_2: f32 = 0.0;
357            const SIN_FRAC_PI_2: f32 = 1.0;
358            // rotation around z by PI radians
359            Self::from_xyzw(0.0, 0.0, SIN_FRAC_PI_2, COS_FRAC_PI_2)
360        } else {
361            // vector3 cross where z=0
362            let z = from.x * to.y - to.x * from.y;
363            let w = 1.0 + dot;
364            // calculate length with x=0 and y=0 to normalize
365            let len_rcp = 1.0 / math::sqrt(z * z + w * w);
366            Self::from_xyzw(0.0, 0.0, z * len_rcp, w * len_rcp)
367        }
368    }
369
370    /// Returns the rotation axis (normalized) and angle (in radians) of `self`.
371    #[inline]
372    #[must_use]
373    pub fn to_axis_angle(self) -> (Vec3, f32) {
374        const EPSILON: f32 = 1.0e-8;
375        let v = Vec3::new(self.x, self.y, self.z);
376        let length = v.length();
377        if length >= EPSILON {
378            let angle = 2.0 * math::atan2(length, self.w);
379            let axis = v / length;
380            (axis, angle)
381        } else {
382            (Vec3::X, 0.0)
383        }
384    }
385
386    /// Returns the rotation axis scaled by the rotation in radians.
387    #[inline]
388    #[must_use]
389    pub fn to_scaled_axis(self) -> Vec3 {
390        let (axis, angle) = self.to_axis_angle();
391        axis * angle
392    }
393
394    /// Returns the rotation angles for the given euler rotation sequence.
395    #[inline]
396    #[must_use]
397    pub fn to_euler(self, euler: EulerRot) -> (f32, f32, f32) {
398        euler.convert_quat(self)
399    }
400
401    /// `[x, y, z, w]`
402    #[inline]
403    #[must_use]
404    pub fn to_array(&self) -> [f32; 4] {
405        [self.x, self.y, self.z, self.w]
406    }
407
408    /// Returns the vector part of the quaternion.
409    #[inline]
410    #[must_use]
411    pub fn xyz(self) -> Vec3 {
412        Vec3::new(self.x, self.y, self.z)
413    }
414
415    /// Returns the quaternion conjugate of `self`. For a unit quaternion the
416    /// conjugate is also the inverse.
417    #[inline]
418    #[must_use]
419    pub fn conjugate(self) -> Self {
420        const SIGN: __m128 = m128_from_f32x4([-0.0, -0.0, -0.0, 0.0]);
421        Self(unsafe { _mm_xor_ps(self.0, SIGN) })
422    }
423
424    /// Returns the inverse of a normalized quaternion.
425    ///
426    /// Typically quaternion inverse returns the conjugate of a normalized quaternion.
427    /// Because `self` is assumed to already be unit length this method *does not* normalize
428    /// before returning the conjugate.
429    ///
430    /// # Panics
431    ///
432    /// Will panic if `self` is not normalized when `glam_assert` is enabled.
433    #[inline]
434    #[must_use]
435    pub fn inverse(self) -> Self {
436        glam_assert!(self.is_normalized());
437        self.conjugate()
438    }
439
440    /// Computes the dot product of `self` and `rhs`. The dot product is
441    /// equal to the cosine of the angle between two quaternion rotations.
442    #[inline]
443    #[must_use]
444    pub fn dot(self, rhs: Self) -> f32 {
445        Vec4::from(self).dot(Vec4::from(rhs))
446    }
447
448    /// Computes the length of `self`.
449    #[doc(alias = "magnitude")]
450    #[inline]
451    #[must_use]
452    pub fn length(self) -> f32 {
453        Vec4::from(self).length()
454    }
455
456    /// Computes the squared length of `self`.
457    ///
458    /// This is generally faster than `length()` as it avoids a square
459    /// root operation.
460    #[doc(alias = "magnitude2")]
461    #[inline]
462    #[must_use]
463    pub fn length_squared(self) -> f32 {
464        Vec4::from(self).length_squared()
465    }
466
467    /// Computes `1.0 / length()`.
468    ///
469    /// For valid results, `self` must _not_ be of length zero.
470    #[inline]
471    #[must_use]
472    pub fn length_recip(self) -> f32 {
473        Vec4::from(self).length_recip()
474    }
475
476    /// Returns `self` normalized to length 1.0.
477    ///
478    /// For valid results, `self` must _not_ be of length zero.
479    ///
480    /// Panics
481    ///
482    /// Will panic if `self` is zero length when `glam_assert` is enabled.
483    #[inline]
484    #[must_use]
485    pub fn normalize(self) -> Self {
486        Self::from_vec4(Vec4::from(self).normalize())
487    }
488
489    /// Returns `true` if, and only if, all elements are finite.
490    /// If any element is either `NaN`, positive or negative infinity, this will return `false`.
491    #[inline]
492    #[must_use]
493    pub fn is_finite(self) -> bool {
494        Vec4::from(self).is_finite()
495    }
496
497    #[inline]
498    #[must_use]
499    pub fn is_nan(self) -> bool {
500        Vec4::from(self).is_nan()
501    }
502
503    /// Returns whether `self` of length `1.0` or not.
504    ///
505    /// Uses a precision threshold of `1e-6`.
506    #[inline]
507    #[must_use]
508    pub fn is_normalized(self) -> bool {
509        Vec4::from(self).is_normalized()
510    }
511
512    #[inline]
513    #[must_use]
514    pub fn is_near_identity(self) -> bool {
515        // Based on https://github.com/nfrechette/rtm `rtm::quat_near_identity`
516        let threshold_angle = 0.002_847_144_6;
517        // Because of floating point precision, we cannot represent very small rotations.
518        // The closest f32 to 1.0 that is not 1.0 itself yields:
519        // 0.99999994.acos() * 2.0  = 0.000690533954 rad
520        //
521        // An error threshold of 1.e-6 is used by default.
522        // (1.0 - 1.e-6).acos() * 2.0 = 0.00284714461 rad
523        // (1.0 - 1.e-7).acos() * 2.0 = 0.00097656250 rad
524        //
525        // We don't really care about the angle value itself, only if it's close to 0.
526        // This will happen whenever quat.w is close to 1.0.
527        // If the quat.w is close to -1.0, the angle will be near 2*PI which is close to
528        // a negative 0 rotation. By forcing quat.w to be positive, we'll end up with
529        // the shortest path.
530        let positive_w_angle = math::acos_approx(math::abs(self.w)) * 2.0;
531        positive_w_angle < threshold_angle
532    }
533
534    /// Returns the angle (in radians) for the minimal rotation
535    /// for transforming this quaternion into another.
536    ///
537    /// Both quaternions must be normalized.
538    ///
539    /// # Panics
540    ///
541    /// Will panic if `self` or `rhs` are not normalized when `glam_assert` is enabled.
542    #[inline]
543    #[must_use]
544    pub fn angle_between(self, rhs: Self) -> f32 {
545        glam_assert!(self.is_normalized() && rhs.is_normalized());
546        math::acos_approx(math::abs(self.dot(rhs))) * 2.0
547    }
548
549    /// Returns true if the absolute difference of all elements between `self` and `rhs`
550    /// is less than or equal to `max_abs_diff`.
551    ///
552    /// This can be used to compare if two quaternions contain similar elements. It works
553    /// best when comparing with a known value. The `max_abs_diff` that should be used used
554    /// depends on the values being compared against.
555    ///
556    /// For more see
557    /// [comparing floating point numbers](https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/).
558    #[inline]
559    #[must_use]
560    pub fn abs_diff_eq(self, rhs: Self, max_abs_diff: f32) -> bool {
561        Vec4::from(self).abs_diff_eq(Vec4::from(rhs), max_abs_diff)
562    }
563
564    /// Performs a linear interpolation between `self` and `rhs` based on
565    /// the value `s`.
566    ///
567    /// When `s` is `0.0`, the result will be equal to `self`.  When `s`
568    /// is `1.0`, the result will be equal to `rhs`.
569    ///
570    /// # Panics
571    ///
572    /// Will panic if `self` or `end` are not normalized when `glam_assert` is enabled.
573    #[doc(alias = "mix")]
574    #[inline]
575    #[must_use]
576    pub fn lerp(self, end: Self, s: f32) -> Self {
577        glam_assert!(self.is_normalized());
578        glam_assert!(end.is_normalized());
579
580        const NEG_ZERO: __m128 = m128_from_f32x4([-0.0; 4]);
581        let start = self.0;
582        let end = end.0;
583        unsafe {
584            let dot = dot4_into_m128(start, end);
585            // Calculate the bias, if the dot product is positive or zero, there is no bias
586            // but if it is negative, we want to flip the 'end' rotation XYZW components
587            let bias = _mm_and_ps(dot, NEG_ZERO);
588            let interpolated = _mm_add_ps(
589                _mm_mul_ps(_mm_sub_ps(_mm_xor_ps(end, bias), start), _mm_set_ps1(s)),
590                start,
591            );
592            Quat(interpolated).normalize()
593        }
594    }
595
596    /// Performs a spherical linear interpolation between `self` and `end`
597    /// based on the value `s`.
598    ///
599    /// When `s` is `0.0`, the result will be equal to `self`.  When `s`
600    /// is `1.0`, the result will be equal to `end`.
601    ///
602    /// # Panics
603    ///
604    /// Will panic if `self` or `end` are not normalized when `glam_assert` is enabled.
605    #[inline]
606    #[must_use]
607    pub fn slerp(self, mut end: Self, s: f32) -> Self {
608        // http://number-none.com/product/Understanding%20Slerp,%20Then%20Not%20Using%20It/
609        glam_assert!(self.is_normalized());
610        glam_assert!(end.is_normalized());
611
612        const DOT_THRESHOLD: f32 = 0.9995;
613
614        // Note that a rotation can be represented by two quaternions: `q` and
615        // `-q`. The slerp path between `q` and `end` will be different from the
616        // path between `-q` and `end`. One path will take the long way around and
617        // one will take the short way. In order to correct for this, the `dot`
618        // product between `self` and `end` should be positive. If the `dot`
619        // product is negative, slerp between `self` and `-end`.
620        let mut dot = self.dot(end);
621        if dot < 0.0 {
622            end = -end;
623            dot = -dot;
624        }
625
626        if dot > DOT_THRESHOLD {
627            // assumes lerp returns a normalized quaternion
628            self.lerp(end, s)
629        } else {
630            let theta = math::acos_approx(dot);
631
632            let x = 1.0 - s;
633            let y = s;
634            let z = 1.0;
635
636            unsafe {
637                let tmp = _mm_mul_ps(_mm_set_ps1(theta), _mm_set_ps(0.0, z, y, x));
638                let tmp = m128_sin(tmp);
639
640                let scale1 = _mm_shuffle_ps(tmp, tmp, 0b00_00_00_00);
641                let scale2 = _mm_shuffle_ps(tmp, tmp, 0b01_01_01_01);
642                let theta_sin = _mm_shuffle_ps(tmp, tmp, 0b10_10_10_10);
643
644                Self(_mm_div_ps(
645                    _mm_add_ps(_mm_mul_ps(self.0, scale1), _mm_mul_ps(end.0, scale2)),
646                    theta_sin,
647                ))
648            }
649        }
650    }
651
652    /// Multiplies a quaternion and a 3D vector, returning the rotated vector.
653    ///
654    /// # Panics
655    ///
656    /// Will panic if `self` is not normalized when `glam_assert` is enabled.
657    #[inline]
658    #[must_use]
659    pub fn mul_vec3(self, rhs: Vec3) -> Vec3 {
660        glam_assert!(self.is_normalized());
661
662        self.mul_vec3a(rhs.into()).into()
663    }
664
665    /// Multiplies two quaternions. If they each represent a rotation, the result will
666    /// represent the combined rotation.
667    ///
668    /// Note that due to floating point rounding the result may not be perfectly normalized.
669    ///
670    /// # Panics
671    ///
672    /// Will panic if `self` or `rhs` are not normalized when `glam_assert` is enabled.
673    #[inline]
674    #[must_use]
675    pub fn mul_quat(self, rhs: Self) -> Self {
676        glam_assert!(self.is_normalized());
677        glam_assert!(rhs.is_normalized());
678
679        // Based on https://github.com/nfrechette/rtm `rtm::quat_mul`
680        const CONTROL_WZYX: __m128 = m128_from_f32x4([1.0, -1.0, 1.0, -1.0]);
681        const CONTROL_ZWXY: __m128 = m128_from_f32x4([1.0, 1.0, -1.0, -1.0]);
682        const CONTROL_YXWZ: __m128 = m128_from_f32x4([-1.0, 1.0, 1.0, -1.0]);
683
684        let lhs = self.0;
685        let rhs = rhs.0;
686
687        unsafe {
688            let r_xxxx = _mm_shuffle_ps(lhs, lhs, 0b00_00_00_00);
689            let r_yyyy = _mm_shuffle_ps(lhs, lhs, 0b01_01_01_01);
690            let r_zzzz = _mm_shuffle_ps(lhs, lhs, 0b10_10_10_10);
691            let r_wwww = _mm_shuffle_ps(lhs, lhs, 0b11_11_11_11);
692
693            let lxrw_lyrw_lzrw_lwrw = _mm_mul_ps(r_wwww, rhs);
694            let l_wzyx = _mm_shuffle_ps(rhs, rhs, 0b00_01_10_11);
695
696            let lwrx_lzrx_lyrx_lxrx = _mm_mul_ps(r_xxxx, l_wzyx);
697            let l_zwxy = _mm_shuffle_ps(l_wzyx, l_wzyx, 0b10_11_00_01);
698
699            let lwrx_nlzrx_lyrx_nlxrx = _mm_mul_ps(lwrx_lzrx_lyrx_lxrx, CONTROL_WZYX);
700
701            let lzry_lwry_lxry_lyry = _mm_mul_ps(r_yyyy, l_zwxy);
702            let l_yxwz = _mm_shuffle_ps(l_zwxy, l_zwxy, 0b00_01_10_11);
703
704            let lzry_lwry_nlxry_nlyry = _mm_mul_ps(lzry_lwry_lxry_lyry, CONTROL_ZWXY);
705
706            let lyrz_lxrz_lwrz_lzrz = _mm_mul_ps(r_zzzz, l_yxwz);
707            let result0 = _mm_add_ps(lxrw_lyrw_lzrw_lwrw, lwrx_nlzrx_lyrx_nlxrx);
708
709            let nlyrz_lxrz_lwrz_wlzrz = _mm_mul_ps(lyrz_lxrz_lwrz_lzrz, CONTROL_YXWZ);
710            let result1 = _mm_add_ps(lzry_lwry_nlxry_nlyry, nlyrz_lxrz_lwrz_wlzrz);
711
712            Self(_mm_add_ps(result0, result1))
713        }
714    }
715
716    /// Creates a quaternion from a 3x3 rotation matrix inside a 3D affine transform.
717    #[inline]
718    #[must_use]
719    pub fn from_affine3(a: &crate::Affine3A) -> Self {
720        #[allow(clippy::useless_conversion)]
721        Self::from_rotation_axes(
722            a.matrix3.x_axis.into(),
723            a.matrix3.y_axis.into(),
724            a.matrix3.z_axis.into(),
725        )
726    }
727
728    /// Multiplies a quaternion and a 3D vector, returning the rotated vector.
729    #[inline]
730    #[must_use]
731    pub fn mul_vec3a(self, rhs: Vec3A) -> Vec3A {
732        unsafe {
733            const TWO: __m128 = m128_from_f32x4([2.0; 4]);
734            let w = _mm_shuffle_ps(self.0, self.0, 0b11_11_11_11);
735            let b = self.0;
736            let b2 = dot3_into_m128(b, b);
737            Vec3A(_mm_add_ps(
738                _mm_add_ps(
739                    _mm_mul_ps(rhs.0, _mm_sub_ps(_mm_mul_ps(w, w), b2)),
740                    _mm_mul_ps(b, _mm_mul_ps(dot3_into_m128(rhs.0, b), TWO)),
741                ),
742                _mm_mul_ps(Vec3A(b).cross(rhs).into(), _mm_mul_ps(w, TWO)),
743            ))
744        }
745    }
746
747    #[inline]
748    #[must_use]
749    pub fn as_dquat(self) -> DQuat {
750        DQuat::from_xyzw(self.x as f64, self.y as f64, self.z as f64, self.w as f64)
751    }
752
753    #[inline]
754    #[must_use]
755    #[deprecated(since = "0.24.2", note = "Use as_dquat() instead")]
756    pub fn as_f64(self) -> DQuat {
757        self.as_dquat()
758    }
759}
760
761#[cfg(not(target_arch = "spirv"))]
762impl fmt::Debug for Quat {
763    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
764        fmt.debug_tuple(stringify!(Quat))
765            .field(&self.x)
766            .field(&self.y)
767            .field(&self.z)
768            .field(&self.w)
769            .finish()
770    }
771}
772
773#[cfg(not(target_arch = "spirv"))]
774impl fmt::Display for Quat {
775    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
776        write!(fmt, "[{}, {}, {}, {}]", self.x, self.y, self.z, self.w)
777    }
778}
779
780impl Add<Quat> for Quat {
781    type Output = Self;
782    /// Adds two quaternions.
783    ///
784    /// The sum is not guaranteed to be normalized.
785    ///
786    /// Note that addition is not the same as combining the rotations represented by the
787    /// two quaternions! That corresponds to multiplication.
788    #[inline]
789    fn add(self, rhs: Self) -> Self {
790        Self::from_vec4(Vec4::from(self) + Vec4::from(rhs))
791    }
792}
793
794impl Sub<Quat> for Quat {
795    type Output = Self;
796    /// Subtracts the `rhs` quaternion from `self`.
797    ///
798    /// The difference is not guaranteed to be normalized.
799    #[inline]
800    fn sub(self, rhs: Self) -> Self {
801        Self::from_vec4(Vec4::from(self) - Vec4::from(rhs))
802    }
803}
804
805impl Mul<f32> for Quat {
806    type Output = Self;
807    /// Multiplies a quaternion by a scalar value.
808    ///
809    /// The product is not guaranteed to be normalized.
810    #[inline]
811    fn mul(self, rhs: f32) -> Self {
812        Self::from_vec4(Vec4::from(self) * rhs)
813    }
814}
815
816impl Div<f32> for Quat {
817    type Output = Self;
818    /// Divides a quaternion by a scalar value.
819    /// The quotient is not guaranteed to be normalized.
820    #[inline]
821    fn div(self, rhs: f32) -> Self {
822        Self::from_vec4(Vec4::from(self) / rhs)
823    }
824}
825
826impl Mul<Quat> for Quat {
827    type Output = Self;
828    /// Multiplies two quaternions. If they each represent a rotation, the result will
829    /// represent the combined rotation.
830    ///
831    /// Note that due to floating point rounding the result may not be perfectly
832    /// normalized.
833    ///
834    /// # Panics
835    ///
836    /// Will panic if `self` or `rhs` are not normalized when `glam_assert` is enabled.
837    #[inline]
838    fn mul(self, rhs: Self) -> Self {
839        self.mul_quat(rhs)
840    }
841}
842
843impl MulAssign<Quat> for Quat {
844    /// Multiplies two quaternions. If they each represent a rotation, the result will
845    /// represent the combined rotation.
846    ///
847    /// Note that due to floating point rounding the result may not be perfectly
848    /// normalized.
849    ///
850    /// # Panics
851    ///
852    /// Will panic if `self` or `rhs` are not normalized when `glam_assert` is enabled.
853    #[inline]
854    fn mul_assign(&mut self, rhs: Self) {
855        *self = self.mul_quat(rhs);
856    }
857}
858
859impl Mul<Vec3> for Quat {
860    type Output = Vec3;
861    /// Multiplies a quaternion and a 3D vector, returning the rotated vector.
862    ///
863    /// # Panics
864    ///
865    /// Will panic if `self` is not normalized when `glam_assert` is enabled.
866    #[inline]
867    fn mul(self, rhs: Vec3) -> Self::Output {
868        self.mul_vec3(rhs)
869    }
870}
871
872impl Neg for Quat {
873    type Output = Self;
874    #[inline]
875    fn neg(self) -> Self {
876        self * -1.0
877    }
878}
879
880impl Default for Quat {
881    #[inline]
882    fn default() -> Self {
883        Self::IDENTITY
884    }
885}
886
887impl PartialEq for Quat {
888    #[inline]
889    fn eq(&self, rhs: &Self) -> bool {
890        Vec4::from(*self).eq(&Vec4::from(*rhs))
891    }
892}
893
894#[cfg(not(target_arch = "spirv"))]
895impl AsRef<[f32; 4]> for Quat {
896    #[inline]
897    fn as_ref(&self) -> &[f32; 4] {
898        unsafe { &*(self as *const Self as *const [f32; 4]) }
899    }
900}
901
902impl Sum<Self> for Quat {
903    fn sum<I>(iter: I) -> Self
904    where
905        I: Iterator<Item = Self>,
906    {
907        iter.fold(Self::ZERO, Self::add)
908    }
909}
910
911impl<'a> Sum<&'a Self> for Quat {
912    fn sum<I>(iter: I) -> Self
913    where
914        I: Iterator<Item = &'a Self>,
915    {
916        iter.fold(Self::ZERO, |a, &b| Self::add(a, b))
917    }
918}
919
920impl Product for Quat {
921    fn product<I>(iter: I) -> Self
922    where
923        I: Iterator<Item = Self>,
924    {
925        iter.fold(Self::IDENTITY, Self::mul)
926    }
927}
928
929impl<'a> Product<&'a Self> for Quat {
930    fn product<I>(iter: I) -> Self
931    where
932        I: Iterator<Item = &'a Self>,
933    {
934        iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b))
935    }
936}
937
938impl Mul<Vec3A> for Quat {
939    type Output = Vec3A;
940    #[inline]
941    fn mul(self, rhs: Vec3A) -> Self::Output {
942        self.mul_vec3a(rhs)
943    }
944}
945
946impl From<Quat> for Vec4 {
947    #[inline]
948    fn from(q: Quat) -> Self {
949        Self(q.0)
950    }
951}
952
953impl From<Quat> for (f32, f32, f32, f32) {
954    #[inline]
955    fn from(q: Quat) -> Self {
956        Vec4::from(q).into()
957    }
958}
959
960impl From<Quat> for [f32; 4] {
961    #[inline]
962    fn from(q: Quat) -> Self {
963        Vec4::from(q).into()
964    }
965}
966
967impl From<Quat> for __m128 {
968    #[inline]
969    fn from(q: Quat) -> Self {
970        q.0
971    }
972}
973
974impl Deref for Quat {
975    type Target = crate::deref::Vec4<f32>;
976    #[inline]
977    fn deref(&self) -> &Self::Target {
978        unsafe { &*(self as *const Self).cast() }
979    }
980}
981
982impl DerefMut for Quat {
983    #[inline]
984    fn deref_mut(&mut self) -> &mut Self::Target {
985        unsafe { &mut *(self as *mut Self).cast() }
986    }
987}