1use num::Float;
5
6use crate::v::{TVector, v3::Vector3};
7use crate::m::{TMatrix, m4::{TM4, Matrix4}};
8
9pub trait TQuaternion<F: Float + std::fmt::Debug> {
11 fn from_axis_and_angle(v: &Vector3<F>, a: F) -> Self;
13 fn identity() -> Self;
15 fn conjugate(&self) -> Self;
17 fn me(&self) -> &Quaternion<F>;
19 fn to_m4_left(&self) -> Matrix4<F>;
21 fn to_m4_right(&self) -> Matrix4<F>;
23 fn to_m4_rot(&self) -> Matrix4<F>;
27}
28
29pub type Quaternion<F> = [F; 4];
31
32impl<F: Float + std::fmt::Debug + std::iter::Sum> TQuaternion<F> for Quaternion<F> {
34 fn from_axis_and_angle(v: &Vector3<F>, a: F) -> Self {
36 let t = a / <F>::from(2.0).unwrap();
37 let d = v.iter().map(|&p| p * p).sum::<F>().sqrt();
38 let n = v.iter().map(|&p| p / d).collect::<Vec<_>>();
39 [t.cos(), n[0] * t.sin(), n[1] * t.sin(), n[2] * t.sin()]
40 }
41 fn identity() -> Self {
43 Self::new(&(0..4).into_iter().map(|i|
44 <F>::from(if i == 0 { 1.0 } else { 0.0 }).unwrap()
45 ).collect::<Vec<_>>())
46 }
47 fn conjugate(&self) -> Self {
49 [self[0], -self[1], -self[2], -self[3]]
50 }
51 fn me(&self) -> &Quaternion<F> {
53 self
54 }
55 fn to_m4_left(&self) -> Matrix4<F> {
57 Matrix4::<F>::from_q_left(self)
58 }
59 fn to_m4_right(&self) -> Matrix4<F> {
61 Matrix4::<F>::from_p_right(self)
62 }
63 fn to_m4_rot(&self) -> Matrix4<F> {
67 let m4p = Matrix4::from_p_right(&self.conjugate());
68 let m4q = Matrix4::from_q_left(self);
69 m4q.dot_m(&m4p) }
71}