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(crate) 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::Affine3A) -> Self {
847        #[allow(clippy::useless_conversion)]
848        Self::from_rotation_axes(
849            a.matrix3.x_axis.into(),
850            a.matrix3.y_axis.into(),
851            a.matrix3.z_axis.into(),
852        )
853    }
854
855    /// Multiplies a quaternion and a 3D vector, returning the rotated vector.
856    #[inline]
857    #[must_use]
858    pub fn mul_vec3a(self, rhs: Vec3A) -> Vec3A {
859        unsafe {
860            let w = self.w;
861            let b = Vec3A::from(self.0);
862            let b2 = b.length_squared();
863            Vec3A(vaddq_f32(
864                vaddq_f32(
865                    vmulq_n_f32(rhs.0, (w * w) - b2),
866                    vmulq_n_f32(b.0, rhs.dot(b) * 2.0),
867                ),
868                vmulq_n_f32(b.cross(rhs).0, w * 2.0),
869            ))
870        }
871    }
872
873    #[inline]
874    #[must_use]
875    pub fn as_dquat(self) -> DQuat {
876        DQuat::from_xyzw(self.x as f64, self.y as f64, self.z as f64, self.w as f64)
877    }
878}
879
880impl fmt::Debug for Quat {
881    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
882        fmt.debug_tuple(stringify!(Quat))
883            .field(&self.x)
884            .field(&self.y)
885            .field(&self.z)
886            .field(&self.w)
887            .finish()
888    }
889}
890
891impl fmt::Display for Quat {
892    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
893        if let Some(p) = f.precision() {
894            write!(
895                f,
896                "[{:.*}, {:.*}, {:.*}, {:.*}]",
897                p, self.x, p, self.y, p, self.z, p, self.w
898            )
899        } else {
900            write!(f, "[{}, {}, {}, {}]", self.x, self.y, self.z, self.w)
901        }
902    }
903}
904
905impl Add for Quat {
906    type Output = Self;
907    /// Adds two quaternions.
908    ///
909    /// The sum is not guaranteed to be normalized.
910    ///
911    /// Note that addition is not the same as combining the rotations represented by the
912    /// two quaternions! That corresponds to multiplication.
913    #[inline]
914    fn add(self, rhs: Self) -> Self {
915        Self::from_vec4(Vec4::from(self) + Vec4::from(rhs))
916    }
917}
918
919impl Add<&Self> for Quat {
920    type Output = Self;
921    #[inline]
922    fn add(self, rhs: &Self) -> Self {
923        self.add(*rhs)
924    }
925}
926
927impl Add<&Quat> for &Quat {
928    type Output = Quat;
929    #[inline]
930    fn add(self, rhs: &Quat) -> Quat {
931        (*self).add(*rhs)
932    }
933}
934
935impl Add<Quat> for &Quat {
936    type Output = Quat;
937    #[inline]
938    fn add(self, rhs: Quat) -> Quat {
939        (*self).add(rhs)
940    }
941}
942
943impl AddAssign for Quat {
944    #[inline]
945    fn add_assign(&mut self, rhs: Self) {
946        *self = self.add(rhs);
947    }
948}
949
950impl AddAssign<&Self> for Quat {
951    #[inline]
952    fn add_assign(&mut self, rhs: &Self) {
953        self.add_assign(*rhs);
954    }
955}
956
957impl Sub for Quat {
958    type Output = Self;
959    /// Subtracts the `rhs` quaternion from `self`.
960    ///
961    /// The difference is not guaranteed to be normalized.
962    #[inline]
963    fn sub(self, rhs: Self) -> Self {
964        Self::from_vec4(Vec4::from(self) - Vec4::from(rhs))
965    }
966}
967
968impl Sub<&Self> for Quat {
969    type Output = Self;
970    #[inline]
971    fn sub(self, rhs: &Self) -> Self {
972        self.sub(*rhs)
973    }
974}
975
976impl Sub<&Quat> for &Quat {
977    type Output = Quat;
978    #[inline]
979    fn sub(self, rhs: &Quat) -> Quat {
980        (*self).sub(*rhs)
981    }
982}
983
984impl Sub<Quat> for &Quat {
985    type Output = Quat;
986    #[inline]
987    fn sub(self, rhs: Quat) -> Quat {
988        (*self).sub(rhs)
989    }
990}
991
992impl SubAssign for Quat {
993    #[inline]
994    fn sub_assign(&mut self, rhs: Self) {
995        *self = self.sub(rhs);
996    }
997}
998
999impl SubAssign<&Self> for Quat {
1000    #[inline]
1001    fn sub_assign(&mut self, rhs: &Self) {
1002        self.sub_assign(*rhs);
1003    }
1004}
1005
1006impl Mul<f32> for Quat {
1007    type Output = Self;
1008    /// Multiplies a quaternion by a scalar value.
1009    ///
1010    /// The product is not guaranteed to be normalized.
1011    #[inline]
1012    fn mul(self, rhs: f32) -> Self {
1013        Self::from_vec4(Vec4::from(self) * rhs)
1014    }
1015}
1016
1017impl Mul<&f32> for Quat {
1018    type Output = Self;
1019    #[inline]
1020    fn mul(self, rhs: &f32) -> Self {
1021        self.mul(*rhs)
1022    }
1023}
1024
1025impl Mul<&f32> for &Quat {
1026    type Output = Quat;
1027    #[inline]
1028    fn mul(self, rhs: &f32) -> Quat {
1029        (*self).mul(*rhs)
1030    }
1031}
1032
1033impl Mul<f32> for &Quat {
1034    type Output = Quat;
1035    #[inline]
1036    fn mul(self, rhs: f32) -> Quat {
1037        (*self).mul(rhs)
1038    }
1039}
1040
1041impl MulAssign<f32> for Quat {
1042    #[inline]
1043    fn mul_assign(&mut self, rhs: f32) {
1044        *self = self.mul(rhs);
1045    }
1046}
1047
1048impl MulAssign<&f32> for Quat {
1049    #[inline]
1050    fn mul_assign(&mut self, rhs: &f32) {
1051        self.mul_assign(*rhs);
1052    }
1053}
1054
1055impl Div<f32> for Quat {
1056    type Output = Self;
1057    /// Divides a quaternion by a scalar value.
1058    /// The quotient is not guaranteed to be normalized.
1059    #[inline]
1060    fn div(self, rhs: f32) -> Self {
1061        Self::from_vec4(Vec4::from(self) / rhs)
1062    }
1063}
1064
1065impl Div<&f32> for Quat {
1066    type Output = Self;
1067    #[inline]
1068    fn div(self, rhs: &f32) -> Self {
1069        self.div(*rhs)
1070    }
1071}
1072
1073impl Div<&f32> for &Quat {
1074    type Output = Quat;
1075    #[inline]
1076    fn div(self, rhs: &f32) -> Quat {
1077        (*self).div(*rhs)
1078    }
1079}
1080
1081impl Div<f32> for &Quat {
1082    type Output = Quat;
1083    #[inline]
1084    fn div(self, rhs: f32) -> Quat {
1085        (*self).div(rhs)
1086    }
1087}
1088
1089impl DivAssign<f32> for Quat {
1090    #[inline]
1091    fn div_assign(&mut self, rhs: f32) {
1092        *self = self.div(rhs);
1093    }
1094}
1095
1096impl DivAssign<&f32> for Quat {
1097    #[inline]
1098    fn div_assign(&mut self, rhs: &f32) {
1099        self.div_assign(*rhs);
1100    }
1101}
1102
1103impl Mul for Quat {
1104    type Output = Self;
1105    /// Multiplies two quaternions. If they each represent a rotation, the result will
1106    /// represent the combined rotation.
1107    ///
1108    /// Note that due to floating point rounding the result may not be perfectly
1109    /// normalized.
1110    ///
1111    /// # Panics
1112    ///
1113    /// Will panic if `self` or `rhs` are not normalized when `glam_assert` is enabled.
1114    #[inline]
1115    fn mul(self, rhs: Self) -> Self {
1116        self.mul_quat(rhs)
1117    }
1118}
1119
1120impl Mul<&Self> for Quat {
1121    type Output = Self;
1122    #[inline]
1123    fn mul(self, rhs: &Self) -> Self {
1124        self.mul(*rhs)
1125    }
1126}
1127
1128impl Mul<&Quat> for &Quat {
1129    type Output = Quat;
1130    #[inline]
1131    fn mul(self, rhs: &Quat) -> Quat {
1132        (*self).mul(*rhs)
1133    }
1134}
1135
1136impl Mul<Quat> for &Quat {
1137    type Output = Quat;
1138    #[inline]
1139    fn mul(self, rhs: Quat) -> Quat {
1140        (*self).mul(rhs)
1141    }
1142}
1143
1144impl MulAssign for Quat {
1145    #[inline]
1146    fn mul_assign(&mut self, rhs: Self) {
1147        *self = self.mul(rhs);
1148    }
1149}
1150
1151impl MulAssign<&Self> for Quat {
1152    #[inline]
1153    fn mul_assign(&mut self, rhs: &Self) {
1154        self.mul_assign(*rhs);
1155    }
1156}
1157
1158impl Mul<Vec3> for Quat {
1159    type Output = Vec3;
1160    /// Multiplies a quaternion and a 3D vector, returning the rotated vector.
1161    ///
1162    /// # Panics
1163    ///
1164    /// Will panic if `self` is not normalized when `glam_assert` is enabled.
1165    #[inline]
1166    fn mul(self, rhs: Vec3) -> Self::Output {
1167        self.mul_vec3(rhs)
1168    }
1169}
1170
1171impl Mul<&Vec3> for Quat {
1172    type Output = Vec3;
1173    #[inline]
1174    fn mul(self, rhs: &Vec3) -> Vec3 {
1175        self.mul(*rhs)
1176    }
1177}
1178
1179impl Mul<&Vec3> for &Quat {
1180    type Output = Vec3;
1181    #[inline]
1182    fn mul(self, rhs: &Vec3) -> Vec3 {
1183        (*self).mul(*rhs)
1184    }
1185}
1186
1187impl Mul<Vec3> for &Quat {
1188    type Output = Vec3;
1189    #[inline]
1190    fn mul(self, rhs: Vec3) -> Vec3 {
1191        (*self).mul(rhs)
1192    }
1193}
1194
1195impl Mul<Vec3A> for Quat {
1196    type Output = Vec3A;
1197    #[inline]
1198    fn mul(self, rhs: Vec3A) -> Self::Output {
1199        self.mul_vec3a(rhs)
1200    }
1201}
1202
1203impl Mul<&Vec3A> for Quat {
1204    type Output = Vec3A;
1205    #[inline]
1206    fn mul(self, rhs: &Vec3A) -> Vec3A {
1207        self.mul(*rhs)
1208    }
1209}
1210
1211impl Mul<&Vec3A> for &Quat {
1212    type Output = Vec3A;
1213    #[inline]
1214    fn mul(self, rhs: &Vec3A) -> Vec3A {
1215        (*self).mul(*rhs)
1216    }
1217}
1218
1219impl Mul<Vec3A> for &Quat {
1220    type Output = Vec3A;
1221    #[inline]
1222    fn mul(self, rhs: Vec3A) -> Vec3A {
1223        (*self).mul(rhs)
1224    }
1225}
1226
1227impl Neg for Quat {
1228    type Output = Self;
1229    #[inline]
1230    fn neg(self) -> Self {
1231        self * -1.0
1232    }
1233}
1234
1235impl Neg for &Quat {
1236    type Output = Quat;
1237    #[inline]
1238    fn neg(self) -> Quat {
1239        (*self).neg()
1240    }
1241}
1242
1243impl Default for Quat {
1244    #[inline]
1245    fn default() -> Self {
1246        Self::IDENTITY
1247    }
1248}
1249
1250impl PartialEq for Quat {
1251    #[inline]
1252    fn eq(&self, rhs: &Self) -> bool {
1253        Vec4::from(*self).eq(&Vec4::from(*rhs))
1254    }
1255}
1256
1257impl AsRef<[f32; 4]> for Quat {
1258    #[inline]
1259    fn as_ref(&self) -> &[f32; 4] {
1260        unsafe { &*(self as *const Self as *const [f32; 4]) }
1261    }
1262}
1263
1264impl Sum<Self> for Quat {
1265    fn sum<I>(iter: I) -> Self
1266    where
1267        I: Iterator<Item = Self>,
1268    {
1269        iter.fold(Self::ZERO, Self::add)
1270    }
1271}
1272
1273impl<'a> Sum<&'a Self> for Quat {
1274    fn sum<I>(iter: I) -> Self
1275    where
1276        I: Iterator<Item = &'a Self>,
1277    {
1278        iter.fold(Self::ZERO, |a, &b| Self::add(a, b))
1279    }
1280}
1281
1282impl Product for Quat {
1283    fn product<I>(iter: I) -> Self
1284    where
1285        I: Iterator<Item = Self>,
1286    {
1287        iter.fold(Self::IDENTITY, Self::mul)
1288    }
1289}
1290
1291impl<'a> Product<&'a Self> for Quat {
1292    fn product<I>(iter: I) -> Self
1293    where
1294        I: Iterator<Item = &'a Self>,
1295    {
1296        iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b))
1297    }
1298}
1299
1300impl From<Quat> for Vec4 {
1301    #[inline]
1302    fn from(q: Quat) -> Self {
1303        Self(q.0)
1304    }
1305}
1306
1307impl From<Quat> for (f32, f32, f32, f32) {
1308    #[inline]
1309    fn from(q: Quat) -> Self {
1310        Vec4::from(q).into()
1311    }
1312}
1313
1314impl From<Quat> for [f32; 4] {
1315    #[inline]
1316    fn from(q: Quat) -> Self {
1317        Vec4::from(q).into()
1318    }
1319}
1320
1321impl From<Quat> for float32x4_t {
1322    #[inline]
1323    fn from(q: Quat) -> Self {
1324        q.0
1325    }
1326}
1327
1328impl Deref for Quat {
1329    type Target = crate::deref::Vec4<f32>;
1330    #[inline]
1331    fn deref(&self) -> &Self::Target {
1332        unsafe { &*(self as *const Self).cast() }
1333    }
1334}
1335
1336impl DerefMut for Quat {
1337    #[inline]
1338    fn deref_mut(&mut self) -> &mut Self::Target {
1339        unsafe { &mut *(self as *mut Self).cast() }
1340    }
1341}