From c474045e489067b6598d8ee072e41a91fcdc579d Mon Sep 17 00:00:00 2001 From: Kitlith Date: Thu, 23 Feb 2023 16:53:09 -0800 Subject: [PATCH 1/2] Switch to a "static standing" universe. This is WIP and has yet to be tested. Would be completely unsurprised if applying the translation and rotation is currently incorrect. Just haven't gotten around to testing/tweaking it yet. --- Cargo.lock | 32 +++++++++++++-- overlay/Cargo.toml | 7 +++- overlay/src/main.rs | 23 ++++++++++- overlay/src/model/bone.rs | 2 +- overlay/src/universe.rs | 86 +++++++++++++++++++++++++++++++++++++++ 5 files changed, 142 insertions(+), 8 deletions(-) create mode 100644 overlay/src/universe.rs diff --git a/Cargo.lock b/Cargo.lock index 5c63388c..4512782d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -761,6 +761,27 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "enumset" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19be8061a06ab6f3a6cf21106c873578bf01bd42ad15e0311a9c76161cb1c753" +dependencies = [ + "enumset_derive", +] + +[[package]] +name = "enumset_derive" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03e7b551eba279bf0fa88b83a46330168c1560a52a94f5126f892f0b364ab3e0" +dependencies = [ + "darling 0.14.2", + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "env_logger" version = "0.9.3" @@ -1500,6 +1521,7 @@ dependencies = [ "num-complex", "num-rational", "num-traits", + "serde", "simba 0.7.3", "typenum", ] @@ -1657,6 +1679,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ae39348c8bc5fbd7f40c727a9925f03517afd2ab27d46702108b6a7e5414c19" dependencies = [ "num-traits", + "serde", ] [[package]] @@ -1812,10 +1835,10 @@ dependencies = [ [[package]] name = "ovr_overlay" version = "0.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bca515c469ad7eb699480b5dc61d1c83e1e9694e7c39435ce458a3f9fbdce14" +source = "git+https://github.com/TheButlah/ovr_overlay#ffc57149724a9efade7160a2494a882d4c7c92fd" dependencies = [ "derive_more", + "enumset", "lazy_static", "log", "nalgebra 0.30.1", @@ -1827,8 +1850,7 @@ dependencies = [ [[package]] name = "ovr_overlay_sys" version = "0.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16b5e4888d82a67dd8c3d47103aa751083bfe88de063ece9846715c2a78fcbab" +source = "git+https://github.com/TheButlah/ovr_overlay#ffc57149724a9efade7160a2494a882d4c7c92fd" dependencies = [ "autocxx", "autocxx-build", @@ -2414,6 +2436,8 @@ dependencies = [ "num-derive", "num-traits", "ovr_overlay", + "serde", + "serde_json", "solarxr", "stackvec", "tokio", diff --git a/overlay/Cargo.toml b/overlay/Cargo.toml index 76ce701a..09722d00 100644 --- a/overlay/Cargo.toml +++ b/overlay/Cargo.toml @@ -13,10 +13,13 @@ rust-version.workspace = true clap = { version = "4", features = ["derive"] } color-eyre = "0.6" lazy_static = "1" -nalgebra = "0.30" +nalgebra = { version = "0.30", features = ["serde-serialize"] } num-derive = "0.3" num-traits = "0.2" -ovr_overlay = { version = "=0.0.0", features = ["nalgebra"] } +#ovr_overlay = { version = "=0.0.0", features = ["nalgebra"] } +ovr_overlay = { git = "https://github.com/TheButlah/ovr_overlay", features = ["nalgebra", "ovr_system", "ovr_chaperone_setup"]} +serde = "1.0" +serde_json = "1.0" stackvec = "0.2" tokio = { version = "1", features = ["full"] } solarxr = { path = "../networking/solarxr" } diff --git a/overlay/src/main.rs b/overlay/src/main.rs index 7dfc2c71..4d8df780 100644 --- a/overlay/src/main.rs +++ b/overlay/src/main.rs @@ -1,5 +1,6 @@ mod color; mod model; +mod universe; pub use self::color::RGBA; @@ -151,6 +152,22 @@ async fn overlay( .build(mngr) .wrap_err("Could not create skeleton")?; + let system_mngr = &mut context.system_mngr(); + log::info!("Acquiring universe"); + let universe = loop { + let id: Result = system_mngr.get_tracked_device_property( + orv::TrackedDeviceIndex::HMD, + ovr::sys::ETrackedDeviceProperty::Prop_CurrentUniverseId_Uint64, + ); + match id { + Ok(id) => match universe::search_universe(&context, id) { + Some(d) => break d, + None => {} // TODO: fallback to 0 translation, or maybe standing universe? + }, + Err(_) => {} // TODO: log error, but only once? + } + }; + log::info!("Overlay Loop"); let loop_ = async { @@ -212,9 +229,13 @@ async fn overlay( }; let length = b.bone_length(); - let pos = Translation3::new(pos.x(), pos.y(), pos.z()); + let pos = Translation3::new(pos.x(), pos.y(), pos.z()) + * universe.translation; let rot = UnitQuaternion::from_quaternion( [rot.x(), rot.y(), rot.z(), rot.w()].into(), + ) * UnitQuaternion::from_axis_angle( + &nalgebra::Vector3::y_axis(), + universe.yaw, ); if is_skeleton_visible { hidden_bones.remove(&bone_kind); diff --git a/overlay/src/model/bone.rs b/overlay/src/model/bone.rs index e253e2e9..8286db0d 100644 --- a/overlay/src/model/bone.rs +++ b/overlay/src/model/bone.rs @@ -136,7 +136,7 @@ impl Bone { let col_major_3x4 = Matrix3x4::from(&transform); mngr.set_transform_absolute( overlay, - TrackingUniverseOrigin::TrackingUniverseStanding, + TrackingUniverseOrigin::TrackingUniverseRawAndUncalibrated, &col_major_3x4, ) .wrap_err("Failed to set transform")?; diff --git a/overlay/src/universe.rs b/overlay/src/universe.rs new file mode 100644 index 00000000..ed508614 --- /dev/null +++ b/overlay/src/universe.rs @@ -0,0 +1,86 @@ +use ovr_overlay as ovr; +use serde::{ + de::{self, Deserializer, Visitor}, + Deserialize, +}; +use serde_json::from_slice; +use std::fmt; + +// From https://github.com/serde-rs/json/issues/412#issuecomment-365856864 +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +struct UniverseId(u64); + +impl<'de> Deserialize<'de> for UniverseId { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + struct IdVisitor; + + impl<'de> Visitor<'de> for IdVisitor { + type Value = UniverseId; + + fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.write_str("universe ID as a number or string") + } + + fn visit_u64(self, id: u64) -> Result + where + E: de::Error, + { + Ok(UniverseId(id)) + } + + fn visit_str(self, id: &str) -> Result + where + E: de::Error, + { + id.parse().map(UniverseId).map_err(de::Error::custom) + } + } + + deserializer.deserialize_any(IdVisitor) + } +} + +#[derive(Deserialize)] +pub(crate) struct UniverseTranslation { + pub translation: nalgebra::Translation3, + pub yaw: f32, +} + +#[derive(Deserialize)] +struct Universe { + universe_id: UniverseId, + standing: UniverseTranslation, +} + +#[derive(Deserialize)] +struct Document { + universes: Vec, +} + +pub(crate) fn search_universe( + context: &ovr::Context, + universe_id: u64, +) -> Option { + let chaperone_setup = context.chaperone_setup_mngr().export_live_to_buffer()?; + + // note: in theory we could parse in a streaming fashion using an appropriate json library + // instead of reading in everything all at once and then filtering. + // in practice this will probably never matter. + let document: Document = match from_slice(chaperone_setup.as_bytes()) { + Ok(res) => res, + Err(err) => { + // TODO: only log this once? + log::error!("Error parsing universe json: {}", err); + return None; + } + }; + + document + .universes + .into_iter() + .find(|u| u.universe_id.0 == universe_id) + .map(|u| u.standing) +} From 7a95a32e86f2117f310d8f0becaa1d8481d104c7 Mon Sep 17 00:00:00 2001 From: Kitlith Date: Thu, 2 Mar 2023 15:23:55 -0800 Subject: [PATCH 2/2] Fix some things. Still need to figure out how to apply the universe translation/rotation. In the driver, we just pass it as the 'WorldFromDriver' translation/rotation. Parsing the current universe works though, now, after merging the fixup PR to ovr_overlay. --- overlay/src/main.rs | 20 ++++++++++++-------- overlay/src/universe.rs | 7 ++++--- 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/overlay/src/main.rs b/overlay/src/main.rs index 4d8df780..f409b7ca 100644 --- a/overlay/src/main.rs +++ b/overlay/src/main.rs @@ -156,7 +156,7 @@ async fn overlay( log::info!("Acquiring universe"); let universe = loop { let id: Result = system_mngr.get_tracked_device_property( - orv::TrackedDeviceIndex::HMD, + ovr::TrackedDeviceIndex::HMD, ovr::sys::ETrackedDeviceProperty::Prop_CurrentUniverseId_Uint64, ); match id { @@ -164,8 +164,9 @@ async fn overlay( Some(d) => break d, None => {} // TODO: fallback to 0 translation, or maybe standing universe? }, - Err(_) => {} // TODO: log error, but only once? + Err(e) => log::error!("Error: {}", e), // TODO: log error, but only once? } + tokio::time::sleep(Duration::from_secs(1)).await; }; log::info!("Overlay Loop"); @@ -229,13 +230,9 @@ async fn overlay( }; let length = b.bone_length(); - let pos = Translation3::new(pos.x(), pos.y(), pos.z()) - * universe.translation; + let pos = Translation3::new(pos.x(), pos.y(), pos.z()); let rot = UnitQuaternion::from_quaternion( [rot.x(), rot.y(), rot.z(), rot.w()].into(), - ) * UnitQuaternion::from_axis_angle( - &nalgebra::Vector3::y_axis(), - universe.yaw, ); if is_skeleton_visible { hidden_bones.remove(&bone_kind); @@ -264,10 +261,17 @@ async fn overlay( length, } in bones { - let iso = Isometry { + let mut iso = Isometry { rotation: rot, translation: pos, }; + // TODO: this isn't correct yet. + iso *= universe.translation.inverse(); + iso *= UnitQuaternion::from_axis_angle( + &nalgebra::Vector3::y_axis(), + universe.yaw, + ) + .inverse(); skeleton.set_isometry(kind, iso); skeleton.set_length(kind, length); } diff --git a/overlay/src/universe.rs b/overlay/src/universe.rs index ed508614..7827b2b6 100644 --- a/overlay/src/universe.rs +++ b/overlay/src/universe.rs @@ -43,19 +43,20 @@ impl<'de> Deserialize<'de> for UniverseId { } } -#[derive(Deserialize)] +#[derive(Debug, Deserialize)] pub(crate) struct UniverseTranslation { pub translation: nalgebra::Translation3, pub yaw: f32, } -#[derive(Deserialize)] +#[derive(Debug, Deserialize)] struct Universe { + #[serde(rename = "universeID")] universe_id: UniverseId, standing: UniverseTranslation, } -#[derive(Deserialize)] +#[derive(Debug, Deserialize)] struct Document { universes: Vec, }