1 // Generated from quat.rs.tera template. Edit the template, not the generated file.
2
3 use crate::{
4 coresimd::*,
5 euler::{EulerFromQuaternion, EulerRot, EulerToQuaternion},
6 f32::math,
7 DQuat, Mat3, Mat3A, Mat4, Vec2, Vec3, Vec3A, Vec4,
8 };
9
10 use core::simd::*;
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) f32x4);
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::from_array([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(f32x4::from_array(a))
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: f32x4 = f32x4::from_array([-1.0, -1.0, -1.0, 1.0]);
413 Self(self.0.mul(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: f32x4 = f32x4::from_array([-0.0; 4]);
573 let start = self.0;
574 let end = end.0;
575 let dot = dot4_into_f32x4(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 = f32x4_bitand(dot, NEG_ZERO);
579 let interpolated = start + ((f32x4_bitxor(end, bias) - start) * f32x4::splat(s));
580 Quat(interpolated).normalize()
581 }
582
583 /// Performs a spherical linear interpolation between `self` and `end`
584 /// based on the value `s`.
585 ///
586 /// When `s` is `0.0`, the result will be equal to `self`. When `s`
587 /// is `1.0`, the result will be equal to `end`.
588 ///
589 /// # Panics
590 ///
591 /// Will panic if `self` or `end` are not normalized when `glam_assert` is enabled.
592 #[inline]
593 #[must_use]
slerp(self, mut end: Self, s: f32) -> Self594 pub fn slerp(self, mut end: Self, s: f32) -> Self {
595 // http://number-none.com/product/Understanding%20Slerp,%20Then%20Not%20Using%20It/
596 glam_assert!(self.is_normalized());
597 glam_assert!(end.is_normalized());
598
599 const DOT_THRESHOLD: f32 = 0.9995;
600
601 // Note that a rotation can be represented by two quaternions: `q` and
602 // `-q`. The slerp path between `q` and `end` will be different from the
603 // path between `-q` and `end`. One path will take the long way around and
604 // one will take the short way. In order to correct for this, the `dot`
605 // product between `self` and `end` should be positive. If the `dot`
606 // product is negative, slerp between `self` and `-end`.
607 let mut dot = self.dot(end);
608 if dot < 0.0 {
609 end = -end;
610 dot = -dot;
611 }
612
613 if dot > DOT_THRESHOLD {
614 // assumes lerp returns a normalized quaternion
615 self.lerp(end, s)
616 } else {
617 let theta = math::acos_approx(dot);
618
619 let x = math::sin(theta * (1.0 - s));
620 let y = math::sin(theta * s);
621 let z = math::sin(theta);
622 let w = 0.0;
623 let tmp = f32x4::from_array([x, y, z, w]);
624
625 let scale1 = simd_swizzle!(tmp, [0, 0, 0, 0]);
626 let scale2 = simd_swizzle!(tmp, [1, 1, 1, 1]);
627 let theta_sin = simd_swizzle!(tmp, [2, 2, 2, 2]);
628
629 Self(self.0.mul(scale1).add(end.0.mul(scale2)).div(theta_sin))
630 }
631 }
632
633 /// Multiplies a quaternion and a 3D vector, returning the rotated vector.
634 ///
635 /// # Panics
636 ///
637 /// Will panic if `self` is not normalized when `glam_assert` is enabled.
638 #[inline]
639 #[must_use]
mul_vec3(self, rhs: Vec3) -> Vec3640 pub fn mul_vec3(self, rhs: Vec3) -> Vec3 {
641 glam_assert!(self.is_normalized());
642
643 self.mul_vec3a(rhs.into()).into()
644 }
645
646 /// Multiplies two quaternions. If they each represent a rotation, the result will
647 /// represent the combined rotation.
648 ///
649 /// Note that due to floating point rounding the result may not be perfectly normalized.
650 ///
651 /// # Panics
652 ///
653 /// Will panic if `self` or `rhs` are not normalized when `glam_assert` is enabled.
654 #[inline]
655 #[must_use]
mul_quat(self, rhs: Self) -> Self656 pub fn mul_quat(self, rhs: Self) -> Self {
657 glam_assert!(self.is_normalized());
658 glam_assert!(rhs.is_normalized());
659
660 let lhs = self.0;
661 let rhs = rhs.0;
662
663 const CONTROL_WZYX: f32x4 = f32x4::from_array([1.0, -1.0, 1.0, -1.0]);
664 const CONTROL_ZWXY: f32x4 = f32x4::from_array([1.0, 1.0, -1.0, -1.0]);
665 const CONTROL_YXWZ: f32x4 = f32x4::from_array([-1.0, 1.0, 1.0, -1.0]);
666
667 let r_xxxx = simd_swizzle!(lhs, [0, 0, 0, 0]);
668 let r_yyyy = simd_swizzle!(lhs, [1, 1, 1, 1]);
669 let r_zzzz = simd_swizzle!(lhs, [2, 2, 2, 2]);
670 let r_wwww = simd_swizzle!(lhs, [3, 3, 3, 3]);
671
672 let lxrw_lyrw_lzrw_lwrw = r_wwww * rhs;
673 let l_wzyx = simd_swizzle!(rhs, [3, 2, 1, 0]);
674
675 let lwrx_lzrx_lyrx_lxrx = r_xxxx * l_wzyx;
676 let l_zwxy = simd_swizzle!(l_wzyx, [1, 0, 3, 2]);
677
678 let lwrx_nlzrx_lyrx_nlxrx = lwrx_lzrx_lyrx_lxrx * CONTROL_WZYX;
679
680 let lzry_lwry_lxry_lyry = r_yyyy * l_zwxy;
681 let l_yxwz = simd_swizzle!(l_zwxy, [3, 2, 1, 0]);
682
683 let lzry_lwry_nlxry_nlyry = lzry_lwry_lxry_lyry * CONTROL_ZWXY;
684
685 let lyrz_lxrz_lwrz_lzrz = r_zzzz * l_yxwz;
686 let result0 = lxrw_lyrw_lzrw_lwrw + lwrx_nlzrx_lyrx_nlxrx;
687
688 let nlyrz_lxrz_lwrz_wlzrz = lyrz_lxrz_lwrz_lzrz * CONTROL_YXWZ;
689 let result1 = lzry_lwry_nlxry_nlyry + nlyrz_lxrz_lwrz_wlzrz;
690 Self(result0 + result1)
691 }
692
693 /// Creates a quaternion from a 3x3 rotation matrix inside a 3D affine transform.
694 #[inline]
695 #[must_use]
from_affine3(a: &crate::Affine3A) -> Self696 pub fn from_affine3(a: &crate::Affine3A) -> Self {
697 #[allow(clippy::useless_conversion)]
698 Self::from_rotation_axes(
699 a.matrix3.x_axis.into(),
700 a.matrix3.y_axis.into(),
701 a.matrix3.z_axis.into(),
702 )
703 }
704
705 /// Multiplies a quaternion and a 3D vector, returning the rotated vector.
706 #[inline]
707 #[must_use]
mul_vec3a(self, rhs: Vec3A) -> Vec3A708 pub fn mul_vec3a(self, rhs: Vec3A) -> Vec3A {
709 const TWO: f32x4 = f32x4::from_array([2.0; 4]);
710 let w = simd_swizzle!(self.0, [3, 3, 3, 3]);
711 let b = self.0;
712 let b2 = dot3_into_f32x4(b, b);
713 Vec3A(
714 rhs.0
715 .mul(w.mul(w).sub(b2))
716 .add(b.mul(dot3_into_f32x4(rhs.0, b).mul(TWO)))
717 .add(Vec3A(b).cross(rhs).0.mul(w.mul(TWO))),
718 )
719 }
720
721 #[inline]
722 #[must_use]
as_dquat(self) -> DQuat723 pub fn as_dquat(self) -> DQuat {
724 DQuat::from_xyzw(self.x as f64, self.y as f64, self.z as f64, self.w as f64)
725 }
726
727 #[inline]
728 #[must_use]
729 #[deprecated(since = "0.24.2", note = "Use as_dquat() instead")]
as_f64(self) -> DQuat730 pub fn as_f64(self) -> DQuat {
731 self.as_dquat()
732 }
733 }
734
735 #[cfg(not(target_arch = "spirv"))]
736 impl fmt::Debug for Quat {
fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result737 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
738 fmt.debug_tuple(stringify!(Quat))
739 .field(&self.x)
740 .field(&self.y)
741 .field(&self.z)
742 .field(&self.w)
743 .finish()
744 }
745 }
746
747 #[cfg(not(target_arch = "spirv"))]
748 impl fmt::Display for Quat {
fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result749 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
750 write!(fmt, "[{}, {}, {}, {}]", self.x, self.y, self.z, self.w)
751 }
752 }
753
754 impl Add<Quat> for Quat {
755 type Output = Self;
756 /// Adds two quaternions.
757 ///
758 /// The sum is not guaranteed to be normalized.
759 ///
760 /// Note that addition is not the same as combining the rotations represented by the
761 /// two quaternions! That corresponds to multiplication.
762 #[inline]
add(self, rhs: Self) -> Self763 fn add(self, rhs: Self) -> Self {
764 Self::from_vec4(Vec4::from(self) + Vec4::from(rhs))
765 }
766 }
767
768 impl Sub<Quat> for Quat {
769 type Output = Self;
770 /// Subtracts the `rhs` quaternion from `self`.
771 ///
772 /// The difference is not guaranteed to be normalized.
773 #[inline]
sub(self, rhs: Self) -> Self774 fn sub(self, rhs: Self) -> Self {
775 Self::from_vec4(Vec4::from(self) - Vec4::from(rhs))
776 }
777 }
778
779 impl Mul<f32> for Quat {
780 type Output = Self;
781 /// Multiplies a quaternion by a scalar value.
782 ///
783 /// The product is not guaranteed to be normalized.
784 #[inline]
mul(self, rhs: f32) -> Self785 fn mul(self, rhs: f32) -> Self {
786 Self::from_vec4(Vec4::from(self) * rhs)
787 }
788 }
789
790 impl Div<f32> for Quat {
791 type Output = Self;
792 /// Divides a quaternion by a scalar value.
793 /// The quotient is not guaranteed to be normalized.
794 #[inline]
div(self, rhs: f32) -> Self795 fn div(self, rhs: f32) -> Self {
796 Self::from_vec4(Vec4::from(self) / rhs)
797 }
798 }
799
800 impl Mul<Quat> for Quat {
801 type Output = Self;
802 /// Multiplies two quaternions. If they each represent a rotation, the result will
803 /// represent the combined rotation.
804 ///
805 /// Note that due to floating point rounding the result may not be perfectly
806 /// normalized.
807 ///
808 /// # Panics
809 ///
810 /// Will panic if `self` or `rhs` are not normalized when `glam_assert` is enabled.
811 #[inline]
mul(self, rhs: Self) -> Self812 fn mul(self, rhs: Self) -> Self {
813 self.mul_quat(rhs)
814 }
815 }
816
817 impl MulAssign<Quat> for Quat {
818 /// Multiplies two quaternions. If they each represent a rotation, the result will
819 /// represent the combined rotation.
820 ///
821 /// Note that due to floating point rounding the result may not be perfectly
822 /// normalized.
823 ///
824 /// # Panics
825 ///
826 /// Will panic if `self` or `rhs` are not normalized when `glam_assert` is enabled.
827 #[inline]
mul_assign(&mut self, rhs: Self)828 fn mul_assign(&mut self, rhs: Self) {
829 *self = self.mul_quat(rhs);
830 }
831 }
832
833 impl Mul<Vec3> for Quat {
834 type Output = Vec3;
835 /// Multiplies a quaternion and a 3D vector, returning the rotated vector.
836 ///
837 /// # Panics
838 ///
839 /// Will panic if `self` is not normalized when `glam_assert` is enabled.
840 #[inline]
mul(self, rhs: Vec3) -> Self::Output841 fn mul(self, rhs: Vec3) -> Self::Output {
842 self.mul_vec3(rhs)
843 }
844 }
845
846 impl Neg for Quat {
847 type Output = Self;
848 #[inline]
neg(self) -> Self849 fn neg(self) -> Self {
850 self * -1.0
851 }
852 }
853
854 impl Default for Quat {
855 #[inline]
default() -> Self856 fn default() -> Self {
857 Self::IDENTITY
858 }
859 }
860
861 impl PartialEq for Quat {
862 #[inline]
eq(&self, rhs: &Self) -> bool863 fn eq(&self, rhs: &Self) -> bool {
864 Vec4::from(*self).eq(&Vec4::from(*rhs))
865 }
866 }
867
868 #[cfg(not(target_arch = "spirv"))]
869 impl AsRef<[f32; 4]> for Quat {
870 #[inline]
as_ref(&self) -> &[f32; 4]871 fn as_ref(&self) -> &[f32; 4] {
872 unsafe { &*(self as *const Self as *const [f32; 4]) }
873 }
874 }
875
876 impl Sum<Self> for Quat {
sum<I>(iter: I) -> Self where I: Iterator<Item = Self>,877 fn sum<I>(iter: I) -> Self
878 where
879 I: Iterator<Item = Self>,
880 {
881 iter.fold(Self::ZERO, Self::add)
882 }
883 }
884
885 impl<'a> Sum<&'a Self> for Quat {
sum<I>(iter: I) -> Self where I: Iterator<Item = &'a Self>,886 fn sum<I>(iter: I) -> Self
887 where
888 I: Iterator<Item = &'a Self>,
889 {
890 iter.fold(Self::ZERO, |a, &b| Self::add(a, b))
891 }
892 }
893
894 impl Product for Quat {
product<I>(iter: I) -> Self where I: Iterator<Item = Self>,895 fn product<I>(iter: I) -> Self
896 where
897 I: Iterator<Item = Self>,
898 {
899 iter.fold(Self::IDENTITY, Self::mul)
900 }
901 }
902
903 impl<'a> Product<&'a Self> for Quat {
product<I>(iter: I) -> Self where I: Iterator<Item = &'a Self>,904 fn product<I>(iter: I) -> Self
905 where
906 I: Iterator<Item = &'a Self>,
907 {
908 iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b))
909 }
910 }
911
912 impl Mul<Vec3A> for Quat {
913 type Output = Vec3A;
914 #[inline]
mul(self, rhs: Vec3A) -> Self::Output915 fn mul(self, rhs: Vec3A) -> Self::Output {
916 self.mul_vec3a(rhs)
917 }
918 }
919
920 impl From<Quat> for Vec4 {
921 #[inline]
from(q: Quat) -> Self922 fn from(q: Quat) -> Self {
923 Self(q.0)
924 }
925 }
926
927 impl From<Quat> for (f32, f32, f32, f32) {
928 #[inline]
from(q: Quat) -> Self929 fn from(q: Quat) -> Self {
930 Vec4::from(q).into()
931 }
932 }
933
934 impl From<Quat> for [f32; 4] {
935 #[inline]
from(q: Quat) -> Self936 fn from(q: Quat) -> Self {
937 Vec4::from(q).into()
938 }
939 }
940
941 impl From<Quat> for f32x4 {
942 #[inline]
from(q: Quat) -> Self943 fn from(q: Quat) -> Self {
944 q.0
945 }
946 }
947
948 impl Deref for Quat {
949 type Target = crate::deref::Vec4<f32>;
950 #[inline]
deref(&self) -> &Self::Target951 fn deref(&self) -> &Self::Target {
952 unsafe { &*(self as *const Self).cast() }
953 }
954 }
955
956 impl DerefMut for Quat {
957 #[inline]
deref_mut(&mut self) -> &mut Self::Target958 fn deref_mut(&mut self) -> &mut Self::Target {
959 unsafe { &mut *(self as *mut Self).cast() }
960 }
961 }
962