fix camera jitter
This commit is contained in:
@@ -2,11 +2,13 @@ use bevy::{
|
|||||||
prelude::*,
|
prelude::*,
|
||||||
render::{
|
render::{
|
||||||
camera::{ManualTextureView, ManualTextureViewHandle, ManualTextureViews, RenderTarget},
|
camera::{ManualTextureView, ManualTextureViewHandle, ManualTextureViews, RenderTarget},
|
||||||
|
extract_component::{ExtractComponent, ExtractComponentPlugin},
|
||||||
|
extract_resource::ExtractResourcePlugin,
|
||||||
renderer::render_system,
|
renderer::render_system,
|
||||||
Render, RenderApp, RenderSet,
|
Render, RenderApp, RenderSet,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use bevy_xr::camera::{XrCameraBundle, XrProjection, XrView};
|
use bevy_xr::camera::{XrCamera, XrCameraBundle, XrProjection};
|
||||||
use openxr::{CompositionLayerFlags, ViewStateFlags};
|
use openxr::{CompositionLayerFlags, ViewStateFlags};
|
||||||
|
|
||||||
use crate::resources::*;
|
use crate::resources::*;
|
||||||
@@ -18,7 +20,11 @@ pub struct XrRenderPlugin;
|
|||||||
|
|
||||||
impl Plugin for XrRenderPlugin {
|
impl Plugin for XrRenderPlugin {
|
||||||
fn build(&self, app: &mut App) {
|
fn build(&self, app: &mut App) {
|
||||||
app.add_systems(
|
app.add_plugins((
|
||||||
|
ExtractComponentPlugin::<XrView>::default(),
|
||||||
|
ExtractResourcePlugin::<XrViews>::default(),
|
||||||
|
))
|
||||||
|
.add_systems(
|
||||||
First,
|
First,
|
||||||
(
|
(
|
||||||
init_views.run_if(resource_added::<XrGraphicsInfo>),
|
init_views.run_if(resource_added::<XrGraphicsInfo>),
|
||||||
@@ -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;
|
pub const XR_TEXTURE_INDEX: u32 = 3383858418;
|
||||||
|
|
||||||
// TODO: have cameras initialized externally and then recieved by this function.
|
// 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);
|
add_texture_view(&mut manual_texture_views, temp_tex, &graphics_info, index);
|
||||||
|
|
||||||
let entity = commands
|
let entity = commands
|
||||||
.spawn(XrCameraBundle {
|
.spawn((XrCameraBundle {
|
||||||
camera: Camera {
|
camera: Camera {
|
||||||
target: RenderTarget::TextureView(view_handle),
|
target: RenderTarget::TextureView(view_handle),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
..Default::default()
|
..Default::default()
|
||||||
})
|
},))
|
||||||
.id();
|
.id();
|
||||||
views.push(entity);
|
views.push((entity, default()));
|
||||||
}
|
}
|
||||||
commands.insert_resource(XrViews(views));
|
commands.insert_resource(XrViews(views));
|
||||||
}
|
}
|
||||||
@@ -86,27 +95,49 @@ pub fn wait_frame(mut frame_waiter: ResMut<XrFrameWaiter>, mut commands: Command
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn update_views(
|
pub fn update_views(
|
||||||
mut views: Query<(&mut Transform, &mut XrProjection), With<XrView>>,
|
mut views: Query<(&mut Transform, &mut XrProjection), With<XrCamera>>,
|
||||||
view_entities: Res<XrViews>,
|
mut view_entities: ResMut<XrViews>,
|
||||||
session: Res<XrSession>,
|
session: Res<XrSession>,
|
||||||
stage: Res<XrStage>,
|
stage: Res<XrStage>,
|
||||||
time: Res<XrTime>,
|
time: Res<XrTime>,
|
||||||
|
mut openxr_views: Local<Vec<openxr::View>>,
|
||||||
) {
|
) {
|
||||||
let _span = info_span!("xr_wait_frame");
|
let _span = info_span!("xr_wait_frame");
|
||||||
let (_flags, xr_views) = session
|
let (flags, xr_views) = session
|
||||||
.locate_views(
|
.locate_views(
|
||||||
openxr::ViewConfigurationType::PRIMARY_STEREO,
|
openxr::ViewConfigurationType::PRIMARY_STEREO,
|
||||||
**time,
|
**time,
|
||||||
&stage,
|
&stage,
|
||||||
)
|
)
|
||||||
.expect("Failed to locate views");
|
.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() {
|
for (i, view) in openxr_views.iter().enumerate() {
|
||||||
if let Some((mut transform, mut projection)) = view_entities
|
if let Some(((mut transform, mut projection), mut xr_view)) = view_entities
|
||||||
.0
|
.0
|
||||||
.get(i)
|
.get_mut(i)
|
||||||
.and_then(|entity| views.get_mut(*entity).ok())
|
.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);
|
let projection_matrix = calculate_projection(projection.near, view.fov);
|
||||||
projection.projection_matrix = projection_matrix;
|
projection.projection_matrix = projection_matrix;
|
||||||
|
|
||||||
@@ -267,37 +298,10 @@ pub fn end_frame(
|
|||||||
stage: Res<XrStage>,
|
stage: Res<XrStage>,
|
||||||
display_time: Res<XrTime>,
|
display_time: Res<XrTime>,
|
||||||
graphics_info: Res<XrGraphicsInfo>,
|
graphics_info: Res<XrGraphicsInfo>,
|
||||||
mut openxr_views: Local<Vec<openxr::View>>,
|
openxr_views: Res<XrViews>,
|
||||||
) {
|
) {
|
||||||
let _span = info_span!("xr_end_frame");
|
let _span = info_span!("xr_end_frame");
|
||||||
swapchain.release_image().unwrap();
|
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 {
|
let rect = openxr::Rect2Di {
|
||||||
offset: openxr::Offset2Di { x: 0, y: 0 },
|
offset: openxr::Offset2Di { x: 0, y: 0 },
|
||||||
extent: openxr::Extent2Di {
|
extent: openxr::Extent2Di {
|
||||||
@@ -314,8 +318,8 @@ pub fn end_frame(
|
|||||||
.space(&stage)
|
.space(&stage)
|
||||||
.views(&[
|
.views(&[
|
||||||
CompositionLayerProjectionView::new()
|
CompositionLayerProjectionView::new()
|
||||||
.pose(openxr_views[0].pose)
|
.pose(openxr_views.0[0].1.pose)
|
||||||
.fov(openxr_views[0].fov)
|
.fov(openxr_views.0[0].1.fov)
|
||||||
.sub_image(
|
.sub_image(
|
||||||
SwapchainSubImage::new()
|
SwapchainSubImage::new()
|
||||||
.swapchain(&swapchain)
|
.swapchain(&swapchain)
|
||||||
@@ -323,8 +327,8 @@ pub fn end_frame(
|
|||||||
.image_rect(rect),
|
.image_rect(rect),
|
||||||
),
|
),
|
||||||
CompositionLayerProjectionView::new()
|
CompositionLayerProjectionView::new()
|
||||||
.pose(openxr_views[1].pose)
|
.pose(openxr_views.0[1].1.pose)
|
||||||
.fov(openxr_views[1].fov)
|
.fov(openxr_views.0[1].1.fov)
|
||||||
.sub_image(
|
.sub_image(
|
||||||
SwapchainSubImage::new()
|
SwapchainSubImage::new()
|
||||||
.swapchain(&swapchain)
|
.swapchain(&swapchain)
|
||||||
|
|||||||
@@ -278,4 +278,4 @@ pub struct XrGraphicsInfo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Resource, ExtractResource)]
|
#[derive(Clone, Resource, ExtractResource)]
|
||||||
pub struct XrViews(pub Vec<Entity>);
|
pub struct XrViews(pub Vec<(Entity, openxr::View)>);
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ impl Default for XrProjection {
|
|||||||
|
|
||||||
/// Marker component for an XR view. It is the backends responsibility to update this.
|
/// Marker component for an XR view. It is the backends responsibility to update this.
|
||||||
#[derive(Clone, Copy, Component, Debug, Default)]
|
#[derive(Clone, Copy, Component, Debug, Default)]
|
||||||
pub struct XrView;
|
pub struct XrCamera;
|
||||||
|
|
||||||
impl CameraProjection for XrProjection {
|
impl CameraProjection for XrProjection {
|
||||||
fn get_projection_matrix(&self) -> Mat4 {
|
fn get_projection_matrix(&self) -> Mat4 {
|
||||||
@@ -106,7 +106,7 @@ pub struct XrCameraBundle {
|
|||||||
pub color_grading: ColorGrading,
|
pub color_grading: ColorGrading,
|
||||||
pub exposure: Exposure,
|
pub exposure: Exposure,
|
||||||
pub main_texture_usages: CameraMainTextureUsages,
|
pub main_texture_usages: CameraMainTextureUsages,
|
||||||
pub view: XrView,
|
pub view: XrCamera,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for XrCameraBundle {
|
impl Default for XrCameraBundle {
|
||||||
@@ -125,7 +125,7 @@ impl Default for XrCameraBundle {
|
|||||||
exposure: Default::default(),
|
exposure: Default::default(),
|
||||||
main_texture_usages: Default::default(),
|
main_texture_usages: Default::default(),
|
||||||
dither: DebandDither::Enabled,
|
dither: DebandDither::Enabled,
|
||||||
view: XrView,
|
view: XrCamera,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user