Merge pull request #126 from Schmarni-Dev/oxr_overlays_attempt_2

Add EXTX_overlay support, but better and more complete
This commit is contained in:
Schmarni
2024-06-25 20:33:39 +02:00
committed by GitHub
6 changed files with 223 additions and 4 deletions

View File

@@ -0,0 +1,95 @@
//! A simple 3D scene with light shining over a cube sitting on a plane.
use bevy::prelude::*;
use bevy_openxr::{add_xr_plugins, init::OxrInitPlugin, types::OxrExtensions};
use bevy_xr::session::XrStatus;
use openxr::EnvironmentBlendMode;
use wgpu::TextureFormat;
fn main() {
App::new()
.add_plugins(add_xr_plugins(DefaultPlugins).build().set(OxrInitPlugin {
exts: {
let mut exts = OxrExtensions::default();
exts.enable_hand_tracking();
exts.other.push("XR_EXTX_overlay\0".into());
exts
},
// blend_modes: Some({
// let mut v = Vec::new();
// v.push(EnvironmentBlendMode::ALPHA_BLEND);
// v.push(EnvironmentBlendMode::ADDITIVE);
// v.push(EnvironmentBlendMode::OPAQUE);
// v
// }),
// formats: Some({
// let mut v = Vec::new();
// // v.push(TextureFormat::Rgba8Uint);
// v.push(TextureFormat::Rgba8Unorm);
// v.push(TextureFormat::Rgba8UnormSrgb);
// v
// }),
..OxrInitPlugin::default()
}))
.insert_resource(ClearColor(Color::NONE))
.add_plugins(bevy_xr_utils::hand_gizmos::HandGizmosPlugin)
.add_systems(Startup, setup)
.add_systems(Update, handle_input)
.run();
}
fn handle_input(
keys: Res<ButtonInput<KeyCode>>,
mut end: EventWriter<bevy_xr::session::EndXrSession>,
mut _destroy: EventWriter<bevy_xr::session::DestroyXrSession>,
mut _begin: EventWriter<bevy_xr::session::BeginXrSession>,
mut create: EventWriter<bevy_xr::session::CreateXrSession>,
state: Res<XrStatus>,
) {
if keys.just_pressed(KeyCode::KeyE) {
info!("sending end");
end.send_default();
}
if keys.just_pressed(KeyCode::KeyC) {
info!("sending create");
create.send_default();
}
if keys.just_pressed(KeyCode::KeyI) {
info!("current state: {:?}", *state);
}
}
/// set up a simple 3D scene
fn setup(
mut commands: Commands,
mut meshes: ResMut<Assets<Mesh>>,
mut materials: ResMut<Assets<StandardMaterial>>,
) {
// circular base
// commands.spawn(PbrBundle {
// mesh: meshes.add(Circle::new(4.0)),
// material: materials.add(Color::WHITE),
// transform: Transform::from_rotation(Quat::from_rotation_x(-std::f32::consts::FRAC_PI_2)),
// ..default()
// });
// cube
commands.spawn(PbrBundle {
mesh: meshes.add(Cuboid::new(1.0, 1.0, 1.0)),
material: materials.add(Color::rgb_u8(124, 144, 255)),
transform: Transform::from_xyz(0.0, 2.5, 0.0),
..default()
});
// light
commands.spawn(PointLightBundle {
point_light: PointLight {
shadows_enabled: true,
..default()
},
transform: Transform::from_xyz(4.0, 8.0, 4.0),
..default()
});
commands.spawn(Camera3dBundle {
transform: Transform::from_xyz(-2.5, 4.5, 9.0).looking_at(Vec3::ZERO, Vec3::Y),
..default()
});
}

View File

