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     wasm32::*,
7     DQuat, Mat3, Mat3A, Mat4, Vec2, Vec3, Vec3A, Vec4,
8 };
9 
10 use core::arch::wasm32::*;
11 
12 #[cfg(not(target_arch = "spirv"))]
13 use core::fmt;
14 use core::iter::{Product, Sum};
15 use core::ops::{Add, Deref, DerefMut, Div, Mul, MulAssign, Neg, Sub};
16 
17 /// Creates a quaternion from `x`, `y`, `z` and `w` values.
18 ///
19 /// This should generally not be called manually unless you know what you are doing. Use
20 /// one of the other constructors instead such as `identity` or `from_axis_angle`.
21 #[inline]
22 #[must_use]
quat(x: f32, y: f32, z: f32, w: f32) -> Quat23 pub const fn quat(x: f32, y: f32, z: f32, w: f32) -> Quat {
24     Quat::from_xyzw(x, y, z, w)
25 }
26 
27 /// A quaternion representing an orientation.
28 ///
29 /// This quaternion is intended to be of unit length but may denormalize due to
30 /// floating point "error creep" which can occur when successive quaternion
31 /// operations are applied.
32 ///
33 /// SIMD vector types are used for storage on supported platforms.
34 ///
35 /// This type is 16 byte aligned.
36 #[derive(Clone, Copy)]
37 #[repr(transparent)]
38 pub struct Quat(pub(crate) v128);
39 
40 impl Quat {
41     /// All zeros.
42     const ZERO: Self = Self::from_array([0.0; 4]);
43 
44     /// The identity quaternion. Corresponds to no rotation.
45     pub const IDENTITY: Self = Self::from_xyzw(0.0, 0.0, 0.0, 1.0);
46 
47     /// All NANs.
48     pub const NAN: Self = Self::from_array([f32::NAN; 4]);
49 
50     /// Creates a new rotation quaternion.
51     ///
52     /// This should generally not be called manually unless you know what you are doing.
53     /// Use one of the other constructors instead such as `identity` or `from_axis_angle`.
54     ///
55     /// `from_xyzw` is mostly used by unit tests and `serde` deserialization.
56     ///
57     /// # Preconditions
58     ///
59     /// This function does not check if the input is normalized, it is up to the user to
60     /// provide normalized input or to normalized the resulting quaternion.
61     #[inline(always)]
62     #[must_use]
from_xyzw(x: f32, y: f32, z: f32, w: f32) -> Self63     pub const fn from_xyzw(x: f32, y: f32, z: f32, w: f32) -> Self {
64         Self(f32x4(x, y, z, w))
65     }
66 
67     /// Creates a rotation quaternion from an array.
68     ///
69     /// # Preconditions
70     ///
71     /// This function does not check if the input is normalized, it is up to the user to
72     /// provide normalized input or to normalized the resulting quaternion.
73     #[inline]
74     #[must_use]
from_array(a: [f32; 4]) -> Self75     pub const fn from_array(a: [f32; 4]) -> Self {
76         Self::from_xyzw(a[0], a[1], a[2], a[3])
77     }
78 
79     /// Creates a new rotation quaternion from a 4D vector.
80     ///
81     /// # Preconditions
82     ///
83     /// This function does not check if the input is normalized, it is up to the user to
84     /// provide normalized input or to normalized the resulting quaternion.
85     #[inline]
86     #[must_use]
from_vec4(v: Vec4) -> Self87     pub const fn from_vec4(v: Vec4) -> Self {
88         Self(v.0)
89     }
90 
91     /// Creates a rotation quaternion from a slice.
92     ///
93     /// # Preconditions
94     ///
95     /// This function does not check if the input is normalized, it is up to the user to
96     /// provide normalized input or to normalized the resulting quaternion.
97     ///
98     /// # Panics
99     ///
100     /// Panics if `slice` length is less than 4.
101     #[inline]
102     #[must_use]
from_slice(slice: &[f32]) -> Self103     pub fn from_slice(slice: &[f32]) -> Self {
104         Self::from_xyzw(slice[0], slice[1], slice[2], slice[3])
105     }
106 
107     /// Writes the quaternion to an unaligned slice.
108     ///
109     /// # Panics
110     ///
111     /// Panics if `slice` length is less than 4.
112     #[inline]
write_to_slice(self, slice: &mut [f32])113     pub fn write_to_slice(self, slice: &mut [f32]) {
114         slice[0] = self.x;
115         slice[1] = self.y;
116         slice[2] = self.z;
117         slice[3] = self.w;
118     }
119 
120     /// Create a quaternion for a normalized rotation `axis` and `angle` (in radians).
121     ///
122     /// The axis must be a unit vector.
123     ///
124     /// # Panics
125     ///
126     /// Will panic if `axis` is not normalized when `glam_assert` is enabled.
127     #[inline]
128     #[must_use]
from_axis_angle(axis: Vec3, angle: f32) -> Self129     pub fn from_axis_angle(axis: Vec3, angle: f32) -> Self {
130         glam_assert!(axis.is_normalized());
131         let (s, c) = math::sin_cos(angle * 0.5);
132         let v = axis * s;
133         Self::from_xyzw(v.x, v.y, v.z, c)
134     }
135 
136     /// Create a quaternion that rotates `v.length()` radians around `v.normalize()`.
137     ///
138     /// `from_scaled_axis(Vec3::ZERO)` results in the identity quaternion.
139     #[inline]
140     #[must_use]
from_scaled_axis(v: Vec3) -> Self141     pub fn from_scaled_axis(v: Vec3) -> Self {
142         let length = v.length();
143         if length == 0.0 {
144             Self::IDENTITY
145         } else {
146             Self::from_axis_angle(v / length, length)
147         }
148     }
149 
150     /// Creates a quaternion from the `angle` (in radians) around the x axis.
151     #[inline]
152     #[must_use]
from_rotation_x(angle: f32) -> Self153     pub fn from_rotation_x(angle: f32) -> Self {
154         let (s, c) = math::sin_cos(angle * 0.5);
155         Self::from_xyzw(s, 0.0, 0.0, c)
156     }
157 
158     /// Creates a quaternion from the `angle` (in radians) around the y axis.
159     #[inline]
160     #[must_use]
from_rotation_y(angle: f32) -> Self161     pub fn from_rotation_y(angle: f32) -> Self {
162         let (s, c) = math::sin_cos(angle * 0.5);
163         Self::from_xyzw(0.0, s, 0.0, c)
164     }
165 
166     /// Creates a quaternion from the `angle` (in radians) around the z axis.
167     #[inline]
168     #[must_use]
from_rotation_z(angle: f32) -> Self169     pub fn from_rotation_z(angle: f32) -> Self {
170         let (s, c) = math::sin_cos(angle * 0.5);
171         Self::from_xyzw(0.0, 0.0, s, c)
172     }
173 
174     /// Creates a quaternion from the given Euler rotation sequence and the angles (in radians).
175     #[inline]
176     #[must_use]
from_euler(euler: EulerRot, a: f32, b: f32, c: f32) -> Self177     pub fn from_euler(euler: EulerRot, a: f32, b: f32, c: f32) -> Self {
178         euler.new_quat(a, b, c)
179     }
180 
181     /// From the columns of a 3x3 rotation matrix.
182     #[inline]
183     #[must_use]
from_rotation_axes(x_axis: Vec3, y_axis: Vec3, z_axis: Vec3) -> Self184     pub(crate) fn from_rotation_axes(x_axis: Vec3, y_axis: Vec3, z_axis: Vec3) -> Self {
185         // Based on https://github.com/microsoft/DirectXMath `XM$quaternionRotationMatrix`
186         let (m00, m01, m02) = x_axis.into();
187         let (m10, m11, m12) = y_axis.into();
188         let (m20, m21, m22) = z_axis.into();
189         if m22 <= 0.0 {
190             // x^2 + y^2 >= z^2 + w^2
191             let dif10 = m11 - m00;
192             let omm22 = 1.0 - m22;
193             if dif10 <= 0.0 {
194                 // x^2 >= y^2
195                 let four_xsq = omm22 - dif10;
196                 let inv4x = 0.5 / math::sqrt(four_xsq);
197                 Self::from_xyzw(
198                     four_xsq * inv4x,
199                     (m01 + m10) * inv4x,
200                     (m02 + m20) * inv4x,
201                     (m12 - m21) * inv4x,
202                 )
203             } else {
204                 // y^2 >= x^2
205                 let four_ysq = omm22 + dif10;
206                 let inv4y = 0.5 / math::sqrt(four_ysq);
207                 Self::from_xyzw(
208                     (m01 + m10) * inv4y,
209                     four_ysq * inv4y,
210                     (m12 + m21) * inv4y,
211                     (m20 - m02) * inv4y,
212                 )
213             }
214         } else {
215             // z^2 + w^2 >= x^2 + y^2
216             let sum10 = m11 + m00;
217             let opm22 = 1.0 + m22;
218             if sum10 <= 0.0 {
219                 // z^2 >= w^2
220                 let four_zsq = opm22 - sum10;
221                 let inv4z = 0.5 / math::sqrt(four_zsq);
222                 Self::from_xyzw(
223                     (m02 + m20) * inv4z,
224                     (m12 + m21) * inv4z,
225                     four_zsq * inv4z,
226                     (m01 - m10) * inv4z,
227                 )
228             } else {
229                 // w^2 >= z^2
230                 let four_wsq = opm22 + sum10;
231                 let inv4w = 0.5 / math::sqrt(four_wsq);
232                 Self::from_xyzw(
233                     (m12 - m21) * inv4w,
234                     (m20 - m02) * inv4w,
235                     (m01 - m10) * inv4w,
236                     four_wsq * inv4w,
237                 )
238             }
239         }
240     }
241 
242     /// Creates a quaternion from a 3x3 rotation matrix.
243     #[inline]
244     #[must_use]
from_mat3(mat: &Mat3) -> Self245     pub fn from_mat3(mat: &Mat3) -> Self {
246         Self::from_rotation_axes(mat.x_axis, mat.y_axis, mat.z_axis)
247     }
248 
249     /// Creates a quaternion from a 3x3 SIMD aligned rotation matrix.
250     #[inline]
251     #[must_use]
from_mat3a(mat: &Mat3A) -> Self252     pub fn from_mat3a(mat: &Mat3A) -> Self {
253         Self::from_rotation_axes(mat.x_axis.into(), mat.y_axis.into(), mat.z_axis.into())
254     }
255 
256     /// Creates a quaternion from a 3x3 rotation matrix inside a homogeneous 4x4 matrix.
257     #[inline]
258     #[must_use]
from_mat4(mat: &Mat4) -> Self259     pub fn from_mat4(mat: &Mat4) -> Self {
260         Self::from_rotation_axes(
261             mat.x_axis.truncate(),
262             mat.y_axis.truncate(),
263             mat.z_axis.truncate(),
264         )
265     }
266 
267     /// Gets the minimal rotation for transforming `from` to `to`.  The rotation is in the
268     /// plane spanned by the two vectors.  Will rotate at most 180 degrees.
269     ///
270     /// The inputs must be unit vectors.
271     ///
272     /// `from_rotation_arc(from, to) * from ≈ to`.
273     ///
274     /// For near-singular cases (from≈to and from≈-to) the current implementation
275     /// is only accurate to about 0.001 (for `f32`).
276     ///
277     /// # Panics
278     ///
279     /// Will panic if `from` or `to` are not normalized when `glam_assert` is enabled.
280     #[must_use]
from_rotation_arc(from: Vec3, to: Vec3) -> Self281     pub fn from_rotation_arc(from: Vec3, to: Vec3) -> Self {
282         glam_assert!(from.is_normalized());
283         glam_assert!(to.is_normalized());
284 
285         const ONE_MINUS_EPS: f32 = 1.0 - 2.0 * core::f32::EPSILON;
286         let dot = from.dot(to);
287         if dot > ONE_MINUS_EPS {
288             // 0° singulary: from ≈ to
289             Self::IDENTITY
290         } else if dot < -ONE_MINUS_EPS {
291             // 180° singulary: from ≈ -to
292             use core::f32::consts::PI; // half a turn = ��/2 = 180°
293             Self::from_axis_angle(from.any_orthonormal_vector(), PI)
294         } else {
295             let c = from.cross(to);
296             Self::from_xyzw(c.x, c.y, c.z, 1.0 + dot).normalize()
297         }
298     }
299 
300     /// Gets the minimal rotation for transforming `from` to either `to` or `-to`.  This means
301     /// that the resulting quaternion will rotate `from` so that it is colinear with `to`.
302     ///
303     /// The rotation is in the plane spanned by the two vectors.  Will rotate at most 90
304     /// degrees.
305     ///
306     /// The inputs must be unit vectors.
307     ///
308     /// `to.dot(from_rotation_arc_colinear(from, to) * from).abs() ≈ 1`.
309     ///
310     /// # Panics
311     ///
312     /// Will panic if `from` or `to` are not normalized when `glam_assert` is enabled.
313     #[inline]
314     #[must_use]
from_rotation_arc_colinear(from: Vec3, to: Vec3) -> Self315     pub fn from_rotation_arc_colinear(from: Vec3, to: Vec3) -> Self {
316         if from.dot(to) < 0.0 {
317             Self::from_rotation_arc(from, -to)
318         } else {
319             Self::from_rotation_arc(from, to)
320         }
321     }
322 
323     /// Gets the minimal rotation for transforming `from` to `to`.  The resulting rotation is
324     /// around the z axis. Will rotate at most 180 degrees.
325     ///
326     /// The inputs must be unit vectors.
327     ///
328     /// `from_rotation_arc_2d(from, to) * from ≈ to`.
329     ///
330     /// For near-singular cases (from≈to and from≈-to) the current implementation
331     /// is only accurate to about 0.001 (for `f32`).
332     ///
333     /// # Panics
334     ///
335     /// Will panic if `from` or `to` are not normalized when `glam_assert` is enabled.
336     #[must_use]
from_rotation_arc_2d(from: Vec2, to: Vec2) -> Self337     pub fn from_rotation_arc_2d(from: Vec2, to: Vec2) -> Self {
338         glam_assert!(from.is_normalized());
339         glam_assert!(to.is_normalized());
340 
341         const ONE_MINUS_EPSILON: f32 = 1.0 - 2.0 * core::f32::EPSILON;
342         let dot = from.dot(to);
343         if dot > ONE_MINUS_EPSILON {
344             // 0° singulary: from ≈ to
345             Self::IDENTITY
346         } else if dot < -ONE_MINUS_EPSILON {
347             // 180° singulary: from ≈ -to
348             const COS_FRAC_PI_2: f32 = 0.0;
349             const SIN_FRAC_PI_2: f32 = 1.0;
350             // rotation around z by PI radians
351             Self::from_xyzw(0.0, 0.0, SIN_FRAC_PI_2, COS_FRAC_PI_2)
352         } else {
353             // vector3 cross where z=0
354             let z = from.x * to.y - to.x * from.y;
355             let w = 1.0 + dot;
356             // calculate length with x=0 and y=0 to normalize
357             let len_rcp = 1.0 / math::sqrt(z * z + w * w);
358             Self::from_xyzw(0.0, 0.0, z * len_rcp, w * len_rcp)
359         }
360     }
361 
362     /// Returns the rotation axis (normalized) and angle (in radians) of `self`.
363     #[inline]
364     #[must_use]
to_axis_angle(self) -> (Vec3, f32)365     pub fn to_axis_angle(self) -> (Vec3, f32) {
366         const EPSILON: f32 = 1.0e-8;
367         let v = Vec3::new(self.x, self.y, self.z);
368         let length = v.length();
369         if length >= EPSILON {
370             let angle = 2.0 * math::atan2(length, self.w);
371             let axis = v / length;
372             (axis, angle)
373         } else {
374             (Vec3::X, 0.0)
375         }
376     }
377 
378     /// Returns the rotation axis scaled by the rotation in radians.
379     #[inline]
380     #[must_use]
to_scaled_axis(self) -> Vec3381     pub fn to_scaled_axis(self) -> Vec3 {
382         let (axis, angle) = self.to_axis_angle();
383         axis * angle
384     }
385 
386     /// Returns the rotation angles for the given euler rotation sequence.
387     #[inline]
388     #[must_use]
to_euler(self, euler: EulerRot) -> (f32, f32, f32)389     pub fn to_euler(self, euler: EulerRot) -> (f32, f32, f32) {
390         euler.convert_quat(self)
391     }
392 
393     /// `[x, y, z, w]`
394     #[inline]
395     #[must_use]
to_array(&self) -> [f32; 4]396     pub fn to_array(&self) -> [f32; 4] {
397         [self.x, self.y, self.z, self.w]
398     }
399 
400     /// Returns the vector part of the quaternion.
401     #[inline]
402     #[must_use]
xyz(self) -> Vec3403     pub fn xyz(self) -> Vec3 {
404         Vec3::new(self.x, self.y, self.z)
405     }
406 
407     /// Returns the quaternion conjugate of `self`. For a unit quaternion the
408     /// conjugate is also the inverse.
409     #[inline]
410     #[must_use]
conjugate(self) -> Self411     pub fn conjugate(self) -> Self {
412         const SIGN: v128 = v128_from_f32x4([-1.0, -1.0, -1.0, 1.0]);
413         Self(f32x4_mul(self.0, SIGN))
414     }
415 
416     /// Returns the inverse of a normalized quaternion.
417     ///
418     /// Typically quaternion inverse returns the conjugate of a normalized quaternion.
419     /// Because `self` is assumed to already be unit length this method *does not* normalize
420     /// before returning the conjugate.
421     ///
422     /// # Panics
423     ///
424     /// Will panic if `self` is not normalized when `glam_assert` is enabled.
425     #[inline]
426     #[must_use]
inverse(self) -> Self427     pub fn inverse(self) -> Self {
428         glam_assert!(self.is_normalized());
429         self.conjugate()
430     }
431 
432     /// Computes the dot product of `self` and `rhs`. The dot product is
433     /// equal to the cosine of the angle between two quaternion rotations.
434     #[inline]
435     #[must_use]
dot(self, rhs: Self) -> f32436     pub fn dot(self, rhs: Self) -> f32 {
437         Vec4::from(self).dot(Vec4::from(rhs))
438     }
439 
440     /// Computes the length of `self`.
441     #[doc(alias = "magnitude")]
442     #[inline]
443     #[must_use]
length(self) -> f32444     pub fn length(self) -> f32 {
445         Vec4::from(self).length()
446     }
447 
448     /// Computes the squared length of `self`.
449     ///
450     /// This is generally faster than `length()` as it avoids a square
451     /// root operation.
452     #[doc(alias = "magnitude2")]
453     #[inline]
454     #[must_use]
length_squared(self) -> f32455     pub fn length_squared(self) -> f32 {
456         Vec4::from(self).length_squared()
457     }
458 
459     /// Computes `1.0 / length()`.
460     ///
461     /// For valid results, `self` must _not_ be of length zero.
462     #[inline]
463     #[must_use]
length_recip(self) -> f32464     pub fn length_recip(self) -> f32 {
465         Vec4::from(self).length_recip()
466     }
467 
468     /// Returns `self` normalized to length 1.0.
469     ///
470     /// For valid results, `self` must _not_ be of length zero.
471     ///
472     /// Panics
473     ///
474     /// Will panic if `self` is zero length when `glam_assert` is enabled.
475     #[inline]
476     #[must_use]
normalize(self) -> Self477     pub fn normalize(self) -> Self {
478         Self::from_vec4(Vec4::from(self).normalize())
479     }
480 
481     /// Returns `true` if, and only if, all elements are finite.
482     /// If any element is either `NaN`, positive or negative infinity, this will return `false`.
483     #[inline]
484     #[must_use]
is_finite(self) -> bool485     pub fn is_finite(self) -> bool {
486         Vec4::from(self).is_finite()
487     }
488 
489     #[inline]
490     #[must_use]
is_nan(self) -> bool491     pub fn is_nan(self) -> bool {
492         Vec4::from(self).is_nan()
493     }
494 
495     /// Returns whether `self` of length `1.0` or not.
496     ///
497     /// Uses a precision threshold of `1e-6`.
498     #[inline]
499     #[must_use]
is_normalized(self) -> bool500     pub fn is_normalized(self) -> bool {
501         Vec4::from(self).is_normalized()
502     }
503 
504     #[inline]
505     #[must_use]
is_near_identity(self) -> bool506     pub fn is_near_identity(self) -> bool {
507         // Based on https://github.com/nfrechette/rtm `rtm::quat_near_identity`
508         let threshold_angle = 0.002_847_144_6;
509         // Because of floating point precision, we cannot represent very small rotations.
510         // The closest f32 to 1.0 that is not 1.0 itself yields:
511         // 0.99999994.acos() * 2.0  = 0.000690533954 rad
512         //
513         // An error threshold of 1.e-6 is used by default.
514         // (1.0 - 1.e-6).acos() * 2.0 = 0.00284714461 rad
515         // (1.0 - 1.e-7).acos() * 2.0 = 0.00097656250 rad
516         //
517         // We don't really care about the angle value itself, only if it's close to 0.
518         // This will happen whenever quat.w is close to 1.0.
519         // If the quat.w is close to -1.0, the angle will be near 2*PI which is close to
520         // a negative 0 rotation. By forcing quat.w to be positive, we'll end up with
521         // the shortest path.
522         let positive_w_angle = math::acos_approx(math::abs(self.w)) * 2.0;
523         positive_w_angle < threshold_angle
524     }
525 
526     /// Returns the angle (in radians) for the minimal rotation
527     /// for transforming this quaternion into another.
528     ///
529     /// Both quaternions must be normalized.
530     ///
531     /// # Panics
532     ///
533     /// Will panic if `self` or `rhs` are not normalized when `glam_assert` is enabled.
534     #[inline]
535     #[must_use]
angle_between(self, rhs: Self) -> f32536     pub fn angle_between(self, rhs: Self) -> f32 {
537         glam_assert!(self.is_normalized() && rhs.is_normalized());
538         math::acos_approx(math::abs(self.dot(rhs))) * 2.0
539     }
540 
541     /// Returns true if the absolute difference of all elements between `self` and `rhs`
542     /// is less than or equal to `max_abs_diff`.
543     ///
544     /// This can be used to compare if two quaternions contain similar elements. It works
545     /// best when comparing with a known value. The `max_abs_diff` that should be used used
546     /// depends on the values being compared against.
547     ///
548     /// For more see
549     /// [comparing floating point numbers](https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/).
550     #[inline]
551     #[must_use]
abs_diff_eq(self, rhs: Self, max_abs_diff: f32) -> bool552     pub fn abs_diff_eq(self, rhs: Self, max_abs_diff: f32) -> bool {
553         Vec4::from(self).abs_diff_eq(Vec4::from(rhs), max_abs_diff)
554     }
555 
556     /// Performs a linear interpolation between `self` and `rhs` based on
557     /// the value `s`.
558     ///
559     /// When `s` is `0.0`, the result will be equal to `self`.  When `s`
560     /// is `1.0`, the result will be equal to `rhs`.
561     ///
562     /// # Panics
563     ///
564     /// Will panic if `self` or `end` are not normalized when `glam_assert` is enabled.
565     #[doc(alias = "mix")]
566     #[inline]
567     #[must_use]
lerp(self, end: Self, s: f32) -> Self568     pub fn lerp(self, end: Self, s: f32) -> Self {
569         glam_assert!(self.is_normalized());
570         glam_assert!(end.is_normalized());
571 
572         const NEG_ZERO: v128 = v128_from_f32x4([-0.0; 4]);
573         let start = self.0;
574         let end = end.0;
575         let dot = dot4_into_v128(start, end);
576         // Calculate the bias, if the dot product is positive or zero, there is no bias
577         // but if it is negative, we want to flip the 'end' rotation XYZW components
578         let bias = v128_and(dot, NEG_ZERO);
579         let interpolated = f32x4_add(
580             f32x4_mul(f32x4_sub(v128_xor(end, bias), start), f32x4_splat(s)),
581             start,
582         );
583         Quat(interpolated).normalize()
584     }
585 
586     /// Performs a spherical linear interpolation between `self` and `end`
587     /// based on the value `s`.
588     ///
589     /// When `s` is `0.0`, the result will be equal to `self`.  When `s`
590     /// is `1.0`, the result will be equal to `end`.
591     ///
592     /// # Panics
593     ///
594     /// Will panic if `self` or `end` are not normalized when `glam_assert` is enabled.
595     #[inline]
596     #[must_use]
slerp(self, mut end: Self, s: f32) -> Self597     pub fn slerp(self, mut end: Self, s: f32) -> Self {
598         // http://number-none.com/product/Understanding%20Slerp,%20Then%20Not%20Using%20It/
599         glam_assert!(self.is_normalized());
600         glam_assert!(end.is_normalized());
601 
602         const DOT_THRESHOLD: f32 = 0.9995;
603 
604         // Note that a rotation can be represented by two quaternions: `q` and
605         // `-q`. The slerp path between `q` and `end` will be different from the
606         // path between `-q` and `end`. One path will take the long way around and
607         // one will take the short way. In order to correct for this, the `dot`
608         // product between `self` and `end` should be positive. If the `dot`
609         // product is negative, slerp between `self` and `-end`.
610         let mut dot = self.dot(end);
611         if dot < 0.0 {
612             end = -end;
613             dot = -dot;
614         }
615 
616         if dot > DOT_THRESHOLD {
617             // assumes lerp returns a normalized quaternion
618             self.lerp(end, s)
619         } else {
620             let theta = math::acos_approx(dot);
621 
622             // TODO: v128_sin is broken
623             // let x = 1.0 - s;
624             // let y = s;
625             // let z = 1.0;
626             // let w = 0.0;
627             // let tmp = f32x4_mul(f32x4_splat(theta), f32x4(x, y, z, w));
628             // let tmp = v128_sin(tmp);
629             let x = math::sin(theta * (1.0 - s));
630             let y = math::sin(theta * s);
631             let z = math::sin(theta);
632             let w = 0.0;
633             let tmp = f32x4(x, y, z, w);
634 
635             let scale1 = i32x4_shuffle::<0, 0, 4, 4>(tmp, tmp);
636             let scale2 = i32x4_shuffle::<1, 1, 5, 5>(tmp, tmp);
637             let theta_sin = i32x4_shuffle::<2, 2, 6, 6>(tmp, tmp);
638 
639             Self(f32x4_div(
640                 f32x4_add(f32x4_mul(self.0, scale1), f32x4_mul(end.0, scale2)),
641                 theta_sin,
642             ))
643         }
644     }
645 
646     /// Multiplies a quaternion and a 3D vector, returning the rotated vector.
647     ///
648     /// # Panics
649     ///
650     /// Will panic if `self` is not normalized when `glam_assert` is enabled.
651     #[inline]
652     #[must_use]
mul_vec3(self, rhs: Vec3) -> Vec3653     pub fn mul_vec3(self, rhs: Vec3) -> Vec3 {
654         glam_assert!(self.is_normalized());
655 
656         self.mul_vec3a(rhs.into()).into()
657     }
658 
659     /// Multiplies two quaternions. If they each represent a rotation, the result will
660     /// represent the combined rotation.
661     ///
662     /// Note that due to floating point rounding the result may not be perfectly normalized.
663     ///
664     /// # Panics
665     ///
666     /// Will panic if `self` or `rhs` are not normalized when `glam_assert` is enabled.
667     #[inline]
668     #[must_use]
mul_quat(self, rhs: Self) -> Self669     pub fn mul_quat(self, rhs: Self) -> Self {
670         glam_assert!(self.is_normalized());
671         glam_assert!(rhs.is_normalized());
672 
673         let lhs = self.0;
674         let rhs = rhs.0;
675 
676         const CONTROL_WZYX: v128 = v128_from_f32x4([1.0, -1.0, 1.0, -1.0]);
677         const CONTROL_ZWXY: v128 = v128_from_f32x4([1.0, 1.0, -1.0, -1.0]);
678         const CONTROL_YXWZ: v128 = v128_from_f32x4([-1.0, 1.0, 1.0, -1.0]);
679 
680         let r_xxxx = i32x4_shuffle::<0, 0, 4, 4>(lhs, lhs);
681         let r_yyyy = i32x4_shuffle::<1, 1, 5, 5>(lhs, lhs);
682         let r_zzzz = i32x4_shuffle::<2, 2, 6, 6>(lhs, lhs);
683         let r_wwww = i32x4_shuffle::<3, 3, 7, 7>(lhs, lhs);
684 
685         let lxrw_lyrw_lzrw_lwrw = f32x4_mul(r_wwww, rhs);
686         let l_wzyx = i32x4_shuffle::<3, 2, 5, 4>(rhs, rhs);
687 
688         let lwrx_lzrx_lyrx_lxrx = f32x4_mul(r_xxxx, l_wzyx);
689         let l_zwxy = i32x4_shuffle::<1, 0, 7, 6>(l_wzyx, l_wzyx);
690 
691         let lwrx_nlzrx_lyrx_nlxrx = f32x4_mul(lwrx_lzrx_lyrx_lxrx, CONTROL_WZYX);
692 
693         let lzry_lwry_lxry_lyry = f32x4_mul(r_yyyy, l_zwxy);
694         let l_yxwz = i32x4_shuffle::<3, 2, 5, 4>(l_zwxy, l_zwxy);
695 
696         let lzry_lwry_nlxry_nlyry = f32x4_mul(lzry_lwry_lxry_lyry, CONTROL_ZWXY);
697 
698         let lyrz_lxrz_lwrz_lzrz = f32x4_mul(r_zzzz, l_yxwz);
699         let result0 = f32x4_add(lxrw_lyrw_lzrw_lwrw, lwrx_nlzrx_lyrx_nlxrx);
700 
701         let nlyrz_lxrz_lwrz_wlzrz = f32x4_mul(lyrz_lxrz_lwrz_lzrz, CONTROL_YXWZ);
702         let result1 = f32x4_add(lzry_lwry_nlxry_nlyry, nlyrz_lxrz_lwrz_wlzrz);
703 
704         Self(f32x4_add(result0, result1))
705     }
706 
707     /// Creates a quaternion from a 3x3 rotation matrix inside a 3D affine transform.
708     #[inline]
709     #[must_use]
from_affine3(a: &crate::Affine3A) -> Self710     pub fn from_affine3(a: &crate::Affine3A) -> Self {
711         #[allow(clippy::useless_conversion)]
712         Self::from_rotation_axes(
713             a.matrix3.x_axis.into(),
714             a.matrix3.y_axis.into(),
715             a.matrix3.z_axis.into(),
716         )
717     }
718 
719     /// Multiplies a quaternion and a 3D vector, returning the rotated vector.
720     #[inline]
721     #[must_use]
mul_vec3a(self, rhs: Vec3A) -> Vec3A722     pub fn mul_vec3a(self, rhs: Vec3A) -> Vec3A {
723         const TWO: v128 = v128_from_f32x4([2.0; 4]);
724         let w = i32x4_shuffle::<3, 3, 7, 7>(self.0, self.0);
725         let b = self.0;
726         let b2 = dot3_into_v128(b, b);
727         Vec3A(f32x4_add(
728             f32x4_add(
729                 f32x4_mul(rhs.0, f32x4_sub(f32x4_mul(w, w), b2)),
730                 f32x4_mul(b, f32x4_mul(dot3_into_v128(rhs.0, b), TWO)),
731             ),
732             f32x4_mul(Vec3A(b).cross(rhs).into(), f32x4_mul(w, TWO)),
733         ))
734     }
735 
736     #[inline]
737     #[must_use]
as_dquat(self) -> DQuat738     pub fn as_dquat(self) -> DQuat {
739         DQuat::from_xyzw(self.x as f64, self.y as f64, self.z as f64, self.w as f64)
740     }
741 
742     #[inline]
743     #[must_use]
744     #[deprecated(since = "0.24.2", note = "Use as_dquat() instead")]
as_f64(self) -> DQuat745     pub fn as_f64(self) -> DQuat {
746         self.as_dquat()
747     }
748 }
749 
750 #[cfg(not(target_arch = "spirv"))]
751 impl fmt::Debug for Quat {
fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result752     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
753         fmt.debug_tuple(stringify!(Quat))
754             .field(&self.x)
755             .field(&self.y)
756             .field(&self.z)
757             .field(&self.w)
758             .finish()
759     }
760 }
761 
762 #[cfg(not(target_arch = "spirv"))]
763 impl fmt::Display for Quat {
fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result764     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
765         write!(fmt, "[{}, {}, {}, {}]", self.x, self.y, self.z, self.w)
766     }
767 }
768 
769 impl Add<Quat> for Quat {
770     type Output = Self;
771     /// Adds two quaternions.
772     ///
773     /// The sum is not guaranteed to be normalized.
774     ///
775     /// Note that addition is not the same as combining the rotations represented by the
776     /// two quaternions! That corresponds to multiplication.
777     #[inline]
add(self, rhs: Self) -> Self778     fn add(self, rhs: Self) -> Self {
779         Self::from_vec4(Vec4::from(self) + Vec4::from(rhs))
780     }
781 }
782 
783 impl Sub<Quat> for Quat {
784     type Output = Self;
785     /// Subtracts the `rhs` quaternion from `self`.
786     ///
787     /// The difference is not guaranteed to be normalized.
788     #[inline]
sub(self, rhs: Self) -> Self789     fn sub(self, rhs: Self) -> Self {
790         Self::from_vec4(Vec4::from(self) - Vec4::from(rhs))
791     }
792 }
793 
794 impl Mul<f32> for Quat {
795     type Output = Self;
796     /// Multiplies a quaternion by a scalar value.
797     ///
798     /// The product is not guaranteed to be normalized.
799     #[inline]
mul(self, rhs: f32) -> Self800     fn mul(self, rhs: f32) -> Self {
801         Self::from_vec4(Vec4::from(self) * rhs)
802     }
803 }
804 
805 impl Div<f32> for Quat {
806     type Output = Self;
807     /// Divides a quaternion by a scalar value.
808     /// The quotient is not guaranteed to be normalized.
809     #[inline]
div(self, rhs: f32) -> Self810     fn div(self, rhs: f32) -> Self {
811         Self::from_vec4(Vec4::from(self) / rhs)
812     }
813 }
814 
815 impl Mul<Quat> for Quat {
816     type Output = Self;
817     /// Multiplies two quaternions. If they each represent a rotation, the result will
818     /// represent the combined rotation.
819     ///
820     /// Note that due to floating point rounding the result may not be perfectly
821     /// normalized.
822     ///
823     /// # Panics
824     ///
825     /// Will panic if `self` or `rhs` are not normalized when `glam_assert` is enabled.
826     #[inline]
mul(self, rhs: Self) -> Self827     fn mul(self, rhs: Self) -> Self {
828         self.mul_quat(rhs)
829     }
830 }
831 
832 impl MulAssign<Quat> for Quat {
833     /// Multiplies two quaternions. If they each represent a rotation, the result will
834     /// represent the combined rotation.
835     ///
836     /// Note that due to floating point rounding the result may not be perfectly
837     /// normalized.
838     ///
839     /// # Panics
840     ///
841     /// Will panic if `self` or `rhs` are not normalized when `glam_assert` is enabled.
842     #[inline]
mul_assign(&mut self, rhs: Self)843     fn mul_assign(&mut self, rhs: Self) {
844         *self = self.mul_quat(rhs);
845     }
846 }
847 
848 impl Mul<Vec3> for Quat {
849     type Output = Vec3;
850     /// Multiplies a quaternion and a 3D vector, returning the rotated vector.
851     ///
852     /// # Panics
853     ///
854     /// Will panic if `self` is not normalized when `glam_assert` is enabled.
855     #[inline]
mul(self, rhs: Vec3) -> Self::Output856     fn mul(self, rhs: Vec3) -> Self::Output {
857         self.mul_vec3(rhs)
858     }
859 }
860 
861 impl Neg for Quat {
862     type Output = Self;
863     #[inline]
neg(self) -> Self864     fn neg(self) -> Self {
865         self * -1.0
866     }
867 }
868 
869 impl Default for Quat {
870     #[inline]
default() -> Self871     fn default() -> Self {
872         Self::IDENTITY
873     }
874 }
875 
876 impl PartialEq for Quat {
877     #[inline]
eq(&self, rhs: &Self) -> bool878     fn eq(&self, rhs: &Self) -> bool {
879         Vec4::from(*self).eq(&Vec4::from(*rhs))
880     }
881 }
882 
883 #[cfg(not(target_arch = "spirv"))]
884 impl AsRef<[f32; 4]> for Quat {
885     #[inline]
as_ref(&self) -> &[f32; 4]886     fn as_ref(&self) -> &[f32; 4] {
887         unsafe { &*(self as *const Self as *const [f32; 4]) }
888     }
889 }
890 
891 impl Sum<Self> for Quat {
sum<I>(iter: I) -> Self where I: Iterator<Item = Self>,892     fn sum<I>(iter: I) -> Self
893     where
894         I: Iterator<Item = Self>,
895     {
896         iter.fold(Self::ZERO, Self::add)
897     }
898 }
899 
900 impl<'a> Sum<&'a Self> for Quat {
sum<I>(iter: I) -> Self where I: Iterator<Item = &'a Self>,901     fn sum<I>(iter: I) -> Self
902     where
903         I: Iterator<Item = &'a Self>,
904     {
905         iter.fold(Self::ZERO, |a, &b| Self::add(a, b))
906     }
907 }
908 
909 impl Product for Quat {
product<I>(iter: I) -> Self where I: Iterator<Item = Self>,910     fn product<I>(iter: I) -> Self
911     where
912         I: Iterator<Item = Self>,
913     {
914         iter.fold(Self::IDENTITY, Self::mul)
915     }
916 }
917 
918 impl<'a> Product<&'a Self> for Quat {
product<I>(iter: I) -> Self where I: Iterator<Item = &'a Self>,919     fn product<I>(iter: I) -> Self
920     where
921         I: Iterator<Item = &'a Self>,
922     {
923         iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b))
924     }
925 }
926 
927 impl Mul<Vec3A> for Quat {
928     type Output = Vec3A;
929     #[inline]
mul(self, rhs: Vec3A) -> Self::Output930     fn mul(self, rhs: Vec3A) -> Self::Output {
931         self.mul_vec3a(rhs)
932     }
933 }
934 
935 impl From<Quat> for Vec4 {
936     #[inline]
from(q: Quat) -> Self937     fn from(q: Quat) -> Self {
938         Self(q.0)
939     }
940 }
941 
942 impl From<Quat> for (f32, f32, f32, f32) {
943     #[inline]
from(q: Quat) -> Self944     fn from(q: Quat) -> Self {
945         Vec4::from(q).into()
946     }
947 }
948 
949 impl From<Quat> for [f32; 4] {
950     #[inline]
from(q: Quat) -> Self951     fn from(q: Quat) -> Self {
952         Vec4::from(q).into()
953     }
954 }
955 
956 impl From<Quat> for v128 {
957     #[inline]
from(q: Quat) -> Self958     fn from(q: Quat) -> Self {
959         q.0
960     }
961 }
962 
963 impl Deref for Quat {
964     type Target = crate::deref::Vec4<f32>;
965     #[inline]
deref(&self) -> &Self::Target966     fn deref(&self) -> &Self::Target {
967         unsafe { &*(self as *const Self).cast() }
968     }
969 }
970 
971 impl DerefMut for Quat {
972     #[inline]
deref_mut(&mut self) -> &mut Self::Target973     fn deref_mut(&mut self) -> &mut Self::Target {
974         unsafe { &mut *(self as *mut Self).cast() }
975     }
976 }
977