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