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 DQuat, Mat3, Mat3A, Mat4, Vec2, Vec3, Vec3A, Vec4,
7 };
8
9 #[cfg(not(target_arch = "spirv"))]
10 use core::fmt;
11 use core::iter::{Product, Sum};
12 use core::ops::{Add, Div, Mul, MulAssign, Neg, Sub};
13
14 /// Creates a quaternion from `x`, `y`, `z` and `w` values.
15 ///
16 /// This should generally not be called manually unless you know what you are doing. Use
17 /// one of the other constructors instead such as `identity` or `from_axis_angle`.
18 #[inline]
19 #[must_use]
quat(x: f32, y: f32, z: f32, w: f32) -> Quat20 pub const fn quat(x: f32, y: f32, z: f32, w: f32) -> Quat {
21 Quat::from_xyzw(x, y, z, w)
22 }
23
24 /// A quaternion representing an orientation.
25 ///
26 /// This quaternion is intended to be of unit length but may denormalize due to
27 /// floating point "error creep" which can occur when successive quaternion
28 /// operations are applied.
29 #[derive(Clone, Copy)]
30 #[cfg_attr(
31 not(any(feature = "scalar-math", target_arch = "spirv")),
32 repr(align(16))
33 )]
34 #[cfg_attr(not(target_arch = "spirv"), repr(C))]
35 #[cfg_attr(target_arch = "spirv", repr(simd))]
36 pub struct Quat {
37 pub x: f32,
38 pub y: f32,
39 pub z: f32,
40 pub w: f32,
41 }
42
43 impl Quat {
44 /// All zeros.
45 const ZERO: Self = Self::from_array([0.0; 4]);
46
47 /// The identity quaternion. Corresponds to no rotation.
48 pub const IDENTITY: Self = Self::from_xyzw(0.0, 0.0, 0.0, 1.0);
49
50 /// All NANs.
51 pub const NAN: Self = Self::from_array([f32::NAN; 4]);
52
53 /// Creates a new rotation quaternion.
54 ///
55 /// This should generally not be called manually unless you know what you are doing.
56 /// Use one of the other constructors instead such as `identity` or `from_axis_angle`.
57 ///
58 /// `from_xyzw` is mostly used by unit tests and `serde` deserialization.
59 ///
60 /// # Preconditions
61 ///
62 /// This function does not check if the input is normalized, it is up to the user to
63 /// provide normalized input or to normalized the resulting quaternion.
64 #[inline(always)]
65 #[must_use]
from_xyzw(x: f32, y: f32, z: f32, w: f32) -> Self66 pub const fn from_xyzw(x: f32, y: f32, z: f32, w: f32) -> Self {
67 Self { x, y, z, w }
68 }
69
70 /// Creates a rotation quaternion from an array.
71 ///
72 /// # Preconditions
73 ///
74 /// This function does not check if the input is normalized, it is up to the user to
75 /// provide normalized input or to normalized the resulting quaternion.
76 #[inline]
77 #[must_use]
from_array(a: [f32; 4]) -> Self78 pub const fn from_array(a: [f32; 4]) -> Self {
79 Self::from_xyzw(a[0], a[1], a[2], a[3])
80 }
81
82 /// Creates a new rotation quaternion from a 4D vector.
83 ///
84 /// # Preconditions
85 ///
86 /// This function does not check if the input is normalized, it is up to the user to
87 /// provide normalized input or to normalized the resulting quaternion.
88 #[inline]
89 #[must_use]
from_vec4(v: Vec4) -> Self90 pub const fn from_vec4(v: Vec4) -> Self {
91 Self {
92 x: v.x,
93 y: v.y,
94 z: v.z,
95 w: v.w,
96 }
97 }
98
99 /// Creates a rotation quaternion from a slice.
100 ///
101 /// # Preconditions
102 ///
103 /// This function does not check if the input is normalized, it is up to the user to
104 /// provide normalized input or to normalized the resulting quaternion.
105 ///
106 /// # Panics
107 ///
108 /// Panics if `slice` length is less than 4.
109 #[inline]
110 #[must_use]
from_slice(slice: &[f32]) -> Self111 pub fn from_slice(slice: &[f32]) -> Self {
112 Self::from_xyzw(slice[0], slice[1], slice[2], slice[3])
113 }
114
115 /// Writes the quaternion to an unaligned slice.
116 ///
117 /// # Panics
118 ///
119 /// Panics if `slice` length is less than 4.
120 #[inline]
write_to_slice(self, slice: &mut [f32])121 pub fn write_to_slice(self, slice: &mut [f32]) {
122 slice[0] = self.x;
123 slice[1] = self.y;
124 slice[2] = self.z;
125 slice[3] = self.w;
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 Self {
421 x: -self.x,
422 y: -self.y,
423 z: -self.z,
424 w: self.w,
425 }
426 }
427
428 /// Returns the inverse of a normalized quaternion.
429 ///
430 /// Typically quaternion inverse returns the conjugate of a normalized quaternion.
431 /// Because `self` is assumed to already be unit length this method *does not* normalize
432 /// before returning the conjugate.
433 ///
434 /// # Panics
435 ///
436 /// Will panic if `self` is not normalized when `glam_assert` is enabled.
437 #[inline]
438 #[must_use]
inverse(self) -> Self439 pub fn inverse(self) -> Self {
440 glam_assert!(self.is_normalized());
441 self.conjugate()
442 }
443
444 /// Computes the dot product of `self` and `rhs`. The dot product is
445 /// equal to the cosine of the angle between two quaternion rotations.
446 #[inline]
447 #[must_use]
dot(self, rhs: Self) -> f32448 pub fn dot(self, rhs: Self) -> f32 {
449 Vec4::from(self).dot(Vec4::from(rhs))
450 }
451
452 /// Computes the length of `self`.
453 #[doc(alias = "magnitude")]
454 #[inline]
455 #[must_use]
length(self) -> f32456 pub fn length(self) -> f32 {
457 Vec4::from(self).length()
458 }
459
460 /// Computes the squared length of `self`.
461 ///
462 /// This is generally faster than `length()` as it avoids a square
463 /// root operation.
464 #[doc(alias = "magnitude2")]
465 #[inline]
466 #[must_use]
length_squared(self) -> f32467 pub fn length_squared(self) -> f32 {
468 Vec4::from(self).length_squared()
469 }
470
471 /// Computes `1.0 / length()`.
472 ///
473 /// For valid results, `self` must _not_ be of length zero.
474 #[inline]
475 #[must_use]
length_recip(self) -> f32476 pub fn length_recip(self) -> f32 {
477 Vec4::from(self).length_recip()
478 }
479
480 /// Returns `self` normalized to length 1.0.
481 ///
482 /// For valid results, `self` must _not_ be of length zero.
483 ///
484 /// Panics
485 ///
486 /// Will panic if `self` is zero length when `glam_assert` is enabled.
487 #[inline]
488 #[must_use]
normalize(self) -> Self489 pub fn normalize(self) -> Self {
490 Self::from_vec4(Vec4::from(self).normalize())
491 }
492
493 /// Returns `true` if, and only if, all elements are finite.
494 /// If any element is either `NaN`, positive or negative infinity, this will return `false`.
495 #[inline]
496 #[must_use]
is_finite(self) -> bool497 pub fn is_finite(self) -> bool {
498 Vec4::from(self).is_finite()
499 }
500
501 #[inline]
502 #[must_use]
is_nan(self) -> bool503 pub fn is_nan(self) -> bool {
504 Vec4::from(self).is_nan()
505 }
506
507 /// Returns whether `self` of length `1.0` or not.
508 ///
509 /// Uses a precision threshold of `1e-6`.
510 #[inline]
511 #[must_use]
is_normalized(self) -> bool512 pub fn is_normalized(self) -> bool {
513 Vec4::from(self).is_normalized()
514 }
515
516 #[inline]
517 #[must_use]
is_near_identity(self) -> bool518 pub fn is_near_identity(self) -> bool {
519 // Based on https://github.com/nfrechette/rtm `rtm::quat_near_identity`
520 let threshold_angle = 0.002_847_144_6;
521 // Because of floating point precision, we cannot represent very small rotations.
522 // The closest f32 to 1.0 that is not 1.0 itself yields:
523 // 0.99999994.acos() * 2.0 = 0.000690533954 rad
524 //
525 // An error threshold of 1.e-6 is used by default.
526 // (1.0 - 1.e-6).acos() * 2.0 = 0.00284714461 rad
527 // (1.0 - 1.e-7).acos() * 2.0 = 0.00097656250 rad
528 //
529 // We don't really care about the angle value itself, only if it's close to 0.
530 // This will happen whenever quat.w is close to 1.0.
531 // If the quat.w is close to -1.0, the angle will be near 2*PI which is close to
532 // a negative 0 rotation. By forcing quat.w to be positive, we'll end up with
533 // the shortest path.
534 let positive_w_angle = math::acos_approx(math::abs(self.w)) * 2.0;
535 positive_w_angle < threshold_angle
536 }
537
538 /// Returns the angle (in radians) for the minimal rotation
539 /// for transforming this quaternion into another.
540 ///
541 /// Both quaternions must be normalized.
542 ///
543 /// # Panics
544 ///
545 /// Will panic if `self` or `rhs` are not normalized when `glam_assert` is enabled.
546 #[inline]
547 #[must_use]
angle_between(self, rhs: Self) -> f32548 pub fn angle_between(self, rhs: Self) -> f32 {
549 glam_assert!(self.is_normalized() && rhs.is_normalized());
550 math::acos_approx(math::abs(self.dot(rhs))) * 2.0
551 }
552
553 /// Returns true if the absolute difference of all elements between `self` and `rhs`
554 /// is less than or equal to `max_abs_diff`.
555 ///
556 /// This can be used to compare if two quaternions contain similar elements. It works
557 /// best when comparing with a known value. The `max_abs_diff` that should be used used
558 /// depends on the values being compared against.
559 ///
560 /// For more see
561 /// [comparing floating point numbers](https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/).
562 #[inline]
563 #[must_use]
abs_diff_eq(self, rhs: Self, max_abs_diff: f32) -> bool564 pub fn abs_diff_eq(self, rhs: Self, max_abs_diff: f32) -> bool {
565 Vec4::from(self).abs_diff_eq(Vec4::from(rhs), max_abs_diff)
566 }
567
568 /// Performs a linear interpolation between `self` and `rhs` based on
569 /// the value `s`.
570 ///
571 /// When `s` is `0.0`, the result will be equal to `self`. When `s`
572 /// is `1.0`, the result will be equal to `rhs`.
573 ///
574 /// # Panics
575 ///
576 /// Will panic if `self` or `end` are not normalized when `glam_assert` is enabled.
577 #[doc(alias = "mix")]
578 #[inline]
579 #[must_use]
lerp(self, end: Self, s: f32) -> Self580 pub fn lerp(self, end: Self, s: f32) -> Self {
581 glam_assert!(self.is_normalized());
582 glam_assert!(end.is_normalized());
583
584 let start = self;
585 let dot = start.dot(end);
586 let bias = if dot >= 0.0 { 1.0 } else { -1.0 };
587 let interpolated = start.add(end.mul(bias).sub(start).mul(s));
588 interpolated.normalize()
589 }
590
591 /// Performs a spherical linear interpolation between `self` and `end`
592 /// based on the value `s`.
593 ///
594 /// When `s` is `0.0`, the result will be equal to `self`. When `s`
595 /// is `1.0`, the result will be equal to `end`.
596 ///
597 /// # Panics
598 ///
599 /// Will panic if `self` or `end` are not normalized when `glam_assert` is enabled.
600 #[inline]
601 #[must_use]
slerp(self, mut end: Self, s: f32) -> Self602 pub fn slerp(self, mut end: Self, s: f32) -> Self {
603 // http://number-none.com/product/Understanding%20Slerp,%20Then%20Not%20Using%20It/
604 glam_assert!(self.is_normalized());
605 glam_assert!(end.is_normalized());
606
607 const DOT_THRESHOLD: f32 = 0.9995;
608
609 // Note that a rotation can be represented by two quaternions: `q` and
610 // `-q`. The slerp path between `q` and `end` will be different from the
611 // path between `-q` and `end`. One path will take the long way around and
612 // one will take the short way. In order to correct for this, the `dot`
613 // product between `self` and `end` should be positive. If the `dot`
614 // product is negative, slerp between `self` and `-end`.
615 let mut dot = self.dot(end);
616 if dot < 0.0 {
617 end = -end;
618 dot = -dot;
619 }
620
621 if dot > DOT_THRESHOLD {
622 // assumes lerp returns a normalized quaternion
623 self.lerp(end, s)
624 } else {
625 let theta = math::acos_approx(dot);
626
627 let scale1 = math::sin(theta * (1.0 - s));
628 let scale2 = math::sin(theta * s);
629 let theta_sin = math::sin(theta);
630
631 self.mul(scale1).add(end.mul(scale2)).mul(1.0 / theta_sin)
632 }
633 }
634
635 /// Multiplies a quaternion and a 3D vector, returning the rotated vector.
636 ///
637 /// # Panics
638 ///
639 /// Will panic if `self` is not normalized when `glam_assert` is enabled.
640 #[inline]
641 #[must_use]
mul_vec3(self, rhs: Vec3) -> Vec3642 pub fn mul_vec3(self, rhs: Vec3) -> Vec3 {
643 glam_assert!(self.is_normalized());
644
645 let w = self.w;
646 let b = Vec3::new(self.x, self.y, self.z);
647 let b2 = b.dot(b);
648 rhs.mul(w * w - b2)
649 .add(b.mul(rhs.dot(b) * 2.0))
650 .add(b.cross(rhs).mul(w * 2.0))
651 }
652
653 /// Multiplies two quaternions. If they each represent a rotation, the result will
654 /// represent the combined rotation.
655 ///
656 /// Note that due to floating point rounding the result may not be perfectly normalized.
657 ///
658 /// # Panics
659 ///
660 /// Will panic if `self` or `rhs` are not normalized when `glam_assert` is enabled.
661 #[inline]
662 #[must_use]
mul_quat(self, rhs: Self) -> Self663 pub fn mul_quat(self, rhs: Self) -> Self {
664 glam_assert!(self.is_normalized());
665 glam_assert!(rhs.is_normalized());
666
667 let (x0, y0, z0, w0) = self.into();
668 let (x1, y1, z1, w1) = rhs.into();
669 Self::from_xyzw(
670 w0 * x1 + x0 * w1 + y0 * z1 - z0 * y1,
671 w0 * y1 - x0 * z1 + y0 * w1 + z0 * x1,
672 w0 * z1 + x0 * y1 - y0 * x1 + z0 * w1,
673 w0 * w1 - x0 * x1 - y0 * y1 - z0 * z1,
674 )
675 }
676
677 /// Creates a quaternion from a 3x3 rotation matrix inside a 3D affine transform.
678 #[inline]
679 #[must_use]
from_affine3(a: &crate::Affine3A) -> Self680 pub fn from_affine3(a: &crate::Affine3A) -> Self {
681 #[allow(clippy::useless_conversion)]
682 Self::from_rotation_axes(
683 a.matrix3.x_axis.into(),
684 a.matrix3.y_axis.into(),
685 a.matrix3.z_axis.into(),
686 )
687 }
688
689 /// Multiplies a quaternion and a 3D vector, returning the rotated vector.
690 #[inline]
691 #[must_use]
mul_vec3a(self, rhs: Vec3A) -> Vec3A692 pub fn mul_vec3a(self, rhs: Vec3A) -> Vec3A {
693 self.mul_vec3(rhs.into()).into()
694 }
695
696 #[inline]
697 #[must_use]
as_dquat(self) -> DQuat698 pub fn as_dquat(self) -> DQuat {
699 DQuat::from_xyzw(self.x as f64, self.y as f64, self.z as f64, self.w as f64)
700 }
701
702 #[inline]
703 #[must_use]
704 #[deprecated(since = "0.24.2", note = "Use as_dquat() instead")]
as_f64(self) -> DQuat705 pub fn as_f64(self) -> DQuat {
706 self.as_dquat()
707 }
708 }
709
710 #[cfg(not(target_arch = "spirv"))]
711 impl fmt::Debug for Quat {
fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result712 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
713 fmt.debug_tuple(stringify!(Quat))
714 .field(&self.x)
715 .field(&self.y)
716 .field(&self.z)
717 .field(&self.w)
718 .finish()
719 }
720 }
721
722 #[cfg(not(target_arch = "spirv"))]
723 impl fmt::Display for Quat {
fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result724 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
725 write!(fmt, "[{}, {}, {}, {}]", self.x, self.y, self.z, self.w)
726 }
727 }
728
729 impl Add<Quat> for Quat {
730 type Output = Self;
731 /// Adds two quaternions.
732 ///
733 /// The sum is not guaranteed to be normalized.
734 ///
735 /// Note that addition is not the same as combining the rotations represented by the
736 /// two quaternions! That corresponds to multiplication.
737 #[inline]
add(self, rhs: Self) -> Self738 fn add(self, rhs: Self) -> Self {
739 Self::from_vec4(Vec4::from(self) + Vec4::from(rhs))
740 }
741 }
742
743 impl Sub<Quat> for Quat {
744 type Output = Self;
745 /// Subtracts the `rhs` quaternion from `self`.
746 ///
747 /// The difference is not guaranteed to be normalized.
748 #[inline]
sub(self, rhs: Self) -> Self749 fn sub(self, rhs: Self) -> Self {
750 Self::from_vec4(Vec4::from(self) - Vec4::from(rhs))
751 }
752 }
753
754 impl Mul<f32> for Quat {
755 type Output = Self;
756 /// Multiplies a quaternion by a scalar value.
757 ///
758 /// The product is not guaranteed to be normalized.
759 #[inline]
mul(self, rhs: f32) -> Self760 fn mul(self, rhs: f32) -> Self {
761 Self::from_vec4(Vec4::from(self) * rhs)
762 }
763 }
764
765 impl Div<f32> for Quat {
766 type Output = Self;
767 /// Divides a quaternion by a scalar value.
768 /// The quotient is not guaranteed to be normalized.
769 #[inline]
div(self, rhs: f32) -> Self770 fn div(self, rhs: f32) -> Self {
771 Self::from_vec4(Vec4::from(self) / rhs)
772 }
773 }
774
775 impl Mul<Quat> for Quat {
776 type Output = Self;
777 /// Multiplies two quaternions. If they each represent a rotation, the result will
778 /// represent the combined rotation.
779 ///
780 /// Note that due to floating point rounding the result may not be perfectly
781 /// normalized.
782 ///
783 /// # Panics
784 ///
785 /// Will panic if `self` or `rhs` are not normalized when `glam_assert` is enabled.
786 #[inline]
mul(self, rhs: Self) -> Self787 fn mul(self, rhs: Self) -> Self {
788 self.mul_quat(rhs)
789 }
790 }
791
792 impl MulAssign<Quat> for Quat {
793 /// Multiplies two quaternions. If they each represent a rotation, the result will
794 /// represent the combined rotation.
795 ///
796 /// Note that due to floating point rounding the result may not be perfectly
797 /// normalized.
798 ///
799 /// # Panics
800 ///
801 /// Will panic if `self` or `rhs` are not normalized when `glam_assert` is enabled.
802 #[inline]
mul_assign(&mut self, rhs: Self)803 fn mul_assign(&mut self, rhs: Self) {
804 *self = self.mul_quat(rhs);
805 }
806 }
807
808 impl Mul<Vec3> for Quat {
809 type Output = Vec3;
810 /// Multiplies a quaternion and a 3D vector, returning the rotated vector.
811 ///
812 /// # Panics
813 ///
814 /// Will panic if `self` is not normalized when `glam_assert` is enabled.
815 #[inline]
mul(self, rhs: Vec3) -> Self::Output816 fn mul(self, rhs: Vec3) -> Self::Output {
817 self.mul_vec3(rhs)
818 }
819 }
820
821 impl Neg for Quat {
822 type Output = Self;
823 #[inline]
neg(self) -> Self824 fn neg(self) -> Self {
825 self * -1.0
826 }
827 }
828
829 impl Default for Quat {
830 #[inline]
default() -> Self831 fn default() -> Self {
832 Self::IDENTITY
833 }
834 }
835
836 impl PartialEq for Quat {
837 #[inline]
eq(&self, rhs: &Self) -> bool838 fn eq(&self, rhs: &Self) -> bool {
839 Vec4::from(*self).eq(&Vec4::from(*rhs))
840 }
841 }
842
843 #[cfg(not(target_arch = "spirv"))]
844 impl AsRef<[f32; 4]> for Quat {
845 #[inline]
as_ref(&self) -> &[f32; 4]846 fn as_ref(&self) -> &[f32; 4] {
847 unsafe { &*(self as *const Self as *const [f32; 4]) }
848 }
849 }
850
851 impl Sum<Self> for Quat {
sum<I>(iter: I) -> Self where I: Iterator<Item = Self>,852 fn sum<I>(iter: I) -> Self
853 where
854 I: Iterator<Item = Self>,
855 {
856 iter.fold(Self::ZERO, Self::add)
857 }
858 }
859
860 impl<'a> Sum<&'a Self> for Quat {
sum<I>(iter: I) -> Self where I: Iterator<Item = &'a Self>,861 fn sum<I>(iter: I) -> Self
862 where
863 I: Iterator<Item = &'a Self>,
864 {
865 iter.fold(Self::ZERO, |a, &b| Self::add(a, b))
866 }
867 }
868
869 impl Product for Quat {
product<I>(iter: I) -> Self where I: Iterator<Item = Self>,870 fn product<I>(iter: I) -> Self
871 where
872 I: Iterator<Item = Self>,
873 {
874 iter.fold(Self::IDENTITY, Self::mul)
875 }
876 }
877
878 impl<'a> Product<&'a Self> for Quat {
product<I>(iter: I) -> Self where I: Iterator<Item = &'a Self>,879 fn product<I>(iter: I) -> Self
880 where
881 I: Iterator<Item = &'a Self>,
882 {
883 iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b))
884 }
885 }
886
887 impl Mul<Vec3A> for Quat {
888 type Output = Vec3A;
889 #[inline]
mul(self, rhs: Vec3A) -> Self::Output890 fn mul(self, rhs: Vec3A) -> Self::Output {
891 self.mul_vec3a(rhs)
892 }
893 }
894
895 impl From<Quat> for Vec4 {
896 #[inline]
from(q: Quat) -> Self897 fn from(q: Quat) -> Self {
898 Self::new(q.x, q.y, q.z, q.w)
899 }
900 }
901
902 impl From<Quat> for (f32, f32, f32, f32) {
903 #[inline]
from(q: Quat) -> Self904 fn from(q: Quat) -> Self {
905 (q.x, q.y, q.z, q.w)
906 }
907 }
908
909 impl From<Quat> for [f32; 4] {
910 #[inline]
from(q: Quat) -> Self911 fn from(q: Quat) -> Self {
912 [q.x, q.y, q.z, q.w]
913 }
914 }
915