1use crate::{sys::MndResult, Monado};
2use std::{
3 ffi::{c_char, CStr},
4 vec,
5};
6
7#[repr(C)]
8#[derive(Debug, Default, Clone, Copy)]
9pub(crate) struct MndPose {
10 pub orientation: MndQuaternion,
11 pub position: MndVector3,
12}
13#[repr(C)]
14#[derive(Debug, Default, Clone, Copy)]
15pub(crate) struct MndQuaternion {
16 pub x: f32,
17 pub y: f32,
18 pub z: f32,
19 pub w: f32,
20}
21impl From<MndQuaternion> for mint::Quaternion<f32> {
22 fn from(q: MndQuaternion) -> Self {
23 mint::Quaternion {
24 v: mint::Vector3 {
25 x: q.x,
26 y: q.y,
27 z: q.z,
28 },
29 s: q.w,
30 }
31 }
32}
33impl From<mint::Quaternion<f32>> for MndQuaternion {
34 fn from(q: mint::Quaternion<f32>) -> Self {
35 Self {
36 x: q.v.x,
37 y: q.v.y,
38 z: q.v.z,
39 w: q.s,
40 }
41 }
42}
43
44#[repr(C)]
45#[derive(Debug, Default, Clone, Copy)]
46pub(crate) struct MndVector3 {
47 pub x: f32,
48 pub y: f32,
49 pub z: f32,
50}
51impl From<MndVector3> for mint::Vector3<f32> {
52 fn from(v: MndVector3) -> Self {
53 mint::Vector3 {
54 x: v.x,
55 y: v.y,
56 z: v.z,
57 }
58 }
59}
60impl From<mint::Vector3<f32>> for MndVector3 {
61 fn from(v: mint::Vector3<f32>) -> Self {
62 Self {
63 x: v.x,
64 y: v.y,
65 z: v.z,
66 }
67 }
68}
69
70#[repr(C)]
71#[derive(Debug, Clone, Copy, PartialEq, Eq)]
72pub enum ReferenceSpaceType {
73 View = 0,
74 Local = 1,
75 LocalFloor = 2,
76 Stage = 3,
77 Unbounded = 4,
78}
79
80#[derive(Debug, Clone, Copy, PartialEq)]
81pub struct Pose {
82 pub position: mint::Vector3<f32>,
83 pub orientation: mint::Quaternion<f32>,
84}
85impl From<MndPose> for Pose {
86 fn from(value: MndPose) -> Self {
87 Self {
88 position: value.position.into(),
89 orientation: value.orientation.into(),
90 }
91 }
92}
93impl From<Pose> for MndPose {
94 fn from(value: Pose) -> Self {
95 Self {
96 orientation: value.orientation.into(),
97 position: value.position.into(),
98 }
99 }
100}
101
102impl Monado {
103 pub fn tracking_origins(
104 &self,
105 ) -> Result<impl IntoIterator<Item = TrackingOrigin<'_>>, MndResult> {
106 let mut count = 0;
107 unsafe {
108 self.api
109 .mnd_root_get_tracking_origin_count(self.root, &mut count)
110 .to_result()?
111 };
112 let mut tracking_origins: Vec<Option<TrackingOrigin>> =
113 vec::from_elem(None, count as usize);
114 for (id, origin) in tracking_origins.iter_mut().enumerate() {
115 let mut c_name: *const c_char = std::ptr::null_mut();
116 unsafe {
117 self.api
118 .mnd_root_get_tracking_origin_name(self.root, id as u32, &mut c_name)
119 .to_result()?
120 };
121 let name = unsafe {
122 CStr::from_ptr(c_name)
123 .to_str()
124 .map_err(|_| MndResult::ErrorInvalidValue)?
125 .to_owned()
126 };
127 origin.replace(TrackingOrigin {
128 monado: self,
129 id: id as u32,
130 name,
131 });
132 }
133 Ok(tracking_origins.into_iter().flatten())
134 }
135
136 pub fn get_reference_space_offset(
137 &self,
138 space_type: ReferenceSpaceType,
139 ) -> Result<Pose, MndResult> {
140 let mut mnd_pose = MndPose::default();
141 unsafe {
142 self.api
143 .mnd_root_get_reference_space_offset(self.root, space_type, &mut mnd_pose)
144 .to_result()?;
145 }
146 Ok(mnd_pose.into())
147 }
148 pub fn set_reference_space_offset(
149 &self,
150 space_type: ReferenceSpaceType,
151 pose: Pose,
152 ) -> Result<(), MndResult> {
153 unsafe {
154 self.api
155 .mnd_root_set_reference_space_offset(self.root, space_type, &pose.into())
156 .to_result()
157 }
158 }
159}
160
161#[derive(Clone)]
162pub struct TrackingOrigin<'m> {
163 monado: &'m Monado,
164 pub id: u32,
165 pub name: String,
166}
167impl TrackingOrigin<'_> {
168 pub fn get_offset(&self) -> Result<Pose, MndResult> {
169 let mut mnd_pose = MndPose::default();
170 unsafe {
171 self.monado
172 .api
173 .mnd_root_get_tracking_origin_offset(self.monado.root, self.id, &mut mnd_pose)
174 .to_result()?;
175 }
176 Ok(mnd_pose.into())
177 }
178 pub fn set_offset(&self, pose: Pose) -> Result<(), MndResult> {
179 unsafe {
180 self.monado
181 .api
182 .mnd_root_set_tracking_origin_offset(self.monado.root, self.id, &pose.into())
183 .to_result()
184 }
185 }
186}
187
188#[test]
189fn test_spaces() {
190 let monado = Monado::auto_connect().unwrap();
191 for tracking_origin in monado.tracking_origins().unwrap() {
192 dbg!(
193 tracking_origin.id,
194 &tracking_origin.name,
195 tracking_origin.get_offset().unwrap()
196 );
197 println!();
198 }
199 let test_reference_space = |space_type| -> Result<Pose, MndResult> {
200 let offset = monado.get_reference_space_offset(space_type)?;
201 monado.set_reference_space_offset(space_type, offset)?;
202 Ok(offset)
203 };
204
205 let _ = dbg!(test_reference_space(ReferenceSpaceType::Local));
206 let _ = dbg!(test_reference_space(ReferenceSpaceType::LocalFloor));
207 let _ = dbg!(test_reference_space(ReferenceSpaceType::Stage));
208 let _ = dbg!(test_reference_space(ReferenceSpaceType::Unbounded));
209 let _ = dbg!(test_reference_space(ReferenceSpaceType::View));
210}