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