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