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