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