1use crate::vector::Vector3;
2use crate::IntoMint;
3use core::marker::PhantomData;
4
5#[derive(Clone, Copy, Debug, Hash, PartialEq, PartialOrd, Eq, Ord)]
9#[repr(C)]
10pub struct Quaternion<T> {
11 pub v: Vector3<T>,
13 pub s: T,
15}
16
17impl<T> IntoMint for Quaternion<T> {
18 type MintType = Quaternion<T>;
19}
20
21impl<T> From<[T; 4]> for Quaternion<T> {
22 fn from([x, y, z, s]: [T; 4]) -> Self {
23 Quaternion {
24 s,
25 v: Vector3::from([x, y, z]),
26 }
27 }
28}
29
30impl<T> From<Quaternion<T>> for [T; 4] {
31 fn from(quaternion: Quaternion<T>) -> [T; 4] {
32 [quaternion.v.x, quaternion.v.y, quaternion.v.z, quaternion.s]
33 }
34}
35
36impl<T> AsRef<[T; 4]> for Quaternion<T> {
37 fn as_ref(&self) -> &[T; 4] {
38 unsafe { ::core::mem::transmute(self) }
39 }
40}
41
42impl<T> AsMut<[T; 4]> for Quaternion<T> {
43 fn as_mut(&mut self) -> &mut [T; 4] {
44 unsafe { ::core::mem::transmute(self) }
45 }
46}
47
48#[cfg(feature = "serde")]
49impl<T> ::serde::Serialize for Quaternion<T>
50where
51 T: ::serde::Serialize,
52{
53 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
54 where
55 S: ::serde::Serializer,
56 {
57 AsRef::<[T; 4]>::as_ref(self).serialize(serializer)
58 }
59}
60
61#[cfg(feature = "serde")]
62impl<'de, T> ::serde::Deserialize<'de> for Quaternion<T>
63where
64 T: ::serde::Deserialize<'de>,
65{
66 fn deserialize<S>(deserializer: S) -> Result<Self, S::Error>
67 where
68 S: ::serde::Deserializer<'de>,
69 {
70 <[T; 4]>::deserialize(deserializer).map(Quaternion::<T>::from)
71 }
72}
73
74#[derive(Clone, Copy, Debug, Hash, PartialEq, PartialOrd, Eq, Ord)]
83#[repr(C)]
84pub struct EulerAngles<T, B> {
85 pub a: T,
87 pub b: T,
89 pub c: T,
91 pub marker: PhantomData<B>,
93}
94
95#[derive(Clone, Copy, Debug, Hash, PartialEq, PartialOrd, Eq, Ord)]
97pub enum IntraXYZ {}
98#[derive(Clone, Copy, Debug, Hash, PartialEq, PartialOrd, Eq, Ord)]
100pub enum IntraZXZ {}
101#[derive(Clone, Copy, Debug, Hash, PartialEq, PartialOrd, Eq, Ord)]
103pub enum IntraZYX {}
104#[derive(Clone, Copy, Debug, Hash, PartialEq, PartialOrd, Eq, Ord)]
106pub enum ExtraXYZ {}
107#[derive(Clone, Copy, Debug, Hash, PartialEq, PartialOrd, Eq, Ord)]
109pub enum ExtraZXZ {}
110#[derive(Clone, Copy, Debug, Hash, PartialEq, PartialOrd, Eq, Ord)]
112pub enum ExtraZYX {}
113
114impl<T, B> From<[T; 3]> for EulerAngles<T, B> {
115 fn from([a, b, c]: [T; 3]) -> Self {
116 EulerAngles {
117 a,
118 b,
119 c,
120 marker: PhantomData,
121 }
122 }
123}
124
125impl<T, B> From<EulerAngles<T, B>> for [T; 3] {
126 fn from(euler: EulerAngles<T, B>) -> [T; 3] {
127 [euler.a, euler.b, euler.c]
128 }
129}
130
131#[cfg(feature = "serde")]
132impl<T, B> ::serde::Serialize for EulerAngles<T, B>
133where
134 T: ::serde::Serialize,
135{
136 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
137 where
138 S: ::serde::Serializer,
139 {
140 [&self.a, &self.b, &self.c].serialize(serializer)
141 }
142}
143
144#[cfg(feature = "serde")]
145impl<'de, T, B> ::serde::Deserialize<'de> for EulerAngles<T, B>
146where
147 T: ::serde::Deserialize<'de>,
148{
149 fn deserialize<S>(deserializer: S) -> Result<Self, S::Error>
150 where
151 S: ::serde::Deserializer<'de>,
152 {
153 <[T; 3]>::deserialize(deserializer).map(EulerAngles::<T, B>::from)
154 }
155}
156
157macro_rules! reverse {
158 ($from:ident -> $to:ident) => {
159 impl<T> From<EulerAngles<T, $from>> for EulerAngles<T, $to> {
160 fn from(other: EulerAngles<T, $from>) -> Self {
161 EulerAngles {
162 a: other.c,
163 b: other.b,
164 c: other.a,
165 marker: PhantomData,
166 }
167 }
168 }
169 };
170 ($from:ident <-> $to:ident) => {
171 reverse!($from -> $to);
172 reverse!($to -> $from);
173 };
174}
175
176reverse!(IntraXYZ <-> ExtraZYX);
177reverse!(IntraZXZ <-> ExtraZXZ);
178reverse!(IntraZYX <-> ExtraXYZ);