From e1d5de1a941188d7bf9f27730451d38a73762197 Mon Sep 17 00:00:00 2001 From: awtterpip Date: Thu, 14 Mar 2024 19:40:50 -0500 Subject: [PATCH] fix camera jitter --- crates/bevy_openxr/src/render.rs | 92 +++++++++++++++-------------- crates/bevy_openxr/src/resources.rs | 2 +- crates/bevy_xr/src/camera.rs | 6 +- 3 files changed, 52 insertions(+), 48 deletions(-) diff --git a/crates/bevy_openxr/src/render.rs b/crates/bevy_openxr/src/render.rs index effa944..58b576f 100644 --- a/crates/bevy_openxr/src/render.rs +++ b/crates/bevy_openxr/src/render.rs @@ -2,11 +2,13 @@ use bevy::{ prelude::*, render::{ camera::{ManualTextureView, ManualTextureViewHandle, ManualTextureViews, RenderTarget}, + extract_component::{ExtractComponent, ExtractComponentPlugin}, + extract_resource::ExtractResourcePlugin, renderer::render_system, Render, RenderApp, RenderSet, }, }; -use bevy_xr::camera::{XrCameraBundle, XrProjection, XrView}; +use bevy_xr::camera::{XrCamera, XrCameraBundle, XrProjection}; use openxr::{CompositionLayerFlags, ViewStateFlags}; use crate::resources::*; @@ -18,7 +20,11 @@ pub struct XrRenderPlugin; impl Plugin for XrRenderPlugin { fn build(&self, app: &mut App) { - app.add_systems( + app.add_plugins(( + ExtractComponentPlugin::::default(), + ExtractResourcePlugin::::default(), + )) + .add_systems( First, ( init_views.run_if(resource_added::), @@ -42,6 +48,9 @@ impl Plugin for XrRenderPlugin { } } +#[derive(Component, ExtractComponent, Clone)] +pub struct XrView(pub openxr::View); + pub const XR_TEXTURE_INDEX: u32 = 3383858418; // TODO: have cameras initialized externally and then recieved by this function. @@ -62,15 +71,15 @@ pub fn init_views( add_texture_view(&mut manual_texture_views, temp_tex, &graphics_info, index); let entity = commands - .spawn(XrCameraBundle { + .spawn((XrCameraBundle { camera: Camera { target: RenderTarget::TextureView(view_handle), ..Default::default() }, ..Default::default() - }) + },)) .id(); - views.push(entity); + views.push((entity, default())); } commands.insert_resource(XrViews(views)); } @@ -86,27 +95,49 @@ pub fn wait_frame(mut frame_waiter: ResMut, mut commands: Command } pub fn update_views( - mut views: Query<(&mut Transform, &mut XrProjection), With>, - view_entities: Res, + mut views: Query<(&mut Transform, &mut XrProjection), With>, + mut view_entities: ResMut, session: Res, stage: Res, time: Res, + mut openxr_views: Local>, ) { let _span = info_span!("xr_wait_frame"); - let (_flags, xr_views) = session + let (flags, xr_views) = session .locate_views( openxr::ViewConfigurationType::PRIMARY_STEREO, **time, &stage, ) .expect("Failed to locate views"); + if openxr_views.len() != xr_views.len() { + openxr_views.resize(xr_views.len(), default()); + } + match ( + flags & ViewStateFlags::ORIENTATION_VALID == ViewStateFlags::ORIENTATION_VALID, + flags & ViewStateFlags::POSITION_VALID == ViewStateFlags::POSITION_VALID, + ) { + (true, true) => *openxr_views = xr_views, + (true, false) => { + for (i, view) in openxr_views.iter_mut().enumerate() { + view.pose.orientation = xr_views[i].pose.orientation; + } + } + (false, true) => { + for (i, view) in openxr_views.iter_mut().enumerate() { + view.pose.position = xr_views[i].pose.position; + } + } + (false, false) => {} + } - for (i, view) in xr_views.iter().enumerate() { - if let Some((mut transform, mut projection)) = view_entities + for (i, view) in openxr_views.iter().enumerate() { + if let Some(((mut transform, mut projection), mut xr_view)) = view_entities .0 - .get(i) - .and_then(|entity| views.get_mut(*entity).ok()) + .get_mut(i) + .and_then(|(entity, view)| views.get_mut(*entity).ok().map(|res| (res, view))) { + *xr_view = *view; let projection_matrix = calculate_projection(projection.near, view.fov); projection.projection_matrix = projection_matrix; @@ -267,37 +298,10 @@ pub fn end_frame( stage: Res, display_time: Res, graphics_info: Res, - mut openxr_views: Local>, + openxr_views: Res, ) { let _span = info_span!("xr_end_frame"); swapchain.release_image().unwrap(); - let (flags, views) = session - .locate_views( - openxr::ViewConfigurationType::PRIMARY_STEREO, - **display_time, - &stage, - ) - .expect("Failed to locate views"); - if openxr_views.len() != views.len() { - openxr_views.resize(views.len(), default()); - } - match ( - flags & ViewStateFlags::ORIENTATION_VALID == ViewStateFlags::ORIENTATION_VALID, - flags & ViewStateFlags::POSITION_VALID == ViewStateFlags::POSITION_VALID, - ) { - (true, true) => *openxr_views = views, - (true, false) => { - for (i, view) in openxr_views.iter_mut().enumerate() { - view.pose.orientation = views[i].pose.orientation; - } - } - (false, true) => { - for (i, view) in openxr_views.iter_mut().enumerate() { - view.pose.position = views[i].pose.position; - } - } - (false, false) => {} - } let rect = openxr::Rect2Di { offset: openxr::Offset2Di { x: 0, y: 0 }, extent: openxr::Extent2Di { @@ -314,8 +318,8 @@ pub fn end_frame( .space(&stage) .views(&[ CompositionLayerProjectionView::new() - .pose(openxr_views[0].pose) - .fov(openxr_views[0].fov) + .pose(openxr_views.0[0].1.pose) + .fov(openxr_views.0[0].1.fov) .sub_image( SwapchainSubImage::new() .swapchain(&swapchain) @@ -323,8 +327,8 @@ pub fn end_frame( .image_rect(rect), ), CompositionLayerProjectionView::new() - .pose(openxr_views[1].pose) - .fov(openxr_views[1].fov) + .pose(openxr_views.0[1].1.pose) + .fov(openxr_views.0[1].1.fov) .sub_image( SwapchainSubImage::new() .swapchain(&swapchain) diff --git a/crates/bevy_openxr/src/resources.rs b/crates/bevy_openxr/src/resources.rs index 2f9d148..4154d6d 100644 --- a/crates/bevy_openxr/src/resources.rs +++ b/crates/bevy_openxr/src/resources.rs @@ -278,4 +278,4 @@ pub struct XrGraphicsInfo { } #[derive(Clone, Resource, ExtractResource)] -pub struct XrViews(pub Vec); +pub struct XrViews(pub Vec<(Entity, openxr::View)>); diff --git a/crates/bevy_xr/src/camera.rs b/crates/bevy_xr/src/camera.rs index 913262b..47f40b0 100644 --- a/crates/bevy_xr/src/camera.rs +++ b/crates/bevy_xr/src/camera.rs @@ -52,7 +52,7 @@ impl Default for XrProjection { /// Marker component for an XR view. It is the backends responsibility to update this. #[derive(Clone, Copy, Component, Debug, Default)] -pub struct XrView; +pub struct XrCamera; impl CameraProjection for XrProjection { fn get_projection_matrix(&self) -> Mat4 { @@ -106,7 +106,7 @@ pub struct XrCameraBundle { pub color_grading: ColorGrading, pub exposure: Exposure, pub main_texture_usages: CameraMainTextureUsages, - pub view: XrView, + pub view: XrCamera, } impl Default for XrCameraBundle { @@ -125,7 +125,7 @@ impl Default for XrCameraBundle { exposure: Default::default(), main_texture_usages: Default::default(), dither: DebandDither::Enabled, - view: XrView, + view: XrCamera, } } }