glam/f32/neon/
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    neon::*,
7    DQuat, Mat3, Mat3A, Mat4, Vec2, Vec3, Vec3A, Vec4,
8};
9
10use core::arch::aarch64::*;
11
12use core::fmt;
13use core::iter::{Product, Sum};
14use core::ops::{
15    Add, AddAssign, Deref, DerefMut, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign,
16};
17
18#[repr(C)]
19union UnionCast {
20    a: [f32; 4],
21    v: Quat,
22}
23
24/// Creates a quaternion from `x`, `y`, `z` and `w` values.
25///
26/// This should generally not be called manually unless you know what you are doing. Use
27/// one of the other constructors instead such as `identity` or `from_axis_angle`.
28#[inline]
29#[must_use]
30pub const fn quat(x: f32, y: f32, z: f32, w: f32) -> Quat {
31    Quat::from_xyzw(x, y, z, w)
32}
33
34/// A quaternion representing an orientation.
35///
36/// This quaternion is intended to be of unit length but may denormalize due to
37/// floating point "error creep" which can occur when successive quaternion
38/// operations are applied.
39///
40/// SIMD vector types are used for storage on supported platforms.
41///
42/// This type is 16 byte aligned.
43#[derive(Clone, Copy)]
44#[cfg_attr(feature = "bytemuck", derive(bytemuck::Pod, bytemuck::Zeroable))]
45#[repr(transparent)]
46pub struct Quat(pub(crate) float32x4_t);
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 { vld1q_f32(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 { vst1q_f32(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    /// Creates a quaterion rotation from a facing direction and an up direction.
400    ///
401    /// For a left-handed view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`.
402    ///
403    /// # Panics
404    ///
405    /// Will panic if `up` is not normalized when `glam_assert` is enabled.
406    #[inline]
407    #[must_use]
408    pub fn look_to_lh(dir: Vec3, up: Vec3) -> Self {
409        Self::look_to_rh(-dir, up)
410    }
411
412    /// Creates a quaterion rotation from facing direction and an up direction.
413    ///
414    /// For a right-handed view coordinate system with `+X=right`, `+Y=up` and `+Z=back`.
415    ///
416    /// # Panics
417    ///
418    /// Will panic if `dir` and `up` are not normalized when `glam_assert` is enabled.
419    #[inline]
420    #[must_use]
421    pub fn look_to_rh(dir: Vec3, up: Vec3) -> Self {
422        glam_assert!(dir.is_normalized());
423        glam_assert!(up.is_normalized());
424        let f = dir;
425        let s = f.cross(up).normalize();
426        let u = s.cross(f);
427
428        Self::from_rotation_axes(
429            Vec3::new(s.x, u.x, -f.x),
430            Vec3::new(s.y, u.y, -f.y),
431            Vec3::new(s.z, u.z, -f.z),
432        )
433    }
434
435    /// Creates a left-handed view matrix using a camera position, a focal point, and an up
436    /// direction.
437    ///
438    /// For a left-handed view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`.
439    ///
440    /// # Panics
441    ///
442    /// Will panic if `up` is not normalized when `glam_assert` is enabled.
443    #[inline]
444    #[must_use]
445    pub fn look_at_lh(eye: Vec3, center: Vec3, up: Vec3) -> Self {
446        Self::look_to_lh(center.sub(eye).normalize(), up)
447    }
448
449    /// Creates a right-handed view matrix using a camera position, an up direction, and a focal
450    /// point.
451    ///
452    /// For a right-handed view coordinate system with `+X=right`, `+Y=up` and `+Z=back`.
453    ///
454    /// # Panics
455    ///
456    /// Will panic if `up` is not normalized when `glam_assert` is enabled.
457    #[inline]
458    #[must_use]
459    pub fn look_at_rh(eye: Vec3, center: Vec3, up: Vec3) -> Self {
460        Self::look_to_rh(center.sub(eye).normalize(), up)
461    }
462
463    /// Returns the rotation axis (normalized) and angle (in radians) of `self`.
464    #[inline]
465    #[must_use]
466    pub fn to_axis_angle(self) -> (Vec3, f32) {
467        const EPSILON: f32 = 1.0e-8;
468        let v = Vec3::new(self.x, self.y, self.z);
469        let length = v.length();
470        if length >= EPSILON {
471            let angle = 2.0 * math::atan2(length, self.w);
472            let axis = v / length;
473            (axis, angle)
474        } else {
475            (Vec3::X, 0.0)
476        }
477    }
478
479    /// Returns the rotation axis scaled by the rotation in radians.
480    #[inline]
481    #[must_use]
482    pub fn to_scaled_axis(self) -> Vec3 {
483        let (axis, angle) = self.to_axis_angle();
484        axis * angle
485    }
486
487    /// Returns the rotation angles for the given euler rotation sequence.
488    #[inline]
489    #[must_use]
490    pub fn to_euler(self, order: EulerRot) -> (f32, f32, f32) {
491        self.to_euler_angles(order)
492    }
493
494    /// `[x, y, z, w]`
495    #[inline]
496    #[must_use]
497    pub fn to_array(&self) -> [f32; 4] {
498        [self.x, self.y, self.z, self.w]
499    }
500
501    /// Returns the vector part of the quaternion.
502    #[inline]
503    #[must_use]
504    pub fn xyz(self) -> Vec3 {
505        Vec3::new(self.x, self.y, self.z)
506    }
507
508    /// Returns the quaternion conjugate of `self`. For a unit quaternion the
509    /// conjugate is also the inverse.
510    #[inline]
511    #[must_use]
512    pub fn conjugate(self) -> Self {
513        const SIGN: float32x4_t = f32x4_from_array([-1.0, -1.0, -1.0, 1.0]);
514        Self(unsafe { vmulq_f32(self.0, SIGN) })
515    }
516
517    /// Returns the inverse of a normalized quaternion.
518    ///
519    /// Typically quaternion inverse returns the conjugate of a normalized quaternion.
520    /// Because `self` is assumed to already be unit length this method *does not* normalize
521    /// before returning the conjugate.
522    ///
523    /// # Panics
524    ///
525    /// Will panic if `self` is not normalized when `glam_assert` is enabled.
526    #[inline]
527    #[must_use]
528    pub fn inverse(self) -> Self {
529        glam_assert!(self.is_normalized());
530        self.conjugate()
531    }
532
533    /// Computes the dot product of `self` and `rhs`. The dot product is
534    /// equal to the cosine of the angle between two quaternion rotations.
535    #[inline]
536    #[must_use]
537    pub fn dot(self, rhs: Self) -> f32 {
538        Vec4::from(self).dot(Vec4::from(rhs))
539    }
540
541    /// Computes the length of `self`.
542    #[doc(alias = "magnitude")]
543    #[inline]
544    #[must_use]
545    pub fn length(self) -> f32 {
546        Vec4::from(self).length()
547    }
548
549    /// Computes the squared length of `self`.
550    ///
551    /// This is generally faster than `length()` as it avoids a square
552    /// root operation.
553    #[doc(alias = "magnitude2")]
554    #[inline]
555    #[must_use]
556    pub fn length_squared(self) -> f32 {
557        Vec4::from(self).length_squared()
558    }
559
560    /// Computes `1.0 / length()`.
561    ///
562    /// For valid results, `self` must _not_ be of length zero.
563    #[inline]
564    #[must_use]
565    pub fn length_recip(self) -> f32 {
566        Vec4::from(self).length_recip()
567    }
568
569    /// Returns `self` normalized to length 1.0.
570    ///
571    /// For valid results, `self` must _not_ be of length zero.
572    ///
573    /// Panics
574    ///
575    /// Will panic if `self` is zero length when `glam_assert` is enabled.
576    #[inline]
577    #[must_use]
578    pub fn normalize(self) -> Self {
579        Self::from_vec4(Vec4::from(self).normalize())
580    }
581
582    /// Returns `true` if, and only if, all elements are finite.
583    /// If any element is either `NaN`, positive or negative infinity, this will return `false`.
584    #[inline]
585    #[must_use]
586    pub fn is_finite(self) -> bool {
587        Vec4::from(self).is_finite()
588    }
589
590    /// Returns `true` if any elements are `NAN`.
591    #[inline]
592    #[must_use]
593    pub fn is_nan(self) -> bool {
594        Vec4::from(self).is_nan()
595    }
596
597    /// Returns whether `self` of length `1.0` or not.
598    ///
599    /// Uses a precision threshold of `1e-6`.
600    #[inline]
601    #[must_use]
602    pub fn is_normalized(self) -> bool {
603        Vec4::from(self).is_normalized()
604    }
605
606    #[inline]
607    #[must_use]
608    pub fn is_near_identity(self) -> bool {
609        // Based on https://github.com/nfrechette/rtm `rtm::quat_near_identity`
610        let threshold_angle = 0.002_847_144_6;
611        // Because of floating point precision, we cannot represent very small rotations.
612        // The closest f32 to 1.0 that is not 1.0 itself yields:
613        // 0.99999994.acos() * 2.0  = 0.000690533954 rad
614        //
615        // An error threshold of 1.e-6 is used by default.
616        // (1.0 - 1.e-6).acos() * 2.0 = 0.00284714461 rad
617        // (1.0 - 1.e-7).acos() * 2.0 = 0.00097656250 rad
618        //
619        // We don't really care about the angle value itself, only if it's close to 0.
620        // This will happen whenever quat.w is close to 1.0.
621        // If the quat.w is close to -1.0, the angle will be near 2*PI which is close to
622        // a negative 0 rotation. By forcing quat.w to be positive, we'll end up with
623        // the shortest path.
624        let positive_w_angle = math::acos_approx(math::abs(self.w)) * 2.0;
625        positive_w_angle < threshold_angle
626    }
627
628    /// Returns the angle (in radians) for the minimal rotation
629    /// for transforming this quaternion into another.
630    ///
631    /// Both quaternions must be normalized.
632    ///
633    /// # Panics
634    ///
635    /// Will panic if `self` or `rhs` are not normalized when `glam_assert` is enabled.
636    #[inline]
637    #[must_use]
638    pub fn angle_between(self, rhs: Self) -> f32 {
639        glam_assert!(self.is_normalized() && rhs.is_normalized());
640        math::acos_approx(math::abs(self.dot(rhs))) * 2.0
641    }
642
643    /// Rotates towards `rhs` up to `max_angle` (in radians).
644    ///
645    /// When `max_angle` is `0.0`, the result will be equal to `self`. When `max_angle` is equal to
646    /// `self.angle_between(rhs)`, the result will be equal to `rhs`. If `max_angle` is negative,
647    /// rotates towards the exact opposite of `rhs`. Will not go past the target.
648    ///
649    /// Both quaternions must be normalized.
650    ///
651    /// # Panics
652    ///
653    /// Will panic if `self` or `rhs` are not normalized when `glam_assert` is enabled.
654    #[inline]
655    #[must_use]
656    pub fn rotate_towards(&self, rhs: Self, max_angle: f32) -> Self {
657        glam_assert!(self.is_normalized() && rhs.is_normalized());
658        let angle = self.angle_between(rhs);
659        if angle <= 1e-4 {
660            return rhs;
661        }
662        let s = (max_angle / angle).clamp(-1.0, 1.0);
663        self.slerp(rhs, s)
664    }
665
666    /// Returns true if the absolute difference of all elements between `self` and `rhs`
667    /// is less than or equal to `max_abs_diff`.
668    ///
669    /// This can be used to compare if two quaternions contain similar elements. It works
670    /// best when comparing with a known value. The `max_abs_diff` that should be used used
671    /// depends on the values being compared against.
672    ///
673    /// For more see
674    /// [comparing floating point numbers](https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/).
675    #[inline]
676    #[must_use]
677    pub fn abs_diff_eq(self, rhs: Self, max_abs_diff: f32) -> bool {
678        Vec4::from(self).abs_diff_eq(Vec4::from(rhs), max_abs_diff)
679    }
680
681    #[inline(always)]
682    #[must_use]
683    fn lerp_impl(self, end: Self, s: f32) -> Self {
684        (self * (1.0 - s) + end * s).normalize()
685    }
686
687    /// Performs a linear interpolation between `self` and `rhs` based on
688    /// the value `s`.
689    ///
690    /// When `s` is `0.0`, the result will be equal to `self`.  When `s`
691    /// is `1.0`, the result will be equal to `rhs`.
692    ///
693    /// # Panics
694    ///
695    /// Will panic if `self` or `end` are not normalized when `glam_assert` is enabled.
696    #[doc(alias = "mix")]
697    #[inline]
698    #[must_use]
699    pub fn lerp(self, end: Self, s: f32) -> Self {
700        glam_assert!(self.is_normalized());
701        glam_assert!(end.is_normalized());
702
703        const NEG_ZERO: float32x4_t = f32x4_from_array([-0.0; 4]);
704        unsafe {
705            let dot = dot4_into_f32x4(self.0, end.0);
706            // Calculate the bias, if the dot product is positive or zero, there is no bias
707            // but if it is negative, we want to flip the 'end' rotation XYZW components
708            let bias = vandq_u32(vreinterpretq_u32_f32(dot), vreinterpretq_u32_f32(NEG_ZERO));
709            self.lerp_impl(
710                Self(vreinterpretq_f32_u32(veorq_u32(
711                    vreinterpretq_u32_f32(end.0),
712                    bias,
713                ))),
714                s,
715            )
716        }
717    }
718
719    /// Performs a spherical linear interpolation between `self` and `end`
720    /// based on the value `s`.
721    ///
722    /// When `s` is `0.0`, the result will be equal to `self`.  When `s`
723    /// is `1.0`, the result will be equal to `end`.
724    ///
725    /// # Panics
726    ///
727    /// Will panic if `self` or `end` are not normalized when `glam_assert` is enabled.
728    #[inline]
729    #[must_use]
730    pub fn slerp(self, mut end: Self, s: f32) -> Self {
731        // http://number-none.com/product/Understanding%20Slerp,%20Then%20Not%20Using%20It/
732        glam_assert!(self.is_normalized());
733        glam_assert!(end.is_normalized());
734
735        // Note that a rotation can be represented by two quaternions: `q` and
736        // `-q`. The slerp path between `q` and `end` will be different from the
737        // path between `-q` and `end`. One path will take the long way around and
738        // one will take the short way. In order to correct for this, the `dot`
739        // product between `self` and `end` should be positive. If the `dot`
740        // product is negative, slerp between `self` and `-end`.
741        let mut dot = self.dot(end);
742        if dot < 0.0 {
743            end = -end;
744            dot = -dot;
745        }
746
747        const DOT_THRESHOLD: f32 = 1.0 - f32::EPSILON;
748        if dot > DOT_THRESHOLD {
749            // if above threshold perform linear interpolation to avoid divide by zero
750            self.lerp_impl(end, s)
751        } else {
752            let theta = math::acos_approx(dot);
753
754            let scale1 = math::sin(theta * (1.0 - s));
755            let scale2 = math::sin(theta * s);
756            let theta_sin = math::sin(theta);
757            ((self * scale1) + (end * scale2)) * (1.0 / theta_sin)
758        }
759    }
760
761    /// Multiplies a quaternion and a 3D vector, returning the rotated vector.
762    ///
763    /// # Panics
764    ///
765    /// Will panic if `self` is not normalized when `glam_assert` is enabled.
766    #[inline]
767    #[must_use]
768    pub fn mul_vec3(self, rhs: Vec3) -> Vec3 {
769        glam_assert!(self.is_normalized());
770
771        self.mul_vec3a(rhs.into()).into()
772    }
773
774    /// Multiplies two quaternions. If they each represent a rotation, the result will
775    /// represent the combined rotation.
776    ///
777    /// Note that due to floating point rounding the result may not be perfectly normalized.
778    ///
779    /// # Panics
780    ///
781    /// Will panic if `self` or `rhs` are not normalized when `glam_assert` is enabled.
782    #[inline]
783    #[must_use]
784    pub fn mul_quat(self, rhs: Self) -> Self {
785        unsafe {
786            let lhs = self.0;
787            let rhs = rhs.0;
788
789            const CONTROL_WZYX: float32x4_t = f32x4_from_array([1.0, -1.0, 1.0, -1.0]);
790            const CONTROL_ZWXY: float32x4_t = f32x4_from_array([1.0, 1.0, -1.0, -1.0]);
791            const CONTROL_YXWZ: float32x4_t = f32x4_from_array([-1.0, 1.0, 1.0, -1.0]);
792
793            let r_xxxx = vdupq_laneq_f32(lhs, 0);
794            let r_yyyy = vdupq_laneq_f32(lhs, 1);
795            let r_zzzz = vdupq_laneq_f32(lhs, 2);
796            let r_wwww = vdupq_laneq_f32(lhs, 3);
797
798            let lxrw_lyrw_lzrw_lwrw = vmulq_f32(r_wwww, rhs);
799            //let l_wzyx = simd_swizzle!(rhs, [3, 2, 1, 0]);
800            let l_wzyx = vrev64q_f32(rhs);
801            let l_wzyx = vextq_f32(l_wzyx, l_wzyx, 2);
802
803            let lwrx_lzrx_lyrx_lxrx = vmulq_f32(r_xxxx, l_wzyx);
804            //let l_zwxy = simd_swizzle!(l_wzyx, [1, 0, 3, 2]);
805            let l_zwxy = vrev64q_f32(l_wzyx);
806
807            let lwrx_nlzrx_lyrx_nlxrx = vmulq_f32(lwrx_lzrx_lyrx_lxrx, CONTROL_WZYX);
808
809            let lzry_lwry_lxry_lyry = vmulq_f32(r_yyyy, l_zwxy);
810            // let l_yxwz = simd_swizzle!(l_zwxy, [3, 2, 1, 0]);
811            let l_yxwz = vrev64q_f32(l_zwxy);
812            let l_yxwz = vextq_f32(l_yxwz, l_yxwz, 2);
813
814            let lzry_lwry_nlxry_nlyry = vmulq_f32(lzry_lwry_lxry_lyry, CONTROL_ZWXY);
815
816            let lyrz_lxrz_lwrz_lzrz = vmulq_f32(r_zzzz, l_yxwz);
817            let result0 = vaddq_f32(lxrw_lyrw_lzrw_lwrw, lwrx_nlzrx_lyrx_nlxrx);
818
819            let nlyrz_lxrz_lwrz_wlzrz = vmulq_f32(lyrz_lxrz_lwrz_lzrz, CONTROL_YXWZ);
820            let result1 = vaddq_f32(lzry_lwry_nlxry_nlyry, nlyrz_lxrz_lwrz_wlzrz);
821            Self(vaddq_f32(result0, result1))
822        }
823    }
824
825    /// Creates a quaternion from a 3x3 rotation matrix inside a 3D affine transform.
826    ///
827    /// Note if the input affine matrix contain scales, shears, or other non-rotation
828    /// transformations then the resulting quaternion will be ill-defined.
829    ///
830    /// # Panics
831    ///
832    /// Will panic if any input affine matrix column is not normalized when `glam_assert` is
833    /// enabled.
834    #[inline]
835    #[must_use]
836    pub fn from_affine3(a: &crate::Affine3A) -> Self {
837        #[allow(clippy::useless_conversion)]
838        Self::from_rotation_axes(
839            a.matrix3.x_axis.into(),
840            a.matrix3.y_axis.into(),
841            a.matrix3.z_axis.into(),
842        )
843    }
844
845    /// Multiplies a quaternion and a 3D vector, returning the rotated vector.
846    #[inline]
847    #[must_use]
848    pub fn mul_vec3a(self, rhs: Vec3A) -> Vec3A {
849        unsafe {
850            let w = self.w;
851            let b = Vec3A::from(self.0);
852            let b2 = b.length_squared();
853            Vec3A(vaddq_f32(
854                vaddq_f32(
855                    vmulq_n_f32(rhs.0, (w * w) - b2),
856                    vmulq_n_f32(b.0, rhs.dot(b) * 2.0),
857                ),
858                vmulq_n_f32(b.cross(rhs).0, w * 2.0),
859            ))
860        }
861    }
862
863    #[inline]
864    #[must_use]
865    pub fn as_dquat(self) -> DQuat {
866        DQuat::from_xyzw(self.x as f64, self.y as f64, self.z as f64, self.w as f64)
867    }
868}
869
870impl fmt::Debug for Quat {
871    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
872        fmt.debug_tuple(stringify!(Quat))
873            .field(&self.x)
874            .field(&self.y)
875            .field(&self.z)
876            .field(&self.w)
877            .finish()
878    }
879}
880
881impl fmt::Display for Quat {
882    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
883        if let Some(p) = f.precision() {
884            write!(
885                f,
886                "[{:.*}, {:.*}, {:.*}, {:.*}]",
887                p, self.x, p, self.y, p, self.z, p, self.w
888            )
889        } else {
890            write!(f, "[{}, {}, {}, {}]", self.x, self.y, self.z, self.w)
891        }
892    }
893}
894
895impl Add for Quat {
896    type Output = Self;
897    /// Adds two quaternions.
898    ///
899    /// The sum is not guaranteed to be normalized.
900    ///
901    /// Note that addition is not the same as combining the rotations represented by the
902    /// two quaternions! That corresponds to multiplication.
903    #[inline]
904    fn add(self, rhs: Self) -> Self {
905        Self::from_vec4(Vec4::from(self) + Vec4::from(rhs))
906    }
907}
908
909impl Add<&Self> for Quat {
910    type Output = Self;
911    #[inline]
912    fn add(self, rhs: &Self) -> Self {
913        self.add(*rhs)
914    }
915}
916
917impl Add<&Quat> for &Quat {
918    type Output = Quat;
919    #[inline]
920    fn add(self, rhs: &Quat) -> Quat {
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 AddAssign for Quat {
934    #[inline]
935    fn add_assign(&mut self, rhs: Self) {
936        *self = self.add(rhs);
937    }
938}
939
940impl AddAssign<&Self> for Quat {
941    #[inline]
942    fn add_assign(&mut self, rhs: &Self) {
943        self.add_assign(*rhs);
944    }
945}
946
947impl Sub for Quat {
948    type Output = Self;
949    /// Subtracts the `rhs` quaternion from `self`.
950    ///
951    /// The difference is not guaranteed to be normalized.
952    #[inline]
953    fn sub(self, rhs: Self) -> Self {
954        Self::from_vec4(Vec4::from(self) - Vec4::from(rhs))
955    }
956}
957
958impl Sub<&Self> for Quat {
959    type Output = Self;
960    #[inline]
961    fn sub(self, rhs: &Self) -> Self {
962        self.sub(*rhs)
963    }
964}
965
966impl Sub<&Quat> for &Quat {
967    type Output = Quat;
968    #[inline]
969    fn sub(self, rhs: &Quat) -> Quat {
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 SubAssign for Quat {
983    #[inline]
984    fn sub_assign(&mut self, rhs: Self) {
985        *self = self.sub(rhs);
986    }
987}
988
989impl SubAssign<&Self> for Quat {
990    #[inline]
991    fn sub_assign(&mut self, rhs: &Self) {
992        self.sub_assign(*rhs);
993    }
994}
995
996impl Mul<f32> for Quat {
997    type Output = Self;
998    /// Multiplies a quaternion by a scalar value.
999    ///
1000    /// The product is not guaranteed to be normalized.
1001    #[inline]
1002    fn mul(self, rhs: f32) -> Self {
1003        Self::from_vec4(Vec4::from(self) * rhs)
1004    }
1005}
1006
1007impl Mul<&f32> for Quat {
1008    type Output = Self;
1009    #[inline]
1010    fn mul(self, rhs: &f32) -> Self {
1011        self.mul(*rhs)
1012    }
1013}
1014
1015impl Mul<&f32> for &Quat {
1016    type Output = Quat;
1017    #[inline]
1018    fn mul(self, rhs: &f32) -> Quat {
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 MulAssign<f32> for Quat {
1032    #[inline]
1033    fn mul_assign(&mut self, rhs: f32) {
1034        *self = self.mul(rhs);
1035    }
1036}
1037
1038impl MulAssign<&f32> for Quat {
1039    #[inline]
1040    fn mul_assign(&mut self, rhs: &f32) {
1041        self.mul_assign(*rhs);
1042    }
1043}
1044
1045impl Div<f32> for Quat {
1046    type Output = Self;
1047    /// Divides a quaternion by a scalar value.
1048    /// The quotient is not guaranteed to be normalized.
1049    #[inline]
1050    fn div(self, rhs: f32) -> Self {
1051        Self::from_vec4(Vec4::from(self) / rhs)
1052    }
1053}
1054
1055impl Div<&f32> for Quat {
1056    type Output = Self;
1057    #[inline]
1058    fn div(self, rhs: &f32) -> Self {
1059        self.div(*rhs)
1060    }
1061}
1062
1063impl Div<&f32> for &Quat {
1064    type Output = Quat;
1065    #[inline]
1066    fn div(self, rhs: &f32) -> Quat {
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 DivAssign<f32> for Quat {
1080    #[inline]
1081    fn div_assign(&mut self, rhs: f32) {
1082        *self = self.div(rhs);
1083    }
1084}
1085
1086impl DivAssign<&f32> for Quat {
1087    #[inline]
1088    fn div_assign(&mut self, rhs: &f32) {
1089        self.div_assign(*rhs);
1090    }
1091}
1092
1093impl Mul for Quat {
1094    type Output = Self;
1095    /// Multiplies two quaternions. If they each represent a rotation, the result will
1096    /// represent the combined rotation.
1097    ///
1098    /// Note that due to floating point rounding the result may not be perfectly
1099    /// normalized.
1100    ///
1101    /// # Panics
1102    ///
1103    /// Will panic if `self` or `rhs` are not normalized when `glam_assert` is enabled.
1104    #[inline]
1105    fn mul(self, rhs: Self) -> Self {
1106        self.mul_quat(rhs)
1107    }
1108}
1109
1110impl Mul<&Self> for Quat {
1111    type Output = Self;
1112    #[inline]
1113    fn mul(self, rhs: &Self) -> Self {
1114        self.mul(*rhs)
1115    }
1116}
1117
1118impl Mul<&Quat> for &Quat {
1119    type Output = Quat;
1120    #[inline]
1121    fn mul(self, rhs: &Quat) -> Quat {
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 MulAssign for Quat {
1135    #[inline]
1136    fn mul_assign(&mut self, rhs: Self) {
1137        *self = self.mul(rhs);
1138    }
1139}
1140
1141impl MulAssign<&Self> for Quat {
1142    #[inline]
1143    fn mul_assign(&mut self, rhs: &Self) {
1144        self.mul_assign(*rhs);
1145    }
1146}
1147
1148impl Mul<Vec3> for Quat {
1149    type Output = Vec3;
1150    /// Multiplies a quaternion and a 3D vector, returning the rotated vector.
1151    ///
1152    /// # Panics
1153    ///
1154    /// Will panic if `self` is not normalized when `glam_assert` is enabled.
1155    #[inline]
1156    fn mul(self, rhs: Vec3) -> Self::Output {
1157        self.mul_vec3(rhs)
1158    }
1159}
1160
1161impl Mul<&Vec3> for Quat {
1162    type Output = Vec3;
1163    #[inline]
1164    fn mul(self, rhs: &Vec3) -> Vec3 {
1165        self.mul(*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<Vec3A> for Quat {
1186    type Output = Vec3A;
1187    #[inline]
1188    fn mul(self, rhs: Vec3A) -> Self::Output {
1189        self.mul_vec3a(rhs)
1190    }
1191}
1192
1193impl Mul<&Vec3A> for Quat {
1194    type Output = Vec3A;
1195    #[inline]
1196    fn mul(self, rhs: &Vec3A) -> Vec3A {
1197        self.mul(*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 Neg for Quat {
1218    type Output = Self;
1219    #[inline]
1220    fn neg(self) -> Self {
1221        self * -1.0
1222    }
1223}
1224
1225impl Neg for &Quat {
1226    type Output = Quat;
1227    #[inline]
1228    fn neg(self) -> Quat {
1229        (*self).neg()
1230    }
1231}
1232
1233impl Default for Quat {
1234    #[inline]
1235    fn default() -> Self {
1236        Self::IDENTITY
1237    }
1238}
1239
1240impl PartialEq for Quat {
1241    #[inline]
1242    fn eq(&self, rhs: &Self) -> bool {
1243        Vec4::from(*self).eq(&Vec4::from(*rhs))
1244    }
1245}
1246
1247impl AsRef<[f32; 4]> for Quat {
1248    #[inline]
1249    fn as_ref(&self) -> &[f32; 4] {
1250        unsafe { &*(self as *const Self as *const [f32; 4]) }
1251    }
1252}
1253
1254impl Sum<Self> for Quat {
1255    fn sum<I>(iter: I) -> Self
1256    where
1257        I: Iterator<Item = Self>,
1258    {
1259        iter.fold(Self::ZERO, Self::add)
1260    }
1261}
1262
1263impl<'a> Sum<&'a Self> for Quat {
1264    fn sum<I>(iter: I) -> Self
1265    where
1266        I: Iterator<Item = &'a Self>,
1267    {
1268        iter.fold(Self::ZERO, |a, &b| Self::add(a, b))
1269    }
1270}
1271
1272impl Product for Quat {
1273    fn product<I>(iter: I) -> Self
1274    where
1275        I: Iterator<Item = Self>,
1276    {
1277        iter.fold(Self::IDENTITY, Self::mul)
1278    }
1279}
1280
1281impl<'a> Product<&'a Self> for Quat {
1282    fn product<I>(iter: I) -> Self
1283    where
1284        I: Iterator<Item = &'a Self>,
1285    {
1286        iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b))
1287    }
1288}
1289
1290impl From<Quat> for Vec4 {
1291    #[inline]
1292    fn from(q: Quat) -> Self {
1293        Self(q.0)
1294    }
1295}
1296
1297impl From<Quat> for (f32, f32, f32, f32) {
1298    #[inline]
1299    fn from(q: Quat) -> Self {
1300        Vec4::from(q).into()
1301    }
1302}
1303
1304impl From<Quat> for [f32; 4] {
1305    #[inline]
1306    fn from(q: Quat) -> Self {
1307        Vec4::from(q).into()
1308    }
1309}
1310
1311impl From<Quat> for float32x4_t {
1312    #[inline]
1313    fn from(q: Quat) -> Self {
1314        q.0
1315    }
1316}
1317
1318impl Deref for Quat {
1319    type Target = crate::deref::Vec4<f32>;
1320    #[inline]
1321    fn deref(&self) -> &Self::Target {
1322        unsafe { &*(self as *const Self).cast() }
1323    }
1324}
1325
1326impl DerefMut for Quat {
1327    #[inline]
1328    fn deref_mut(&mut self) -> &mut Self::Target {
1329        unsafe { &mut *(self as *mut Self).cast() }
1330    }
1331}