1use crate::vec::Vec3;
2use num_traits::Float;
3use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Sub, SubAssign};
4
5pub type Quatf = Quat<f32>;
6pub type Quatd = Quat<f64>;
7
8#[derive(Debug, PartialEq, Default, Clone, Copy)]
9#[repr(C)]
10pub struct Quat<F>
11where
12 F: Float,
13{
14 v: Vec3<F>,
16 w: F,
18}
19
20impl<F> Quat<F>
21where
22 F: Float,
23{
24 #[inline]
26 pub fn new(v: Vec3<F>, w: F) -> Self {
27 Self { v, w }
28 }
29
30 #[inline]
32 pub fn new_vector(v: Vec3<F>) -> Self {
33 Self { v, w: F::zero() }
34 }
35
36 #[inline]
39 pub fn new_axis_rotation(axis: Vec3<F>, angle: F) -> Self {
40 Self {
41 v: axis.normalized() * angle.div(F::from(2).unwrap()).sin(),
42 w: angle.div(F::from(2).unwrap()).cos(),
43 }
44 }
45
46 #[inline]
48 pub fn new_dst_rotation(from: Vec3<F>, to: Vec3<F>) -> Self {
49 let normal = from.cross(to);
50 let angle = to.dot_normalized(from).acos();
51 Self::new_axis_rotation(normal, angle)
52 }
53
54 #[inline]
56 pub fn into_axis_angle(self) -> (Vec3<F>, F) {
57 (
58 self.v.normalized(),
59 F::atan2(self.v.magnitude(), self.w) * F::from(2).unwrap(),
60 )
61 }
62
63 #[inline]
65 pub fn rotate(&self, v: Vec3<F>) -> Vec3<F> {
66 self.product(Self::new_vector(v))
67 .product(self.reciprocal())
68 .v
69 }
70
71 #[inline]
73 pub fn zero() -> Self {
74 Self {
75 w: F::zero(),
76 v: Vec3::zero(),
77 }
78 }
79
80 #[inline]
82 pub fn idenitity() -> Self {
83 Self {
84 w: F::one(),
85 v: Vec3::zero(),
86 }
87 }
88
89 #[inline]
91 pub fn from_parts(x: F, y: F, z: F, w: F) -> Self {
92 Self {
93 v: Vec3 { x, y, z },
94 w,
95 }
96 }
97
98 #[inline]
100 pub fn conjugate(&self) -> Self {
101 Self {
102 v: -self.v,
103 w: self.w,
104 }
105 }
106
107 #[inline]
109 pub fn norm(&self) -> F {
110 F::sqrt(self.sqrt_norm())
111 }
112
113 #[inline]
115 pub fn sqrt_norm(&self) -> F {
116 self.v.sqrt_magnitude() + self.w * self.w
117 }
118
119 #[inline]
121 pub fn normalize(&self) -> Self {
122 *self / self.norm()
123 }
124
125 #[inline]
127 pub fn reciprocal(&self) -> Self {
128 self.conjugate() / self.sqrt_norm()
129 }
130
131 #[inline]
133 pub fn combine(self, other: Self) -> Self {
134 other.product(self)
135 }
136
137 #[inline]
139 pub fn product(&self, other: Self) -> Self {
140 Self {
141 v: Vec3 {
142 x: self.w * other.v.x + self.v.x * other.w + self.v.y * other.v.z
143 - self.v.z * other.v.y,
144 y: self.w * other.v.y - self.v.x * other.v.z
145 + self.v.y * other.w
146 + self.v.z * other.v.x,
147 z: self.w * other.v.z + self.v.x * other.v.y - self.v.y * other.v.x
148 + self.v.z * other.w,
149 },
150 w: self.w * other.w
151 - self.v.x * other.v.x
152 - self.v.y * other.v.y
153 - self.v.z * other.v.z,
154 }
155 }
156}
157
158impl<F> Add for Quat<F>
159where
160 F: Float,
161{
162 type Output = Self;
163
164 #[inline]
165 fn add(self, rhs: Self) -> Self::Output {
166 Self {
167 v: self.v + rhs.v,
168 w: self.w + rhs.w,
169 }
170 }
171}
172
173impl<F> AddAssign for Quat<F>
174where
175 F: Float,
176{
177 #[inline]
178 fn add_assign(&mut self, rhs: Self) {
179 self.v = self.v + rhs.v;
180 self.w = self.w + rhs.w;
181 }
182}
183
184impl<F> Sub for Quat<F>
185where
186 F: Float,
187{
188 type Output = Self;
189
190 #[inline]
191 fn sub(self, rhs: Self) -> Self::Output {
192 Self {
193 v: self.v - rhs.v,
194 w: self.w - rhs.w,
195 }
196 }
197}
198
199impl<F> SubAssign for Quat<F>
200where
201 F: Float,
202{
203 #[inline]
204 fn sub_assign(&mut self, rhs: Self) {
205 self.v = self.v - rhs.v;
206 self.w = self.w - rhs.w;
207 }
208}
209
210impl<F> Mul<F> for Quat<F>
211where
212 F: Float,
213{
214 type Output = Self;
215
216 #[inline]
217 fn mul(self, rhs: F) -> Self::Output {
218 Self {
219 v: self.v * rhs,
220 w: self.w * rhs,
221 }
222 }
223}
224
225impl<F> MulAssign<F> for Quat<F>
226where
227 F: Float,
228{
229 #[inline]
230 fn mul_assign(&mut self, rhs: F) {
231 self.v = self.v * rhs;
232 self.w = self.w * rhs;
233 }
234}
235
236impl<F> Div<F> for Quat<F>
237where
238 F: Float,
239{
240 type Output = Self;
241
242 #[inline]
243 fn div(self, rhs: F) -> Self::Output {
244 Self {
245 v: self.v / rhs,
246 w: self.w / rhs,
247 }
248 }
249}
250
251impl<F> DivAssign<F> for Quat<F>
252where
253 F: Float,
254{
255 #[inline]
256 fn div_assign(&mut self, rhs: F) {
257 self.v = self.v / rhs;
258 self.w = self.w / rhs;
259 }
260}