Skip to main content

glam/f64/
dquat.rs

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