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