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