re_types/datatypes/
rotation_axis_angle_ext.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
use super::RotationAxisAngle;

use crate::datatypes::{Angle, Vec3D};

impl RotationAxisAngle {
    /// The identity rotation, representing no rotation.
    pub const IDENTITY: Self = Self {
        axis: Vec3D([1.0, 0.0, 0.0]), // Might as well use a zero vector here, but putting in the X axis is less error prone.
        angle: Angle::ZERO,
    };

    /// Create a new rotation from an axis and an angle.
    #[inline]
    pub fn new(axis: impl Into<Vec3D>, angle: impl Into<Angle>) -> Self {
        Self {
            axis: axis.into(),
            angle: angle.into(),
        }
    }
}

impl<V: Into<Vec3D>, A: Into<Angle>> From<(V, A)> for RotationAxisAngle {
    fn from((axis, angle): (V, A)) -> Self {
        Self::new(axis, angle)
    }
}

#[cfg(feature = "glam")]
impl From<RotationAxisAngle> for glam::Quat {
    #[inline]
    fn from(val: RotationAxisAngle) -> Self {
        let axis: glam::Vec3 = val.axis.into();
        axis.try_normalize()
            .map(|axis| Self::from_axis_angle(axis, val.angle.radians()))
            .unwrap_or_default()
    }
}

#[cfg(feature = "mint")]
impl From<RotationAxisAngle> for mint::Quaternion<f32> {
    #[inline]
    fn from(val: RotationAxisAngle) -> Self {
        let (s, c) = (val.angle.radians() * 0.5).sin_cos();
        [val.axis.x() * s, val.axis.y() * s, val.axis.z() * s, c].into()
    }
}

impl Default for RotationAxisAngle {
    #[inline]
    fn default() -> Self {
        Self::IDENTITY
    }
}