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(crate) 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 #[allow(clippy::useless_conversion)]
799 Self::from_rotation_axes(
800 a.matrix3.x_axis.into(),
801 a.matrix3.y_axis.into(),
802 a.matrix3.z_axis.into(),
803 )
804 }
805
806 #[inline]
807 #[must_use]
808 pub fn as_quat(self) -> Quat {
809 Quat::from_xyzw(self.x as f32, self.y as f32, self.z as f32, self.w as f32)
810 }
811}
812
813impl fmt::Debug for DQuat {
814 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
815 fmt.debug_tuple(stringify!(DQuat))
816 .field(&self.x)
817 .field(&self.y)
818 .field(&self.z)
819 .field(&self.w)
820 .finish()
821 }
822}
823
824impl fmt::Display for DQuat {
825 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
826 if let Some(p) = f.precision() {
827 write!(
828 f,
829 "[{:.*}, {:.*}, {:.*}, {:.*}]",
830 p, self.x, p, self.y, p, self.z, p, self.w
831 )
832 } else {
833 write!(f, "[{}, {}, {}, {}]", self.x, self.y, self.z, self.w)
834 }
835 }
836}
837
838impl Add for DQuat {
839 type Output = Self;
840 /// Adds two quaternions.
841 ///
842 /// The sum is not guaranteed to be normalized.
843 ///
844 /// Note that addition is not the same as combining the rotations represented by the
845 /// two quaternions! That corresponds to multiplication.
846 #[inline]
847 fn add(self, rhs: Self) -> Self {
848 Self::from_vec4(DVec4::from(self) + DVec4::from(rhs))
849 }
850}
851
852impl Add<&Self> for DQuat {
853 type Output = Self;
854 #[inline]
855 fn add(self, rhs: &Self) -> Self {
856 self.add(*rhs)
857 }
858}
859
860impl Add<&DQuat> for &DQuat {
861 type Output = DQuat;
862 #[inline]
863 fn add(self, rhs: &DQuat) -> DQuat {
864 (*self).add(*rhs)
865 }
866}
867
868impl Add<DQuat> for &DQuat {
869 type Output = DQuat;
870 #[inline]
871 fn add(self, rhs: DQuat) -> DQuat {
872 (*self).add(rhs)
873 }
874}
875
876impl AddAssign for DQuat {
877 #[inline]
878 fn add_assign(&mut self, rhs: Self) {
879 *self = self.add(rhs);
880 }
881}
882
883impl AddAssign<&Self> for DQuat {
884 #[inline]
885 fn add_assign(&mut self, rhs: &Self) {
886 self.add_assign(*rhs);
887 }
888}
889
890impl Sub for DQuat {
891 type Output = Self;
892 /// Subtracts the `rhs` quaternion from `self`.
893 ///
894 /// The difference is not guaranteed to be normalized.
895 #[inline]
896 fn sub(self, rhs: Self) -> Self {
897 Self::from_vec4(DVec4::from(self) - DVec4::from(rhs))
898 }
899}
900
901impl Sub<&Self> for DQuat {
902 type Output = Self;
903 #[inline]
904 fn sub(self, rhs: &Self) -> Self {
905 self.sub(*rhs)
906 }
907}
908
909impl Sub<&DQuat> for &DQuat {
910 type Output = DQuat;
911 #[inline]
912 fn sub(self, rhs: &DQuat) -> DQuat {
913 (*self).sub(*rhs)
914 }
915}
916
917impl Sub<DQuat> for &DQuat {
918 type Output = DQuat;
919 #[inline]
920 fn sub(self, rhs: DQuat) -> DQuat {
921 (*self).sub(rhs)
922 }
923}
924
925impl SubAssign for DQuat {
926 #[inline]
927 fn sub_assign(&mut self, rhs: Self) {
928 *self = self.sub(rhs);
929 }
930}
931
932impl SubAssign<&Self> for DQuat {
933 #[inline]
934 fn sub_assign(&mut self, rhs: &Self) {
935 self.sub_assign(*rhs);
936 }
937}
938
939impl Mul<f64> for DQuat {
940 type Output = Self;
941 /// Multiplies a quaternion by a scalar value.
942 ///
943 /// The product is not guaranteed to be normalized.
944 #[inline]
945 fn mul(self, rhs: f64) -> Self {
946 Self::from_vec4(DVec4::from(self) * rhs)
947 }
948}
949
950impl Mul<&f64> for DQuat {
951 type Output = Self;
952 #[inline]
953 fn mul(self, rhs: &f64) -> Self {
954 self.mul(*rhs)
955 }
956}
957
958impl Mul<&f64> for &DQuat {
959 type Output = DQuat;
960 #[inline]
961 fn mul(self, rhs: &f64) -> DQuat {
962 (*self).mul(*rhs)
963 }
964}
965
966impl Mul<f64> for &DQuat {
967 type Output = DQuat;
968 #[inline]
969 fn mul(self, rhs: f64) -> DQuat {
970 (*self).mul(rhs)
971 }
972}
973
974impl MulAssign<f64> for DQuat {
975 #[inline]
976 fn mul_assign(&mut self, rhs: f64) {
977 *self = self.mul(rhs);
978 }
979}
980
981impl MulAssign<&f64> for DQuat {
982 #[inline]
983 fn mul_assign(&mut self, rhs: &f64) {
984 self.mul_assign(*rhs);
985 }
986}
987
988impl Div<f64> for DQuat {
989 type Output = Self;
990 /// Divides a quaternion by a scalar value.
991 /// The quotient is not guaranteed to be normalized.
992 #[inline]
993 fn div(self, rhs: f64) -> Self {
994 Self::from_vec4(DVec4::from(self) / rhs)
995 }
996}
997
998impl Div<&f64> for DQuat {
999 type Output = Self;
1000 #[inline]
1001 fn div(self, rhs: &f64) -> Self {
1002 self.div(*rhs)
1003 }
1004}
1005
1006impl Div<&f64> for &DQuat {
1007 type Output = DQuat;
1008 #[inline]
1009 fn div(self, rhs: &f64) -> DQuat {
1010 (*self).div(*rhs)
1011 }
1012}
1013
1014impl Div<f64> for &DQuat {
1015 type Output = DQuat;
1016 #[inline]
1017 fn div(self, rhs: f64) -> DQuat {
1018 (*self).div(rhs)
1019 }
1020}
1021
1022impl DivAssign<f64> for DQuat {
1023 #[inline]
1024 fn div_assign(&mut self, rhs: f64) {
1025 *self = self.div(rhs);
1026 }
1027}
1028
1029impl DivAssign<&f64> for DQuat {
1030 #[inline]
1031 fn div_assign(&mut self, rhs: &f64) {
1032 self.div_assign(*rhs);
1033 }
1034}
1035
1036impl Mul for DQuat {
1037 type Output = Self;
1038 /// Multiplies two quaternions. If they each represent a rotation, the result will
1039 /// represent the combined rotation.
1040 ///
1041 /// Note that due to floating point rounding the result may not be perfectly
1042 /// normalized.
1043 ///
1044 /// # Panics
1045 ///
1046 /// Will panic if `self` or `rhs` are not normalized when `glam_assert` is enabled.
1047 #[inline]
1048 fn mul(self, rhs: Self) -> Self {
1049 self.mul_quat(rhs)
1050 }
1051}
1052
1053impl Mul<&Self> for DQuat {
1054 type Output = Self;
1055 #[inline]
1056 fn mul(self, rhs: &Self) -> Self {
1057 self.mul(*rhs)
1058 }
1059}
1060
1061impl Mul<&DQuat> for &DQuat {
1062 type Output = DQuat;
1063 #[inline]
1064 fn mul(self, rhs: &DQuat) -> DQuat {
1065 (*self).mul(*rhs)
1066 }
1067}
1068
1069impl Mul<DQuat> for &DQuat {
1070 type Output = DQuat;
1071 #[inline]
1072 fn mul(self, rhs: DQuat) -> DQuat {
1073 (*self).mul(rhs)
1074 }
1075}
1076
1077impl MulAssign for DQuat {
1078 #[inline]
1079 fn mul_assign(&mut self, rhs: Self) {
1080 *self = self.mul(rhs);
1081 }
1082}
1083
1084impl MulAssign<&Self> for DQuat {
1085 #[inline]
1086 fn mul_assign(&mut self, rhs: &Self) {
1087 self.mul_assign(*rhs);
1088 }
1089}
1090
1091impl Mul<DVec3> for DQuat {
1092 type Output = DVec3;
1093 /// Multiplies a quaternion and a 3D vector, returning the rotated vector.
1094 ///
1095 /// # Panics
1096 ///
1097 /// Will panic if `self` is not normalized when `glam_assert` is enabled.
1098 #[inline]
1099 fn mul(self, rhs: DVec3) -> Self::Output {
1100 self.mul_vec3(rhs)
1101 }
1102}
1103
1104impl Mul<&DVec3> for DQuat {
1105 type Output = DVec3;
1106 #[inline]
1107 fn mul(self, rhs: &DVec3) -> DVec3 {
1108 self.mul(*rhs)
1109 }
1110}
1111
1112impl Mul<&DVec3> for &DQuat {
1113 type Output = DVec3;
1114 #[inline]
1115 fn mul(self, rhs: &DVec3) -> DVec3 {
1116 (*self).mul(*rhs)
1117 }
1118}
1119
1120impl Mul<DVec3> for &DQuat {
1121 type Output = DVec3;
1122 #[inline]
1123 fn mul(self, rhs: DVec3) -> DVec3 {
1124 (*self).mul(rhs)
1125 }
1126}
1127
1128impl Neg for DQuat {
1129 type Output = Self;
1130 #[inline]
1131 fn neg(self) -> Self {
1132 self * -1.0
1133 }
1134}
1135
1136impl Neg for &DQuat {
1137 type Output = DQuat;
1138 #[inline]
1139 fn neg(self) -> DQuat {
1140 (*self).neg()
1141 }
1142}
1143
1144impl Default for DQuat {
1145 #[inline]
1146 fn default() -> Self {
1147 Self::IDENTITY
1148 }
1149}
1150
1151impl PartialEq for DQuat {
1152 #[inline]
1153 fn eq(&self, rhs: &Self) -> bool {
1154 DVec4::from(*self).eq(&DVec4::from(*rhs))
1155 }
1156}
1157
1158impl AsRef<[f64; 4]> for DQuat {
1159 #[inline]
1160 fn as_ref(&self) -> &[f64; 4] {
1161 unsafe { &*(self as *const Self as *const [f64; 4]) }
1162 }
1163}
1164
1165impl Sum<Self> for DQuat {
1166 fn sum<I>(iter: I) -> Self
1167 where
1168 I: Iterator<Item = Self>,
1169 {
1170 iter.fold(Self::ZERO, Self::add)
1171 }
1172}
1173
1174impl<'a> Sum<&'a Self> for DQuat {
1175 fn sum<I>(iter: I) -> Self
1176 where
1177 I: Iterator<Item = &'a Self>,
1178 {
1179 iter.fold(Self::ZERO, |a, &b| Self::add(a, b))
1180 }
1181}
1182
1183impl Product for DQuat {
1184 fn product<I>(iter: I) -> Self
1185 where
1186 I: Iterator<Item = Self>,
1187 {
1188 iter.fold(Self::IDENTITY, Self::mul)
1189 }
1190}
1191
1192impl<'a> Product<&'a Self> for DQuat {
1193 fn product<I>(iter: I) -> Self
1194 where
1195 I: Iterator<Item = &'a Self>,
1196 {
1197 iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b))
1198 }
1199}
1200
1201impl From<DQuat> for DVec4 {
1202 #[inline]
1203 fn from(q: DQuat) -> Self {
1204 Self::new(q.x, q.y, q.z, q.w)
1205 }
1206}
1207
1208impl From<DQuat> for (f64, f64, f64, f64) {
1209 #[inline]
1210 fn from(q: DQuat) -> Self {
1211 (q.x, q.y, q.z, q.w)
1212 }
1213}
1214
1215impl From<DQuat> for [f64; 4] {
1216 #[inline]
1217 fn from(q: DQuat) -> Self {
1218 [q.x, q.y, q.z, q.w]
1219 }
1220}