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