libmonado_rs/
space.rs

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}