ewq/quat/
rot.rs

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    /// Vector part.
15    v: Vec3<F>,
16    /// Scalar part.
17    w: F,
18}
19
20impl<F> Quat<F>
21where
22    F: Float,
23{
24    /// Creates new quaternion.
25    #[inline]
26    pub fn new(v: Vec3<F>, w: F) -> Self {
27        Self { v, w }
28    }
29
30    /// Creates new quaternion with `v` as vector part and `0` for scalar.
31    #[inline]
32    pub fn new_vector(v: Vec3<F>) -> Self {
33        Self { v, w: F::zero() }
34    }
35
36    /// Creates new quaternion that represents a rotation around `axis` by `angle` radians.
37    /// Method can accept denormalized input.
38    #[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    /// Creates new quaternion that represents a rotation that moves vector `from` to vector `to`.
47    #[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    /// Recovers angle axis representation of the quaternion.
55    #[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    /// Rotates vector `v` by the rotation defined by this quaternion.
64    #[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    /// Creates new zero quaternion.
72    #[inline]
73    pub fn zero() -> Self {
74        Self {
75            w: F::zero(),
76            v: Vec3::zero(),
77        }
78    }
79
80    /// Creates new identity quaternion.
81    #[inline]
82    pub fn idenitity() -> Self {
83        Self {
84            w: F::one(),
85            v: Vec3::zero(),
86        }
87    }
88
89    /// Creates new quaternion from individual parts.
90    #[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    /// Computes the conjugate of the quaternion.
99    #[inline]
100    pub fn conjugate(&self) -> Self {
101        Self {
102            v: -self.v,
103            w: self.w,
104        }
105    }
106
107    /// Computes the norm of the quaternion.
108    #[inline]
109    pub fn norm(&self) -> F {
110        F::sqrt(self.sqrt_norm())
111    }
112
113    /// Computes the squared norm of the quaternion.
114    #[inline]
115    pub fn sqrt_norm(&self) -> F {
116        self.v.sqrt_magnitude() + self.w * self.w
117    }
118
119    /// Normalizes quaternion preserving direction but reducing its norm to `1`.
120    #[inline]
121    pub fn normalize(&self) -> Self {
122        *self / self.norm()
123    }
124
125    /// Computes the reciprocal of the quaternion.
126    #[inline]
127    pub fn reciprocal(&self) -> Self {
128        self.conjugate() / self.sqrt_norm()
129    }
130
131    /// Combines two rotations. Applying `self` first and then `other.
132    #[inline]
133    pub fn combine(self, other: Self) -> Self {
134        other.product(self)
135    }
136
137    /// Computes the hamilton product between two vectors.
138    #[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}