1use glam::{Quat, Vec3};
2
3#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
5pub enum SensorKind {
6 #[default]
7 None,
8 Gyroscope,
9 Accelerometer,
10 GyroscopeAccelerometer,
11}
12
13impl SensorKind {
14 pub fn has_gyroscope(self) -> bool {
15 matches!(self, Self::Gyroscope | Self::GyroscopeAccelerometer)
16 }
17
18 pub fn has_accelerometer(self) -> bool {
19 matches!(self, Self::Accelerometer | Self::GyroscopeAccelerometer)
20 }
21}
22
23#[derive(Debug, Clone, Copy, PartialEq, Default)]
25pub struct MotionSample {
26 pub acceleration: Vec3,
27 pub angular_velocity: Vec3,
28}
29
30pub trait MotionSource {
32 fn kind(&self) -> SensorKind;
33 fn sample(&self) -> Option<MotionSample>;
34}
35
36#[derive(Debug, Clone, Copy, PartialEq, Default)]
38pub struct MotionSnapshot {
39 pub kind: SensorKind,
40 pub orientation: Quat,
42 pub angular_velocity: Vec3,
43 pub acceleration: Vec3,
44}
45
46pub const GRAVITY: f32 = 9.806_65;
48
49#[derive(Debug, Clone, Copy, PartialEq)]
54pub struct MotionTracker {
55 kind: SensorKind,
56 orientation: Quat,
57 angular_velocity: Vec3,
58 acceleration: Vec3,
59}
60
61impl MotionTracker {
62 pub fn new(kind: SensorKind) -> Self {
63 Self {
64 kind,
65 orientation: Quat::IDENTITY,
66 angular_velocity: Vec3::ZERO,
67 acceleration: Vec3::ZERO,
68 }
69 }
70
71 pub fn kind(&self) -> SensorKind {
72 self.kind
73 }
74
75 pub fn integrate(&mut self, sample: MotionSample, dt_seconds: f32) {
78 if dt_seconds > 0.0 && self.kind.has_gyroscope() {
79 let spin = sample.angular_velocity * dt_seconds;
80 if spin.length_squared() > 0.0 {
81 self.orientation = (self.orientation * Quat::from_scaled_axis(spin)).normalize();
82 }
83 self.angular_velocity = sample.angular_velocity;
84 }
85 if self.kind.has_accelerometer() {
86 self.acceleration = sample.acceleration;
87 }
88 }
89
90 pub fn recenter(&mut self) {
92 self.orientation = Quat::IDENTITY;
93 self.angular_velocity = Vec3::ZERO;
94 self.acceleration = Vec3::ZERO;
95 }
96
97 pub fn orientation(&self) -> Quat {
98 self.orientation
99 }
100
101 pub fn angular_velocity(&self) -> Vec3 {
102 self.angular_velocity
103 }
104
105 pub fn acceleration(&self) -> Vec3 {
106 self.acceleration
107 }
108
109 pub fn gravity(&self) -> Vec3 {
112 self.orientation.inverse() * Vec3::new(0.0, -GRAVITY, 0.0)
113 }
114
115 pub fn snapshot(&self) -> MotionSnapshot {
116 MotionSnapshot {
117 kind: self.kind,
118 orientation: self.orientation,
119 angular_velocity: self.angular_velocity,
120 acceleration: self.acceleration,
121 }
122 }
123}