1use derive_cmp_ops::{CmpAdd, CmpAddAssign, CmpNeg, CmpSub, CmpSubAssign};
2
3use crate::vectors::{Vec3, Vec4, DVec4, DVec3};
4
5#[derive(Clone, Copy, CmpAdd, CmpSub, CmpAddAssign, CmpSubAssign, CmpNeg, Debug, PartialEq)]
6pub struct Quat{
9 pub r: f32,
10 pub i: f32,
11 pub j: f32,
12 pub k: f32
13}
14impl Quat{
15 pub const IDENTITY: Self = Self { r: 1.0, i: 0.0, j: 0.0, k: 0.0 };
16 pub fn from_x_rot(angle: f32) -> Self{
18 let a = angle / 2.0;
19 Self { r: a.cos(), i: a.sin(), j: 0.0, k: 0.0 }
20 }
21 pub fn from_y_rot(angle: f32) -> Self{
23 let a = angle / 2.0;
24 Self { r: a.cos(), i: 0.0, j: a.sin(), k: 0.0 }
25 }
26 pub fn from_z_rot(angle: f32) -> Self{
28 let a = angle / 2.0;
29 Self { r: a.cos(), i: 0.0, j: 0.0, k: a.sin() }
30 }
31 pub fn from_axis_rot(angle: f32, axis: Vec3) -> Self{
33 let a = angle / 2.0;
34 Self{
35 r: a.cos(),
36 i: a.sin() * axis.x,
37 j: a.sin() * axis.y,
38 k: a.sin() * axis.z,
39 }
40 }
41 pub fn inverse(self) -> Self {
43 let Quat { r, i, j, k } = self;
44 if r == 0.0 && i == 0.0 && j == 0.0 && k == 0.0 {
45 panic!("tried to get inverse of zero quaternion");
46 }
47 let scalar = r*r + i*i + j*j + k*k;
48 Self {
49 r: r / scalar,
50 i: -i / scalar,
51 j: -j / scalar,
52 k: -k / scalar
53 }
54 }
55}
56impl From<Vec4> for Quat {
57 fn from(value: Vec4) -> Self {
58 Self { r: value.x, i: value.y, j: value.z, k: value.w }
59 }
60}
61impl From<DQuat> for Quat {
62 fn from(value: DQuat) -> Self {
63 Self { r: value.r as f32, i: value.i as f32, j: value.j as f32, k: value.k as f32 }
64 }
65}
66impl std::ops::Mul<Quat> for f32 {
67 fn mul(self, rhs: Quat) -> Self::Output {
68 Quat {
69 r: rhs.r * self,
70 i: rhs.i * self,
71 j: rhs.j * self,
72 k: rhs.k * self
73 }
74 }
75 type Output = Quat;
76}
77impl std::ops::Mul<f32> for Quat {
78 fn mul(self, rhs: f32) -> Self::Output {
79 Self {
80 r: self.r * rhs,
81 i: self.i * rhs,
82 j: self.j * rhs,
83 k: self.k * rhs
84 }
85 }
86 type Output = Self;
87}
88impl std::ops::MulAssign<f32> for Quat { fn mul_assign(&mut self, rhs: f32) { *self = *self * rhs } }
89impl std::ops::Rem<Quat> for f32 {
90 fn rem(self, rhs: Quat) -> Self::Output {
91 Quat {
92 r: rhs.r % self,
93 i: rhs.i % self,
94 j: rhs.j % self,
95 k: rhs.k % self
96 }
97 }
98 type Output = Quat;
99}
100impl std::ops::Rem<f32> for Quat {
101 fn rem(self, rhs: f32) -> Self::Output {
102 Self {
103 r: self.r % rhs,
104 i: self.i % rhs,
105 j: self.j % rhs,
106 k: self.k % rhs
107 }
108 }
109 type Output = Self;
110}
111impl std::ops::RemAssign<f32> for Quat { fn rem_assign(&mut self, rhs: f32) { *self = *self % rhs } }
112impl std::ops::Div<Quat> for f32 {
113 fn div(self, rhs: Quat) -> Self::Output {
114 Quat {
115 r: rhs.r / self,
116 i: rhs.i / self,
117 j: rhs.j / self,
118 k: rhs.k / self
119 }
120 }
121 type Output = Quat;
122}
123impl std::ops::Div<f32> for Quat {
124 fn div(self, rhs: f32) -> Self::Output { self * (1.0/rhs) }
125 type Output = Self;
126}
127impl std::ops::DivAssign<f32> for Quat { fn div_assign(&mut self, rhs: f32) { *self = *self / rhs } }
128impl std::ops::Mul for Quat {
129 fn mul(self, rhs: Self) -> Self::Output {
130 let a = self;
131 let b = rhs;
132 Self {
133 r: a.r*b.r - a.i*b.i - a.j*b.j - a.k*b.k,
134 i: a.r*b.i + a.i*b.r + a.j*b.k - a.k*b.j,
135 j: a.r*b.j - a.i*b.k + a.j*b.r + a.k*b.i,
136 k: a.r*b.k + a.i*b.j - a.j*b.i + a.k*b.r
137 }
138 }
139 type Output = Self;
140}
141impl std::ops::MulAssign for Quat { fn mul_assign(&mut self, rhs: Self) { *self = *self * rhs } }
142#[allow(clippy::suspicious_arithmetic_impl)]
143impl std::ops::Div for Quat {
144 fn div(self, rhs: Self) -> Self::Output { self * rhs.inverse() }
145 type Output = Self;
146}
147impl std::ops::DivAssign for Quat { fn div_assign(&mut self, rhs: Self) { *self = *self / rhs } }
148#[test]
149fn quaternion_inverse() {
150 let a = Quat::from_x_rot(3.0);
151 let inv_a = a.inverse();
152 assert!(a * inv_a == Quat { r: 1.0, i: 0.0, j: 0.0, k: 0.0 });
153}
154
155#[derive(Clone, Copy, CmpAdd, CmpSub, CmpAddAssign, CmpSubAssign, CmpNeg, Debug, PartialEq)]
156pub struct DQuat {
159 pub r: f64,
160 pub i: f64,
161 pub j: f64,
162 pub k: f64
163}
164impl DQuat {
165 pub const IDENTITY: Self = Self { r: 1.0, i: 0.0, j: 0.0, k: 0.0 };
166 pub fn from_x_rot(angle: f64) -> Self {
168 let a = angle / 2.0;
169 Self { r: a.cos(), i: a.sin(), j: 0.0, k: 0.0 }
170 }
171 pub fn from_y_rot(angle: f64) -> Self {
173 let a = angle / 2.0;
174 Self { r: a.cos(), i: 0.0, j: a.sin(), k: 0.0 }
175 }
176 pub fn from_z_rot(angle: f64) -> Self {
178 let a = angle / 2.0;
179 Self { r: a.cos(), i: 0.0, j: 0.0, k: a.sin() }
180 }
181 pub fn from_axis_rot(angle: f64, axis: DVec3) -> Self {
183 let a = angle / 2.0;
184 Self{
185 r: a.cos(),
186 i: a.sin() * axis.x,
187 j: a.sin() * axis.y,
188 k: a.sin() * axis.z,
189 }
190 }
191 pub fn inverse(self) -> Self {
193 let DQuat { r, i, j, k } = self;
194 if r == 0.0 && i == 0.0 && j == 0.0 && k == 0.0 {
195 panic!("tried to get inverse of zero quaternion");
196 }
197 let scalar = r*r + i*i + j*j + k*k;
198 Self {
199 r: r / scalar,
200 i: -i / scalar,
201 j: -j / scalar,
202 k: -k / scalar
203 }
204 }
205}
206impl From<DVec4> for DQuat {
207 fn from(value: DVec4) -> Self {
208 Self { r: value.x, i: value.y, j: value.z, k: value.w }
209 }
210}
211impl From<Quat> for DQuat {
212 fn from(value: Quat) -> Self {
213 Self { r: value.r as f64, i: value.i as f64, j: value.j as f64, k: value.k as f64 }
214 }
215}
216#[test]
217fn dquaternion_inverse() {
218 let a = DQuat::from_x_rot(3.0);
219 let inv_a = a.inverse();
220 assert!(a * inv_a == DQuat { r: 1.0, i: 0.0, j: 0.0, k: 0.0 });
221}
222
223impl std::ops::Mul<DQuat> for f64 {
224 fn mul(self, rhs: DQuat) -> Self::Output {
225 DQuat {
226 r: rhs.r * self,
227 i: rhs.i * self,
228 j: rhs.j * self,
229 k: rhs.k * self
230 }
231 }
232 type Output = DQuat;
233}
234impl std::ops::Mul<f64> for DQuat {
235 fn mul(self, rhs: f64) -> Self::Output {
236 Self {
237 r: self.r * rhs,
238 i: self.i * rhs,
239 j: self.j * rhs,
240 k: self.k * rhs
241 }
242 }
243 type Output = Self;
244}
245impl std::ops::MulAssign<f64> for DQuat { fn mul_assign(&mut self, rhs: f64) { *self = *self * rhs } }
246impl std::ops::Rem<DQuat> for f64 {
247 fn rem(self, rhs: DQuat) -> Self::Output {
248 DQuat {
249 r: rhs.r % self,
250 i: rhs.i % self,
251 j: rhs.j % self,
252 k: rhs.k % self
253 }
254 }
255 type Output = DQuat;
256}
257impl std::ops::Rem<f64> for DQuat {
258 fn rem(self, rhs: f64) -> Self::Output {
259 Self {
260 r: self.r % rhs,
261 i: self.i % rhs,
262 j: self.j % rhs,
263 k: self.k % rhs
264 }
265 }
266 type Output = Self;
267}
268impl std::ops::RemAssign<f64> for DQuat { fn rem_assign(&mut self, rhs: f64) { *self = *self % rhs } }
269impl std::ops::Div<DQuat> for f64 {
270 fn div(self, rhs: DQuat) -> Self::Output {
271 DQuat {
272 r: rhs.r / self,
273 i: rhs.i / self,
274 j: rhs.j / self,
275 k: rhs.k / self
276 }
277 }
278 type Output = DQuat;
279}
280impl std::ops::Div<f64> for DQuat {
281 fn div(self, rhs: f64) -> Self::Output { self * (1.0/rhs) }
282 type Output = Self;
283}
284impl std::ops::DivAssign<f64> for DQuat { fn div_assign(&mut self, rhs: f64) { *self = *self / rhs } }
285impl std::ops::Mul for DQuat {
286 fn mul(self, rhs: Self) -> Self::Output {
287 let a = self;
288 let b = rhs;
289 Self {
290 r: a.r*b.r - a.i*b.i - a.j*b.j - a.k*b.k,
291 i: a.r*b.i + a.i*b.r + a.j*b.k - a.k*b.j,
292 j: a.r*b.j - a.i*b.k + a.j*b.r + a.k*b.i,
293 k: a.r*b.k + a.i*b.j - a.j*b.i + a.k*b.r
294 }
295 }
296 type Output = Self;
297}
298impl std::ops::MulAssign for DQuat { fn mul_assign(&mut self, rhs: Self) { *self = *self * rhs } }
299#[allow(clippy::suspicious_arithmetic_impl)]
300impl std::ops::Div for DQuat {
301 fn div(self, rhs: Self) -> Self::Output { self * rhs.inverse() }
302 type Output = Self;
303}
304impl std::ops::DivAssign for DQuat { fn div_assign(&mut self, rhs: Self) { *self = *self / rhs } }