@@ -1,6 +1,9 @@
use bevy::prelude::{Deref, DerefMut}; use bevy::{ecs::system::Resource, prelude::{Deref, DerefMut}};
use openxr::ExtensionSet; use openxr::ExtensionSet;
#[derive(Clone, Debug, Eq, PartialEq, Deref, DerefMut, Resource)]
pub struct OxrEnabledExtensions(pub OxrExtensions);
#[derive(Clone, Debug, Eq, PartialEq, Deref, DerefMut)] #[derive(Clone, Debug, Eq, PartialEq, Deref, DerefMut)]
pub struct OxrExtensions(ExtensionSet); pub struct OxrExtensions(ExtensionSet);
impl OxrExtensions { impl OxrExtensions {

View File

@@ -1,3 +1,4 @@
pub mod handtracking; pub mod handtracking;
#[cfg(feature = "passthrough")] #[cfg(feature = "passthrough")]
pub mod passthrough; pub mod passthrough;
pub mod overlay;

View File

@@ -0,0 +1,95 @@
use std::{mem, ptr};
use bevy::prelude::*;
use openxr::sys;
use crate::{
next_chain::{OxrNextChainStructBase, OxrNextChainStructProvider},
openxr::exts::OxrEnabledExtensions,
session::{OxrSessionCreateNextChain, OxrSessionCreateNextProvider},
};
pub struct OxrOverlayPlugin;
impl Plugin for OxrOverlayPlugin {
fn build(&self, app: &mut bevy::prelude::App) {
app.add_event::<OxrOverlaySessionEvent>();
app.init_resource::<OxrOverlaySettings>();
app.add_systems(First, add_overlay_info_to_chain);
}
}
#[derive(Resource)]
pub struct OxrOverlaySettings {
pub session_layer_placement: u32,
pub flags: openxr::OverlaySessionCreateFlagsEXTX,
}
impl Default for OxrOverlaySettings {
fn default() -> Self {
OxrOverlaySettings {
session_layer_placement: 0,
flags: openxr::OverlaySessionCreateFlagsEXTX::EMPTY,
}
}
}
fn add_overlay_info_to_chain(
mut chain: NonSendMut<OxrSessionCreateNextChain>,
exts: Res<OxrEnabledExtensions>,
settings: Res<OxrOverlaySettings>,
) {
if exts.other.contains(&"XR_EXTX_overlay\0".to_string()) {
chain.push(OxrSessionCreateInfoOverlay::new(
settings.flags,
settings.session_layer_placement,
));
}
}
#[derive(Event, Clone, Copy, Debug)]
pub enum OxrOverlaySessionEvent {
MainSessionVisibilityChanged {
visible: bool,
flags: openxr::OverlayMainSessionFlagsEXTX,
},
}
pub struct OxrSessionCreateInfoOverlay {
inner: sys::SessionCreateInfoOverlayEXTX,
}
impl OxrSessionCreateInfoOverlay {
pub const fn new(
flags: openxr::OverlaySessionCreateFlagsEXTX,
session_layers_placement: u32,
) -> Self {
Self {
inner: sys::SessionCreateInfoOverlayEXTX {
ty: sys::SessionCreateInfoOverlayEXTX::TYPE,
next: ptr::null(),
create_flags: flags,
session_layers_placement,
},
}
}
}
impl Default for OxrSessionCreateInfoOverlay {
fn default() -> Self {
Self::new(openxr::OverlaySessionCreateFlagsEXTX::EMPTY, 0)
}
}
impl OxrNextChainStructProvider for OxrSessionCreateInfoOverlay {
fn header(&self) -> &OxrNextChainStructBase {
unsafe { mem::transmute(&self.inner) }
}
fn set_next(&mut self, next: &OxrNextChainStructBase) {
self.inner.next = next as *const _ as *const _;
}
fn clear_next(&mut self) {
self.inner.next = ptr::null();
}
}
impl OxrSessionCreateNextProvider for OxrSessionCreateInfoOverlay {}

View File

@@ -28,7 +28,9 @@ use bevy_xr::session::XrStatus;
use bevy_xr::session::XrStatusChanged; use bevy_xr::session::XrStatusChanged;
use crate::error::OxrError; use crate::error::OxrError;
use crate::features::overlay::OxrOverlaySessionEvent;
use crate::graphics::*; use crate::graphics::*;
use crate::openxr::exts::OxrEnabledExtensions;
use crate::resources::*; use crate::resources::*;
use crate::session::OxrSession; use crate::session::OxrSession;
use crate::session::OxrSessionCreateNextChain; use crate::session::OxrSessionCreateNextChain;
@@ -97,7 +99,9 @@ impl Plugin for OxrInitPlugin {
system_id, system_id,
WgpuGraphics(device, queue, adapter_info, adapter, wgpu_instance), WgpuGraphics(device, queue, adapter_info, adapter, wgpu_instance),
session_create_info, session_create_info,
enabled_exts,
)) => { )) => {
app.insert_resource(enabled_exts);
app.add_plugins(( app.add_plugins((
RenderPlugin { RenderPlugin {
render_creation: RenderCreation::manual( render_creation: RenderCreation::manual(
@@ -197,7 +201,15 @@ pub fn update_root_transform(
} }
impl OxrInitPlugin { impl OxrInitPlugin {
fn init_xr(&self) -> Result<(OxrInstance, OxrSystemId, WgpuGraphics, SessionConfigInfo)> { fn init_xr(
&self,
) -> Result<(
OxrInstance,
OxrSystemId,
WgpuGraphics,
SessionConfigInfo,
OxrEnabledExtensions,
)> {
#[cfg(windows)] #[cfg(windows)]
let entry = OxrEntry(openxr::Entry::linked()); let entry = OxrEntry(openxr::Entry::linked());
#[cfg(not(windows))] #[cfg(not(windows))]
@@ -236,7 +248,7 @@ impl OxrInitPlugin {
let instance = entry.create_instance( let instance = entry.create_instance(
self.app_info.clone(), self.app_info.clone(),
exts, exts.clone(),
// &["XR_APILAYER_LUNARG_api_dump"], // &["XR_APILAYER_LUNARG_api_dump"],
&[], &[],
backend, backend,
@@ -274,6 +286,7 @@ impl OxrInitPlugin {
OxrSystemId(system_id), OxrSystemId(system_id),
graphics, graphics,
session_create_info, session_create_info,
OxrEnabledExtensions(exts),
)) ))
} }
} }
@@ -495,6 +508,7 @@ pub fn poll_events(
mut status: ResMut<XrStatus>, mut status: ResMut<XrStatus>,
mut changed_event: EventWriter<XrStatusChanged>, mut changed_event: EventWriter<XrStatusChanged>,
mut session_status_events: EventWriter<OxrSessionStatusEvent>, mut session_status_events: EventWriter<OxrSessionStatusEvent>,
mut overlay_writer: Option<ResMut<Events<OxrOverlaySessionEvent>>>,
) { ) {
let _span = info_span!("xr_poll_events"); let _span = info_span!("xr_poll_events");
let mut buffer = Default::default(); let mut buffer = Default::default();
@@ -534,6 +548,16 @@ pub fn poll_events(
} }
InstanceLossPending(_) => {} InstanceLossPending(_) => {}
EventsLost(e) => warn!("lost {} XR events", e.lost_event_count()), EventsLost(e) => warn!("lost {} XR events", e.lost_event_count()),
MainSessionVisibilityChangedEXTX(d) => {
if let Some(writer) = overlay_writer.as_mut() {
writer.send(OxrOverlaySessionEvent::MainSessionVisibilityChanged {
visible: d.visible(),
flags: d.flags(),
});
} else {
warn!("Overlay Event Recieved without the OverlayPlugin being added!");
}
}
_ => {} _ => {}
} }
} }

View File

@@ -26,12 +26,12 @@ pub mod graphics;
pub mod helper_traits; pub mod helper_traits;
pub mod init; pub mod init;
pub mod layer_builder; pub mod layer_builder;
pub mod next_chain;
pub mod reference_space; pub mod reference_space;
pub mod render; pub mod render;
pub mod resources; pub mod resources;
pub mod session; pub mod session;
pub mod types; pub mod types;
pub mod next_chain;
pub fn add_xr_plugins<G: PluginGroup>(plugins: G) -> PluginGroupBuilder { pub fn add_xr_plugins<G: PluginGroup>(plugins: G) -> PluginGroupBuilder {
plugins plugins
@@ -49,6 +49,7 @@ pub fn add_xr_plugins<G: PluginGroup>(plugins: G) -> PluginGroupBuilder {
.add(action_set_attaching::OxrActionAttachingPlugin) .add(action_set_attaching::OxrActionAttachingPlugin)
.add(action_binding::OxrActionBindingPlugin) .add(action_binding::OxrActionBindingPlugin)
.add(action_set_syncing::OxrActionSyncingPlugin) .add(action_set_syncing::OxrActionSyncingPlugin)
.add(features::overlay::OxrOverlayPlugin)
// .add(XrActionPlugin) // .add(XrActionPlugin)
// we should probably handle the exiting ourselfs so that we can correctly end the // we should probably handle the exiting ourselfs so that we can correctly end the
// session and instance // session and instance