1use core::ops::{Mul, MulAssign};
31
32use crate::matrix::TMat4x4;
33use crate::traits::CrossProduct;
34use crate::traits::DotProduct;
35use crate::traits::Inverse;
36use crate::traits::InverseAssign;
37use crate::traits::Length;
38use crate::traits::Normalize;
39use crate::traits::NormalizeAssign;
40use crate::traits::Real;
41use crate::vector::TVec3;
42
43#[repr(align(16))]
44#[derive(Copy, Clone, Debug)]
45pub struct TQuat<T: Real> {
46 data: [T; 4],
47}
48
49impl<T: Real> TQuat<T> {
50 #[inline]
54 pub fn new(scalar: T, vector: TVec3<T>) -> Self {
55 let data = [vector[0], vector[1], vector[2], scalar];
56 TQuat { data }
57 }
58
59 #[inline]
63 pub fn identity() -> Self {
64 Self::new(T::one(), [T::zero(), T::zero(), T::zero()].into())
65 }
66
67 #[inline]
71 pub fn from_euler_angles(angles: TVec3<T>) -> Self {
72 let two = T::one() + T::one();
73 let half_angles: TVec3<T> = angles / two;
74 let sin_x = half_angles[0].sin();
75 let cos_x = half_angles[0].cos();
76 let sin_y = half_angles[1].sin();
77 let cos_y = half_angles[1].cos();
78 let sin_z = half_angles[2].sin();
79 let cos_z = half_angles[2].cos();
80 let vector = TVec3::<T>::new(
81 sin_x * cos_y * cos_z - cos_x * sin_y * sin_z,
82 cos_x * sin_y * cos_z + sin_x * cos_y * sin_z,
83 cos_x * cos_y * sin_z - sin_x * sin_y * cos_z,
84 );
85 let scalar = cos_x * cos_y * cos_z + sin_x * sin_y * sin_z;
86 Self::new(scalar, vector)
87 }
88
89 #[inline]
90 pub fn from_angle_axis(angle: T, axis: TVec3<T>) -> TQuat<T> {
91 let two = T::one() + T::one();
92
93 let half_angle: T = angle / two;
94
95 TQuat::<T>::new(half_angle.cos(), axis.normalize() * half_angle.sin())
96 }
97
98 #[inline]
102 pub fn as_angle_axis(&self) -> (T, TVec3<T>) {
103 let axis = if self.scalar() > T::zero() {
104 self.vector()
105 } else {
106 -self.vector()
107 };
108 let axis = axis.normalize();
109 let two = T::one() + T::one();
110 let angle = two
111 * T::atan2(
112 axis.length(),
113 if self.scalar() > T::zero() {
114 self.scalar()
115 } else {
116 -self.scalar()
117 },
118 );
119 (angle, axis)
120 }
121
122 pub fn conjugate(&self) -> TQuat<T> {
126 TQuat::<T>::new(self.scalar(), -self.vector())
127 }
128
129 #[inline]
133 pub fn scalar(&self) -> T {
134 self.data[3]
135 }
136
137 #[inline]
141 pub fn scalar_mut(&mut self) -> &mut T {
142 &mut self.data[3]
143 }
144
145 #[inline]
149 pub fn vector(&self) -> TVec3<T> {
150 TVec3::<T>::new(self.data[0], self.data[1], self.data[2])
151 }
152}
153
154impl<T: Real> Mul<TQuat<T>> for TQuat<T> {
155 type Output = TQuat<T>;
156
157 #[inline]
158 fn mul(mut self, rhs: TQuat<T>) -> Self::Output {
159 self.mul_assign(rhs);
160 self
161 }
162}
163
164impl<T: Real> MulAssign<TQuat<T>> for TQuat<T> {
165 #[inline]
166 fn mul_assign(&mut self, rhs: TQuat<T>) {
167 let lhs_scalar = self.scalar();
168 let rhs_scalar = rhs.scalar();
169 let lhs_vector = self.vector();
170 let rhs_vector = rhs.vector();
171 self.data[3] = (rhs_scalar * lhs_scalar) - (lhs_vector.dot(&rhs_vector));
172 let vector =
173 (rhs_vector * lhs_scalar) + (lhs_vector * rhs_scalar) + lhs_vector.cross(&rhs_vector);
174 self.data[0] = vector[0];
175 self.data[1] = vector[1];
176 self.data[2] = vector[2];
177 }
178}
179
180impl<T: Real> Mul<TVec3<T>> for TQuat<T> {
181 type Output = TVec3<T>;
182
183 #[inline]
184 #[allow(clippy::suspicious_arithmetic_impl)]
185 fn mul(self, rhs: TVec3<T>) -> Self::Output {
186 let two = T::one() + T::one();
187 let t = self.vector().cross(&rhs) * two;
188 rhs + (t * self.scalar()) + self.vector().cross(&t)
189 }
190}
191
192impl<T: Real> Inverse for TQuat<T> {
193 #[inline]
194 fn inverse(mut self) -> Self {
195 self.inverse_assign();
196 self
197 }
198}
199
200impl<T: Real> InverseAssign for TQuat<T> {
201 #[inline]
202 fn inverse_assign(&mut self) {
203 self.data[0] = -self.data[0];
204 self.data[1] = -self.data[1];
205 self.data[2] = -self.data[2];
206 }
207}
208
209impl<T: Real> Normalize for TQuat<T> {
210 #[inline]
211 fn normalize(mut self) -> Self {
212 self.normalize_assign();
213 self
214 }
215}
216
217impl<T: Real> NormalizeAssign for TQuat<T> {
218 #[inline]
219 fn normalize_assign(&mut self) {
220 let len: T = (self.scalar() * self.scalar() + self.vector().dot(&self.vector())).sqrt();
221 let len: T = T::one() / len;
222 *self.scalar_mut() *= len;
223 let vector = self.vector() * len;
224 self.data[0] = vector[0];
225 self.data[1] = vector[1];
226 self.data[2] = vector[2];
227 }
228}
229
230impl<T: Real> Into<TMat4x4<T>> for TQuat<T> {
231 fn into(self) -> TMat4x4<T> {
232 let mut result = TMat4x4::<T>::identity();
233
234 let two = T::one() + T::one();
235
236 let qxx = self.data[0] * self.data[0];
237 let qyy = self.data[1] * self.data[1];
238 let qzz = self.data[2] * self.data[2];
239 let qxz = self.data[0] * self.data[2];
240 let qxy = self.data[0] * self.data[1];
241 let qyz = self.data[1] * self.data[2];
242 let qwx = self.data[3] * self.data[0];
243 let qwy = self.data[3] * self.data[1];
244 let qwz = self.data[3] * self.data[2];
245
246 result[(0, 0)] = T::one() - two * (qyy + qzz);
247 result[(1, 0)] = two * (qxy + qwz);
248 result[(2, 0)] = two * (qxz - qwy);
249
250 result[(0, 1)] = two * (qxy - qwz);
251 result[(1, 1)] = T::one() - two * (qxx + qzz);
252 result[(2, 1)] = two * (qyz + qwx);
253
254 result[(0, 2)] = two * (qxz + qwy);
255 result[(1, 2)] = two * (qyz - qwx);
256 result[(2, 2)] = T::one() - two * (qxx + qyy);
257
258 result
259 }
260}