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