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