Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

openxr: Add support for hand interaction extensions #151

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion webxr/Cargo.toml
Expand Up @@ -41,7 +41,7 @@ gleam = "0.9"
glutin = { version = "0.21", optional = true }
log = "0.4.6"
gvr-sys = { version = "0.7", optional = true }
openxr = { version = "0.9.1", optional = true }
openxr = { version = "0.12.1", optional = true }
serde = { version = "1.0", optional = true }
surfman = { version = "0.1", features = ["sm-osmesa"] }
surfman-chains = "0.3"
Expand Down
30 changes: 28 additions & 2 deletions webxr/openxr/input.rs
Expand Up @@ -80,7 +80,8 @@ const IDENTITY_POSE: Posef = Posef {
z: 0.,
},
};
pub struct OpenXRInput {

pub(crate) struct OpenXRInput {
id: InputId,
action_aim_pose: Action<Posef>,
action_aim_space: Space,
Expand Down Expand Up @@ -159,11 +160,36 @@ impl OpenXRInput {
}
}

pub fn setup_inputs(instance: &Instance, session: &Session<D3D11>) -> (ActionSet, Self, Self) {
pub fn setup_inputs(
instance: &Instance,
session: &Session<D3D11>,
interaction: super::HandInteraction,
) -> (ActionSet, Self, Self) {
let action_set = instance.create_action_set("hands", "Hands", 0).unwrap();
let right_hand = OpenXRInput::new(InputId(0), Handedness::Right, &action_set, &session);
let left_hand = OpenXRInput::new(InputId(1), Handedness::Left, &action_set, &session);

if interaction != super::HandInteraction::None {
let mut bindings =
right_hand.get_bindings(instance, "select/value", Some("squeeze/value"));
bindings.extend(
left_hand
.get_bindings(instance, "select/value", Some("squeeze/value"))
.into_iter(),
);

let path = if interaction == super::HandInteraction::Final {
"/interaction_profiles/microsoft/hand_interaction"
} else {
"/interaction_profiles/microsoft/hand_interaction_preview"
};

let path_controller = instance.string_to_path(path).unwrap();
instance
.suggest_interaction_profile_bindings(path_controller, &bindings)
.unwrap();
}

let mut bindings =
right_hand.get_bindings(instance, "trigger/value", Some("squeeze/click"));
bindings.extend(
Expand Down
55 changes: 47 additions & 8 deletions webxr/openxr/mod.rs
Expand Up @@ -121,23 +121,55 @@ impl OpenXrDiscovery {
}
}

fn create_instance() -> Result<Instance, String> {
#[derive(PartialEq, Eq, Debug, Copy, Clone)]
pub(crate) enum HandInteraction {
None,
Preview,
Final,
}

struct CreatedInstance {
instance: Instance,
interaction: HandInteraction,
}

fn create_instance() -> Result<CreatedInstance, String> {
let entry = Entry::load().map_err(|e| format!("{:?}", e))?;
let supported = entry
.enumerate_extensions()
.map_err(|e| format!("{:?}", e))?;
let preview = supported
.other
.iter()
.find(|f| &**f == "XR_MSFT_hand_interaction_preview\0")
.is_some();

let app_info = ApplicationInfo {
application_name: "firefox.reality",
application_version: 1,
engine_name: "servo",
engine_version: 1,
};

let exts = ExtensionSet {
khr_d3d11_enable: true,
..Default::default()
let mut exts = ExtensionSet::default();
exts.khr_d3d11_enable = true;
let interaction = if supported.msft_hand_interaction {
exts.msft_hand_interaction = true;
HandInteraction::Final
} else if preview {
exts.other.push("XR_MSFT_hand_interaction_preview\0".into());
HandInteraction::Preview
} else {
HandInteraction::None
};

entry
let inst = entry
.create_instance(&app_info, &exts)
.map_err(|e| format!("{:?}", e))
.map_err(|e| format!("{:?}", e))?;
Ok(CreatedInstance {
instance: inst,
interaction,
})
}

fn pick_format(formats: &[dxgiformat::DXGI_FORMAT]) -> dxgiformat::DXGI_FORMAT {
Expand Down Expand Up @@ -165,7 +197,11 @@ impl DiscoveryAPI<SwapChains> for OpenXrDiscovery {
init: &SessionInit,
xr: SessionBuilder,
) -> Result<WebXrSession, Error> {
let instance = create_instance().map_err(|e| Error::BackendSpecific(e))?;
let CreatedInstance {
instance,
interaction,
} = create_instance().map_err(|e| Error::BackendSpecific(e))?;

if self.supports_session(mode) {
let gl_thread = self.gl_thread.clone();
let provider_registration = self.provider_registration.clone();
Expand All @@ -180,6 +216,7 @@ impl DiscoveryAPI<SwapChains> for OpenXrDiscovery {
granted_features,
id,
context_menu_provider,
interaction,
)
})
} else {
Expand Down Expand Up @@ -412,6 +449,7 @@ impl OpenXrDevice {
granted_features: Vec<String>,
id: SessionId,
context_menu_provider: Box<dyn ContextMenuProvider>,
interaction: HandInteraction,
) -> Result<OpenXrDevice, Error> {
let (device_tx, device_rx) = crossbeam_channel::unbounded();
let (provider_tx, provider_rx) = crossbeam_channel::unbounded();
Expand Down Expand Up @@ -562,7 +600,8 @@ impl OpenXrDevice {

// input

let (action_set, right_hand, left_hand) = OpenXRInput::setup_inputs(&instance, &session);
let (action_set, right_hand, left_hand) =
OpenXRInput::setup_inputs(&instance, &session, interaction);

Ok(OpenXrDevice {
instance,
Expand Down