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    DMat3, DMat4, DVec2, DVec3, DVec4, Quat,
5    euler::{EulerRot, FromEuler, ToEuler},
6    f64::math,
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    /// Returns the rotation axis (normalized) and angle (in radians) of `self`.
404    #[inline]
405    #[must_use]
406    pub fn to_axis_angle(self) -> (DVec3, f64) {
407        const EPSILON: f64 = 1.0e-8;
408        let v = DVec3::new(self.x, self.y, self.z);
409        let length = v.length();
410        if length >= EPSILON {
411            let angle = 2.0 * math::atan2(length, self.w);
412            let axis = v / length;
413            (axis, angle)
414        } else {
415            (DVec3::X, 0.0)
416        }
417    }
418
419    /// Returns the rotation axis scaled by the rotation in radians.
420    #[inline]
421    #[must_use]
422    pub fn to_scaled_axis(self) -> DVec3 {
423        let (axis, angle) = self.to_axis_angle();
424        axis * angle
425    }
426
427    /// Returns the rotation angles for the given euler rotation sequence.
428    ///
429    /// # Panics
430    ///
431    /// Will panic if `self` is not normalized when `glam_assert` is enabled.
432    #[inline]
433    #[must_use]
434    #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
435    pub fn to_euler(self, order: EulerRot) -> (f64, f64, f64) {
436        DMat3::from_quat(self).to_euler_angles(order)
437    }
438
439    /// Converts `self` to `[x, y, z, w]`
440    #[inline]
441    #[must_use]
442    pub const fn to_array(&self) -> [f64; 4] {
443        [self.x, self.y, self.z, self.w]
444    }
445
446    /// Returns the vector part of the quaternion.
447    #[inline]
448    #[must_use]
449    pub fn xyz(self) -> DVec3 {
450        DVec3::new(self.x, self.y, self.z)
451    }
452
453    /// Returns the quaternion conjugate of `self`. For a unit quaternion the
454    /// conjugate is also the inverse.
455    #[inline]
456    #[must_use]
457    pub fn conjugate(self) -> Self {
458        Self {
459            x: -self.x,
460            y: -self.y,
461            z: -self.z,
462            w: self.w,
463        }
464    }
465
466    /// Returns the inverse of a normalized quaternion.
467    ///
468    /// Typically quaternion inverse returns the conjugate of a normalized quaternion.
469    /// Because `self` is assumed to already be unit length this method *does not* normalize
470    /// before returning the conjugate.
471    ///
472    /// # Panics
473    ///
474    /// Will panic if `self` is not normalized when `glam_assert` is enabled.
475    #[inline]
476    #[must_use]
477    #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
478    pub fn inverse(self) -> Self {
479        glam_assert!(self.is_normalized());
480        self.conjugate()
481    }
482
483    /// Computes the dot product of `self` and `rhs`. The dot product is
484    /// equal to the cosine of the angle between two quaternion rotations.
485    #[inline]
486    #[must_use]
487    pub fn dot(self, rhs: Self) -> f64 {
488        DVec4::from(self).dot(DVec4::from(rhs))
489    }
490
491    /// Computes the length of `self`.
492    #[doc(alias = "magnitude")]
493    #[inline]
494    #[must_use]
495    pub fn length(self) -> f64 {
496        DVec4::from(self).length()
497    }
498
499    /// Computes the squared length of `self`.
500    ///
501    /// This is generally faster than `length()` as it avoids a square
502    /// root operation.
503    #[doc(alias = "magnitude2")]
504    #[inline]
505    #[must_use]
506    pub fn length_squared(self) -> f64 {
507        DVec4::from(self).length_squared()
508    }
509
510    /// Computes `1.0 / length()`.
511    ///
512    /// For valid results, `self` must _not_ be of length zero.
513    #[inline]
514    #[must_use]
515    pub fn length_recip(self) -> f64 {
516        DVec4::from(self).length_recip()
517    }
518
519    /// Returns `self` normalized to length 1.0.
520    ///
521    /// For valid results, `self` must _not_ be of length zero.
522    ///
523    /// # Panics
524    ///
525    /// Will panic if `self` is zero length when `glam_assert` is enabled.
526    #[inline]
527    #[must_use]
528    #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
529    pub fn normalize(self) -> Self {
530        Self::from_vec4(DVec4::from(self).normalize())
531    }
532
533    /// Returns `true` if, and only if, all elements are finite.
534    /// If any element is either `NaN`, positive or negative infinity, this will return `false`.
535    #[inline]
536    #[must_use]
537    pub fn is_finite(self) -> bool {
538        DVec4::from(self).is_finite()
539    }
540
541    /// Returns `true` if any elements are `NAN`.
542    #[inline]
543    #[must_use]
544    pub fn is_nan(self) -> bool {
545        DVec4::from(self).is_nan()
546    }
547
548    /// Returns whether `self` of length `1.0` or not.
549    ///
550    /// Uses a precision threshold of `1e-6`.
551    #[inline]
552    #[must_use]
553    pub fn is_normalized(self) -> bool {
554        DVec4::from(self).is_normalized()
555    }
556
557    /// Returns `true` if `self` represents a rotation near the identity.
558    #[inline]
559    #[must_use]
560    pub fn is_near_identity(self) -> bool {
561        // Based on https://github.com/nfrechette/rtm `rtm::quat_near_identity`
562        // The shortest rotation angle is `2 * acos(abs(w))`. Since `acos` is monotonically
563        // decreasing, comparing `abs(w)` to the cosine threshold avoids calculating the angle.
564        // Equivalent to an angular threshold of `(1.0 - 1e-14).acos() * 2.0`.
565        const THRESHOLD: f64 = 1.0 - 1e-14;
566        self.w.abs() > THRESHOLD
567    }
568
569    /// Returns the angle (in radians) for the minimal rotation between two quaternions
570    /// in the range `[0, +π]`.
571    ///
572    /// Both quaternions must be normalized.
573    ///
574    /// # Panics
575    ///
576    /// Will panic if `self` or `rhs` are not normalized when `glam_assert` is enabled.
577    #[inline]
578    #[must_use]
579    #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
580    pub fn angle_between(self, rhs: Self) -> f64 {
581        glam_assert!(self.is_normalized() && rhs.is_normalized());
582        math::acos_approx(self.dot(rhs).abs()) * 2.0
583    }
584
585    /// Rotates towards `rhs` up to `max_angle` (in radians).
586    ///
587    /// When `max_angle` is `0.0`, the result will be equal to `self`. When `max_angle` is equal to
588    /// `self.angle_between(rhs)`, the result will be equal to `rhs`. If `max_angle` is negative,
589    /// rotates towards the exact opposite of `rhs`. Will not go past the target.
590    ///
591    /// Both quaternions must be normalized.
592    ///
593    /// # Panics
594    ///
595    /// Will panic if `self` or `rhs` are not normalized when `glam_assert` is enabled.
596    #[inline]
597    #[must_use]
598    #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
599    pub fn rotate_towards(self, rhs: Self, max_angle: f64) -> Self {
600        glam_assert!(self.is_normalized() && rhs.is_normalized());
601        let angle = self.angle_between(rhs);
602        if angle <= 1e-4 {
603            return rhs;
604        }
605        if max_angle < 0.0 {
606            // The rotation opposite `rhs` is the component of `self` orthogonal to it.
607            let target = (self - rhs * self.dot(rhs)).normalize();
608            let angle = self.angle_between(target);
609            if angle <= 1e-4 {
610                return target;
611            }
612            return self.slerp(target, (-max_angle / angle).clamp(0.0, 1.0));
613        }
614        self.slerp(rhs, (max_angle / angle).clamp(0.0, 1.0))
615    }
616
617    /// Returns true if the absolute difference of all elements between `self` and `rhs`
618    /// is less than or equal to `max_abs_diff`.
619    ///
620    /// This can be used to compare if two quaternions contain similar elements. It works
621    /// best when comparing with a known value. The `max_abs_diff` that should be used used
622    /// depends on the values being compared against.
623    ///
624    /// For more see
625    /// [comparing floating point numbers](https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/).
626    #[inline]
627    #[must_use]
628    pub fn abs_diff_eq(self, rhs: Self, max_abs_diff: f64) -> bool {
629        DVec4::from(self).abs_diff_eq(DVec4::from(rhs), max_abs_diff)
630    }
631
632    #[inline(always)]
633    #[must_use]
634    #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
635    fn lerp_impl(self, end: Self, s: f64) -> Self {
636        (self * (1.0 - s) + end * s).normalize()
637    }
638
639    /// Performs a linear interpolation between `self` and `rhs` based on
640    /// the value `s`, using the form `self * (1.0 - s) + end * s` before normalizing.
641    ///
642    /// When `s` is `0.0`, the result will be equal to `self`.  When `s`
643    /// is `1.0`, the result will be equal to `rhs`.
644    ///
645    /// This interpolates linearly between the two rotations and does not rotate at a constant
646    /// angular velocity; see [`slerp`](Self::slerp) if that is required.
647    ///
648    /// # Panics
649    ///
650    /// Will panic if `self` or `end` are not normalized when `glam_assert` is enabled.
651    #[doc(alias = "mix")]
652    #[inline]
653    #[must_use]
654    #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
655    pub fn lerp(self, end: Self, s: f64) -> Self {
656        glam_assert!(self.is_normalized());
657        glam_assert!(end.is_normalized());
658
659        let dot = self.dot(end);
660        let bias = if dot >= 0.0 { 1.0 } else { -1.0 };
661        self.lerp_impl(end * bias, s)
662    }
663
664    #[inline(always)]
665    #[must_use]
666    fn slerp_impl(self, end: Self, dot: f64, s: f64) -> Self {
667        let theta = math::acos_approx(dot);
668
669        let scale1 = math::sin(theta * (1.0 - s));
670        let scale2 = math::sin(theta * s);
671        let theta_sin = math::sin(theta);
672        ((self * scale1) + (end * scale2)) * (1.0 / theta_sin)
673    }
674
675    /// Performs a spherical linear interpolation between `self` and `end`
676    /// based on the value `s`.
677    ///
678    /// When `s` is `0.0`, the result will be equal to `self`.  When `s`
679    /// is `1.0`, the result will be equal to `end`.
680    ///
681    /// # Panics
682    ///
683    /// Will panic if `self` or `end` are not normalized when `glam_assert` is enabled.
684    #[inline]
685    #[must_use]
686    #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
687    pub fn slerp(self, mut end: Self, s: f64) -> Self {
688        // http://number-none.com/product/Understanding%20Slerp,%20Then%20Not%20Using%20It/
689        glam_assert!(self.is_normalized());
690        glam_assert!(end.is_normalized());
691
692        // Note that a rotation can be represented by two quaternions: `q` and
693        // `-q`. The slerp path between `q` and `end` will be different from the
694        // path between `-q` and `end`. One path will take the long way around and
695        // one will take the short way. In order to correct for this, the `dot`
696        // product between `self` and `end` should be positive. If the `dot`
697        // product is negative, slerp between `self` and `-end`.
698        let mut dot = self.dot(end);
699        if dot < 0.0 {
700            end = -end;
701            dot = -dot;
702        }
703
704        const DOT_THRESHOLD: f64 = 1.0 - f64::EPSILON;
705        if dot > DOT_THRESHOLD {
706            // if above threshold perform linear interpolation to avoid divide by zero
707            self.lerp_impl(end, s)
708        } else {
709            self.slerp_impl(end, dot, s)
710        }
711    }
712
713    /// Performs a spherical linear interpolation between `self` and `end` based on the value `s`,
714    /// preserving the rotation direction.
715    ///
716    /// When `s` is `0.0`, the result will be equal to `self`.  When `s` is `1.0`, the result will
717    /// be equal to `end`.
718    ///
719    /// When the dot product of `self` and `end` is negative, the standard [`slerp`](Self::slerp)
720    /// will flip the end quaternion to take the shortest path, while this method will take the
721    /// longer arc. This is useful when the intended rotation direction must be preserved.
722    ///
723    /// # Panics
724    ///
725    /// Will panic if `self` or `end` are not normalized when `glam_assert` is enabled.
726    #[inline]
727    #[must_use]
728    #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
729    pub fn slerp_long(self, end: Self, s: f64) -> Self {
730        glam_assert!(self.is_normalized());
731        glam_assert!(end.is_normalized());
732
733        let dot = self.dot(end);
734
735        const DOT_THRESHOLD: f64 = 1.0 - f64::EPSILON;
736        if dot.abs() > DOT_THRESHOLD {
737            // if above threshold perform linear interpolation to avoid divide by zero
738            self.lerp_impl(end, s)
739        } else {
740            self.slerp_impl(end, dot, s)
741        }
742    }
743
744    /// Multiplies a quaternion and a 3D vector, returning the rotated vector.
745    ///
746    /// # Panics
747    ///
748    /// Will panic if `self` is not normalized when `glam_assert` is enabled.
749    #[inline]
750    #[must_use]
751    #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
752    pub fn mul_vec3(self, rhs: DVec3) -> DVec3 {
753        glam_assert!(self.is_normalized());
754
755        let w = self.w;
756        let b = DVec3::new(self.x, self.y, self.z);
757        let b2 = b.dot(b);
758        rhs.mul(w * w - b2)
759            .add(b.mul(rhs.dot(b) * 2.0))
760            .add(b.cross(rhs).mul(w * 2.0))
761    }
762
763    /// Multiplies two quaternions. If they each represent a rotation, the result will
764    /// represent the combined rotation.
765    ///
766    /// Note that due to floating point rounding the result may not be perfectly normalized.
767    #[inline]
768    #[must_use]
769    pub fn mul_quat(self, rhs: Self) -> Self {
770        let (x0, y0, z0, w0) = self.into();
771        let (x1, y1, z1, w1) = rhs.into();
772        Self::from_xyzw(
773            w0 * x1 + x0 * w1 + y0 * z1 - z0 * y1,
774            w0 * y1 - x0 * z1 + y0 * w1 + z0 * x1,
775            w0 * z1 + x0 * y1 - y0 * x1 + z0 * w1,
776            w0 * w1 - x0 * x1 - y0 * y1 - z0 * z1,
777        )
778    }
779
780    /// Creates a quaternion from a 3x3 rotation matrix inside a 3D affine transform.
781    ///
782    /// Note if the input affine matrix contain scales, shears, or other non-rotation
783    /// transformations then the resulting quaternion will be ill-defined.
784    ///
785    /// # Panics
786    ///
787    /// Will panic if any input affine matrix column is not normalized when `glam_assert` is
788    /// enabled.
789    #[inline]
790    #[must_use]
791    #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
792    pub fn from_affine3(a: &crate::DAffine3) -> Self {
793        Self::from_rotation_axes(a.matrix3.x_axis, a.matrix3.y_axis, a.matrix3.z_axis)
794    }
795
796    #[inline]
797    #[must_use]
798    pub fn as_quat(self) -> Quat {
799        Quat::from_xyzw(self.x as f32, self.y as f32, self.z as f32, self.w as f32)
800    }
801}
802
803impl fmt::Debug for DQuat {
804    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
805        fmt.debug_tuple(stringify!(DQuat))
806            .field(&self.x)
807            .field(&self.y)
808            .field(&self.z)
809            .field(&self.w)
810            .finish()
811    }
812}
813
814impl fmt::Display for DQuat {
815    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
816        if let Some(p) = f.precision() {
817            write!(
818                f,
819                "[{:.*}, {:.*}, {:.*}, {:.*}]",
820                p, self.x, p, self.y, p, self.z, p, self.w
821            )
822        } else {
823            write!(f, "[{}, {}, {}, {}]", self.x, self.y, self.z, self.w)
824        }
825    }
826}
827
828impl Add for DQuat {
829    type Output = Self;
830    /// Adds two quaternions.
831    ///
832    /// The sum is not guaranteed to be normalized.
833    ///
834    /// Note that addition is not the same as combining the rotations represented by the
835    /// two quaternions! That corresponds to multiplication.
836    #[inline]
837    fn add(self, rhs: Self) -> Self {
838        Self::from_vec4(DVec4::from(self) + DVec4::from(rhs))
839    }
840}
841
842impl Add<&Self> for DQuat {
843    type Output = Self;
844    #[inline]
845    fn add(self, rhs: &Self) -> Self {
846        self.add(*rhs)
847    }
848}
849
850impl Add<&DQuat> for &DQuat {
851    type Output = DQuat;
852    #[inline]
853    fn add(self, rhs: &DQuat) -> DQuat {
854        (*self).add(*rhs)
855    }
856}
857
858impl Add<DQuat> for &DQuat {
859    type Output = DQuat;
860    #[inline]
861    fn add(self, rhs: DQuat) -> DQuat {
862        (*self).add(rhs)
863    }
864}
865
866impl AddAssign for DQuat {
867    #[inline]
868    fn add_assign(&mut self, rhs: Self) {
869        *self = self.add(rhs);
870    }
871}
872
873impl AddAssign<&Self> for DQuat {
874    #[inline]
875    fn add_assign(&mut self, rhs: &Self) {
876        self.add_assign(*rhs);
877    }
878}
879
880impl Sub for DQuat {
881    type Output = Self;
882    /// Subtracts the `rhs` quaternion from `self`.
883    ///
884    /// The difference is not guaranteed to be normalized.
885    #[inline]
886    fn sub(self, rhs: Self) -> Self {
887        Self::from_vec4(DVec4::from(self) - DVec4::from(rhs))
888    }
889}
890
891impl Sub<&Self> for DQuat {
892    type Output = Self;
893    #[inline]
894    fn sub(self, rhs: &Self) -> Self {
895        self.sub(*rhs)
896    }
897}
898
899impl Sub<&DQuat> for &DQuat {
900    type Output = DQuat;
901    #[inline]
902    fn sub(self, rhs: &DQuat) -> DQuat {
903        (*self).sub(*rhs)
904    }
905}
906
907impl Sub<DQuat> for &DQuat {
908    type Output = DQuat;
909    #[inline]
910    fn sub(self, rhs: DQuat) -> DQuat {
911        (*self).sub(rhs)
912    }
913}
914
915impl SubAssign for DQuat {
916    #[inline]
917    fn sub_assign(&mut self, rhs: Self) {
918        *self = self.sub(rhs);
919    }
920}
921
922impl SubAssign<&Self> for DQuat {
923    #[inline]
924    fn sub_assign(&mut self, rhs: &Self) {
925        self.sub_assign(*rhs);
926    }
927}
928
929impl Mul<f64> for DQuat {
930    type Output = Self;
931    /// Multiplies a quaternion by a scalar value.
932    ///
933    /// The product is not guaranteed to be normalized.
934    #[inline]
935    fn mul(self, rhs: f64) -> Self {
936        Self::from_vec4(DVec4::from(self) * rhs)
937    }
938}
939
940impl Mul<&f64> for DQuat {
941    type Output = Self;
942    #[inline]
943    fn mul(self, rhs: &f64) -> Self {
944        self.mul(*rhs)
945    }
946}
947
948impl Mul<&f64> for &DQuat {
949    type Output = DQuat;
950    #[inline]
951    fn mul(self, rhs: &f64) -> DQuat {
952        (*self).mul(*rhs)
953    }
954}
955
956impl Mul<f64> for &DQuat {
957    type Output = DQuat;
958    #[inline]
959    fn mul(self, rhs: f64) -> DQuat {
960        (*self).mul(rhs)
961    }
962}
963
964impl MulAssign<f64> for DQuat {
965    #[inline]
966    fn mul_assign(&mut self, rhs: f64) {
967        *self = self.mul(rhs);
968    }
969}
970
971impl MulAssign<&f64> for DQuat {
972    #[inline]
973    fn mul_assign(&mut self, rhs: &f64) {
974        self.mul_assign(*rhs);
975    }
976}
977
978impl Div<f64> for DQuat {
979    type Output = Self;
980    /// Divides a quaternion by a scalar value.
981    /// The quotient is not guaranteed to be normalized.
982    #[inline]
983    fn div(self, rhs: f64) -> Self {
984        Self::from_vec4(DVec4::from(self) / rhs)
985    }
986}
987
988impl Div<&f64> for DQuat {
989    type Output = Self;
990    #[inline]
991    fn div(self, rhs: &f64) -> Self {
992        self.div(*rhs)
993    }
994}
995
996impl Div<&f64> for &DQuat {
997    type Output = DQuat;
998    #[inline]
999    fn div(self, rhs: &f64) -> DQuat {
1000        (*self).div(*rhs)
1001    }
1002}
1003
1004impl Div<f64> for &DQuat {
1005    type Output = DQuat;
1006    #[inline]
1007    fn div(self, rhs: f64) -> DQuat {
1008        (*self).div(rhs)
1009    }
1010}
1011
1012impl DivAssign<f64> for DQuat {
1013    #[inline]
1014    fn div_assign(&mut self, rhs: f64) {
1015        *self = self.div(rhs);
1016    }
1017}
1018
1019impl DivAssign<&f64> for DQuat {
1020    #[inline]
1021    fn div_assign(&mut self, rhs: &f64) {
1022        self.div_assign(*rhs);
1023    }
1024}
1025
1026impl Mul for DQuat {
1027    type Output = Self;
1028    /// Multiplies two quaternions. If they each represent a rotation, the result will
1029    /// represent the combined rotation.
1030    ///
1031    /// Note that due to floating point rounding the result may not be perfectly
1032    /// normalized.
1033    #[inline]
1034    fn mul(self, rhs: Self) -> Self {
1035        self.mul_quat(rhs)
1036    }
1037}
1038
1039impl Mul<&Self> for DQuat {
1040    type Output = Self;
1041    #[inline]
1042    fn mul(self, rhs: &Self) -> Self {
1043        self.mul(*rhs)
1044    }
1045}
1046
1047impl Mul<&DQuat> for &DQuat {
1048    type Output = DQuat;
1049    #[inline]
1050    fn mul(self, rhs: &DQuat) -> DQuat {
1051        (*self).mul(*rhs)
1052    }
1053}
1054
1055impl Mul<DQuat> for &DQuat {
1056    type Output = DQuat;
1057    #[inline]
1058    fn mul(self, rhs: DQuat) -> DQuat {
1059        (*self).mul(rhs)
1060    }
1061}
1062
1063impl MulAssign for DQuat {
1064    #[inline]
1065    fn mul_assign(&mut self, rhs: Self) {
1066        *self = self.mul(rhs);
1067    }
1068}
1069
1070impl MulAssign<&Self> for DQuat {
1071    #[inline]
1072    fn mul_assign(&mut self, rhs: &Self) {
1073        self.mul_assign(*rhs);
1074    }
1075}
1076
1077impl Mul<DVec3> for DQuat {
1078    type Output = DVec3;
1079    /// Multiplies a quaternion and a 3D vector, returning the rotated vector.
1080    ///
1081    /// # Panics
1082    ///
1083    /// Will panic if `self` is not normalized when `glam_assert` is enabled.
1084    #[inline]
1085    #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
1086    fn mul(self, rhs: DVec3) -> Self::Output {
1087        self.mul_vec3(rhs)
1088    }
1089}
1090
1091impl Mul<&DVec3> for DQuat {
1092    type Output = DVec3;
1093    #[inline]
1094    #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
1095    fn mul(self, rhs: &DVec3) -> DVec3 {
1096        self.mul(*rhs)
1097    }
1098}
1099
1100impl Mul<&DVec3> for &DQuat {
1101    type Output = DVec3;
1102    #[inline]
1103    #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
1104    fn mul(self, rhs: &DVec3) -> DVec3 {
1105        (*self).mul(*rhs)
1106    }
1107}
1108
1109impl Mul<DVec3> for &DQuat {
1110    type Output = DVec3;
1111    #[inline]
1112    #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
1113    fn mul(self, rhs: DVec3) -> DVec3 {
1114        (*self).mul(rhs)
1115    }
1116}
1117
1118impl Neg for DQuat {
1119    type Output = Self;
1120    #[inline]
1121    fn neg(self) -> Self {
1122        self * -1.0
1123    }
1124}
1125
1126impl Neg for &DQuat {
1127    type Output = DQuat;
1128    #[inline]
1129    fn neg(self) -> DQuat {
1130        (*self).neg()
1131    }
1132}
1133
1134impl Default for DQuat {
1135    #[inline]
1136    fn default() -> Self {
1137        Self::IDENTITY
1138    }
1139}
1140
1141impl PartialEq for DQuat {
1142    #[inline]
1143    fn eq(&self, rhs: &Self) -> bool {
1144        DVec4::from(*self).eq(&DVec4::from(*rhs))
1145    }
1146}
1147
1148impl AsRef<[f64; 4]> for DQuat {
1149    #[inline]
1150    fn as_ref(&self) -> &[f64; 4] {
1151        unsafe { &*(self as *const Self as *const [f64; 4]) }
1152    }
1153}
1154
1155impl Sum<Self> for DQuat {
1156    fn sum<I>(iter: I) -> Self
1157    where
1158        I: Iterator<Item = Self>,
1159    {
1160        iter.fold(Self::ZERO, Self::add)
1161    }
1162}
1163
1164impl<'a> Sum<&'a Self> for DQuat {
1165    fn sum<I>(iter: I) -> Self
1166    where
1167        I: Iterator<Item = &'a Self>,
1168    {
1169        iter.fold(Self::ZERO, |a, &b| Self::add(a, b))
1170    }
1171}
1172
1173impl Product for DQuat {
1174    fn product<I>(iter: I) -> Self
1175    where
1176        I: Iterator<Item = Self>,
1177    {
1178        iter.fold(Self::IDENTITY, Self::mul)
1179    }
1180}
1181
1182impl<'a> Product<&'a Self> for DQuat {
1183    fn product<I>(iter: I) -> Self
1184    where
1185        I: Iterator<Item = &'a Self>,
1186    {
1187        iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b))
1188    }
1189}
1190
1191impl From<DQuat> for DVec4 {
1192    #[inline]
1193    fn from(q: DQuat) -> Self {
1194        Self::new(q.x, q.y, q.z, q.w)
1195    }
1196}
1197
1198impl From<DQuat> for (f64, f64, f64, f64) {
1199    #[inline]
1200    fn from(q: DQuat) -> Self {
1201        (q.x, q.y, q.z, q.w)
1202    }
1203}
1204
1205impl From<DQuat> for [f64; 4] {
1206    #[inline]
1207    fn from(q: DQuat) -> Self {
1208        [q.x, q.y, q.z, q.w]
1209    }
1210}