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