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