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