feo_math/rotation/
axes.rs

1//! You can represent a rotation through the rotation of axes.
2//! 
3//! TODO: explain
4//! 
5use std::{fmt, ops::{Add, Div, Mul, Neg, Sub}};
6use crate::{F32Fmt, One, Two, Zero, linear_algebra::{matrix3::Matrix3, vector3::Vector3}, rotation::quaternion::Quaternion};
7
8use super::{euler::Euler, rotor::Rotor};
9
10pub static NORMAL_X_AXIS: Vector3<f32>  = Vector3( 1.0,  0.0,  0.0);
11pub static NORMAL_Y_AXIS: Vector3<f32>  = Vector3( 0.0,  1.0,  0.0);
12pub static NORMAL_Z_AXIS: Vector3<f32>  = Vector3( 0.0,  0.0,  1.0);
13
14pub static VULKANO_Y_AXIS: Vector3<f32> = Vector3( 0.0, -1.0,  0.0);
15
16#[derive(Clone, Copy)]
17pub struct Axes<T>{
18    pub x: Vector3<T>, // left
19    pub y: Vector3<T>, // up
20    pub z: Vector3<T>  // frd or forward
21}
22
23impl<T> Axes<T> {
24    /// Returns a set of axes calculated using the passed in x and z axes
25    /// # Arguments
26    /// * `left` - The x axis represented by a Vector3
27    /// * `frd` - The z axis represented by a Vector3
28    pub fn from_left_frd(left: Vector3<T>, frd: Vector3<T>) -> Self 
29    where T: Add<T, Output = T> + Sub<T, Output = T> + Mul<T, Output = T> + Div<T, Output = T> + F32Fmt + Copy{
30        let up = Vector3::cross_product(frd, left);
31
32        let rot_mat =  Matrix3{
33            m: [
34                left.into(),
35                up.into(),
36                frd.into()
37            ]
38        }.transpose();
39        
40        rot_mat.into()
41    }
42
43    /// Returns a set of axes calculated using the passed in y and z axes
44    /// # Arguments
45    /// * `up` - The y axis represented by a Vector3
46    /// * `frd` - The z axis represented by a Vector3
47    pub fn from_up_frd(up: Vector3<T>, frd: Vector3<T>) -> Self 
48    where T: Add<T, Output = T> + Sub<T, Output = T> + Mul<T, Output = T> + Div<T, Output = T> + F32Fmt + Copy {
49        let left = Vector3::cross_product(up, frd);
50
51        let rot_mat = Matrix3{
52            m: [
53                left.into(),
54                up.into(),
55                frd.into()
56            ]
57        }.transpose(); // not needed TODO
58        
59        rot_mat.into()
60    }
61
62    /// Returns a set of axes calculated using the passed in x and y axes
63    /// # Arguments
64    /// * `left` - The x axis represented by a Vector3
65    /// * `up` - The y axis represented by a Vector3
66    pub fn from_left_up(left: Vector3<T>, up: Vector3<T>) -> Self 
67    where T: Add<T, Output = T> + Sub<T, Output = T> + Mul<T, Output = T> + Div<T, Output = T> + F32Fmt + Copy {
68        let frd = Vector3::cross_product(left, up);
69
70        let rot_mat = Matrix3{
71            m: [
72                left.into(),
73                up.into(),
74                frd.into()
75            ]
76        }.transpose();
77        
78        rot_mat.into()
79    }
80}
81
82impl<T> fmt::Debug for Axes<T>
83where T: fmt::Debug + Copy {
84    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
85        write!(f, "Axes: 
86                 \n   x: {:?} 
87                 \n   y: {:?} 
88                 \n   z: {:?}", self.x, self.y, self.z)
89    }
90}
91
92impl<T> From<Quaternion<T>> for Axes<T>
93where T: Add<T, Output = T> + Sub<T, Output = T> + Mul<T, Output = T> + Div<T, Output = T> + Neg<Output = T> + F32Fmt + fmt::Debug + One + Two + Zero + Copy{
94    fn from(q: Quaternion<T>) -> Self {
95        Axes::from(Into::<Matrix3<T>>::into(q))
96    }
97}
98
99impl<T> From<Euler<T>> for Axes<T> 
100where T: Mul<T, Output = T> + Div<T, Output = T> + F32Fmt + Add<T, Output = T> + Copy {
101    fn from(e: Euler<T>) -> Self {
102        Axes::from(Into::<Matrix3<T>>::into(e))
103    }
104}
105
106impl<T> From<Rotor<T>> for Axes<T> 
107where T: Mul<T, Output = T> + Div<T, Output = T> + F32Fmt + Add<T, Output = T> + Copy {
108    fn from(r: Rotor<T>) -> Self {
109        Axes::from(Into::<Matrix3<T>>::into(r))
110    }
111}
112
113impl<T> From<Matrix3<T>> for Axes<T>
114where T: Mul<T, Output = T> + Div<T, Output = T> + F32Fmt + Add<T, Output = T> + Copy {
115    
116        // so the transposed rotation matrix is:
117        // [  left ]
118        // [  up   ] 
119        // [  frd  ]
120
121    fn from(mat: Matrix3<T>) -> Self {
122        let mat = mat.transpose();
123        Axes {
124            x: Vector3::from(mat.m[0]).normalize(None),
125            y: Vector3::from(mat.m[1]).normalize(None),
126            z: Vector3::from(mat.m[2]).normalize(None),
127        }
128    }
129}
130
131impl<T> From<Axes<T>> for Matrix3<T> 
132where T: Copy {
133    fn from(other: Axes<T>) -> Matrix3<T> {
134        Matrix3::new(
135            other.x.into(),
136            other.y.into(),
137            other.z.into(),
138        ).transpose()
139    }
140}