diff --git a/crates/bevy_openxr/src/init.rs b/crates/bevy_openxr/src/init.rs index c6633aa..34e916e 100644 --- a/crates/bevy_openxr/src/init.rs +++ b/crates/bevy_openxr/src/init.rs @@ -7,6 +7,7 @@ use bevy::render::renderer::{ }; use bevy::render::settings::RenderCreation; use bevy::render::{MainWorld, RenderApp, RenderPlugin}; +use bevy::transform::TransformSystem; use bevy::winit::{UpdateMode, WinitSettings}; use bevy_xr::session::{ handle_session, session_available, session_running, status_equals, BeginXrSession, @@ -27,6 +28,9 @@ pub enum XrPreUpdateSet { HandleEvents, } +#[derive(Component)] +pub struct XrTrackingRoot; + #[derive(Resource, Clone, Copy, PartialEq)] pub struct AppExiting(bool); @@ -71,6 +75,7 @@ impl Plugin for XrInitPlugin { synchronous_pipeline_compilation: self.synchronous_pipeline_compilation, }, ExtractResourcePlugin::::default(), + ExtractResourcePlugin::::default(), )) .add_systems( PreUpdate, @@ -93,6 +98,10 @@ impl Plugin for XrInitPlugin { .in_set(XrPreUpdateSet::HandleEvents), ), ) + .add_systems( + PostUpdate, + update_root_transform.after(TransformSystem::TransformPropagate), + ) .add_systems( Last, app_exit_xr @@ -106,13 +115,18 @@ impl Plugin for XrInitPlugin { focused_mode: UpdateMode::Continuous, unfocused_mode: UpdateMode::Continuous, }) + .init_resource::() .insert_non_send_resource(session_create_info); + app.world + .spawn((TransformBundle::default(), XrTrackingRoot)); + let render_app = app.sub_app_mut(RenderApp); render_app .insert_resource(instance) .insert_resource(system_id) .insert_resource(status) + .init_resource::() .add_systems( ExtractSchedule, transfer_xr_resources.run_if(not(session_running)), @@ -150,6 +164,15 @@ impl Plugin for XrInitPlugin { } } +pub fn update_root_transform( + mut root_transform: ResMut, + root: Query<&GlobalTransform, With>, +) { + let transform = root.single(); + + root_transform.0 = *transform; +} + fn xr_entry() -> Result { #[cfg(windows)] let entry = openxr::Entry::linked(); diff --git a/crates/bevy_openxr/src/render.rs b/crates/bevy_openxr/src/render.rs index 51d48d9..1790533 100644 --- a/crates/bevy_openxr/src/render.rs +++ b/crates/bevy_openxr/src/render.rs @@ -3,6 +3,7 @@ use bevy::{ render::{ camera::{ManualTextureView, ManualTextureViewHandle, ManualTextureViews, RenderTarget}, extract_resource::ExtractResourcePlugin, + view::ExtractedView, Render, RenderApp, RenderSet, }, transform::TransformSystem, @@ -23,8 +24,10 @@ impl Plugin for XrRenderPlugin { PreUpdate, ( init_views.run_if(resource_added::), - insert_texture_views.run_if(session_started), wait_frame.run_if(session_started), + insert_texture_views.run_if(session_started), + locate_views.run_if(session_started), + update_views.run_if(session_started), ) .chain() .after(XrPreUpdateSet::HandleEvents), @@ -42,6 +45,9 @@ impl Plugin for XrRenderPlugin { // (insert_texture_views) // .chain() // .in_set(RenderSet::PrepareAssets), + (locate_views, update_views_render_world) + .chain() + .in_set(RenderSet::PrepareAssets), (end_frame).chain().in_set(RenderSet::Cleanup), ) .run_if(session_started), @@ -155,6 +161,26 @@ pub fn update_views( } } +pub fn update_views_render_world( + views: Res, + root: Res, + mut query: Query<(&mut ExtractedView, &XrCamera)>, +) { + for (mut extracted_view, camera) in query.iter_mut() { + let Some(view) = views.get(camera.0 as usize) else { + continue; + }; + let mut transform = Transform::IDENTITY; + let openxr::Quaternionf { x, y, z, w } = view.pose.orientation; + let rotation = Quat::from_xyzw(x, y, z, w); + transform.rotation = rotation; + let openxr::Vector3f { x, y, z } = view.pose.position; + let translation = Vec3::new(x, y, z); + transform.translation = translation; + extracted_view.transform = root.0.mul_transform(transform); + } +} + fn calculate_projection(near_z: f32, fov: openxr::Fovf) -> Mat4 { // symmetric perspective for debugging // let x_fov = (self.fov.angle_left.abs() + self.fov.angle_right.abs()); diff --git a/crates/bevy_openxr/src/resources.rs b/crates/bevy_openxr/src/resources.rs index 411e064..d952a2a 100644 --- a/crates/bevy_openxr/src/resources.rs +++ b/crates/bevy_openxr/src/resources.rs @@ -293,3 +293,6 @@ impl XrSessionStarted { self.0.load(Ordering::SeqCst) } } + +#[derive(ExtractResource, Resource, Clone, Copy, Default)] +pub struct XrRootTransform(pub GlobalTransform);