1 // Generated from quat.rs.tera template. Edit the template, not the generated file.
2 
3 use crate::{
4     euler::{EulerFromQuaternion, EulerRot, EulerToQuaternion},
5     f32::math,
6     DQuat, Mat3, Mat3A, Mat4, Vec2, Vec3, Vec3A, Vec4,
7 };
8 
9 #[cfg(not(target_arch = "spirv"))]
10 use core::fmt;
11 use core::iter::{Product, Sum};
12 use core::ops::{Add, Div, Mul, MulAssign, Neg, Sub};
13 
14 /// Creates a quaternion from `x`, `y`, `z` and `w` values.
15 ///
16 /// This should generally not be called manually unless you know what you are doing. Use
17 /// one of the other constructors instead such as `identity` or `from_axis_angle`.
18 #[inline]
19 #[must_use]
quat(x: f32, y: f32, z: f32, w: f32) -> Quat20 pub const fn quat(x: f32, y: f32, z: f32, w: f32) -> Quat {
21     Quat::from_xyzw(x, y, z, w)
22 }
23 
24 /// A quaternion representing an orientation.
25 ///
26 /// This quaternion is intended to be of unit length but may denormalize due to
27 /// floating point "error creep" which can occur when successive quaternion
28 /// operations are applied.
29 #[derive(Clone, Copy)]
30 #[cfg_attr(
31     not(any(feature = "scalar-math", target_arch = "spirv")),
32     repr(align(16))
33 )]
34 #[cfg_attr(not(target_arch = "spirv"), repr(C))]
35 #[cfg_attr(target_arch = "spirv", repr(simd))]
36 pub struct Quat {
37     pub x: f32,
38     pub y: f32,
39     pub z: f32,
40     pub w: f32,
41 }
42 
43 impl Quat {
44     /// All zeros.
45     const ZERO: Self = Self::from_array([0.0; 4]);
46 
47     /// The identity quaternion. Corresponds to no rotation.
48     pub const IDENTITY: Self = Self::from_xyzw(0.0, 0.0, 0.0, 1.0);
49 
50     /// All NANs.
51     pub const NAN: Self = Self::from_array([f32::NAN; 4]);
52 
53     /// Creates a new rotation quaternion.
54     ///
55     /// This should generally not be called manually unless you know what you are doing.
56     /// Use one of the other constructors instead such as `identity` or `from_axis_angle`.
57     ///
58     /// `from_xyzw` is mostly used by unit tests and `serde` deserialization.
59     ///
60     /// # Preconditions
61     ///
62     /// This function does not check if the input is normalized, it is up to the user to
63     /// provide normalized input or to normalized the resulting quaternion.
64     #[inline(always)]
65     #[must_use]
from_xyzw(x: f32, y: f32, z: f32, w: f32) -> Self66     pub const fn from_xyzw(x: f32, y: f32, z: f32, w: f32) -> Self {
67         Self { x, y, z, w }
68     }
69 
70     /// Creates a rotation quaternion from an array.
71     ///
72     /// # Preconditions
73     ///
74     /// This function does not check if the input is normalized, it is up to the user to
75     /// provide normalized input or to normalized the resulting quaternion.
76     #[inline]
77     #[must_use]
from_array(a: [f32; 4]) -> Self78     pub const fn from_array(a: [f32; 4]) -> Self {
79         Self::from_xyzw(a[0], a[1], a[2], a[3])
80     }
81 
82     /// Creates a new rotation quaternion from a 4D vector.
83     ///
84     /// # Preconditions
85     ///
86     /// This function does not check if the input is normalized, it is up to the user to
87     /// provide normalized input or to normalized the resulting quaternion.
88     #[inline]
89     #[must_use]
from_vec4(v: Vec4) -> Self90     pub const fn from_vec4(v: Vec4) -> Self {
91         Self {
92             x: v.x,
93             y: v.y,
94             z: v.z,
95             w: v.w,
96         }
97     }
98 
99     /// Creates a rotation quaternion from a slice.
100     ///
101     /// # Preconditions
102     ///
103     /// This function does not check if the input is normalized, it is up to the user to
104     /// provide normalized input or to normalized the resulting quaternion.
105     ///
106     /// # Panics
107     ///
108     /// Panics if `slice` length is less than 4.
109     #[inline]
110     #[must_use]
from_slice(slice: &[f32]) -> Self111     pub fn from_slice(slice: &[f32]) -> Self {
112         Self::from_xyzw(slice[0], slice[1], slice[2], slice[3])
113     }
114 
115     /// Writes the quaternion to an unaligned slice.
116     ///
117     /// # Panics
118     ///
119     /// Panics if `slice` length is less than 4.
120     #[inline]
write_to_slice(self, slice: &mut [f32])121     pub fn write_to_slice(self, slice: &mut [f32]) {
122         slice[0] = self.x;
123         slice[1] = self.y;
124         slice[2] = self.z;
125         slice[3] = self.w;
126     }
127 
128     /// Create a quaternion for a normalized rotation `axis` and `angle` (in radians).
129     ///
130     /// The axis must be a unit vector.
131     ///
132     /// # Panics
133     ///
134     /// Will panic if `axis` is not normalized when `glam_assert` is enabled.
135     #[inline]
136     #[must_use]
from_axis_angle(axis: Vec3, angle: f32) -> Self137     pub fn from_axis_angle(axis: Vec3, angle: f32) -> Self {
138         glam_assert!(axis.is_normalized());
139         let (s, c) = math::sin_cos(angle * 0.5);
140         let v = axis * s;
141         Self::from_xyzw(v.x, v.y, v.z, c)
142     }
143 
144     /// Create a quaternion that rotates `v.length()` radians around `v.normalize()`.
145     ///
146     /// `from_scaled_axis(Vec3::ZERO)` results in the identity quaternion.
147     #[inline]
148     #[must_use]
from_scaled_axis(v: Vec3) -> Self149     pub fn from_scaled_axis(v: Vec3) -> Self {
150         let length = v.length();
151         if length == 0.0 {
152             Self::IDENTITY
153         } else {
154             Self::from_axis_angle(v / length, length)
155         }
156     }
157 
158     /// Creates a quaternion from the `angle` (in radians) around the x axis.
159     #[inline]
160     #[must_use]
from_rotation_x(angle: f32) -> Self161     pub fn from_rotation_x(angle: f32) -> Self {
162         let (s, c) = math::sin_cos(angle * 0.5);
163         Self::from_xyzw(s, 0.0, 0.0, c)
164     }
165 
166     /// Creates a quaternion from the `angle` (in radians) around the y axis.
167     #[inline]
168     #[must_use]
from_rotation_y(angle: f32) -> Self169     pub fn from_rotation_y(angle: f32) -> Self {
170         let (s, c) = math::sin_cos(angle * 0.5);
171         Self::from_xyzw(0.0, s, 0.0, c)
172     }
173 
174     /// Creates a quaternion from the `angle` (in radians) around the z axis.
175     #[inline]
176     #[must_use]
from_rotation_z(angle: f32) -> Self177     pub fn from_rotation_z(angle: f32) -> Self {
178         let (s, c) = math::sin_cos(angle * 0.5);
179         Self::from_xyzw(0.0, 0.0, s, c)
180     }
181 
182     /// Creates a quaternion from the given Euler rotation sequence and the angles (in radians).
183     #[inline]
184     #[must_use]
from_euler(euler: EulerRot, a: f32, b: f32, c: f32) -> Self185     pub fn from_euler(euler: EulerRot, a: f32, b: f32, c: f32) -> Self {
186         euler.new_quat(a, b, c)
187     }
188 
189     /// From the columns of a 3x3 rotation matrix.
190     #[inline]
191     #[must_use]
from_rotation_axes(x_axis: Vec3, y_axis: Vec3, z_axis: Vec3) -> Self192     pub(crate) fn from_rotation_axes(x_axis: Vec3, y_axis: Vec3, z_axis: Vec3) -> Self {
193         // Based on https://github.com/microsoft/DirectXMath `XM$quaternionRotationMatrix`
194         let (m00, m01, m02) = x_axis.into();
195         let (m10, m11, m12) = y_axis.into();
196         let (m20, m21, m22) = z_axis.into();
197         if m22 <= 0.0 {
198             // x^2 + y^2 >= z^2 + w^2
199             let dif10 = m11 - m00;
200             let omm22 = 1.0 - m22;
201             if dif10 <= 0.0 {
202                 // x^2 >= y^2
203                 let four_xsq = omm22 - dif10;
204                 let inv4x = 0.5 / math::sqrt(four_xsq);
205                 Self::from_xyzw(
206                     four_xsq * inv4x,
207                     (m01 + m10) * inv4x,
208                     (m02 + m20) * inv4x,
209                     (m12 - m21) * inv4x,
210                 )
211             } else {
212                 // y^2 >= x^2
213                 let four_ysq = omm22 + dif10;
214                 let inv4y = 0.5 / math::sqrt(four_ysq);
215                 Self::from_xyzw(
216                     (m01 + m10) * inv4y,
217                     four_ysq * inv4y,
218                     (m12 + m21) * inv4y,
219                     (m20 - m02) * inv4y,
220                 )
221             }
222         } else {
223             // z^2 + w^2 >= x^2 + y^2
224             let sum10 = m11 + m00;
225             let opm22 = 1.0 + m22;
226             if sum10 <= 0.0 {
227                 // z^2 >= w^2
228                 let four_zsq = opm22 - sum10;
229                 let inv4z = 0.5 / math::sqrt(four_zsq);
230                 Self::from_xyzw(
231                     (m02 + m20) * inv4z,
232                     (m12 + m21) * inv4z,
233                     four_zsq * inv4z,
234                     (m01 - m10) * inv4z,
235                 )
236             } else {
237                 // w^2 >= z^2
238                 let four_wsq = opm22 + sum10;
239                 let inv4w = 0.5 / math::sqrt(four_wsq);
240                 Self::from_xyzw(
241                     (m12 - m21) * inv4w,
242                     (m20 - m02) * inv4w,
243                     (m01 - m10) * inv4w,
244                     four_wsq * inv4w,
245                 )
246             }
247         }
248     }
249 
250     /// Creates a quaternion from a 3x3 rotation matrix.
251     #[inline]
252     #[must_use]
from_mat3(mat: &Mat3) -> Self253     pub fn from_mat3(mat: &Mat3) -> Self {
254         Self::from_rotation_axes(mat.x_axis, mat.y_axis, mat.z_axis)
255     }
256 
257     /// Creates a quaternion from a 3x3 SIMD aligned rotation matrix.
258     #[inline]
259     #[must_use]
from_mat3a(mat: &Mat3A) -> Self260     pub fn from_mat3a(mat: &Mat3A) -> Self {
261         Self::from_rotation_axes(mat.x_axis.into(), mat.y_axis.into(), mat.z_axis.into())
262     }
263 
264     /// Creates a quaternion from a 3x3 rotation matrix inside a homogeneous 4x4 matrix.
265     #[inline]
266     #[must_use]
from_mat4(mat: &Mat4) -> Self267     pub fn from_mat4(mat: &Mat4) -> Self {
268         Self::from_rotation_axes(
269             mat.x_axis.truncate(),
270             mat.y_axis.truncate(),
271             mat.z_axis.truncate(),
272         )
273     }
274 
275     /// Gets the minimal rotation for transforming `from` to `to`.  The rotation is in the
276     /// plane spanned by the two vectors.  Will rotate at most 180 degrees.
277     ///
278     /// The inputs must be unit vectors.
279     ///
280     /// `from_rotation_arc(from, to) * from ≈ to`.
281     ///
282     /// For near-singular cases (from≈to and from≈-to) the current implementation
283     /// is only accurate to about 0.001 (for `f32`).
284     ///
285     /// # Panics
286     ///
287     /// Will panic if `from` or `to` are not normalized when `glam_assert` is enabled.
288     #[must_use]
from_rotation_arc(from: Vec3, to: Vec3) -> Self289     pub fn from_rotation_arc(from: Vec3, to: Vec3) -> Self {
290         glam_assert!(from.is_normalized());
291         glam_assert!(to.is_normalized());
292 
293         const ONE_MINUS_EPS: f32 = 1.0 - 2.0 * core::f32::EPSILON;
294         let dot = from.dot(to);
295         if dot > ONE_MINUS_EPS {
296             // 0° singulary: from ≈ to
297             Self::IDENTITY
298         } else if dot < -ONE_MINUS_EPS {
299             // 180° singulary: from ≈ -to
300             use core::f32::consts::PI; // half a turn = ��/2 = 180°
301             Self::from_axis_angle(from.any_orthonormal_vector(), PI)
302         } else {
303             let c = from.cross(to);
304             Self::from_xyzw(c.x, c.y, c.z, 1.0 + dot).normalize()
305         }
306     }
307 
308     /// Gets the minimal rotation for transforming `from` to either `to` or `-to`.  This means
309     /// that the resulting quaternion will rotate `from` so that it is colinear with `to`.
310     ///
311     /// The rotation is in the plane spanned by the two vectors.  Will rotate at most 90
312     /// degrees.
313     ///
314     /// The inputs must be unit vectors.
315     ///
316     /// `to.dot(from_rotation_arc_colinear(from, to) * from).abs() ≈ 1`.
317     ///
318     /// # Panics
319     ///
320     /// Will panic if `from` or `to` are not normalized when `glam_assert` is enabled.
321     #[inline]
322     #[must_use]
from_rotation_arc_colinear(from: Vec3, to: Vec3) -> Self323     pub fn from_rotation_arc_colinear(from: Vec3, to: Vec3) -> Self {
324         if from.dot(to) < 0.0 {
325             Self::from_rotation_arc(from, -to)
326         } else {
327             Self::from_rotation_arc(from, to)
328         }
329     }
330 
331     /// Gets the minimal rotation for transforming `from` to `to`.  The resulting rotation is
332     /// around the z axis. Will rotate at most 180 degrees.
333     ///
334     /// The inputs must be unit vectors.
335     ///
336     /// `from_rotation_arc_2d(from, to) * from ≈ to`.
337     ///
338     /// For near-singular cases (from≈to and from≈-to) the current implementation
339     /// is only accurate to about 0.001 (for `f32`).
340     ///
341     /// # Panics
342     ///
343     /// Will panic if `from` or `to` are not normalized when `glam_assert` is enabled.
344     #[must_use]
from_rotation_arc_2d(from: Vec2, to: Vec2) -> Self345     pub fn from_rotation_arc_2d(from: Vec2, to: Vec2) -> Self {
346         glam_assert!(from.is_normalized());
347         glam_assert!(to.is_normalized());
348 
349         const ONE_MINUS_EPSILON: f32 = 1.0 - 2.0 * core::f32::EPSILON;
350         let dot = from.dot(to);
351         if dot > ONE_MINUS_EPSILON {
352             // 0° singulary: from ≈ to
353             Self::IDENTITY
354         } else if dot < -ONE_MINUS_EPSILON {
355             // 180° singulary: from ≈ -to
356             const COS_FRAC_PI_2: f32 = 0.0;
357             const SIN_FRAC_PI_2: f32 = 1.0;
358             // rotation around z by PI radians
359             Self::from_xyzw(0.0, 0.0, SIN_FRAC_PI_2, COS_FRAC_PI_2)
360         } else {
361             // vector3 cross where z=0
362             let z = from.x * to.y - to.x * from.y;
363             let w = 1.0 + dot;
364             // calculate length with x=0 and y=0 to normalize
365             let len_rcp = 1.0 / math::sqrt(z * z + w * w);
366             Self::from_xyzw(0.0, 0.0, z * len_rcp, w * len_rcp)
367         }
368     }
369 
370     /// Returns the rotation axis (normalized) and angle (in radians) of `self`.
371     #[inline]
372     #[must_use]
to_axis_angle(self) -> (Vec3, f32)373     pub fn to_axis_angle(self) -> (Vec3, f32) {
374         const EPSILON: f32 = 1.0e-8;
375         let v = Vec3::new(self.x, self.y, self.z);
376         let length = v.length();
377         if length >= EPSILON {
378             let angle = 2.0 * math::atan2(length, self.w);
379             let axis = v / length;
380             (axis, angle)
381         } else {
382             (Vec3::X, 0.0)
383         }
384     }
385 
386     /// Returns the rotation axis scaled by the rotation in radians.
387     #[inline]
388     #[must_use]
to_scaled_axis(self) -> Vec3389     pub fn to_scaled_axis(self) -> Vec3 {
390         let (axis, angle) = self.to_axis_angle();
391         axis * angle
392     }
393 
394     /// Returns the rotation angles for the given euler rotation sequence.
395     #[inline]
396     #[must_use]
to_euler(self, euler: EulerRot) -> (f32, f32, f32)397     pub fn to_euler(self, euler: EulerRot) -> (f32, f32, f32) {
398         euler.convert_quat(self)
399     }
400 
401     /// `[x, y, z, w]`
402     #[inline]
403     #[must_use]
to_array(&self) -> [f32; 4]404     pub fn to_array(&self) -> [f32; 4] {
405         [self.x, self.y, self.z, self.w]
406     }
407 
408     /// Returns the vector part of the quaternion.
409     #[inline]
410     #[must_use]
xyz(self) -> Vec3411     pub fn xyz(self) -> Vec3 {
412         Vec3::new(self.x, self.y, self.z)
413     }
414 
415     /// Returns the quaternion conjugate of `self`. For a unit quaternion the
416     /// conjugate is also the inverse.
417     #[inline]
418     #[must_use]
conjugate(self) -> Self419     pub fn conjugate(self) -> Self {
420         Self {
421             x: -self.x,
422             y: -self.y,
423             z: -self.z,
424             w: self.w,
425         }
426     }
427 
428     /// Returns the inverse of a normalized quaternion.
429     ///
430     /// Typically quaternion inverse returns the conjugate of a normalized quaternion.
431     /// Because `self` is assumed to already be unit length this method *does not* normalize
432     /// before returning the conjugate.
433     ///
434     /// # Panics
435     ///
436     /// Will panic if `self` is not normalized when `glam_assert` is enabled.
437     #[inline]
438     #[must_use]
inverse(self) -> Self439     pub fn inverse(self) -> Self {
440         glam_assert!(self.is_normalized());
441         self.conjugate()
442     }
443 
444     /// Computes the dot product of `self` and `rhs`. The dot product is
445     /// equal to the cosine of the angle between two quaternion rotations.
446     #[inline]
447     #[must_use]
dot(self, rhs: Self) -> f32448     pub fn dot(self, rhs: Self) -> f32 {
449         Vec4::from(self).dot(Vec4::from(rhs))
450     }
451 
452     /// Computes the length of `self`.
453     #[doc(alias = "magnitude")]
454     #[inline]
455     #[must_use]
length(self) -> f32456     pub fn length(self) -> f32 {
457         Vec4::from(self).length()
458     }
459 
460     /// Computes the squared length of `self`.
461     ///
462     /// This is generally faster than `length()` as it avoids a square
463     /// root operation.
464     #[doc(alias = "magnitude2")]
465     #[inline]
466     #[must_use]
length_squared(self) -> f32467     pub fn length_squared(self) -> f32 {
468         Vec4::from(self).length_squared()
469     }
470 
471     /// Computes `1.0 / length()`.
472     ///
473     /// For valid results, `self` must _not_ be of length zero.
474     #[inline]
475     #[must_use]
length_recip(self) -> f32476     pub fn length_recip(self) -> f32 {
477         Vec4::from(self).length_recip()
478     }
479 
480     /// Returns `self` normalized to length 1.0.
481     ///
482     /// For valid results, `self` must _not_ be of length zero.
483     ///
484     /// Panics
485     ///
486     /// Will panic if `self` is zero length when `glam_assert` is enabled.
487     #[inline]
488     #[must_use]
normalize(self) -> Self489     pub fn normalize(self) -> Self {
490         Self::from_vec4(Vec4::from(self).normalize())
491     }
492 
493     /// Returns `true` if, and only if, all elements are finite.
494     /// If any element is either `NaN`, positive or negative infinity, this will return `false`.
495     #[inline]
496     #[must_use]
is_finite(self) -> bool497     pub fn is_finite(self) -> bool {
498         Vec4::from(self).is_finite()
499     }
500 
501     #[inline]
502     #[must_use]
is_nan(self) -> bool503     pub fn is_nan(self) -> bool {
504         Vec4::from(self).is_nan()
505     }
506 
507     /// Returns whether `self` of length `1.0` or not.
508     ///
509     /// Uses a precision threshold of `1e-6`.
510     #[inline]
511     #[must_use]
is_normalized(self) -> bool512     pub fn is_normalized(self) -> bool {
513         Vec4::from(self).is_normalized()
514     }
515 
516     #[inline]
517     #[must_use]
is_near_identity(self) -> bool518     pub fn is_near_identity(self) -> bool {
519         // Based on https://github.com/nfrechette/rtm `rtm::quat_near_identity`
520         let threshold_angle = 0.002_847_144_6;
521         // Because of floating point precision, we cannot represent very small rotations.
522         // The closest f32 to 1.0 that is not 1.0 itself yields:
523         // 0.99999994.acos() * 2.0  = 0.000690533954 rad
524         //
525         // An error threshold of 1.e-6 is used by default.
526         // (1.0 - 1.e-6).acos() * 2.0 = 0.00284714461 rad
527         // (1.0 - 1.e-7).acos() * 2.0 = 0.00097656250 rad
528         //
529         // We don't really care about the angle value itself, only if it's close to 0.
530         // This will happen whenever quat.w is close to 1.0.
531         // If the quat.w is close to -1.0, the angle will be near 2*PI which is close to
532         // a negative 0 rotation. By forcing quat.w to be positive, we'll end up with
533         // the shortest path.
534         let positive_w_angle = math::acos_approx(math::abs(self.w)) * 2.0;
535         positive_w_angle < threshold_angle
536     }
537 
538     /// Returns the angle (in radians) for the minimal rotation
539     /// for transforming this quaternion into another.
540     ///
541     /// Both quaternions must be normalized.
542     ///
543     /// # Panics
544     ///
545     /// Will panic if `self` or `rhs` are not normalized when `glam_assert` is enabled.
546     #[inline]
547     #[must_use]
angle_between(self, rhs: Self) -> f32548     pub fn angle_between(self, rhs: Self) -> f32 {
549         glam_assert!(self.is_normalized() && rhs.is_normalized());
550         math::acos_approx(math::abs(self.dot(rhs))) * 2.0
551     }
552 
553     /// Returns true if the absolute difference of all elements between `self` and `rhs`
554     /// is less than or equal to `max_abs_diff`.
555     ///
556     /// This can be used to compare if two quaternions contain similar elements. It works
557     /// best when comparing with a known value. The `max_abs_diff` that should be used used
558     /// depends on the values being compared against.
559     ///
560     /// For more see
561     /// [comparing floating point numbers](https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/).
562     #[inline]
563     #[must_use]
abs_diff_eq(self, rhs: Self, max_abs_diff: f32) -> bool564     pub fn abs_diff_eq(self, rhs: Self, max_abs_diff: f32) -> bool {
565         Vec4::from(self).abs_diff_eq(Vec4::from(rhs), max_abs_diff)
566     }
567 
568     /// Performs a linear interpolation between `self` and `rhs` based on
569     /// the value `s`.
570     ///
571     /// When `s` is `0.0`, the result will be equal to `self`.  When `s`
572     /// is `1.0`, the result will be equal to `rhs`.
573     ///
574     /// # Panics
575     ///
576     /// Will panic if `self` or `end` are not normalized when `glam_assert` is enabled.
577     #[doc(alias = "mix")]
578     #[inline]
579     #[must_use]
lerp(self, end: Self, s: f32) -> Self580     pub fn lerp(self, end: Self, s: f32) -> Self {
581         glam_assert!(self.is_normalized());
582         glam_assert!(end.is_normalized());
583 
584         let start = self;
585         let dot = start.dot(end);
586         let bias = if dot >= 0.0 { 1.0 } else { -1.0 };
587         let interpolated = start.add(end.mul(bias).sub(start).mul(s));
588         interpolated.normalize()
589     }
590 
591     /// Performs a spherical linear interpolation between `self` and `end`
592     /// based on the value `s`.
593     ///
594     /// When `s` is `0.0`, the result will be equal to `self`.  When `s`
595     /// is `1.0`, the result will be equal to `end`.
596     ///
597     /// # Panics
598     ///
599     /// Will panic if `self` or `end` are not normalized when `glam_assert` is enabled.
600     #[inline]
601     #[must_use]
slerp(self, mut end: Self, s: f32) -> Self602     pub fn slerp(self, mut end: Self, s: f32) -> Self {
603         // http://number-none.com/product/Understanding%20Slerp,%20Then%20Not%20Using%20It/
604         glam_assert!(self.is_normalized());
605         glam_assert!(end.is_normalized());
606 
607         const DOT_THRESHOLD: f32 = 0.9995;
608 
609         // Note that a rotation can be represented by two quaternions: `q` and
610         // `-q`. The slerp path between `q` and `end` will be different from the
611         // path between `-q` and `end`. One path will take the long way around and
612         // one will take the short way. In order to correct for this, the `dot`
613         // product between `self` and `end` should be positive. If the `dot`
614         // product is negative, slerp between `self` and `-end`.
615         let mut dot = self.dot(end);
616         if dot < 0.0 {
617             end = -end;
618             dot = -dot;
619         }
620 
621         if dot > DOT_THRESHOLD {
622             // assumes lerp returns a normalized quaternion
623             self.lerp(end, s)
624         } else {
625             let theta = math::acos_approx(dot);
626 
627             let scale1 = math::sin(theta * (1.0 - s));
628             let scale2 = math::sin(theta * s);
629             let theta_sin = math::sin(theta);
630 
631             self.mul(scale1).add(end.mul(scale2)).mul(1.0 / theta_sin)
632         }
633     }
634 
635     /// Multiplies a quaternion and a 3D vector, returning the rotated vector.
636     ///
637     /// # Panics
638     ///
639     /// Will panic if `self` is not normalized when `glam_assert` is enabled.
640     #[inline]
641     #[must_use]
mul_vec3(self, rhs: Vec3) -> Vec3642     pub fn mul_vec3(self, rhs: Vec3) -> Vec3 {
643         glam_assert!(self.is_normalized());
644 
645         let w = self.w;
646         let b = Vec3::new(self.x, self.y, self.z);
647         let b2 = b.dot(b);
648         rhs.mul(w * w - b2)
649             .add(b.mul(rhs.dot(b) * 2.0))
650             .add(b.cross(rhs).mul(w * 2.0))
651     }
652 
653     /// Multiplies two quaternions. If they each represent a rotation, the result will
654     /// represent the combined rotation.
655     ///
656     /// Note that due to floating point rounding the result may not be perfectly normalized.
657     ///
658     /// # Panics
659     ///
660     /// Will panic if `self` or `rhs` are not normalized when `glam_assert` is enabled.
661     #[inline]
662     #[must_use]
mul_quat(self, rhs: Self) -> Self663     pub fn mul_quat(self, rhs: Self) -> Self {
664         glam_assert!(self.is_normalized());
665         glam_assert!(rhs.is_normalized());
666 
667         let (x0, y0, z0, w0) = self.into();
668         let (x1, y1, z1, w1) = rhs.into();
669         Self::from_xyzw(
670             w0 * x1 + x0 * w1 + y0 * z1 - z0 * y1,
671             w0 * y1 - x0 * z1 + y0 * w1 + z0 * x1,
672             w0 * z1 + x0 * y1 - y0 * x1 + z0 * w1,
673             w0 * w1 - x0 * x1 - y0 * y1 - z0 * z1,
674         )
675     }
676 
677     /// Creates a quaternion from a 3x3 rotation matrix inside a 3D affine transform.
678     #[inline]
679     #[must_use]
from_affine3(a: &crate::Affine3A) -> Self680     pub fn from_affine3(a: &crate::Affine3A) -> Self {
681         #[allow(clippy::useless_conversion)]
682         Self::from_rotation_axes(
683             a.matrix3.x_axis.into(),
684             a.matrix3.y_axis.into(),
685             a.matrix3.z_axis.into(),
686         )
687     }
688 
689     /// Multiplies a quaternion and a 3D vector, returning the rotated vector.
690     #[inline]
691     #[must_use]
mul_vec3a(self, rhs: Vec3A) -> Vec3A692     pub fn mul_vec3a(self, rhs: Vec3A) -> Vec3A {
693         self.mul_vec3(rhs.into()).into()
694     }
695 
696     #[inline]
697     #[must_use]
as_dquat(self) -> DQuat698     pub fn as_dquat(self) -> DQuat {
699         DQuat::from_xyzw(self.x as f64, self.y as f64, self.z as f64, self.w as f64)
700     }
701 
702     #[inline]
703     #[must_use]
704     #[deprecated(since = "0.24.2", note = "Use as_dquat() instead")]
as_f64(self) -> DQuat705     pub fn as_f64(self) -> DQuat {
706         self.as_dquat()
707     }
708 }
709 
710 #[cfg(not(target_arch = "spirv"))]
711 impl fmt::Debug for Quat {
fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result712     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
713         fmt.debug_tuple(stringify!(Quat))
714             .field(&self.x)
715             .field(&self.y)
716             .field(&self.z)
717             .field(&self.w)
718             .finish()
719     }
720 }
721 
722 #[cfg(not(target_arch = "spirv"))]
723 impl fmt::Display for Quat {
fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result724     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
725         write!(fmt, "[{}, {}, {}, {}]", self.x, self.y, self.z, self.w)
726     }
727 }
728 
729 impl Add<Quat> for Quat {
730     type Output = Self;
731     /// Adds two quaternions.
732     ///
733     /// The sum is not guaranteed to be normalized.
734     ///
735     /// Note that addition is not the same as combining the rotations represented by the
736     /// two quaternions! That corresponds to multiplication.
737     #[inline]
add(self, rhs: Self) -> Self738     fn add(self, rhs: Self) -> Self {
739         Self::from_vec4(Vec4::from(self) + Vec4::from(rhs))
740     }
741 }
742 
743 impl Sub<Quat> for Quat {
744     type Output = Self;
745     /// Subtracts the `rhs` quaternion from `self`.
746     ///
747     /// The difference is not guaranteed to be normalized.
748     #[inline]
sub(self, rhs: Self) -> Self749     fn sub(self, rhs: Self) -> Self {
750         Self::from_vec4(Vec4::from(self) - Vec4::from(rhs))
751     }
752 }
753 
754 impl Mul<f32> for Quat {
755     type Output = Self;
756     /// Multiplies a quaternion by a scalar value.
757     ///
758     /// The product is not guaranteed to be normalized.
759     #[inline]
mul(self, rhs: f32) -> Self760     fn mul(self, rhs: f32) -> Self {
761         Self::from_vec4(Vec4::from(self) * rhs)
762     }
763 }
764 
765 impl Div<f32> for Quat {
766     type Output = Self;
767     /// Divides a quaternion by a scalar value.
768     /// The quotient is not guaranteed to be normalized.
769     #[inline]
div(self, rhs: f32) -> Self770     fn div(self, rhs: f32) -> Self {
771         Self::from_vec4(Vec4::from(self) / rhs)
772     }
773 }
774 
775 impl Mul<Quat> for Quat {
776     type Output = Self;
777     /// Multiplies two quaternions. If they each represent a rotation, the result will
778     /// represent the combined rotation.
779     ///
780     /// Note that due to floating point rounding the result may not be perfectly
781     /// normalized.
782     ///
783     /// # Panics
784     ///
785     /// Will panic if `self` or `rhs` are not normalized when `glam_assert` is enabled.
786     #[inline]
mul(self, rhs: Self) -> Self787     fn mul(self, rhs: Self) -> Self {
788         self.mul_quat(rhs)
789     }
790 }
791 
792 impl MulAssign<Quat> for Quat {
793     /// Multiplies two quaternions. If they each represent a rotation, the result will
794     /// represent the combined rotation.
795     ///
796     /// Note that due to floating point rounding the result may not be perfectly
797     /// normalized.
798     ///
799     /// # Panics
800     ///
801     /// Will panic if `self` or `rhs` are not normalized when `glam_assert` is enabled.
802     #[inline]
mul_assign(&mut self, rhs: Self)803     fn mul_assign(&mut self, rhs: Self) {
804         *self = self.mul_quat(rhs);
805     }
806 }
807 
808 impl Mul<Vec3> for Quat {
809     type Output = Vec3;
810     /// Multiplies a quaternion and a 3D vector, returning the rotated vector.
811     ///
812     /// # Panics
813     ///
814     /// Will panic if `self` is not normalized when `glam_assert` is enabled.
815     #[inline]
mul(self, rhs: Vec3) -> Self::Output816     fn mul(self, rhs: Vec3) -> Self::Output {
817         self.mul_vec3(rhs)
818     }
819 }
820 
821 impl Neg for Quat {
822     type Output = Self;
823     #[inline]
neg(self) -> Self824     fn neg(self) -> Self {
825         self * -1.0
826     }
827 }
828 
829 impl Default for Quat {
830     #[inline]
default() -> Self831     fn default() -> Self {
832         Self::IDENTITY
833     }
834 }
835 
836 impl PartialEq for Quat {
837     #[inline]
eq(&self, rhs: &Self) -> bool838     fn eq(&self, rhs: &Self) -> bool {
839         Vec4::from(*self).eq(&Vec4::from(*rhs))
840     }
841 }
842 
843 #[cfg(not(target_arch = "spirv"))]
844 impl AsRef<[f32; 4]> for Quat {
845     #[inline]
as_ref(&self) -> &[f32; 4]846     fn as_ref(&self) -> &[f32; 4] {
847         unsafe { &*(self as *const Self as *const [f32; 4]) }
848     }
849 }
850 
851 impl Sum<Self> for Quat {
sum<I>(iter: I) -> Self where I: Iterator<Item = Self>,852     fn sum<I>(iter: I) -> Self
853     where
854         I: Iterator<Item = Self>,
855     {
856         iter.fold(Self::ZERO, Self::add)
857     }
858 }
859 
860 impl<'a> Sum<&'a Self> for Quat {
sum<I>(iter: I) -> Self where I: Iterator<Item = &'a Self>,861     fn sum<I>(iter: I) -> Self
862     where
863         I: Iterator<Item = &'a Self>,
864     {
865         iter.fold(Self::ZERO, |a, &b| Self::add(a, b))
866     }
867 }
868 
869 impl Product for Quat {
product<I>(iter: I) -> Self where I: Iterator<Item = Self>,870     fn product<I>(iter: I) -> Self
871     where
872         I: Iterator<Item = Self>,
873     {
874         iter.fold(Self::IDENTITY, Self::mul)
875     }
876 }
877 
878 impl<'a> Product<&'a Self> for Quat {
product<I>(iter: I) -> Self where I: Iterator<Item = &'a Self>,879     fn product<I>(iter: I) -> Self
880     where
881         I: Iterator<Item = &'a Self>,
882     {
883         iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b))
884     }
885 }
886 
887 impl Mul<Vec3A> for Quat {
888     type Output = Vec3A;
889     #[inline]
mul(self, rhs: Vec3A) -> Self::Output890     fn mul(self, rhs: Vec3A) -> Self::Output {
891         self.mul_vec3a(rhs)
892     }
893 }
894 
895 impl From<Quat> for Vec4 {
896     #[inline]
from(q: Quat) -> Self897     fn from(q: Quat) -> Self {
898         Self::new(q.x, q.y, q.z, q.w)
899     }
900 }
901 
902 impl From<Quat> for (f32, f32, f32, f32) {
903     #[inline]
from(q: Quat) -> Self904     fn from(q: Quat) -> Self {
905         (q.x, q.y, q.z, q.w)
906     }
907 }
908 
909 impl From<Quat> for [f32; 4] {
910     #[inline]
from(q: Quat) -> Self911     fn from(q: Quat) -> Self {
912         [q.x, q.y, q.z, q.w]
913     }
914 }
915