Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 28 additions & 4 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 5 additions & 2 deletions overlay/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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" }
Expand Down
27 changes: 26 additions & 1 deletion overlay/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
mod color;
mod model;
mod universe;

pub use self::color::RGBA;

Expand Down Expand Up @@ -151,6 +152,23 @@ 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<u64, _> = system_mngr.get_tracked_device_property(
ovr::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(e) => log::error!("Error: {}", e), // TODO: log error, but only once?
}
tokio::time::sleep(Duration::from_secs(1)).await;
};

log::info!("Overlay Loop");

let loop_ = async {
Expand Down Expand Up @@ -243,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);
}
Expand Down
2 changes: 1 addition & 1 deletion overlay/src/model/bone.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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")?;
Expand Down
87 changes: 87 additions & 0 deletions overlay/src/universe.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
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<D>(deserializer: D) -> Result<Self, D::Error>
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<E>(self, id: u64) -> Result<Self::Value, E>
where
E: de::Error,
{
Ok(UniverseId(id))
}

fn visit_str<E>(self, id: &str) -> Result<Self::Value, E>
where
E: de::Error,
{
id.parse().map(UniverseId).map_err(de::Error::custom)
}
}

deserializer.deserialize_any(IdVisitor)
}
}

#[derive(Debug, Deserialize)]
pub(crate) struct UniverseTranslation {
pub translation: nalgebra::Translation3<f32>,
pub yaw: f32,
}

#[derive(Debug, Deserialize)]
struct Universe {
#[serde(rename = "universeID")]
universe_id: UniverseId,
standing: UniverseTranslation,
}

#[derive(Debug, Deserialize)]
struct Document {
universes: Vec<Universe>,
}

pub(crate) fn search_universe(
context: &ovr::Context,
universe_id: u64,
) -> Option<UniverseTranslation> {
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)
}