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
use crate::Vec3;
use auto_ops::*;
#[derive(Debug, Clone, Copy, PartialEq)]
#[repr(C)]
pub struct Quaternion {
pub x: f32,
pub y: f32,
pub z: f32,
pub w: f32,
}
impl Default for Quaternion {
fn default() -> Self {
Self::identity()
}
}
impl Quaternion {
pub fn new(x: f32, y: f32, z: f32, w: f32) -> Self {
Self{x, y, z, w}
}
pub fn identity() -> Self {
Self{x: 0.0, y: 0.0, z: 0.0, w: 1.0}
}
pub fn axis_angle(mut axis: Vec3, radians: f32) -> Self {
axis.normalize();
axis *= (radians * 0.5).sin();
Self {
x: axis.x,
y: axis.y,
z: axis.z,
w: (radians * 0.5).cos(),
}
}
pub fn right(&self) -> Vec3 {
Vec3 {
x: self.x * self.x - self.y * self.y - self.z * self.z + self.w * self.w,
y: 2.0 * (self.z * self.w + self.x * self.y),
z: 2.0 * (self.x * self.z - self.y * self.w),
}
}
pub fn up(&self) -> Vec3 {
Vec3 {
x: 2.0 * (self.x * self.y - self.z * self.w),
y: -self.x * self.x + self.y * self.y - self.z * self.z + self.w * self.w,
z: 2.0 * (self.x * self.w + self.y * self.z),
}
}
pub fn forward(&self) -> Vec3 {
Vec3 {
x: 2.0 * (self.x * self.z + self.y * self.w),
y: 2.0 * (self.y * self.z - self.x * self.w),
z: -self.x * self.x - self.y * self.y + self.z * self.z + self.w * self.w,
}
}
}
impl_op_ex!(* |a: &Quaternion, b: &Quaternion| -> Quaternion { Quaternion {
x: a.w * b.x + a.x * b.w + a.y * b.z - a.z * b.y,
y: a.w * b.y + a.y * b.w + a.z * b.x - a.x * b.z,
z: a.w * b.z + a.z * b.w + a.x * b.y - a.y * b.x,
w: a.w * b.w - a.x * b.x - a.y * b.y - a.z * b.z,
} });
impl_op_ex!(* |a: &Quaternion, b: &Vec3| -> Vec3 {
let x2 = a.x * a.x;
let y2 = a.y * a.y;
let z2 = a.z * a.z;
let w2 = a.w * a.w;
let xx = a.x * b.x;
let yy = a.y * b.y;
let zz = a.z * b.z;
Vec3 {
x: b.x * (x2 - y2 - z2 + w2) + 2.0 * (a.x * yy + a.x * zz + a.w * a.y * b.z - a.w * a.z * b.y),
y: b.y * (-x2 + y2 - z2 + w2) + 2.0 * (a.y * xx + a.y * zz + a.w * a.z * b.x - a.w * a.x * b.z),
z: b.z * (-x2 - y2 + z2 + w2) + 2.0 * (a.z * xx + a.z * yy + a.w * a.x * b.y - a.w * a.y * b.x),
}
});
impl_op_ex!(- |a: &Quaternion| -> Quaternion {
Quaternion {
x: -a.x,
y: -a.y,
z: -a.z,
w: a.w,
}
});