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