From 616bfff672ceb7dfede63a148cf005c94c512451 Mon Sep 17 00:00:00 2001 From: Schmarni Date: Fri, 18 Oct 2024 23:43:39 +0200 Subject: [PATCH 1/3] add openxr specific session running and available conditions Signed-off-by: Schmarni --- Cargo.toml | 1 + .../src/openxr/action_set_syncing.rs | 7 +++--- .../src/openxr/features/handtracking.rs | 8 +++---- .../src/openxr/features/overlay.rs | 7 ++++-- crates/bevy_openxr/src/openxr/init.rs | 2 -- crates/bevy_openxr/src/openxr/mod.rs | 22 ++++++++++++++++++- .../bevy_openxr/src/openxr/reference_space.rs | 2 +- crates/bevy_openxr/src/openxr/spaces.rs | 12 ++++++---- crates/bevy_xr/src/session.rs | 4 +++- 9 files changed, 46 insertions(+), 19 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 4ca265f..19bd499 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,5 +14,6 @@ bevy = { version = "0.14.0", default-features = false, features = [ "bevy_render", "bevy_core_pipeline", "bevy_winit", + "bevy_pbr", "x11", ] } diff --git a/crates/bevy_openxr/src/openxr/action_set_syncing.rs b/crates/bevy_openxr/src/openxr/action_set_syncing.rs index 53f5930..05f6093 100644 --- a/crates/bevy_openxr/src/openxr/action_set_syncing.rs +++ b/crates/bevy_openxr/src/openxr/action_set_syncing.rs @@ -1,6 +1,5 @@ -use crate::session::OxrSession; +use crate::{openxr_session_running, session::OxrSession}; use bevy::prelude::*; -use bevy_mod_xr::session::session_running; #[derive(SystemSet, Debug, Hash, PartialEq, Eq, Clone, Copy)] pub struct OxrActionSetSyncSet; @@ -10,7 +9,9 @@ impl Plugin for OxrActionSyncingPlugin { app.add_event::(); app.add_systems( PreUpdate, - sync_sets.in_set(OxrActionSetSyncSet).run_if(session_running), // .in_set(OxrPreUpdateSet::SyncActions), + sync_sets + .in_set(OxrActionSetSyncSet) + .run_if(openxr_session_running), ); } } diff --git a/crates/bevy_openxr/src/openxr/features/handtracking.rs b/crates/bevy_openxr/src/openxr/features/handtracking.rs index 8da035c..b6c7147 100644 --- a/crates/bevy_openxr/src/openxr/features/handtracking.rs +++ b/crates/bevy_openxr/src/openxr/features/handtracking.rs @@ -1,14 +1,12 @@ use bevy::prelude::*; +use bevy_mod_xr::hands::{HandBone, HandBoneRadius}; use bevy_mod_xr::hands::{LeftHand, RightHand, XrHandBoneEntities, HAND_JOINT_COUNT}; use bevy_mod_xr::session::{XrPreDestroySession, XrSessionCreated, XrTrackingRoot}; use bevy_mod_xr::spaces::{XrPrimaryReferenceSpace, XrReferenceSpace, XrVelocity}; -use bevy_mod_xr::{ - hands::{HandBone, HandBoneRadius}, - session::session_running, -}; use openxr::{SpaceLocationFlags, SpaceVelocityFlags}; use crate::helper_traits::ToVec3; +use crate::openxr_session_running; use crate::resources::OxrFrameState; use crate::resources::Pipelined; use crate::session::OxrSession; @@ -27,7 +25,7 @@ impl Default for HandTrackingPlugin { impl Plugin for HandTrackingPlugin { fn build(&self, app: &mut App) { - app.add_systems(PreUpdate, locate_hands.run_if(session_running)); + app.add_systems(PreUpdate, locate_hands.run_if(openxr_session_running)); if self.default_hands { app.add_systems(XrPreDestroySession, clean_up_default_hands) .add_systems(XrSessionCreated, spawn_default_hands); diff --git a/crates/bevy_openxr/src/openxr/features/overlay.rs b/crates/bevy_openxr/src/openxr/features/overlay.rs index 107048b..7b3d072 100644 --- a/crates/bevy_openxr/src/openxr/features/overlay.rs +++ b/crates/bevy_openxr/src/openxr/features/overlay.rs @@ -1,12 +1,12 @@ use std::{mem, ptr}; use bevy::prelude::*; -use bevy_mod_xr::session::session_available; use openxr::sys; use crate::{ next_chain::{OxrNextChainStructBase, OxrNextChainStructProvider}, openxr::exts::OxrEnabledExtensions, + openxr_session_available, session::{OxrSessionCreateNextChain, OxrSessionCreateNextProvider}, }; @@ -16,7 +16,10 @@ impl Plugin for OxrOverlayPlugin { fn build(&self, app: &mut bevy::prelude::App) { app.add_event::(); app.init_resource::(); - app.add_systems(First, add_overlay_info_to_chain.run_if(session_available)); + app.add_systems( + First, + add_overlay_info_to_chain.run_if(openxr_session_available), + ); } } diff --git a/crates/bevy_openxr/src/openxr/init.rs b/crates/bevy_openxr/src/openxr/init.rs index cea8d00..fa8d4fd 100644 --- a/crates/bevy_openxr/src/openxr/init.rs +++ b/crates/bevy_openxr/src/openxr/init.rs @@ -1,9 +1,7 @@ use std::sync::atomic::Ordering; use std::sync::Arc; -use bevy::ecs::system::RunSystemOnce; use bevy::prelude::*; -use bevy::render::extract_resource::ExtractResource; use bevy::render::extract_resource::ExtractResourcePlugin; use bevy::render::renderer::RenderAdapter; use bevy::render::renderer::RenderAdapterInfo; diff --git a/crates/bevy_openxr/src/openxr/mod.rs b/crates/bevy_openxr/src/openxr/mod.rs index 011837c..d01c0a1 100644 --- a/crates/bevy_openxr/src/openxr/mod.rs +++ b/crates/bevy_openxr/src/openxr/mod.rs @@ -1,14 +1,17 @@ // use actions::XrActionPlugin; use bevy::{ app::{PluginGroup, PluginGroupBuilder}, + prelude::Res, render::RenderPlugin, utils::default, window::{PresentMode, Window, WindowPlugin}, }; -use bevy_mod_xr::camera::XrCameraPlugin; use bevy_mod_xr::session::XrSessionPlugin; +use bevy_mod_xr::{camera::XrCameraPlugin, session::XrState}; use init::OxrInitPlugin; use render::OxrRenderPlugin; +use resources::OxrInstance; +use session::OxrSession; use self::{ features::{handtracking::HandTrackingPlugin, passthrough::OxrPassthroughPlugin}, @@ -33,6 +36,23 @@ pub mod session; pub mod spaces; pub mod types; +/// A [`Condition`](bevy::ecs::schedule::Condition) system that says if the OpenXR session is available. +pub fn openxr_session_available( + status: Option>, + instance: Option>, +) -> bool { + status.is_some_and(|s| *s != XrState::Unavailable) && instance.is_some() +} + +/// A [`Condition`](bevy::ecs::schedule::Condition) system that says if the OpenXR is running. +/// use this when working with OpenXR specific things +pub fn openxr_session_running( + status: Option>, + session: Option>, +) -> bool { + matches!(status.as_deref(), Some(XrState::Running)) & session.is_some() +} + pub fn add_xr_plugins(plugins: G) -> PluginGroupBuilder { plugins .build() diff --git a/crates/bevy_openxr/src/openxr/reference_space.rs b/crates/bevy_openxr/src/openxr/reference_space.rs index 4ed24c3..b797f70 100644 --- a/crates/bevy_openxr/src/openxr/reference_space.rs +++ b/crates/bevy_openxr/src/openxr/reference_space.rs @@ -7,7 +7,7 @@ use bevy_mod_xr::{ spaces::{XrPrimaryReferenceSpace, XrReferenceSpace}, }; -use crate::{init::create_xr_session, session::OxrSession}; +use crate::session::OxrSession; pub struct OxrReferenceSpacePlugin { pub default_primary_ref_space: openxr::ReferenceSpaceType, diff --git a/crates/bevy_openxr/src/openxr/spaces.rs b/crates/bevy_openxr/src/openxr/spaces.rs index 028cc42..40c0e8b 100644 --- a/crates/bevy_openxr/src/openxr/spaces.rs +++ b/crates/bevy_openxr/src/openxr/spaces.rs @@ -2,7 +2,7 @@ use std::{mem::MaybeUninit, ptr, sync::Mutex}; use bevy::{prelude::*, utils::hashbrown::HashSet}; use bevy_mod_xr::{ - session::{session_available, session_running, XrFirst, XrHandleEvents}, + session::{XrFirst, XrHandleEvents}, spaces::{XrDestroySpace, XrPrimaryReferenceSpace, XrReferenceSpace, XrSpace, XrVelocity}, types::XrPose, }; @@ -13,6 +13,7 @@ use openxr::{ use crate::{ helper_traits::{ToPosef, ToQuat, ToVec3}, + openxr_session_available, openxr_session_running, resources::{OxrFrameState, OxrInstance, Pipelined}, session::OxrSession, }; @@ -24,7 +25,10 @@ pub struct OxrSpaceSyncSet; pub struct OxrSpacePatchingPlugin; impl Plugin for OxrSpacePatchingPlugin { fn build(&self, app: &mut App) { - app.add_systems(Startup, patch_destroy_space.run_if(session_available)); + app.add_systems( + Startup, + patch_destroy_space.run_if(openxr_session_available), + ); } } @@ -36,13 +40,13 @@ impl Plugin for OxrSpatialPlugin { XrFirst, destroy_space_event .before(XrHandleEvents::Poll) - .run_if(session_available), + .run_if(openxr_session_available), ) .add_systems( PreUpdate, update_space_transforms .in_set(OxrSpaceSyncSet) - .run_if(session_running), + .run_if(openxr_session_running), ) .observe(add_location_flags) .observe(add_velocity_flags); diff --git a/crates/bevy_xr/src/session.rs b/crates/bevy_xr/src/session.rs index c2d6016..4b9df83 100644 --- a/crates/bevy_xr/src/session.rs +++ b/crates/bevy_xr/src/session.rs @@ -266,6 +266,7 @@ pub fn status_changed_to( } /// A [`Condition`](bevy::ecs::schedule::Condition) system that says if the XR session is available. Returns true as long as [`XrState`] exists and isn't [`Unavailable`](XrStatus::Unavailable). +/// When using backend specific resources use the backend specific condition pub fn session_available(status: Option>) -> bool { status.is_some_and(|s| *s != XrState::Unavailable) } @@ -282,7 +283,8 @@ pub fn session_ready_or_running(status: Option>) -> bool { matches!(status.as_deref(), Some(XrState::Ready | XrState::Running)) } -/// A [`Condition`](bevy::ecs::schedule::Condition) system that says if the XR session is running +/// A [`Condition`](bevy::ecs::schedule::Condition) system that says if the XR session is running. +/// When using backend specific resources use the backend specific condition pub fn session_running(status: Option>) -> bool { matches!(status.as_deref(), Some(XrState::Running)) } From 20f8c47abab70e5140f9a141570d005df403fe3b Mon Sep 17 00:00:00 2001 From: Schmarni Date: Sat, 19 Oct 2024 00:22:10 +0200 Subject: [PATCH 2/3] add space flags to bevy_mod_xr Signed-off-by: Schmarni --- crates/bevy_openxr/src/openxr/spaces.rs | 25 +++++++++++--- crates/bevy_xr/src/spaces.rs | 46 +++++++++++++++++++++++-- 2 files changed, 64 insertions(+), 7 deletions(-) diff --git a/crates/bevy_openxr/src/openxr/spaces.rs b/crates/bevy_openxr/src/openxr/spaces.rs index 40c0e8b..91c74a2 100644 --- a/crates/bevy_openxr/src/openxr/spaces.rs +++ b/crates/bevy_openxr/src/openxr/spaces.rs @@ -3,7 +3,10 @@ use std::{mem::MaybeUninit, ptr, sync::Mutex}; use bevy::{prelude::*, utils::hashbrown::HashSet}; use bevy_mod_xr::{ session::{XrFirst, XrHandleEvents}, - spaces::{XrDestroySpace, XrPrimaryReferenceSpace, XrReferenceSpace, XrSpace, XrVelocity}, + spaces::{ + XrDestroySpace, XrPrimaryReferenceSpace, XrReferenceSpace, XrSpace, XrSpaceLocationFlags, + XrSpaceVelocityFlags, XrVelocity, + }, types::XrPose, }; use openxr::{ @@ -155,7 +158,9 @@ fn update_space_transforms( Option<&mut XrVelocity>, Option<&XrReferenceSpace>, &mut OxrSpaceLocationFlags, + &mut XrSpaceLocationFlags, Option<&mut OxrSpaceVelocityFlags>, + Option<&mut XrSpaceVelocityFlags>, )>, ) { for ( @@ -163,8 +168,10 @@ fn update_space_transforms( space, velocity, ref_space, - mut space_location_flags, - space_velocity_flags, + mut oxr_space_location_flags, + mut xr_space_location_flags, + oxr_space_velocity_flags, + xr_space_velocity_flags, ) in &mut query { let ref_space = ref_space.unwrap_or(&default_ref_space); @@ -186,11 +193,17 @@ fn update_space_transforms( if flags.linear_valid() { velocity.linear = space_velocity.linear_velocity.to_vec3(); } - let Some(mut vel_flags) = space_velocity_flags else { + let Some(mut vel_flags) = oxr_space_velocity_flags else { error!("XrVelocity without OxrSpaceVelocityFlags"); return; }; + let Some(mut xr_vel_flags) = xr_space_velocity_flags else { + error!("XrVelocity without XrSpaceVelocityFlags"); + return; + }; *vel_flags = flags; + xr_vel_flags.linear_valid = vel_flags.linear_valid(); + xr_vel_flags.angular_valid = vel_flags.angular_valid(); Ok(location) } Err(err) => Err(err), @@ -206,7 +219,9 @@ fn update_space_transforms( if flags.rot_valid() { transform.rotation = space_location.pose.orientation.to_quat(); } - *space_location_flags = flags; + *oxr_space_location_flags = flags; + xr_space_location_flags.position_tracked = flags.pos_valid() && flags.pos_tracked(); + xr_space_location_flags.rotation_tracked = flags.rot_valid() && flags.rot_tracked(); } } } diff --git a/crates/bevy_xr/src/spaces.rs b/crates/bevy_xr/src/spaces.rs index cc3d157..4f6a295 100644 --- a/crates/bevy_xr/src/spaces.rs +++ b/crates/bevy_xr/src/spaces.rs @@ -1,14 +1,15 @@ use bevy::{ + ecs::component::StorageType, prelude::*, render::{extract_component::ExtractComponent, extract_resource::ExtractResource}, }; /// Any Spaces will be invalid after the owning session exits #[repr(transparent)] -#[derive(Clone, Copy, Hash, PartialEq, Eq, Reflect, Debug, Component, ExtractComponent)] +#[derive(Clone, Copy, Hash, PartialEq, Eq, Reflect, Debug, ExtractComponent)] pub struct XrSpace(u64); -#[derive(Clone, Copy, Reflect, Debug, Component, ExtractComponent, Default)] +#[derive(Clone, Copy, Reflect, Debug, ExtractComponent, Default)] pub struct XrVelocity { /// Velocity of a space relative to it's reference space pub linear: Vec3, @@ -42,6 +43,22 @@ pub struct XrReferenceSpace(pub XrSpace); )] pub struct XrPrimaryReferenceSpace(pub XrReferenceSpace); +#[derive( + Clone, Copy, Hash, PartialEq, Eq, Reflect, Debug, Component, ExtractComponent, Default, +)] +pub struct XrSpaceLocationFlags { + pub position_tracked: bool, + pub rotation_tracked: bool, +} + +#[derive( + Clone, Copy, Hash, PartialEq, Eq, Reflect, Debug, Component, ExtractComponent, Default, +)] +pub struct XrSpaceVelocityFlags { + pub linear_valid: bool, + pub angular_valid: bool, +} + impl XrSpace { /// # Safety /// only call with known valid handles @@ -52,3 +69,28 @@ impl XrSpace { self.0 } } + +impl Component for XrSpace { + const STORAGE_TYPE: StorageType = StorageType::Table; + + fn register_component_hooks(hooks: &mut bevy::ecs::component::ComponentHooks) { + hooks.on_add(|mut world, entity, _| { + world + .commands() + .entity(entity) + .insert(XrSpaceLocationFlags::default()); + }); + } +} +impl Component for XrVelocity { + const STORAGE_TYPE: StorageType = StorageType::Table; + + fn register_component_hooks(hooks: &mut bevy::ecs::component::ComponentHooks) { + hooks.on_add(|mut world, entity, _| { + world + .commands() + .entity(entity) + .insert(XrSpaceVelocityFlags::default()); + }); + } +} From ac972dd4751e96bba6f1dd023fcb03593ccc6866 Mon Sep 17 00:00:00 2001 From: Schmarni Date: Sat, 19 Oct 2024 00:33:22 +0200 Subject: [PATCH 3/3] implement xr flags for hands Signed-off-by: Schmarni --- .../src/openxr/features/handtracking.rs | 38 +++++++++++++++++-- 1 file changed, 34 insertions(+), 4 deletions(-) diff --git a/crates/bevy_openxr/src/openxr/features/handtracking.rs b/crates/bevy_openxr/src/openxr/features/handtracking.rs index b6c7147..57726e1 100644 --- a/crates/bevy_openxr/src/openxr/features/handtracking.rs +++ b/crates/bevy_openxr/src/openxr/features/handtracking.rs @@ -2,7 +2,10 @@ use bevy::prelude::*; use bevy_mod_xr::hands::{HandBone, HandBoneRadius}; use bevy_mod_xr::hands::{LeftHand, RightHand, XrHandBoneEntities, HAND_JOINT_COUNT}; use bevy_mod_xr::session::{XrPreDestroySession, XrSessionCreated, XrTrackingRoot}; -use bevy_mod_xr::spaces::{XrPrimaryReferenceSpace, XrReferenceSpace, XrVelocity}; +use bevy_mod_xr::spaces::{ + XrPrimaryReferenceSpace, XrReferenceSpace, XrSpaceLocationFlags, XrSpaceVelocityFlags, + XrVelocity, +}; use openxr::{SpaceLocationFlags, SpaceVelocityFlags}; use crate::helper_traits::ToVec3; @@ -47,6 +50,7 @@ pub fn spawn_hand_bones( bone, HandBoneRadius(0.0), OxrSpaceLocationFlags(openxr::SpaceLocationFlags::default()), + XrSpaceLocationFlags::default(), )) .insert(bundle.clone()) .id(); @@ -138,7 +142,9 @@ fn locate_hands( &mut Transform, Option<&mut XrVelocity>, &mut OxrSpaceLocationFlags, + &mut XrSpaceLocationFlags, Option<&mut OxrSpaceVelocityFlags>, + Option<&mut XrSpaceVelocityFlags>, )>, pipelined: Option>, ) { @@ -159,13 +165,21 @@ fn locate_hands( let ref_space = ref_space.map(|v| &v.0).unwrap_or(&default_ref_space.0); let mut clear_flags = || { for e in hand_entities.0.iter() { - let Ok((_, _, _, _, mut flags, vel_flags)) = bone_query.get_mut(*e) else { + let Ok((_, _, _, _, mut flags, mut xr_flags, vel_flags, xr_vel_flags)) = + bone_query.get_mut(*e) + else { continue; }; flags.0 = SpaceLocationFlags::EMPTY; if let Some(mut flags) = vel_flags { flags.0 = SpaceVelocityFlags::EMPTY; } + xr_flags.position_tracked = false; + xr_flags.rotation_tracked = false; + if let Some(mut flags) = xr_vel_flags { + flags.linear_valid = false; + flags.angular_valid = false; + } } }; let (joints, vels) = if wants_velocities { @@ -215,8 +229,16 @@ fn locate_hands( continue; } }; - for (bone, mut bone_radius, mut transform, velocity, mut location_flags, velocity_flags) in - bone_entities + for ( + bone, + mut bone_radius, + mut transform, + velocity, + mut location_flags, + mut xr_location_flags, + velocity_flags, + xr_velocity_flags, + ) in bone_entities { let joint = joints[*bone as usize]; if let Some(mut velocity) = velocity { @@ -228,6 +250,10 @@ fn locate_hands( error!("somehow got a hand bone with an XrVelocity component, but without velocity flags"); continue; }; + let Some(mut xr_vel_flags) = xr_velocity_flags else { + error!("somehow got a hand bone with an XrVelocity component, but without velocity flags"); + continue; + }; let vel = vels[*bone as usize]; let flags = OxrSpaceVelocityFlags(vel.velocity_flags); if flags.linear_valid() { @@ -236,6 +262,8 @@ fn locate_hands( if flags.angular_valid() { velocity.angular = vel.angular_velocity.to_vec3(); } + xr_vel_flags.linear_valid = flags.linear_valid(); + xr_vel_flags.angular_valid = flags.angular_valid(); *vel_flags = flags; } @@ -253,6 +281,8 @@ fn locate_hands( transform.rotation.z = joint.pose.orientation.z; transform.rotation.w = joint.pose.orientation.w; } + xr_location_flags.position_tracked = flags.pos_valid() && flags.pos_tracked(); + xr_location_flags.rotation_tracked = flags.rot_valid() && flags.rot_tracked(); *location_flags = flags; } }