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