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 #[deprecated(
397 since = "0.33.1",
398 note = "use the `glam::dcamera::lh::view::look_to_quat` function instead"
399 )]
400 #[inline]
401 #[must_use]
402 pub fn look_to_lh(dir: DVec3, up: DVec3) -> Self {
403 #[allow(deprecated)]
404 Self::look_to_rh(-dir, up)
405 }
406
407 /// Creates a quaterion rotation from facing direction and an up direction.
408 ///
409 /// For a right-handed view coordinate system with `+X=right`, `+Y=up` and `+Z=back`.
410 ///
411 /// # Panics
412 ///
413 /// Will panic if `dir` and `up` are not normalized when `glam_assert` is enabled.
414 #[deprecated(
415 since = "0.33.1",
416 note = "use the `glam::dcamera::rh::view::look_to_quat` function instead"
417 )]
418 #[inline]
419 #[must_use]
420 pub fn look_to_rh(dir: DVec3, up: DVec3) -> Self {
421 glam_assert!(dir.is_normalized());
422 glam_assert!(up.is_normalized());
423 let f = dir;
424 let s = f.cross(up).normalize();
425 let u = s.cross(f);
426
427 Self::from_rotation_axes(
428 DVec3::new(s.x, u.x, -f.x),
429 DVec3::new(s.y, u.y, -f.y),
430 DVec3::new(s.z, u.z, -f.z),
431 )
432 }
433
434 /// Creates a quaternion rotation from a camera position, a focal point, and an up
435 /// direction.
436 ///
437 /// For a left-handed view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`.
438 ///
439 /// # Panics
440 ///
441 /// Will panic if `up` is not normalized when `glam_assert` is enabled.
442 #[deprecated(
443 since = "0.33.1",
444 note = "use the `glam::dcamera::lh::view::look_at_quat` function instead"
445 )]
446 #[inline]
447 #[must_use]
448 pub fn look_at_lh(eye: DVec3, center: DVec3, up: DVec3) -> Self {
449 #[allow(deprecated)]
450 Self::look_to_lh(center.sub(eye).normalize(), up)
451 }
452
453 /// Creates a quaternion rotation using a camera position, an up direction, and a focal
454 /// point.
455 ///
456 /// For a right-handed view coordinate system with `+X=right`, `+Y=up` and `+Z=back`.
457 ///
458 /// # Panics
459 ///
460 /// Will panic if `up` is not normalized when `glam_assert` is enabled.
461 #[deprecated(
462 since = "0.33.1",
463 note = "use the `glam::dcamera::rh::view::look_at_quat` function instead"
464 )]
465 #[inline]
466 #[must_use]
467 pub fn look_at_rh(eye: DVec3, center: DVec3, up: DVec3) -> Self {
468 #[allow(deprecated)]
469 Self::look_to_rh(center.sub(eye).normalize(), up)
470 }
471
472 /// Returns the rotation axis (normalized) and angle (in radians) of `self`.
473 #[inline]
474 #[must_use]
475 pub fn to_axis_angle(self) -> (DVec3, f64) {
476 const EPSILON: f64 = 1.0e-8;
477 let v = DVec3::new(self.x, self.y, self.z);
478 let length = v.length();
479 if length >= EPSILON {
480 let angle = 2.0 * math::atan2(length, self.w);
481 let axis = v / length;
482 (axis, angle)
483 } else {
484 (DVec3::X, 0.0)
485 }
486 }
487
488 /// Returns the rotation axis scaled by the rotation in radians.
489 #[inline]
490 #[must_use]
491 pub fn to_scaled_axis(self) -> DVec3 {
492 let (axis, angle) = self.to_axis_angle();
493 axis * angle
494 }
495
496 /// Returns the rotation angles for the given euler rotation sequence.
497 #[inline]
498 #[must_use]
499 pub fn to_euler(self, order: EulerRot) -> (f64, f64, f64) {
500 self.to_euler_angles(order)
501 }
502
503 /// `[x, y, z, w]`
504 #[inline]
505 #[must_use]
506 pub fn to_array(self) -> [f64; 4] {
507 [self.x, self.y, self.z, self.w]
508 }
509
510 /// Returns the vector part of the quaternion.
511 #[inline]
512 #[must_use]
513 pub fn xyz(self) -> DVec3 {
514 DVec3::new(self.x, self.y, self.z)
515 }
516
517 /// Returns the quaternion conjugate of `self`. For a unit quaternion the
518 /// conjugate is also the inverse.
519 #[inline]
520 #[must_use]
521 pub fn conjugate(self) -> Self {
522 Self {
523 x: -self.x,
524 y: -self.y,
525 z: -self.z,
526 w: self.w,
527 }
528 }
529
530 /// Returns the inverse of a normalized quaternion.
531 ///
532 /// Typically quaternion inverse returns the conjugate of a normalized quaternion.
533 /// Because `self` is assumed to already be unit length this method *does not* normalize
534 /// before returning the conjugate.
535 ///
536 /// # Panics
537 ///
538 /// Will panic if `self` is not normalized when `glam_assert` is enabled.
539 #[inline]
540 #[must_use]
541 pub fn inverse(self) -> Self {
542 glam_assert!(self.is_normalized());
543 self.conjugate()
544 }
545
546 /// Computes the dot product of `self` and `rhs`. The dot product is
547 /// equal to the cosine of the angle between two quaternion rotations.
548 #[inline]
549 #[must_use]
550 pub fn dot(self, rhs: Self) -> f64 {
551 DVec4::from(self).dot(DVec4::from(rhs))
552 }
553
554 /// Computes the length of `self`.
555 #[doc(alias = "magnitude")]
556 #[inline]
557 #[must_use]
558 pub fn length(self) -> f64 {
559 DVec4::from(self).length()
560 }
561
562 /// Computes the squared length of `self`.
563 ///
564 /// This is generally faster than `length()` as it avoids a square
565 /// root operation.
566 #[doc(alias = "magnitude2")]
567 #[inline]
568 #[must_use]
569 pub fn length_squared(self) -> f64 {
570 DVec4::from(self).length_squared()
571 }
572
573 /// Computes `1.0 / length()`.
574 ///
575 /// For valid results, `self` must _not_ be of length zero.
576 #[inline]
577 #[must_use]
578 pub fn length_recip(self) -> f64 {
579 DVec4::from(self).length_recip()
580 }
581
582 /// Returns `self` normalized to length 1.0.
583 ///
584 /// For valid results, `self` must _not_ be of length zero.
585 ///
586 /// Panics
587 ///
588 /// Will panic if `self` is zero length when `glam_assert` is enabled.
589 #[inline]
590 #[must_use]
591 pub fn normalize(self) -> Self {
592 Self::from_vec4(DVec4::from(self).normalize())
593 }
594
595 /// Returns `true` if, and only if, all elements are finite.
596 /// If any element is either `NaN`, positive or negative infinity, this will return `false`.
597 #[inline]
598 #[must_use]
599 pub fn is_finite(self) -> bool {
600 DVec4::from(self).is_finite()
601 }
602
603 /// Returns `true` if any elements are `NAN`.
604 #[inline]
605 #[must_use]
606 pub fn is_nan(self) -> bool {
607 DVec4::from(self).is_nan()
608 }
609
610 /// Returns whether `self` of length `1.0` or not.
611 ///
612 /// Uses a precision threshold of `1e-6`.
613 #[inline]
614 #[must_use]
615 pub fn is_normalized(self) -> bool {
616 DVec4::from(self).is_normalized()
617 }
618
619 #[inline]
620 #[must_use]
621 pub fn is_near_identity(self) -> bool {
622 // Based on https://github.com/nfrechette/rtm `rtm::quat_near_identity`
623 // Because of floating point precision, we cannot represent very small rotations.
624 // The closest f32 to 1.0 that is not 1.0 itself yields:
625 // 0.99999994.acos() * 2.0 = 0.000690533954 rad
626 //
627 // An error threshold of 1.e-6 is used by default.
628 // (1.0 - 1.e-6).acos() * 2.0 = 0.00284714461 rad
629 // (1.0 - 1.e-7).acos() * 2.0 = 0.00097656250 rad
630 //
631 // We don't really care about the angle value itself, only if it's close to 0.
632 // This will happen whenever quat.w is close to 1.0.
633 // If the quat.w is close to -1.0, the angle will be near 2*PI which is close to
634 // a negative 0 rotation. By forcing quat.w to be positive, we'll end up with
635 // the shortest path.
636 //
637 // For f64 we're using a threshhold of
638 // (1.0 - 1e-14).acos() * 2.0
639 const THRESHOLD_ANGLE: f64 = 2.827_296_549_232_347_4e-7;
640 let positive_w_angle = math::acos_approx(math::abs(self.w)) * 2.0;
641 positive_w_angle < THRESHOLD_ANGLE
642 }
643
644 /// Returns the angle (in radians) for the minimal rotation
645 /// for transforming this quaternion into another.
646 ///
647 /// Both quaternions must be normalized.
648 ///
649 /// # Panics
650 ///
651 /// Will panic if `self` or `rhs` are not normalized when `glam_assert` is enabled.
652 #[inline]
653 #[must_use]
654 pub fn angle_between(self, rhs: Self) -> f64 {
655 glam_assert!(self.is_normalized() && rhs.is_normalized());
656 math::acos_approx(math::abs(self.dot(rhs))) * 2.0
657 }
658
659 /// Rotates towards `rhs` up to `max_angle` (in radians).
660 ///
661 /// When `max_angle` is `0.0`, the result will be equal to `self`. When `max_angle` is equal to
662 /// `self.angle_between(rhs)`, the result will be equal to `rhs`. If `max_angle` is negative,
663 /// rotates towards the exact opposite of `rhs`. Will not go past the target.
664 ///
665 /// Both quaternions must be normalized.
666 ///
667 /// # Panics
668 ///
669 /// Will panic if `self` or `rhs` are not normalized when `glam_assert` is enabled.
670 #[inline]
671 #[must_use]
672 pub fn rotate_towards(self, rhs: Self, max_angle: f64) -> Self {
673 glam_assert!(self.is_normalized() && rhs.is_normalized());
674 let angle = self.angle_between(rhs);
675 if angle <= 1e-4 {
676 return rhs;
677 }
678 let s = (max_angle / angle).clamp(-1.0, 1.0);
679 self.slerp(rhs, s)
680 }
681
682 /// Returns true if the absolute difference of all elements between `self` and `rhs`
683 /// is less than or equal to `max_abs_diff`.
684 ///
685 /// This can be used to compare if two quaternions contain similar elements. It works
686 /// best when comparing with a known value. The `max_abs_diff` that should be used used
687 /// depends on the values being compared against.
688 ///
689 /// For more see
690 /// [comparing floating point numbers](https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/).
691 #[inline]
692 #[must_use]
693 pub fn abs_diff_eq(self, rhs: Self, max_abs_diff: f64) -> bool {
694 DVec4::from(self).abs_diff_eq(DVec4::from(rhs), max_abs_diff)
695 }
696
697 #[inline(always)]
698 #[must_use]
699 fn lerp_impl(self, end: Self, s: f64) -> Self {
700 (self * (1.0 - s) + end * s).normalize()
701 }
702
703 /// Performs a linear interpolation between `self` and `rhs` based on
704 /// the value `s`.
705 ///
706 /// When `s` is `0.0`, the result will be equal to `self`. When `s`
707 /// is `1.0`, the result will be equal to `rhs`.
708 ///
709 /// # Panics
710 ///
711 /// Will panic if `self` or `end` are not normalized when `glam_assert` is enabled.
712 #[doc(alias = "mix")]
713 #[inline]
714 #[must_use]
715 pub fn lerp(self, end: Self, s: f64) -> Self {
716 glam_assert!(self.is_normalized());
717 glam_assert!(end.is_normalized());
718
719 let dot = self.dot(end);
720 let bias = if dot >= 0.0 { 1.0 } else { -1.0 };
721 self.lerp_impl(end * bias, s)
722 }
723
724 #[inline(always)]
725 #[must_use]
726 fn slerp_impl(self, end: Self, dot: f64, s: f64) -> Self {
727 let theta = math::acos_approx(dot);
728
729 let scale1 = math::sin(theta * (1.0 - s));
730 let scale2 = math::sin(theta * s);
731 let theta_sin = math::sin(theta);
732 ((self * scale1) + (end * scale2)) * (1.0 / theta_sin)
733 }
734
735 /// Performs a spherical linear interpolation between `self` and `end`
736 /// based on the value `s`.
737 ///
738 /// When `s` is `0.0`, the result will be equal to `self`. When `s`
739 /// is `1.0`, the result will be equal to `end`.
740 ///
741 /// # Panics
742 ///
743 /// Will panic if `self` or `end` are not normalized when `glam_assert` is enabled.
744 #[inline]
745 #[must_use]
746 pub fn slerp(self, mut end: Self, s: f64) -> Self {
747 // http://number-none.com/product/Understanding%20Slerp,%20Then%20Not%20Using%20It/
748 glam_assert!(self.is_normalized());
749 glam_assert!(end.is_normalized());
750
751 // Note that a rotation can be represented by two quaternions: `q` and
752 // `-q`. The slerp path between `q` and `end` will be different from the
753 // path between `-q` and `end`. One path will take the long way around and
754 // one will take the short way. In order to correct for this, the `dot`
755 // product between `self` and `end` should be positive. If the `dot`
756 // product is negative, slerp between `self` and `-end`.
757 let mut dot = self.dot(end);
758 if dot < 0.0 {
759 end = -end;
760 dot = -dot;
761 }
762
763 const DOT_THRESHOLD: f64 = 1.0 - f64::EPSILON;
764 if dot > DOT_THRESHOLD {
765 // if above threshold perform linear interpolation to avoid divide by zero
766 self.lerp_impl(end, s)
767 } else {
768 self.slerp_impl(end, dot, s)
769 }
770 }
771
772 /// Performs a spherical linear interpolation between `self` and `end` based on the value `s`,
773 /// preserving the rotation direction.
774 ///
775 /// When `s` is `0.0`, the result will be equal to `self`. When `s` is `1.0`, the result will
776 /// be equal to `end`.
777 ///
778 /// When the dot product of `self` and `end` is negative, the standard [`slerp`](Self::slerp)
779 /// will flip the end quaternion to take the shortest path, while this method will take the
780 /// longer arc. This is useful when the intended rotation direction must be preserved.
781 ///
782 /// # Panics
783 ///
784 /// Will panic if `self` or `end` are not normalized when `glam_assert` is enabled.
785 #[inline]
786 #[must_use]
787 pub fn slerp_long(self, end: Self, s: f64) -> Self {
788 glam_assert!(self.is_normalized());
789 glam_assert!(end.is_normalized());
790
791 let dot = self.dot(end);
792
793 const DOT_THRESHOLD: f64 = 1.0 - f64::EPSILON;
794 if dot.abs() > DOT_THRESHOLD {
795 // if above threshold perform linear interpolation to avoid divide by zero
796 self.lerp_impl(end, s)
797 } else {
798 self.slerp_impl(end, dot, s)
799 }
800 }
801
802 /// Multiplies a quaternion and a 3D vector, returning the rotated vector.
803 ///
804 /// # Panics
805 ///
806 /// Will panic if `self` is not normalized when `glam_assert` is enabled.
807 #[inline]
808 #[must_use]
809 pub fn mul_vec3(self, rhs: DVec3) -> DVec3 {
810 glam_assert!(self.is_normalized());
811
812 let w = self.w;
813 let b = DVec3::new(self.x, self.y, self.z);
814 let b2 = b.dot(b);
815 rhs.mul(w * w - b2)
816 .add(b.mul(rhs.dot(b) * 2.0))
817 .add(b.cross(rhs).mul(w * 2.0))
818 }
819
820 /// Multiplies two quaternions. If they each represent a rotation, the result will
821 /// represent the combined rotation.
822 ///
823 /// Note that due to floating point rounding the result may not be perfectly normalized.
824 ///
825 /// # Panics
826 ///
827 /// Will panic if `self` or `rhs` are not normalized when `glam_assert` is enabled.
828 #[inline]
829 #[must_use]
830 pub fn mul_quat(self, rhs: Self) -> Self {
831 let (x0, y0, z0, w0) = self.into();
832 let (x1, y1, z1, w1) = rhs.into();
833 Self::from_xyzw(
834 w0 * x1 + x0 * w1 + y0 * z1 - z0 * y1,
835 w0 * y1 - x0 * z1 + y0 * w1 + z0 * x1,
836 w0 * z1 + x0 * y1 - y0 * x1 + z0 * w1,
837 w0 * w1 - x0 * x1 - y0 * y1 - z0 * z1,
838 )
839 }
840
841 /// Creates a quaternion from a 3x3 rotation matrix inside a 3D affine transform.
842 ///
843 /// Note if the input affine matrix contain scales, shears, or other non-rotation
844 /// transformations then the resulting quaternion will be ill-defined.
845 ///
846 /// # Panics
847 ///
848 /// Will panic if any input affine matrix column is not normalized when `glam_assert` is
849 /// enabled.
850 #[inline]
851 #[must_use]
852 pub fn from_affine3(a: &crate::DAffine3) -> Self {
853 Self::from_rotation_axes(a.matrix3.x_axis, a.matrix3.y_axis, a.matrix3.z_axis)
854 }
855
856 #[inline]
857 #[must_use]
858 pub fn as_quat(self) -> Quat {
859 Quat::from_xyzw(self.x as f32, self.y as f32, self.z as f32, self.w as f32)
860 }
861}
862
863impl fmt::Debug for DQuat {
864 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
865 fmt.debug_tuple(stringify!(DQuat))
866 .field(&self.x)
867 .field(&self.y)
868 .field(&self.z)
869 .field(&self.w)
870 .finish()
871 }
872}
873
874impl fmt::Display for DQuat {
875 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
876 if let Some(p) = f.precision() {
877 write!(
878 f,
879 "[{:.*}, {:.*}, {:.*}, {:.*}]",
880 p, self.x, p, self.y, p, self.z, p, self.w
881 )
882 } else {
883 write!(f, "[{}, {}, {}, {}]", self.x, self.y, self.z, self.w)
884 }
885 }
886}
887
888impl Add for DQuat {
889 type Output = Self;
890 /// Adds two quaternions.
891 ///
892 /// The sum is not guaranteed to be normalized.
893 ///
894 /// Note that addition is not the same as combining the rotations represented by the
895 /// two quaternions! That corresponds to multiplication.
896 #[inline]
897 fn add(self, rhs: Self) -> Self {
898 Self::from_vec4(DVec4::from(self) + DVec4::from(rhs))
899 }
900}
901
902impl Add<&Self> for DQuat {
903 type Output = Self;
904 #[inline]
905 fn add(self, rhs: &Self) -> Self {
906 self.add(*rhs)
907 }
908}
909
910impl Add<&DQuat> for &DQuat {
911 type Output = DQuat;
912 #[inline]
913 fn add(self, rhs: &DQuat) -> DQuat {
914 (*self).add(*rhs)
915 }
916}
917
918impl Add<DQuat> for &DQuat {
919 type Output = DQuat;
920 #[inline]
921 fn add(self, rhs: DQuat) -> DQuat {
922 (*self).add(rhs)
923 }
924}
925
926impl AddAssign for DQuat {
927 #[inline]
928 fn add_assign(&mut self, rhs: Self) {
929 *self = self.add(rhs);
930 }
931}
932
933impl AddAssign<&Self> for DQuat {
934 #[inline]
935 fn add_assign(&mut self, rhs: &Self) {
936 self.add_assign(*rhs);
937 }
938}
939
940impl Sub for DQuat {
941 type Output = Self;
942 /// Subtracts the `rhs` quaternion from `self`.
943 ///
944 /// The difference is not guaranteed to be normalized.
945 #[inline]
946 fn sub(self, rhs: Self) -> Self {
947 Self::from_vec4(DVec4::from(self) - DVec4::from(rhs))
948 }
949}
950
951impl Sub<&Self> for DQuat {
952 type Output = Self;
953 #[inline]
954 fn sub(self, rhs: &Self) -> Self {
955 self.sub(*rhs)
956 }
957}
958
959impl Sub<&DQuat> for &DQuat {
960 type Output = DQuat;
961 #[inline]
962 fn sub(self, rhs: &DQuat) -> DQuat {
963 (*self).sub(*rhs)
964 }
965}
966
967impl Sub<DQuat> for &DQuat {
968 type Output = DQuat;
969 #[inline]
970 fn sub(self, rhs: DQuat) -> DQuat {
971 (*self).sub(rhs)
972 }
973}
974
975impl SubAssign for DQuat {
976 #[inline]
977 fn sub_assign(&mut self, rhs: Self) {
978 *self = self.sub(rhs);
979 }
980}
981
982impl SubAssign<&Self> for DQuat {
983 #[inline]
984 fn sub_assign(&mut self, rhs: &Self) {
985 self.sub_assign(*rhs);
986 }
987}
988
989impl Mul<f64> for DQuat {
990 type Output = Self;
991 /// Multiplies a quaternion by a scalar value.
992 ///
993 /// The product is not guaranteed to be normalized.
994 #[inline]
995 fn mul(self, rhs: f64) -> Self {
996 Self::from_vec4(DVec4::from(self) * rhs)
997 }
998}
999
1000impl Mul<&f64> for DQuat {
1001 type Output = Self;
1002 #[inline]
1003 fn mul(self, rhs: &f64) -> Self {
1004 self.mul(*rhs)
1005 }
1006}
1007
1008impl Mul<&f64> for &DQuat {
1009 type Output = DQuat;
1010 #[inline]
1011 fn mul(self, rhs: &f64) -> DQuat {
1012 (*self).mul(*rhs)
1013 }
1014}
1015
1016impl Mul<f64> for &DQuat {
1017 type Output = DQuat;
1018 #[inline]
1019 fn mul(self, rhs: f64) -> DQuat {
1020 (*self).mul(rhs)
1021 }
1022}
1023
1024impl MulAssign<f64> for DQuat {
1025 #[inline]
1026 fn mul_assign(&mut self, rhs: f64) {
1027 *self = self.mul(rhs);
1028 }
1029}
1030
1031impl MulAssign<&f64> for DQuat {
1032 #[inline]
1033 fn mul_assign(&mut self, rhs: &f64) {
1034 self.mul_assign(*rhs);
1035 }
1036}
1037
1038impl Div<f64> for DQuat {
1039 type Output = Self;
1040 /// Divides a quaternion by a scalar value.
1041 /// The quotient is not guaranteed to be normalized.
1042 #[inline]
1043 fn div(self, rhs: f64) -> Self {
1044 Self::from_vec4(DVec4::from(self) / rhs)
1045 }
1046}
1047
1048impl Div<&f64> for DQuat {
1049 type Output = Self;
1050 #[inline]
1051 fn div(self, rhs: &f64) -> Self {
1052 self.div(*rhs)
1053 }
1054}
1055
1056impl Div<&f64> for &DQuat {
1057 type Output = DQuat;
1058 #[inline]
1059 fn div(self, rhs: &f64) -> DQuat {
1060 (*self).div(*rhs)
1061 }
1062}
1063
1064impl Div<f64> for &DQuat {
1065 type Output = DQuat;
1066 #[inline]
1067 fn div(self, rhs: f64) -> DQuat {
1068 (*self).div(rhs)
1069 }
1070}
1071
1072impl DivAssign<f64> for DQuat {
1073 #[inline]
1074 fn div_assign(&mut self, rhs: f64) {
1075 *self = self.div(rhs);
1076 }
1077}
1078
1079impl DivAssign<&f64> for DQuat {
1080 #[inline]
1081 fn div_assign(&mut self, rhs: &f64) {
1082 self.div_assign(*rhs);
1083 }
1084}
1085
1086impl Mul for DQuat {
1087 type Output = Self;
1088 /// Multiplies two quaternions. If they each represent a rotation, the result will
1089 /// represent the combined rotation.
1090 ///
1091 /// Note that due to floating point rounding the result may not be perfectly
1092 /// normalized.
1093 ///
1094 /// # Panics
1095 ///
1096 /// Will panic if `self` or `rhs` are not normalized when `glam_assert` is enabled.
1097 #[inline]
1098 fn mul(self, rhs: Self) -> Self {
1099 self.mul_quat(rhs)
1100 }
1101}
1102
1103impl Mul<&Self> for DQuat {
1104 type Output = Self;
1105 #[inline]
1106 fn mul(self, rhs: &Self) -> Self {
1107 self.mul(*rhs)
1108 }
1109}
1110
1111impl Mul<&DQuat> for &DQuat {
1112 type Output = DQuat;
1113 #[inline]
1114 fn mul(self, rhs: &DQuat) -> DQuat {
1115 (*self).mul(*rhs)
1116 }
1117}
1118
1119impl Mul<DQuat> for &DQuat {
1120 type Output = DQuat;
1121 #[inline]
1122 fn mul(self, rhs: DQuat) -> DQuat {
1123 (*self).mul(rhs)
1124 }
1125}
1126
1127impl MulAssign for DQuat {
1128 #[inline]
1129 fn mul_assign(&mut self, rhs: Self) {
1130 *self = self.mul(rhs);
1131 }
1132}
1133
1134impl MulAssign<&Self> for DQuat {
1135 #[inline]
1136 fn mul_assign(&mut self, rhs: &Self) {
1137 self.mul_assign(*rhs);
1138 }
1139}
1140
1141impl Mul<DVec3> for DQuat {
1142 type Output = DVec3;
1143 /// Multiplies a quaternion and a 3D vector, returning the rotated vector.
1144 ///
1145 /// # Panics
1146 ///
1147 /// Will panic if `self` is not normalized when `glam_assert` is enabled.
1148 #[inline]
1149 fn mul(self, rhs: DVec3) -> Self::Output {
1150 self.mul_vec3(rhs)
1151 }
1152}
1153
1154impl Mul<&DVec3> for DQuat {
1155 type Output = DVec3;
1156 #[inline]
1157 fn mul(self, rhs: &DVec3) -> DVec3 {
1158 self.mul(*rhs)
1159 }
1160}
1161
1162impl Mul<&DVec3> for &DQuat {
1163 type Output = DVec3;
1164 #[inline]
1165 fn mul(self, rhs: &DVec3) -> DVec3 {
1166 (*self).mul(*rhs)
1167 }
1168}
1169
1170impl Mul<DVec3> for &DQuat {
1171 type Output = DVec3;
1172 #[inline]
1173 fn mul(self, rhs: DVec3) -> DVec3 {
1174 (*self).mul(rhs)
1175 }
1176}
1177
1178impl Neg for DQuat {
1179 type Output = Self;
1180 #[inline]
1181 fn neg(self) -> Self {
1182 self * -1.0
1183 }
1184}
1185
1186impl Neg for &DQuat {
1187 type Output = DQuat;
1188 #[inline]
1189 fn neg(self) -> DQuat {
1190 (*self).neg()
1191 }
1192}
1193
1194impl Default for DQuat {
1195 #[inline]
1196 fn default() -> Self {
1197 Self::IDENTITY
1198 }
1199}
1200
1201impl PartialEq for DQuat {
1202 #[inline]
1203 fn eq(&self, rhs: &Self) -> bool {
1204 DVec4::from(*self).eq(&DVec4::from(*rhs))
1205 }
1206}
1207
1208impl AsRef<[f64; 4]> for DQuat {
1209 #[inline]
1210 fn as_ref(&self) -> &[f64; 4] {
1211 unsafe { &*(self as *const Self as *const [f64; 4]) }
1212 }
1213}
1214
1215impl Sum<Self> for DQuat {
1216 fn sum<I>(iter: I) -> Self
1217 where
1218 I: Iterator<Item = Self>,
1219 {
1220 iter.fold(Self::ZERO, Self::add)
1221 }
1222}
1223
1224impl<'a> Sum<&'a Self> for DQuat {
1225 fn sum<I>(iter: I) -> Self
1226 where
1227 I: Iterator<Item = &'a Self>,
1228 {
1229 iter.fold(Self::ZERO, |a, &b| Self::add(a, b))
1230 }
1231}
1232
1233impl Product for DQuat {
1234 fn product<I>(iter: I) -> Self
1235 where
1236 I: Iterator<Item = Self>,
1237 {
1238 iter.fold(Self::IDENTITY, Self::mul)
1239 }
1240}
1241
1242impl<'a> Product<&'a Self> for DQuat {
1243 fn product<I>(iter: I) -> Self
1244 where
1245 I: Iterator<Item = &'a Self>,
1246 {
1247 iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b))
1248 }
1249}
1250
1251impl From<DQuat> for DVec4 {
1252 #[inline]
1253 fn from(q: DQuat) -> Self {
1254 Self::new(q.x, q.y, q.z, q.w)
1255 }
1256}
1257
1258impl From<DQuat> for (f64, f64, f64, f64) {
1259 #[inline]
1260 fn from(q: DQuat) -> Self {
1261 (q.x, q.y, q.z, q.w)
1262 }
1263}
1264
1265impl From<DQuat> for [f64; 4] {
1266 #[inline]
1267 fn from(q: DQuat) -> Self {
1268 [q.x, q.y, q.z, q.w]
1269 }
1270}