aboutsummaryrefslogtreecommitdiff
path: root/src/core/traits/quaternion.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/traits/quaternion.rs')
-rw-r--r--src/core/traits/quaternion.rs140
1 files changed, 0 insertions, 140 deletions
diff --git a/src/core/traits/quaternion.rs b/src/core/traits/quaternion.rs
deleted file mode 100644
index 8a3836c..0000000
--- a/src/core/traits/quaternion.rs
+++ /dev/null
@@ -1,140 +0,0 @@
-use crate::core::{
- storage::XYZ,
- traits::{
- scalar::{FloatEx, NumEx},
- vector::*,
- },
-};
-
-pub trait Quaternion<T: FloatEx>: FloatVector4<T> {
- type SIMDVector3;
-
- #[inline]
- fn from_axis_angle(axis: XYZ<T>, angle: T) -> Self {
- glam_assert!(FloatVector3::is_normalized(axis));
- let (s, c) = (angle * T::HALF).sin_cos();
- let v = axis.mul_scalar(s);
- Self::new(v.x, v.y, v.z, c)
- }
-
- #[inline]
- fn from_rotation_x(angle: T) -> Self {
- let (s, c) = (angle * T::HALF).sin_cos();
- Self::new(s, T::ZERO, T::ZERO, c)
- }
-
- #[inline]
- fn from_rotation_y(angle: T) -> Self {
- let (s, c) = (angle * T::HALF).sin_cos();
- Self::new(T::ZERO, s, T::ZERO, c)
- }
-
- #[inline]
- fn from_rotation_z(angle: T) -> Self {
- let (s, c) = (angle * T::HALF).sin_cos();
- Self::new(T::ZERO, T::ZERO, s, c)
- }
-
- /// From the columns of a 3x3 rotation matrix.
- #[inline]
- fn from_rotation_axes(x_axis: XYZ<T>, y_axis: XYZ<T>, z_axis: XYZ<T>) -> Self {
- // Based on https://github.com/microsoft/DirectXMath `XM$quaternionRotationMatrix`
- // TODO: sse2 version
- let (m00, m01, m02) = x_axis.into_tuple();
- let (m10, m11, m12) = y_axis.into_tuple();
- let (m20, m21, m22) = z_axis.into_tuple();
- if m22 <= T::ZERO {
- // x^2 + y^2 >= z^2 + w^2
- let dif10 = m11 - m00;
- let omm22 = T::ONE - m22;
- if dif10 <= T::ZERO {
- // x^2 >= y^2
- let four_xsq = omm22 - dif10;
- let inv4x = T::HALF / four_xsq.sqrt();
- Self::new(
- four_xsq * inv4x,
- (m01 + m10) * inv4x,
- (m02 + m20) * inv4x,
- (m12 - m21) * inv4x,
- )
- } else {
- // y^2 >= x^2
- let four_ysq = omm22 + dif10;
- let inv4y = T::HALF / four_ysq.sqrt();
- Self::new(
- (m01 + m10) * inv4y,
- four_ysq * inv4y,
- (m12 + m21) * inv4y,
- (m20 - m02) * inv4y,
- )
- }
- } else {
- // z^2 + w^2 >= x^2 + y^2
- let sum10 = m11 + m00;
- let opm22 = T::ONE + m22;
- if sum10 <= T::ZERO {
- // z^2 >= w^2
- let four_zsq = opm22 - sum10;
- let inv4z = T::HALF / four_zsq.sqrt();
- Self::new(
- (m02 + m20) * inv4z,
- (m12 + m21) * inv4z,
- four_zsq * inv4z,
- (m01 - m10) * inv4z,
- )
- } else {
- // w^2 >= z^2
- let four_wsq = opm22 + sum10;
- let inv4w = T::HALF / four_wsq.sqrt();
- Self::new(
- (m12 - m21) * inv4w,
- (m20 - m02) * inv4w,
- (m01 - m10) * inv4w,
- four_wsq * inv4w,
- )
- }
- }
- }
-
- fn to_axis_angle(self) -> (XYZ<T>, T) {
- // const EPSILON: f32 = 1.0e-8;
- // const EPSILON_SQUARED: f32 = EPSILON * EPSILON;
- let (x, y, z, w) = Vector4::into_tuple(self);
- let angle = w.acos_approx() * T::TWO;
- let scale_sq = NumEx::max(T::ONE - w * w, T::ZERO);
- // TODO: constants for epslions?
- if scale_sq >= T::from_f32(1.0e-8 * 1.0e-8) {
- (XYZ { x, y, z }.mul_scalar(scale_sq.sqrt().recip()), angle)
- } else {
- (Vector3Const::X, angle)
- }
- }
-
- #[inline]
- fn is_near_identity(self) -> bool {
- // Based on https://github.com/nfrechette/rtm `rtm::quat_near_identity`
- let threshold_angle = T::from_f64(0.002_847_144_6);
- // Because of floating point precision, we cannot represent very small rotations.
- // The closest f32 to 1.0 that is not 1.0 itself yields:
- // 0.99999994.acos() * 2.0 = 0.000690533954 rad
- //
- // An error threshold of 1.e-6 is used by default.
- // (1.0 - 1.e-6).acos() * 2.0 = 0.00284714461 rad
- // (1.0 - 1.e-7).acos() * 2.0 = 0.00097656250 rad
- //
- // We don't really care about the angle value itself, only if it's close to 0.
- // This will happen whenever quat.w is close to 1.0.
- // If the quat.w is close to -1.0, the angle will be near 2*PI which is close to
- // a negative 0 rotation. By forcing quat.w to be positive, we'll end up with
- // the shortest path.
- let positive_w_angle = self.as_ref_xyzw().w.abs().acos_approx() * T::TWO;
- positive_w_angle < threshold_angle
- }
-
- fn conjugate(self) -> Self;
- fn lerp(self, end: Self, s: T) -> Self;
- fn slerp(self, end: Self, s: T) -> Self;
- fn mul_quaternion(self, other: Self) -> Self;
- fn mul_vector3(self, other: XYZ<T>) -> XYZ<T>;
- fn mul_float4_as_vector3(self, other: Self::SIMDVector3) -> Self::SIMDVector3;
-}