Skip to main content

glam/f64/
dquat.rs

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