1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
use serde::{
Deserialize,
Serialize,
};
use crate::Vector3;
#[derive(Copy, Clone, Default, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
pub struct Quaternion {
pub x: f32,
pub y: f32,
pub z: f32,
pub w: f32,
}
impl Quaternion {
pub const IDENTITY: Self = Self {
x: 0.0,
y: 0.0,
z: 0.0,
w: 1.0,
};
pub fn from_axis_angle(axis: impl Into<Vector3>, theta: f32) -> Self {
let axis = axis.into();
let theta = theta / 2.0;
let s = theta.sin();
let c = theta.cos();
Self {
x: s * axis.x,
y: s * axis.y,
z: s * axis.z,
w: c,
}
}
pub fn from_euler(euler: impl Into<Vector3>) -> Self {
let euler = euler.into() * 0.5;
let cr = euler.x.cos();
let sr = euler.x.sin();
let cp = euler.y.cos();
let sp = euler.y.sin();
let cy = euler.z.cos();
let sy = euler.z.sin();
Self {
x: sr * cp * cy - cr * sp * sy,
y: cr * sp * cy + sr * cp * sy,
z: cr * cp * sy - sr * sp * cy,
w: cr * cp * cy + sr * sp * sy,
}
}
pub fn len_sq(self) -> f32 {
self.x * self.x + self.y * self.y + self.z * self.z + self.w * self.w
}
pub fn len(self) -> f32 {
self.len_sq().sqrt()
}
pub fn norm(self) -> Self {
let len = self.len();
if len == 0.0 {
Default::default()
} else {
let inv = 1.0 / len;
Self {
x: self.x * inv,
y: self.y * inv,
z: self.z * inv,
w: self.w * inv,
}
}
}
pub fn inverse(self) -> Self {
Self {
x: -self.x,
y: -self.y,
z: -self.z,
w: self.w,
}
}
pub fn rotate(self, xyz: Vector3) -> Vector3 {
let t = self.xyz().cross(xyz) * 2.0 * self.w;
(xyz + t) + self.xyz().cross(t)
}
pub fn forward(self) -> Vector3 {
self.rotate(Vector3::FORWARD)
}
pub fn right(self) -> Vector3 {
self.rotate(Vector3::RIGHT)
}
pub fn up(self) -> Vector3 {
self.rotate(Vector3::UP)
}
pub fn xyz(self) -> Vector3 {
Vector3 {
x: self.x,
y: self.y,
z: self.z,
}
}
}