borked
This commit is contained in:
@@ -13,6 +13,7 @@ android:
|
|||||||
# required: true
|
# required: true
|
||||||
uses_permission:
|
uses_permission:
|
||||||
- name: "com.oculus.permission.HAND_TRACKING"
|
- name: "com.oculus.permission.HAND_TRACKING"
|
||||||
|
- name: "android.permission.INTERNET"
|
||||||
application:
|
application:
|
||||||
label: "Bevy Openxr Android"
|
label: "Bevy Openxr Android"
|
||||||
theme: "@android:style/Theme.DeviceDefault.NoActionBar.Fullscreen"
|
theme: "@android:style/Theme.DeviceDefault.NoActionBar.Fullscreen"
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ use bevy_oxr::{
|
|||||||
graphics::{extensions::XrExtensions, XrAppInfo, XrPreferdBlendMode},
|
graphics::{extensions::XrExtensions, XrAppInfo, XrPreferdBlendMode},
|
||||||
input::XrInput,
|
input::XrInput,
|
||||||
resources::{XrFrameState, XrInstance, XrSession},
|
resources::{XrFrameState, XrInstance, XrSession},
|
||||||
xr_init::{xr_only, XrEnableRequest, XrEnableStatus},
|
xr_init::{xr_only, XrStatus},
|
||||||
xr_input::{
|
xr_input::{
|
||||||
actions::XrActionSets,
|
actions::XrActionSets,
|
||||||
debug_gizmos::OpenXrDebugRenderer,
|
debug_gizmos::OpenXrDebugRenderer,
|
||||||
@@ -41,18 +41,18 @@ use bevy_oxr::{
|
|||||||
DefaultXrPlugins,
|
DefaultXrPlugins,
|
||||||
};
|
};
|
||||||
|
|
||||||
fn input_stuff(
|
// fn input_stuff(
|
||||||
keys: Res<Input<KeyCode>>,
|
// keys: Res<Input<KeyCode>>,
|
||||||
status: Res<XrEnableStatus>,
|
// status: Res<XrEnableStatus>,
|
||||||
mut request: EventWriter<XrEnableRequest>,
|
// mut request: EventWriter<XrEnableRequest>,
|
||||||
) {
|
// ) {
|
||||||
if keys.just_pressed(KeyCode::Space) {
|
// if keys.just_pressed(KeyCode::Space) {
|
||||||
match status.into_inner() {
|
// match status.into_inner() {
|
||||||
XrEnableStatus::Enabled => request.send(XrEnableRequest::TryDisable),
|
// XrEnableStatus::Enabled => request.send(XrEnableRequest::TryDisable),
|
||||||
XrEnableStatus::Disabled => request.send(XrEnableRequest::TryEnable),
|
// XrEnableStatus::Disabled => request.send(XrEnableRequest::TryEnable),
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
mod setup;
|
mod setup;
|
||||||
use crate::setup::setup_scene;
|
use crate::setup::setup_scene;
|
||||||
@@ -66,7 +66,7 @@ pub fn main() {
|
|||||||
let mut app = App::new();
|
let mut app = App::new();
|
||||||
let mut xr_extensions = XrExtensions::default();
|
let mut xr_extensions = XrExtensions::default();
|
||||||
|
|
||||||
app.add_systems(Update, input_stuff)
|
app
|
||||||
//lets get the usual diagnostic stuff added
|
//lets get the usual diagnostic stuff added
|
||||||
.add_plugins(LogDiagnosticsPlugin::default())
|
.add_plugins(LogDiagnosticsPlugin::default())
|
||||||
.add_plugins(FrameTimeDiagnosticsPlugin)
|
.add_plugins(FrameTimeDiagnosticsPlugin)
|
||||||
|
|||||||
@@ -103,7 +103,7 @@ pub fn try_full_init(
|
|||||||
)> {
|
)> {
|
||||||
let mut system_state: SystemState<Query<&RawHandleWrapper, With<PrimaryWindow>>> =
|
let mut system_state: SystemState<Query<&RawHandleWrapper, With<PrimaryWindow>>> =
|
||||||
SystemState::new(world);
|
SystemState::new(world);
|
||||||
let primary_window = system_state.get(&world).get_single().ok().cloned();
|
let primary_window = system_state.get(world).get_single().ok().cloned();
|
||||||
let (
|
let (
|
||||||
xr_instance,
|
xr_instance,
|
||||||
setup_info,
|
setup_info,
|
||||||
|
|||||||
296
src/lib.rs
296
src/lib.rs
@@ -6,10 +6,13 @@ pub mod resources;
|
|||||||
pub mod xr_init;
|
pub mod xr_init;
|
||||||
pub mod xr_input;
|
pub mod xr_input;
|
||||||
|
|
||||||
|
use std::fs::File;
|
||||||
|
use std::io::{BufWriter, Write};
|
||||||
|
use std::net::TcpStream;
|
||||||
use std::sync::atomic::AtomicBool;
|
use std::sync::atomic::AtomicBool;
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
|
|
||||||
use crate::xr_init::RenderRestartPlugin;
|
use crate::xr_init::{StartXrSession, XrInitPlugin};
|
||||||
use crate::xr_input::hands::hand_tracking::DisableHandTracking;
|
use crate::xr_input::hands::hand_tracking::DisableHandTracking;
|
||||||
use crate::xr_input::oculus_touch::ActionSets;
|
use crate::xr_input::oculus_touch::ActionSets;
|
||||||
use bevy::app::{AppExit, PluginGroupBuilder};
|
use bevy::app::{AppExit, PluginGroupBuilder};
|
||||||
@@ -18,22 +21,25 @@ use bevy::prelude::*;
|
|||||||
use bevy::render::camera::{ManualTextureView, ManualTextureViewHandle, ManualTextureViews};
|
use bevy::render::camera::{ManualTextureView, ManualTextureViewHandle, ManualTextureViews};
|
||||||
use bevy::render::extract_resource::ExtractResourcePlugin;
|
use bevy::render::extract_resource::ExtractResourcePlugin;
|
||||||
use bevy::render::pipelined_rendering::PipelinedRenderingPlugin;
|
use bevy::render::pipelined_rendering::PipelinedRenderingPlugin;
|
||||||
use bevy::render::renderer::{render_system, RenderInstance};
|
use bevy::render::renderer::RenderInstance;
|
||||||
use bevy::render::settings::RenderCreation;
|
use bevy::render::settings::RenderCreation;
|
||||||
use bevy::render::{Render, RenderApp, RenderPlugin, RenderSet};
|
use bevy::render::{Render, RenderApp, RenderPlugin, RenderSet};
|
||||||
use bevy::window::{PresentMode, PrimaryWindow, RawHandleWrapper};
|
use bevy::window::{PresentMode, PrimaryWindow, RawHandleWrapper};
|
||||||
use eyre::anyhow;
|
|
||||||
use graphics::extensions::XrExtensions;
|
use graphics::extensions::XrExtensions;
|
||||||
use graphics::{XrAppInfo, XrPreferdBlendMode};
|
use graphics::{XrAppInfo, XrPreferdBlendMode};
|
||||||
use input::XrInput;
|
use input::XrInput;
|
||||||
use openxr as xr;
|
use openxr as xr;
|
||||||
// use passthrough::{start_passthrough, supports_passthrough, XrPassthroughLayer};
|
// use passthrough::{start_passthrough, supports_passthrough, XrPassthroughLayer};
|
||||||
use resources::*;
|
use resources::*;
|
||||||
use xr::{FormFactor, FrameWaiter};
|
use xr::FormFactor;
|
||||||
use xr_init::{xr_only, XrEnableStatus, XrRenderData};
|
use xr_init::{
|
||||||
|
xr_only, xr_render_only, CleanupXrData, XrEarlyInitPlugin, XrShouldRender, XrStatus,
|
||||||
|
};
|
||||||
use xr_input::controllers::XrControllerType;
|
use xr_input::controllers::XrControllerType;
|
||||||
use xr_input::hands::emulated::HandEmulationPlugin;
|
use xr_input::hands::emulated::HandEmulationPlugin;
|
||||||
use xr_input::hands::hand_tracking::{HandTrackingData, HandTrackingPlugin};
|
use xr_input::hands::hand_tracking::{HandTrackingData, HandTrackingPlugin};
|
||||||
|
use xr_input::hands::XrHandPlugins;
|
||||||
|
use xr_input::xr_camera::XrCameraType;
|
||||||
use xr_input::OpenXrInput;
|
use xr_input::OpenXrInput;
|
||||||
|
|
||||||
const VIEW_TYPE: xr::ViewConfigurationType = xr::ViewConfigurationType::PRIMARY_STEREO;
|
const VIEW_TYPE: xr::ViewConfigurationType = xr::ViewConfigurationType::PRIMARY_STEREO;
|
||||||
@@ -49,141 +55,119 @@ pub struct OpenXrPlugin {
|
|||||||
app_info: XrAppInfo,
|
app_info: XrAppInfo,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Resource)]
|
|
||||||
pub struct FutureXrResources(
|
|
||||||
pub Arc<
|
|
||||||
Mutex<
|
|
||||||
Option<(
|
|
||||||
XrInstance,
|
|
||||||
XrSession,
|
|
||||||
XrEnvironmentBlendMode,
|
|
||||||
XrResolution,
|
|
||||||
XrFormat,
|
|
||||||
XrSessionRunning,
|
|
||||||
XrSwapchain,
|
|
||||||
XrInput,
|
|
||||||
XrViews,
|
|
||||||
XrFrameState,
|
|
||||||
)>,
|
|
||||||
>,
|
|
||||||
>,
|
|
||||||
);
|
|
||||||
|
|
||||||
impl Plugin for OpenXrPlugin {
|
impl Plugin for OpenXrPlugin {
|
||||||
fn build(&self, app: &mut App) {
|
fn build(&self, app: &mut App) {
|
||||||
app.insert_resource(XrSessionRunning::new(AtomicBool::new(false)));
|
app.insert_resource(XrSessionRunning::new(AtomicBool::new(false)));
|
||||||
// #[cfg(target_os = "android")]
|
|
||||||
// {
|
|
||||||
// let ctx = ndk_context::android_context();
|
|
||||||
// let vm = unsafe { jni::JavaVM::from_raw(ctx.vm().cast()) }.unwrap();
|
|
||||||
// let env = vm.attach_current_thread_permanently();
|
|
||||||
// }
|
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
match graphics::try_full_init(
|
match graphics::initialize_xr_instance(
|
||||||
&mut app.world,
|
SystemState::<Query<&RawHandleWrapper, With<PrimaryWindow>>>::new(&mut app.world)
|
||||||
|
.get(&app.world)
|
||||||
|
.get_single()
|
||||||
|
.ok()
|
||||||
|
.cloned(),
|
||||||
self.reqeusted_extensions.clone(),
|
self.reqeusted_extensions.clone(),
|
||||||
self.prefered_blend_mode,
|
self.prefered_blend_mode,
|
||||||
self.app_info.clone(),
|
self.app_info.clone(),
|
||||||
) {
|
) {
|
||||||
Ok((device, queue, adapter_info, render_adapter, instance)) => {
|
Ok((
|
||||||
|
xr_instance,
|
||||||
|
oxr_session_setup_info,
|
||||||
|
blend_mode,
|
||||||
|
device,
|
||||||
|
queue,
|
||||||
|
adapter_info,
|
||||||
|
render_adapter,
|
||||||
|
instance,
|
||||||
|
)) => {
|
||||||
debug!("Configured wgpu adapter Limits: {:#?}", device.limits());
|
debug!("Configured wgpu adapter Limits: {:#?}", device.limits());
|
||||||
debug!("Configured wgpu adapter Features: {:#?}", device.features());
|
debug!("Configured wgpu adapter Features: {:#?}", device.features());
|
||||||
warn!("Starting in Xr");
|
warn!("Starting with OpenXR Instance");
|
||||||
app.insert_resource(ActionSets(vec![]));
|
app.insert_resource(ActionSets(vec![]));
|
||||||
|
app.insert_resource(xr_instance);
|
||||||
|
app.insert_resource(blend_mode);
|
||||||
|
app.insert_non_send_resource(oxr_session_setup_info);
|
||||||
|
let render_instance = RenderInstance(instance.into());
|
||||||
|
app.insert_resource(render_instance.clone());
|
||||||
app.add_plugins(RenderPlugin {
|
app.add_plugins(RenderPlugin {
|
||||||
render_creation: RenderCreation::Manual(
|
render_creation: RenderCreation::Manual(
|
||||||
device,
|
device,
|
||||||
queue,
|
queue,
|
||||||
adapter_info,
|
adapter_info,
|
||||||
render_adapter,
|
render_adapter,
|
||||||
instance,
|
render_instance,
|
||||||
),
|
),
|
||||||
});
|
});
|
||||||
app.insert_resource(XrEnableStatus::Disabled);
|
app.insert_resource(XrStatus::Disabled);
|
||||||
|
app.world.send_event(StartXrSession);
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
warn!("OpenXR Failed to initialize: {}", err);
|
warn!("OpenXR Instance Failed to initialize: {}", err);
|
||||||
app.add_plugins(RenderPlugin::default());
|
app.add_plugins(RenderPlugin::default());
|
||||||
app.add_plugins(ExtractResourcePlugin::<XrEnableStatus>::default());
|
app.insert_resource(XrStatus::NoInstance);
|
||||||
app.insert_resource(XrEnableStatus::Disabled);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// app.add_systems(PreUpdate, mr_test);
|
|
||||||
#[cfg(target_arch = "wasm32")]
|
#[cfg(target_arch = "wasm32")]
|
||||||
{
|
{
|
||||||
app.add_plugins(RenderPlugin::default());
|
app.add_plugins(RenderPlugin::default());
|
||||||
app.insert_resource(XrEnableStatus::Disabled);
|
app.insert_resource(XrStatus::Disabled);
|
||||||
}
|
}
|
||||||
app.add_plugins(ExtractResourcePlugin::<XrEnableStatus>::default());
|
|
||||||
app.add_systems(
|
app.add_systems(
|
||||||
PreUpdate,
|
PreUpdate,
|
||||||
(xr_poll_events, xr_begin_frame.run_if(xr_only())).chain(),
|
xr_poll_events.run_if(|status: Res<XrStatus>| *status != XrStatus::NoInstance),
|
||||||
);
|
);
|
||||||
}
|
app.add_systems(
|
||||||
|
PreUpdate,
|
||||||
fn finish(&self, app: &mut App) {
|
(
|
||||||
// TODO: Split this up into the indevidual resources
|
xr_reset_should_render,
|
||||||
// app.world.get_resource::<XrEnableStatus>() == Some(&XrEnableStatus::Enabled)
|
apply_deferred,
|
||||||
if true {
|
xr_wait_frame.run_if(xr_only()),
|
||||||
warn!("finished xr init");
|
apply_deferred,
|
||||||
let xr_instance = app
|
locate_views.run_if(xr_only()),
|
||||||
.world
|
apply_deferred,
|
||||||
.get_resource::<XrInstance>()
|
)
|
||||||
.expect("should exist");
|
.chain()
|
||||||
let xr_session = app.world.get_resource::<XrSession>().expect("should exist");
|
.after(xr_poll_events),
|
||||||
let hands = xr_instance.exts().ext_hand_tracking.is_some()
|
);
|
||||||
&& xr_instance
|
let render_app = app.sub_app_mut(RenderApp);
|
||||||
.supports_hand_tracking(
|
render_app.add_systems(
|
||||||
xr_instance
|
Render,
|
||||||
.system(FormFactor::HEAD_MOUNTED_DISPLAY)
|
xr_begin_frame
|
||||||
.unwrap(),
|
.run_if(xr_only())
|
||||||
)
|
.run_if(xr_render_only())
|
||||||
.is_ok_and(|v| v);
|
.after(RenderSet::ExtractCommands)
|
||||||
if hands {
|
.before(xr_pre_frame),
|
||||||
app.insert_resource(HandTrackingData::new(xr_session).unwrap());
|
);
|
||||||
} else {
|
render_app.add_systems(
|
||||||
app.insert_resource(DisableHandTracking::Both);
|
Render,
|
||||||
}
|
xr_pre_frame
|
||||||
let xr_swapchain = app
|
.run_if(xr_only())
|
||||||
.world
|
.run_if(xr_render_only())
|
||||||
.get_resource::<XrSwapchain>()
|
.in_set(RenderSet::Prepare),
|
||||||
.expect("should exist");
|
);
|
||||||
let xr_resolution = app
|
render_app.add_systems(
|
||||||
.world
|
Render,
|
||||||
.get_resource::<XrResolution>()
|
(locate_views, xr_input::xr_camera::xr_camera_head_sync)
|
||||||
.expect("should exist");
|
.chain()
|
||||||
let xr_format = app.world.get_resource::<XrFormat>().expect("should exist");
|
.run_if(xr_only())
|
||||||
|
.run_if(xr_render_only())
|
||||||
let (left, right) = xr_swapchain.get_render_views();
|
.in_set(RenderSet::Prepare),
|
||||||
let left = ManualTextureView {
|
);
|
||||||
texture_view: left.into(),
|
render_app.add_systems(
|
||||||
size: **xr_resolution,
|
Render,
|
||||||
format: **xr_format,
|
xr_end_frame
|
||||||
};
|
.run_if(xr_only())
|
||||||
let right = ManualTextureView {
|
.run_if(xr_render_only())
|
||||||
texture_view: right.into(),
|
.after(RenderSet::Render),
|
||||||
size: **xr_resolution,
|
);
|
||||||
format: **xr_format,
|
render_app.insert_resource(TcpConnection(
|
||||||
};
|
TcpStream::connect("192.168.2.100:6969").unwrap(),
|
||||||
let mut manual_texture_views = app.world.resource_mut::<ManualTextureViews>();
|
));
|
||||||
manual_texture_views.insert(LEFT_XR_TEXTURE_HANDLE, left);
|
|
||||||
manual_texture_views.insert(RIGHT_XR_TEXTURE_HANDLE, right);
|
|
||||||
drop(manual_texture_views);
|
|
||||||
let render_app = app.sub_app_mut(RenderApp);
|
|
||||||
render_app.add_systems(
|
|
||||||
Render,
|
|
||||||
(
|
|
||||||
post_frame
|
|
||||||
.run_if(xr_only())
|
|
||||||
.before(render_system)
|
|
||||||
.after(RenderSet::ExtractCommands),
|
|
||||||
end_frame.run_if(xr_only()).after(render_system),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Resource)]
|
||||||
|
struct TcpConnection(TcpStream);
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct DefaultXrPlugins {
|
pub struct DefaultXrPlugins {
|
||||||
pub reqeusted_extensions: XrExtensions,
|
pub reqeusted_extensions: XrExtensions,
|
||||||
@@ -203,11 +187,10 @@ impl PluginGroup for DefaultXrPlugins {
|
|||||||
app_info: self.app_info.clone(),
|
app_info: self.app_info.clone(),
|
||||||
})
|
})
|
||||||
.add_after::<OpenXrPlugin, _>(OpenXrInput::new(XrControllerType::OculusTouch))
|
.add_after::<OpenXrPlugin, _>(OpenXrInput::new(XrControllerType::OculusTouch))
|
||||||
.add_before::<OpenXrPlugin, _>(RenderRestartPlugin)
|
.add_after::<OpenXrPlugin, _>(XrInitPlugin)
|
||||||
.add(HandEmulationPlugin)
|
.add_before::<OpenXrPlugin, _>(XrEarlyInitPlugin)
|
||||||
.add(HandTrackingPlugin)
|
.add(XrHandPlugins)
|
||||||
.add(XrResourcePlugin)
|
.add(XrResourcePlugin)
|
||||||
// .add(xr_init::RenderRestartPlugin)
|
|
||||||
.set(WindowPlugin {
|
.set(WindowPlugin {
|
||||||
#[cfg(not(target_os = "android"))]
|
#[cfg(not(target_os = "android"))]
|
||||||
primary_window: Some(Window {
|
primary_window: Some(Window {
|
||||||
@@ -227,11 +210,16 @@ impl PluginGroup for DefaultXrPlugins {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn xr_poll_events(
|
fn xr_reset_should_render(mut should: ResMut<XrShouldRender>) {
|
||||||
|
**should = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn xr_poll_events(
|
||||||
instance: Option<Res<XrInstance>>,
|
instance: Option<Res<XrInstance>>,
|
||||||
session: Option<Res<XrSession>>,
|
session: Option<Res<XrSession>>,
|
||||||
session_running: Res<XrSessionRunning>,
|
session_running: Res<XrSessionRunning>,
|
||||||
mut app_exit: EventWriter<AppExit>,
|
mut app_exit: EventWriter<AppExit>,
|
||||||
|
mut cleanup_xr: EventWriter<CleanupXrData>,
|
||||||
) {
|
) {
|
||||||
if let (Some(instance), Some(session)) = (instance, session) {
|
if let (Some(instance), Some(session)) = (instance, session) {
|
||||||
let _span = info_span!("xr_poll_events");
|
let _span = info_span!("xr_poll_events");
|
||||||
@@ -251,6 +239,7 @@ pub fn xr_poll_events(
|
|||||||
xr::SessionState::STOPPING => {
|
xr::SessionState::STOPPING => {
|
||||||
session.end().unwrap();
|
session.end().unwrap();
|
||||||
session_running.store(false, std::sync::atomic::Ordering::Relaxed);
|
session_running.store(false, std::sync::atomic::Ordering::Relaxed);
|
||||||
|
cleanup_xr.send_default();
|
||||||
}
|
}
|
||||||
xr::SessionState::EXITING | xr::SessionState::LOSS_PENDING => {
|
xr::SessionState::EXITING | xr::SessionState::LOSS_PENDING => {
|
||||||
// app_exit.send(AppExit);
|
// app_exit.send(AppExit);
|
||||||
@@ -260,7 +249,9 @@ pub fn xr_poll_events(
|
|||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
InstanceLossPending(_) => return,
|
InstanceLossPending(_) => {
|
||||||
|
app_exit.send_default();
|
||||||
|
}
|
||||||
EventsLost(e) => {
|
EventsLost(e) => {
|
||||||
warn!("lost {} XR events", e.lost_event_count());
|
warn!("lost {} XR events", e.lost_event_count());
|
||||||
}
|
}
|
||||||
@@ -270,13 +261,15 @@ pub fn xr_poll_events(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn xr_begin_frame(
|
fn xr_begin_frame(swapchain: Res<XrSwapchain>) {
|
||||||
session: Res<XrSession>,
|
let _span = info_span!("xr_begin_frame").entered();
|
||||||
|
swapchain.begin().unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn xr_wait_frame(
|
||||||
mut frame_state: ResMut<XrFrameState>,
|
mut frame_state: ResMut<XrFrameState>,
|
||||||
mut frame_waiter: ResMut<XrFrameWaiter>,
|
mut frame_waiter: ResMut<XrFrameWaiter>,
|
||||||
swapchain: Res<XrSwapchain>,
|
mut should_render: ResMut<XrShouldRender>,
|
||||||
mut views: ResMut<XrViews>,
|
|
||||||
input: Res<XrInput>,
|
|
||||||
) {
|
) {
|
||||||
{
|
{
|
||||||
let _span = info_span!("xr_wait_frame").entered();
|
let _span = info_span!("xr_wait_frame").entered();
|
||||||
@@ -287,21 +280,11 @@ pub fn xr_begin_frame(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
**should_render = frame_state.should_render;
|
||||||
{
|
|
||||||
let _span = info_span!("xr_begin_frame").entered();
|
|
||||||
swapchain.begin().unwrap()
|
|
||||||
}
|
|
||||||
{
|
|
||||||
let _span = info_span!("xr_locate_views").entered();
|
|
||||||
**views = session
|
|
||||||
.locate_views(VIEW_TYPE, frame_state.predicted_display_time, &input.stage)
|
|
||||||
.unwrap()
|
|
||||||
.1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn post_frame(
|
pub fn xr_pre_frame(
|
||||||
resolution: Res<XrResolution>,
|
resolution: Res<XrResolution>,
|
||||||
format: Res<XrFormat>,
|
format: Res<XrFormat>,
|
||||||
swapchain: Res<XrSwapchain>,
|
swapchain: Res<XrSwapchain>,
|
||||||
@@ -313,7 +296,9 @@ pub fn post_frame(
|
|||||||
}
|
}
|
||||||
{
|
{
|
||||||
let _span = info_span!("xr_wait_image").entered();
|
let _span = info_span!("xr_wait_image").entered();
|
||||||
|
info!("wait image");
|
||||||
swapchain.wait_image().unwrap();
|
swapchain.wait_image().unwrap();
|
||||||
|
info!("waited image");
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
let _span = info_span!("xr_update_manual_texture_views").entered();
|
let _span = info_span!("xr_update_manual_texture_views").entered();
|
||||||
@@ -333,36 +318,51 @@ pub fn post_frame(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn end_frame(
|
pub fn xr_end_frame(
|
||||||
xr_frame_state: Option<Res<XrFrameState>>,
|
xr_frame_state: Res<XrFrameState>,
|
||||||
views: Option<Res<XrViews>>,
|
views: Res<XrViews>,
|
||||||
input: Option<Res<XrInput>>,
|
input: Res<XrInput>,
|
||||||
swapchain: Option<Res<XrSwapchain>>,
|
swapchain: Res<XrSwapchain>,
|
||||||
resolution: Option<Res<XrResolution>>,
|
resolution: Res<XrResolution>,
|
||||||
environment_blend_mode: Option<Res<XrEnvironmentBlendMode>>,
|
environment_blend_mode: Res<XrEnvironmentBlendMode>,
|
||||||
// _main_thread: NonSend<()>,
|
mut connection: ResMut<TcpConnection>,
|
||||||
#[cfg(target_os = "android")] mut attached: Local<bool>,
|
cams: Query<(&Transform, &XrCameraType)>,
|
||||||
// passthrough_layer: Option<Res<XrPassthroughLayer>>,
|
|
||||||
) {
|
) {
|
||||||
let xr_frame_state = xr_frame_state.unwrap();
|
|
||||||
let views = views.unwrap();
|
|
||||||
let input = input.unwrap();
|
|
||||||
let swapchain = swapchain.unwrap();
|
|
||||||
let resolution = resolution.unwrap();
|
|
||||||
let environment_blend_mode = environment_blend_mode.unwrap();
|
|
||||||
|
|
||||||
#[cfg(target_os = "android")]
|
#[cfg(target_os = "android")]
|
||||||
// if !*attached {
|
|
||||||
{
|
{
|
||||||
let ctx = ndk_context::android_context();
|
let ctx = ndk_context::android_context();
|
||||||
let vm = unsafe { jni::JavaVM::from_raw(ctx.vm().cast()) }.unwrap();
|
let vm = unsafe { jni::JavaVM::from_raw(ctx.vm().cast()) }.unwrap();
|
||||||
let env = vm.attach_current_thread_as_daemon();
|
let env = vm.attach_current_thread_as_daemon();
|
||||||
*attached = true;
|
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
let _span = info_span!("xr_release_image").entered();
|
let _span = info_span!("xr_release_image").entered();
|
||||||
swapchain.release_image().unwrap();
|
swapchain.release_image().unwrap();
|
||||||
}
|
}
|
||||||
|
let mut cam = None;
|
||||||
|
for (t, c) in &cams {
|
||||||
|
if *c == XrCameraType::Xr(xr_input::xr_camera::Eye::Left) {
|
||||||
|
cam = Some(*t);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let _ = std::writeln!(
|
||||||
|
&mut connection.0,
|
||||||
|
"{},{},{},{},{},{},{},{},{},{},{},{},{},{}",
|
||||||
|
views[0].pose.position.x,
|
||||||
|
views[0].pose.position.y,
|
||||||
|
views[0].pose.position.z,
|
||||||
|
views[0].pose.orientation.x,
|
||||||
|
views[0].pose.orientation.y,
|
||||||
|
views[0].pose.orientation.z,
|
||||||
|
views[0].pose.orientation.w,
|
||||||
|
cam.unwrap().translation.x,
|
||||||
|
cam.unwrap().translation.y,
|
||||||
|
cam.unwrap().translation.z,
|
||||||
|
cam.unwrap().rotation.x,
|
||||||
|
cam.unwrap().rotation.y,
|
||||||
|
cam.unwrap().rotation.z,
|
||||||
|
cam.unwrap().rotation.w,
|
||||||
|
);
|
||||||
{
|
{
|
||||||
let _span = info_span!("xr_end_frame").entered();
|
let _span = info_span!("xr_end_frame").entered();
|
||||||
let result = swapchain.end(
|
let result = swapchain.end(
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ use std::sync::Mutex;
|
|||||||
use crate::input::XrInput;
|
use crate::input::XrInput;
|
||||||
// use crate::passthrough::XrPassthroughLayer;
|
// use crate::passthrough::XrPassthroughLayer;
|
||||||
use crate::resource_macros::*;
|
use crate::resource_macros::*;
|
||||||
use crate::xr_init::XrEnableStatus;
|
use crate::xr_init::XrStatus;
|
||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
use bevy::render::extract_resource::ExtractResourcePlugin;
|
use bevy::render::extract_resource::ExtractResourcePlugin;
|
||||||
use openxr as xr;
|
use openxr as xr;
|
||||||
@@ -27,7 +27,6 @@ pub(crate) struct VulkanOXrSessionSetupInfo {
|
|||||||
pub(crate) vk_instance_ptr: *const c_void,
|
pub(crate) vk_instance_ptr: *const c_void,
|
||||||
pub(crate) queue_family_index: u32,
|
pub(crate) queue_family_index: u32,
|
||||||
pub(crate) xr_system_id: xr::SystemId,
|
pub(crate) xr_system_id: xr::SystemId,
|
||||||
// pub(crate) swapchain_create_info: xr::SwapchainCreateInfo<xr::Vulkan>
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) enum OXrSessionSetupInfo {
|
pub(crate) enum OXrSessionSetupInfo {
|
||||||
@@ -46,6 +45,7 @@ impl Plugin for XrResourcePlugin {
|
|||||||
app.add_plugins(ExtractResourcePlugin::<XrInput>::default());
|
app.add_plugins(ExtractResourcePlugin::<XrInput>::default());
|
||||||
app.add_plugins(ExtractResourcePlugin::<XrEnvironmentBlendMode>::default());
|
app.add_plugins(ExtractResourcePlugin::<XrEnvironmentBlendMode>::default());
|
||||||
app.add_plugins(ExtractResourcePlugin::<XrSessionRunning>::default());
|
app.add_plugins(ExtractResourcePlugin::<XrSessionRunning>::default());
|
||||||
|
app.add_plugins(ExtractResourcePlugin::<XrSession>::default());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -219,7 +219,6 @@ impl<G: xr::Graphics> SwapchainInner<G> {
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
// None =>
|
// None =>
|
||||||
info!("swapchain stream lock");
|
|
||||||
let r = self.stream.lock().unwrap().end(
|
let r = self.stream.lock().unwrap().end(
|
||||||
predicted_display_time,
|
predicted_display_time,
|
||||||
environment_blend_mode,
|
environment_blend_mode,
|
||||||
@@ -244,7 +243,6 @@ impl<G: xr::Graphics> SwapchainInner<G> {
|
|||||||
),
|
),
|
||||||
])],
|
])],
|
||||||
);
|
);
|
||||||
info!("swapchain stream done");
|
|
||||||
r
|
r
|
||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
|||||||
433
src/xr_init.rs
433
src/xr_init.rs
@@ -1,433 +0,0 @@
|
|||||||
// Just a lot of code that is meant for something way more complex but hey.
|
|
||||||
// maybe will work on that soon
|
|
||||||
|
|
||||||
use std::sync::Arc;
|
|
||||||
|
|
||||||
use bevy::{
|
|
||||||
ecs::schedule::{ExecutorKind, ScheduleLabel},
|
|
||||||
prelude::*,
|
|
||||||
render::{
|
|
||||||
extract_resource::{ExtractResource, ExtractResourcePlugin},
|
|
||||||
renderer::{
|
|
||||||
self, RenderAdapter, RenderAdapterInfo, RenderDevice, RenderInstance, RenderQueue,
|
|
||||||
},
|
|
||||||
settings::WgpuSettings,
|
|
||||||
},
|
|
||||||
window::{PrimaryWindow, RawHandleWrapper},
|
|
||||||
};
|
|
||||||
use wgpu::Instance;
|
|
||||||
|
|
||||||
use crate::{
|
|
||||||
graphics,
|
|
||||||
input::XrInput,
|
|
||||||
resources::{
|
|
||||||
OXrSessionSetupInfo, XrEnvironmentBlendMode, XrFormat, XrFrameState, XrInstance,
|
|
||||||
XrResolution, XrSession, XrSessionRunning, XrSwapchain, XrViews,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
#[derive(Resource, Clone)]
|
|
||||||
pub struct RenderCreationData {
|
|
||||||
pub device: RenderDevice,
|
|
||||||
pub queue: RenderQueue,
|
|
||||||
pub adapter_info: RenderAdapterInfo,
|
|
||||||
pub render_adapter: RenderAdapter,
|
|
||||||
pub instance: Arc<Instance>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Resource, Clone, ExtractResource)]
|
|
||||||
pub struct XrRenderData {
|
|
||||||
pub xr_instance: XrInstance,
|
|
||||||
pub xr_session: XrSession,
|
|
||||||
pub xr_blend_mode: XrEnvironmentBlendMode,
|
|
||||||
pub xr_resolution: XrResolution,
|
|
||||||
pub xr_format: XrFormat,
|
|
||||||
pub xr_session_running: XrSessionRunning,
|
|
||||||
// pub xr_frame_waiter: XrFrameWaiter,
|
|
||||||
pub xr_swapchain: XrSwapchain,
|
|
||||||
pub xr_input: XrInput,
|
|
||||||
pub xr_views: XrViews,
|
|
||||||
pub xr_frame_state: XrFrameState,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Event, Clone, Copy, Debug)]
|
|
||||||
pub enum XrEnableRequest {
|
|
||||||
TryEnable,
|
|
||||||
TryDisable,
|
|
||||||
}
|
|
||||||
#[derive(Resource, Event, Copy, Clone, PartialEq, Eq, Reflect, ExtractResource)]
|
|
||||||
pub enum XrEnableStatus {
|
|
||||||
Enabled,
|
|
||||||
Disabled,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Resource, Event, Copy, Clone, PartialEq, Eq, Debug, ExtractResource)]
|
|
||||||
pub enum XrNextEnabledState {
|
|
||||||
Enabled,
|
|
||||||
Disabled,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct RenderRestartPlugin;
|
|
||||||
|
|
||||||
#[derive(Debug, ScheduleLabel, Clone, Copy, Hash, PartialEq, Eq)]
|
|
||||||
pub struct XrPreSetup;
|
|
||||||
|
|
||||||
#[derive(Debug, ScheduleLabel, Clone, Copy, Hash, PartialEq, Eq)]
|
|
||||||
pub struct XrSetup;
|
|
||||||
|
|
||||||
#[derive(Debug, ScheduleLabel, Clone, Copy, Hash, PartialEq, Eq)]
|
|
||||||
pub struct XrPrePostSetup;
|
|
||||||
|
|
||||||
#[derive(Debug, ScheduleLabel, Clone, Copy, Hash, PartialEq, Eq)]
|
|
||||||
pub struct XrPostSetup;
|
|
||||||
|
|
||||||
#[derive(Debug, ScheduleLabel, Clone, Copy, Hash, PartialEq, Eq)]
|
|
||||||
pub struct XrPreCleanup;
|
|
||||||
|
|
||||||
#[derive(Debug, ScheduleLabel, Clone, Copy, Hash, PartialEq, Eq)]
|
|
||||||
pub struct XrCleanup;
|
|
||||||
|
|
||||||
#[derive(Debug, ScheduleLabel, Clone, Copy, Hash, PartialEq, Eq)]
|
|
||||||
pub struct XrPostCleanup;
|
|
||||||
|
|
||||||
#[derive(Debug, ScheduleLabel, Clone, Copy, Hash, PartialEq, Eq)]
|
|
||||||
pub struct XrPreRenderUpdate;
|
|
||||||
|
|
||||||
#[derive(Debug, ScheduleLabel, Clone, Copy, Hash, PartialEq, Eq)]
|
|
||||||
pub struct XrRenderUpdate;
|
|
||||||
|
|
||||||
#[derive(Debug, ScheduleLabel, Clone, Copy, Hash, PartialEq, Eq)]
|
|
||||||
pub struct XrPostRenderUpdate;
|
|
||||||
|
|
||||||
pub fn xr_only() -> impl FnMut(Option<Res<'_, XrEnableStatus>>, Res<XrSessionRunning>) -> bool {
|
|
||||||
|status, running| {
|
|
||||||
resource_exists_and_equals(XrEnableStatus::Enabled)(status)
|
|
||||||
&& running.load(std::sync::atomic::Ordering::Relaxed)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Plugin for RenderRestartPlugin {
|
|
||||||
fn build(&self, app: &mut App) {
|
|
||||||
add_schedules(app);
|
|
||||||
app.add_plugins(ExtractResourcePlugin::<XrRenderData>::default())
|
|
||||||
.add_event::<XrEnableRequest>()
|
|
||||||
.add_event::<XrEnableStatus>()
|
|
||||||
.add_event::<StartXrSession>()
|
|
||||||
.add_event::<EndXrSession>()
|
|
||||||
.add_systems(
|
|
||||||
PreUpdate,
|
|
||||||
setup_xr
|
|
||||||
.run_if(|running: Res<XrSessionRunning>| {
|
|
||||||
running.load(std::sync::atomic::Ordering::Relaxed)
|
|
||||||
})
|
|
||||||
.run_if(run_once()),
|
|
||||||
)
|
|
||||||
.add_systems(
|
|
||||||
PostUpdate,
|
|
||||||
update_xr_stuff.run_if(on_event::<XrEnableRequest>()),
|
|
||||||
)
|
|
||||||
.add_systems(XrPreRenderUpdate, decide_next_xr_state)
|
|
||||||
.add_systems(XrPostRenderUpdate, clear_events)
|
|
||||||
.add_systems(
|
|
||||||
XrRenderUpdate,
|
|
||||||
(
|
|
||||||
cleanup_xr.run_if(resource_exists_and_equals(XrNextEnabledState::Disabled)),
|
|
||||||
// handle_xr_enable_requests,
|
|
||||||
apply_deferred,
|
|
||||||
setup_xr, /* .run_if(resource_exists_and_equals(XrEnableStatus::Enabled)) */
|
|
||||||
)
|
|
||||||
.chain(),
|
|
||||||
)
|
|
||||||
.add_systems(XrCleanup, cleanup_oxr_session);
|
|
||||||
app.add_systems(
|
|
||||||
PostUpdate,
|
|
||||||
start_xr_session.run_if(on_event::<StartXrSession>()),
|
|
||||||
);
|
|
||||||
app.add_systems(
|
|
||||||
PostUpdate,
|
|
||||||
stop_xr_session.run_if(on_event::<EndXrSession>()),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn clear_events(mut events: ResMut<Events<XrEnableRequest>>) {
|
|
||||||
events.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
fn add_schedules(app: &mut App) {
|
|
||||||
let schedules = [
|
|
||||||
Schedule::new(XrPreSetup),
|
|
||||||
Schedule::new(XrSetup),
|
|
||||||
Schedule::new(XrPrePostSetup),
|
|
||||||
Schedule::new(XrPostSetup),
|
|
||||||
Schedule::new(XrPreRenderUpdate),
|
|
||||||
Schedule::new(XrRenderUpdate),
|
|
||||||
Schedule::new(XrPostRenderUpdate),
|
|
||||||
Schedule::new(XrPreCleanup),
|
|
||||||
Schedule::new(XrCleanup),
|
|
||||||
Schedule::new(XrPostCleanup),
|
|
||||||
];
|
|
||||||
for mut schedule in schedules {
|
|
||||||
schedule.set_executor_kind(ExecutorKind::SingleThreaded);
|
|
||||||
schedule.set_apply_final_deferred(true);
|
|
||||||
app.add_schedule(schedule);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn setup_xr(world: &mut World) {
|
|
||||||
info!("running setup schedule :3");
|
|
||||||
world.insert_resource(XrEnableStatus::Enabled);
|
|
||||||
world.run_schedule(XrPreSetup);
|
|
||||||
world.run_schedule(XrSetup);
|
|
||||||
world.run_schedule(XrPrePostSetup);
|
|
||||||
world.run_schedule(XrPostSetup);
|
|
||||||
}
|
|
||||||
fn cleanup_xr(world: &mut World) {
|
|
||||||
world.run_schedule(XrPreCleanup);
|
|
||||||
world.run_schedule(XrCleanup);
|
|
||||||
world.run_schedule(XrPostCleanup);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn cleanup_oxr_session(xr_status: Option<Res<XrEnableStatus>>, session: Option<ResMut<XrSession>>) {
|
|
||||||
if let (Some(XrEnableStatus::Disabled), Some(s)) = (xr_status.map(|v| v.into_inner()), session)
|
|
||||||
{
|
|
||||||
s.into_inner().request_exit().unwrap();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn update_xr_stuff(world: &mut World) {
|
|
||||||
world.run_schedule(XrPreRenderUpdate);
|
|
||||||
world.run_schedule(XrRenderUpdate);
|
|
||||||
world.run_schedule(XrPostRenderUpdate);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Event, Clone, Copy, Default)]
|
|
||||||
pub struct StartXrSession;
|
|
||||||
|
|
||||||
#[derive(Event, Clone, Copy, Default)]
|
|
||||||
pub struct EndXrSession;
|
|
||||||
|
|
||||||
fn start_xr_session(
|
|
||||||
mut commands: Commands,
|
|
||||||
instance: Res<XrInstance>,
|
|
||||||
primary_window: Query<&RawHandleWrapper, With<PrimaryWindow>>,
|
|
||||||
setup_info: NonSend<OXrSessionSetupInfo>,
|
|
||||||
render_device: Res<RenderDevice>,
|
|
||||||
render_adapter: Res<RenderAdapter>,
|
|
||||||
render_instance: Res<RenderInstance>,
|
|
||||||
) {
|
|
||||||
let (
|
|
||||||
xr_session,
|
|
||||||
xr_resolution,
|
|
||||||
xr_format,
|
|
||||||
xr_session_running,
|
|
||||||
xr_frame_waiter,
|
|
||||||
xr_swapchain,
|
|
||||||
xr_input,
|
|
||||||
xr_views,
|
|
||||||
xr_frame_state,
|
|
||||||
) = match graphics::start_xr_session(
|
|
||||||
primary_window.get_single().cloned().ok(),
|
|
||||||
&setup_info,
|
|
||||||
&instance,
|
|
||||||
&render_device,
|
|
||||||
&render_adapter,
|
|
||||||
&render_instance,
|
|
||||||
) {
|
|
||||||
Ok(data) => data,
|
|
||||||
Err(err) => {
|
|
||||||
error!("Unable to start OpenXR Session: {}", err);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
commands.insert_resource(xr_session);
|
|
||||||
commands.insert_resource(xr_resolution);
|
|
||||||
commands.insert_resource(xr_format);
|
|
||||||
commands.insert_resource(xr_session_running);
|
|
||||||
commands.insert_resource(xr_frame_waiter);
|
|
||||||
commands.insert_resource(xr_swapchain);
|
|
||||||
commands.insert_resource(xr_input);
|
|
||||||
commands.insert_resource(xr_views);
|
|
||||||
commands.insert_resource(xr_frame_state);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn stop_xr_session(mut commands: Commands, session: ResMut<XrSession>) {
|
|
||||||
match session.request_exit() {
|
|
||||||
Ok(_) => {}
|
|
||||||
Err(err) => {
|
|
||||||
error!("Error while trying to request session exit: {}", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// fn handle_xr_enable_requests(
|
|
||||||
// primary_window: Query<&RawHandleWrapper, With<PrimaryWindow>>,
|
|
||||||
// mut commands: Commands,
|
|
||||||
// next_state: Res<XrNextEnabledState>,
|
|
||||||
// on_main: Option<NonSend<ForceMain>>,
|
|
||||||
// ) {
|
|
||||||
// // Just to force this system onto the main thread because of unsafe code
|
|
||||||
// let _ = on_main;
|
|
||||||
//
|
|
||||||
// let (creation_data, xr_data) = match next_state.into_inner() {
|
|
||||||
// XrNextEnabledState::Enabled => {
|
|
||||||
// let (
|
|
||||||
// device,
|
|
||||||
// queue,
|
|
||||||
// adapter_info,
|
|
||||||
// render_adapter,
|
|
||||||
// instance,
|
|
||||||
// xr_instance,
|
|
||||||
// session,
|
|
||||||
// blend_mode,
|
|
||||||
// resolution,
|
|
||||||
// format,
|
|
||||||
// session_running,
|
|
||||||
// frame_waiter,
|
|
||||||
// swapchain,
|
|
||||||
// input,
|
|
||||||
// views,
|
|
||||||
// frame_state,
|
|
||||||
// ) = graphics::initialize_xr_graphics(primary_window.get_single().ok().cloned())
|
|
||||||
// .unwrap();
|
|
||||||
//
|
|
||||||
// commands.insert_resource(XrEnableStatus::Enabled);
|
|
||||||
// (
|
|
||||||
// RenderCreationData {
|
|
||||||
// device,
|
|
||||||
// queue,
|
|
||||||
// adapter_info,
|
|
||||||
// render_adapter,
|
|
||||||
// instance: Arc::new(instance),
|
|
||||||
// },
|
|
||||||
// Some(XrRenderData {
|
|
||||||
// xr_instance,
|
|
||||||
// xr_session: session,
|
|
||||||
// xr_blend_mode: blend_mode,
|
|
||||||
// xr_resolution: resolution,
|
|
||||||
// xr_format: format,
|
|
||||||
// xr_session_running: session_running,
|
|
||||||
// xr_frame_waiter: frame_waiter,
|
|
||||||
// xr_swapchain: swapchain,
|
|
||||||
// xr_input: input,
|
|
||||||
// xr_views: views,
|
|
||||||
// xr_frame_state: frame_state,
|
|
||||||
// }),
|
|
||||||
// )
|
|
||||||
// }
|
|
||||||
// XrNextEnabledState::Disabled => (
|
|
||||||
// init_non_xr_graphics(primary_window.get_single().ok().cloned()),
|
|
||||||
// None,
|
|
||||||
// ),
|
|
||||||
// };
|
|
||||||
//
|
|
||||||
// commands.insert_resource(creation_data.device);
|
|
||||||
// commands.insert_resource(creation_data.queue);
|
|
||||||
// commands.insert_resource(RenderInstance(creation_data.instance));
|
|
||||||
// commands.insert_resource(creation_data.adapter_info);
|
|
||||||
// commands.insert_resource(creation_data.render_adapter);
|
|
||||||
//
|
|
||||||
// if let Some(xr_data) = xr_data {
|
|
||||||
// // TODO: Remove this lib.rs:144
|
|
||||||
// commands.insert_resource(xr_data.clone());
|
|
||||||
//
|
|
||||||
// commands.insert_resource(xr_data.xr_instance);
|
|
||||||
// commands.insert_resource(xr_data.xr_session);
|
|
||||||
// commands.insert_resource(xr_data.xr_blend_mode);
|
|
||||||
// commands.insert_resource(xr_data.xr_resolution);
|
|
||||||
// commands.insert_resource(xr_data.xr_format);
|
|
||||||
// commands.insert_resource(xr_data.xr_session_running);
|
|
||||||
// commands.insert_resource(xr_data.xr_frame_waiter);
|
|
||||||
// commands.insert_resource(xr_data.xr_input);
|
|
||||||
// commands.insert_resource(xr_data.xr_views);
|
|
||||||
// commands.insert_resource(xr_data.xr_frame_state);
|
|
||||||
// commands.insert_resource(xr_data.xr_swapchain);
|
|
||||||
// } else {
|
|
||||||
// commands.remove_resource::<XrRenderData>();
|
|
||||||
//
|
|
||||||
// commands.remove_resource::<XrInstance>();
|
|
||||||
// commands.remove_resource::<XrSession>();
|
|
||||||
// commands.remove_resource::<XrEnvironmentBlendMode>();
|
|
||||||
// commands.remove_resource::<XrResolution>();
|
|
||||||
// commands.remove_resource::<XrFormat>();
|
|
||||||
// commands.remove_resource::<XrSessionRunning>();
|
|
||||||
// commands.remove_resource::<XrFrameWaiter>();
|
|
||||||
// commands.remove_resource::<XrSwapchain>();
|
|
||||||
// commands.remove_resource::<XrInput>();
|
|
||||||
// commands.remove_resource::<XrViews>();
|
|
||||||
// commands.remove_resource::<XrFrameState>();
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
fn decide_next_xr_state(
|
|
||||||
mut commands: Commands,
|
|
||||||
mut events: EventReader<XrEnableRequest>,
|
|
||||||
xr_status: Option<Res<XrEnableStatus>>,
|
|
||||||
) {
|
|
||||||
info!("hm");
|
|
||||||
let request = match events.read().next() {
|
|
||||||
Some(v) => v,
|
|
||||||
None => return,
|
|
||||||
};
|
|
||||||
info!("ok");
|
|
||||||
match (request, xr_status.as_deref()) {
|
|
||||||
(XrEnableRequest::TryEnable, Some(XrEnableStatus::Enabled)) => {
|
|
||||||
info!("Xr Already Enabled! ignoring request");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
(XrEnableRequest::TryDisable, Some(XrEnableStatus::Disabled)) => {
|
|
||||||
info!("Xr Already Disabled! ignoring request");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// (_, Some(XrEnableStatus::Waiting)) => {
|
|
||||||
// info!("Already Handling Request! ignoring request");
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
let r = match request {
|
|
||||||
XrEnableRequest::TryEnable => XrNextEnabledState::Enabled,
|
|
||||||
XrEnableRequest::TryDisable => XrNextEnabledState::Disabled,
|
|
||||||
};
|
|
||||||
info!("{:#?}", r);
|
|
||||||
commands.insert_resource(r);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn init_non_xr_graphics(primary_window: Option<RawHandleWrapper>) -> RenderCreationData {
|
|
||||||
let settings = WgpuSettings::default();
|
|
||||||
|
|
||||||
let async_renderer = async move {
|
|
||||||
let instance = wgpu::Instance::new(wgpu::InstanceDescriptor {
|
|
||||||
// Probably a bad idea unwraping here but on the other hand no backends
|
|
||||||
backends: settings.backends.unwrap(),
|
|
||||||
dx12_shader_compiler: settings.dx12_shader_compiler.clone(),
|
|
||||||
});
|
|
||||||
let surface = primary_window.map(|wrapper| unsafe {
|
|
||||||
// SAFETY: Plugins should be set up on the main thread.
|
|
||||||
let handle = wrapper.get_handle();
|
|
||||||
instance
|
|
||||||
.create_surface(&handle)
|
|
||||||
.expect("Failed to create wgpu surface")
|
|
||||||
});
|
|
||||||
|
|
||||||
let request_adapter_options = wgpu::RequestAdapterOptions {
|
|
||||||
power_preference: settings.power_preference,
|
|
||||||
compatible_surface: surface.as_ref(),
|
|
||||||
..Default::default()
|
|
||||||
};
|
|
||||||
|
|
||||||
let (device, queue, adapter_info, render_adapter) =
|
|
||||||
renderer::initialize_renderer(&instance, &settings, &request_adapter_options).await;
|
|
||||||
debug!("Configured wgpu adapter Limits: {:#?}", device.limits());
|
|
||||||
debug!("Configured wgpu adapter Features: {:#?}", device.features());
|
|
||||||
RenderCreationData {
|
|
||||||
device,
|
|
||||||
queue,
|
|
||||||
adapter_info,
|
|
||||||
render_adapter,
|
|
||||||
instance: Arc::new(instance),
|
|
||||||
}
|
|
||||||
};
|
|
||||||
// No need for wasm in bevy_oxr web xr would be a different crate
|
|
||||||
futures_lite::future::block_on(async_renderer)
|
|
||||||
}
|
|
||||||
@@ -1,6 +1,15 @@
|
|||||||
use bevy::{app::PluginGroupBuilder, prelude::*};
|
use bevy::{app::PluginGroupBuilder, prelude::*};
|
||||||
|
use openxr::FormFactor;
|
||||||
|
|
||||||
use self::{emulated::HandEmulationPlugin, hand_tracking::HandTrackingPlugin};
|
use crate::{
|
||||||
|
resources::{XrInstance, XrSession},
|
||||||
|
xr_init::XrPreSetup,
|
||||||
|
};
|
||||||
|
|
||||||
|
use self::{
|
||||||
|
emulated::HandEmulationPlugin,
|
||||||
|
hand_tracking::{DisableHandTracking, HandTrackingData, HandTrackingPlugin},
|
||||||
|
};
|
||||||
|
|
||||||
pub mod common;
|
pub mod common;
|
||||||
pub mod emulated;
|
pub mod emulated;
|
||||||
@@ -8,12 +17,35 @@ pub mod hand_tracking;
|
|||||||
|
|
||||||
pub struct XrHandPlugins;
|
pub struct XrHandPlugins;
|
||||||
|
|
||||||
impl PluginGroup for XrHandPlugins {
|
impl Plugin for XrHandPlugins {
|
||||||
fn build(self) -> PluginGroupBuilder {
|
fn build(&self, app: &mut App) {
|
||||||
PluginGroupBuilder::start::<Self>()
|
app.add_plugins(HandTrackingPlugin)
|
||||||
.add(HandTrackingPlugin)
|
.add_plugins(HandPlugin)
|
||||||
.add(HandEmulationPlugin)
|
.add_plugins(HandEmulationPlugin);
|
||||||
.build()
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct HandPlugin;
|
||||||
|
|
||||||
|
impl Plugin for HandPlugin {
|
||||||
|
fn build(&self, app: &mut App) {
|
||||||
|
app.add_systems(XrPreSetup, check_for_handtracking);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn check_for_handtracking(
|
||||||
|
mut commands: Commands,
|
||||||
|
instance: Res<XrInstance>,
|
||||||
|
session: Res<XrSession>,
|
||||||
|
) {
|
||||||
|
let hands = instance.exts().ext_hand_tracking.is_some()
|
||||||
|
&& instance
|
||||||
|
.supports_hand_tracking(instance.system(FormFactor::HEAD_MOUNTED_DISPLAY).unwrap())
|
||||||
|
.is_ok_and(|v| v);
|
||||||
|
if hands {
|
||||||
|
commands.insert_resource(HandTrackingData::new(&session).unwrap());
|
||||||
|
} else {
|
||||||
|
commands.insert_resource(DisableHandTracking::Both);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,11 +10,11 @@ pub mod trackers;
|
|||||||
pub mod xr_camera;
|
pub mod xr_camera;
|
||||||
|
|
||||||
use crate::resources::{XrInstance, XrSession};
|
use crate::resources::{XrInstance, XrSession};
|
||||||
use crate::xr_begin_frame;
|
use crate::xr_init::{xr_only, XrPostSetup, XrPreSetup, XrSetup};
|
||||||
use crate::xr_init::{xr_only, XrPostSetup, XrSetup, XrPreSetup};
|
|
||||||
use crate::xr_input::controllers::XrControllerType;
|
use crate::xr_input::controllers::XrControllerType;
|
||||||
use crate::xr_input::oculus_touch::setup_oculus_controller;
|
use crate::xr_input::oculus_touch::setup_oculus_controller;
|
||||||
use crate::xr_input::xr_camera::{xr_camera_head_sync, Eye, XRProjection, XrCameraBundle};
|
use crate::xr_input::xr_camera::{xr_camera_head_sync, Eye, XRProjection, XrCameraBundle};
|
||||||
|
use crate::{locate_views, xr_wait_frame};
|
||||||
use bevy::app::{App, PostUpdate, Startup};
|
use bevy::app::{App, PostUpdate, Startup};
|
||||||
use bevy::ecs::entity::Entity;
|
use bevy::ecs::entity::Entity;
|
||||||
use bevy::ecs::query::With;
|
use bevy::ecs::query::With;
|
||||||
@@ -24,17 +24,19 @@ use bevy::math::Vec2;
|
|||||||
use bevy::prelude::{BuildChildren, Component, Deref, DerefMut, IntoSystemConfigs, Resource};
|
use bevy::prelude::{BuildChildren, Component, Deref, DerefMut, IntoSystemConfigs, Resource};
|
||||||
use bevy::prelude::{Commands, Plugin, PreUpdate, Quat, Res, SpatialBundle, Update, Vec3};
|
use bevy::prelude::{Commands, Plugin, PreUpdate, Quat, Res, SpatialBundle, Update, Vec3};
|
||||||
use bevy::render::camera::CameraProjectionPlugin;
|
use bevy::render::camera::CameraProjectionPlugin;
|
||||||
|
use bevy::render::extract_component::ExtractComponentPlugin;
|
||||||
use bevy::render::view::{update_frusta, VisibilitySystems};
|
use bevy::render::view::{update_frusta, VisibilitySystems};
|
||||||
use bevy::transform::TransformSystem;
|
use bevy::transform::TransformSystem;
|
||||||
use bevy::utils::HashMap;
|
use bevy::utils::HashMap;
|
||||||
use openxr::Binding;
|
use openxr::Binding;
|
||||||
|
|
||||||
use self::actions::{setup_oxr_actions, OpenXrActionsPlugin};
|
use self::actions::{setup_oxr_actions, OpenXrActionsPlugin};
|
||||||
use self::oculus_touch::{post_action_setup_oculus_controller, ActionSets, init_subaction_path};
|
use self::oculus_touch::{init_subaction_path, post_action_setup_oculus_controller, ActionSets};
|
||||||
use self::trackers::{
|
use self::trackers::{
|
||||||
adopt_open_xr_trackers, update_open_xr_controllers, OpenXRLeftEye, OpenXRRightEye,
|
adopt_open_xr_trackers, update_open_xr_controllers, OpenXRLeftEye, OpenXRRightEye,
|
||||||
OpenXRTrackingRoot,
|
OpenXRTrackingRoot,
|
||||||
};
|
};
|
||||||
|
use self::xr_camera::{XrCameraType, TransformExtract};
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
pub struct OpenXrInput {
|
pub struct OpenXrInput {
|
||||||
@@ -67,7 +69,10 @@ impl Plugin for OpenXrInput {
|
|||||||
app.add_systems(PreUpdate, action_set_system.run_if(xr_only()));
|
app.add_systems(PreUpdate, action_set_system.run_if(xr_only()));
|
||||||
app.add_systems(
|
app.add_systems(
|
||||||
PreUpdate,
|
PreUpdate,
|
||||||
xr_camera_head_sync.run_if(xr_only()).after(xr_begin_frame),
|
xr_camera_head_sync
|
||||||
|
.run_if(xr_only())
|
||||||
|
.after(xr_wait_frame)
|
||||||
|
.after(locate_views),
|
||||||
);
|
);
|
||||||
//update controller trackers
|
//update controller trackers
|
||||||
app.add_systems(Update, update_open_xr_controllers.run_if(xr_only()));
|
app.add_systems(Update, update_open_xr_controllers.run_if(xr_only()));
|
||||||
@@ -79,6 +84,9 @@ impl Plugin for OpenXrInput {
|
|||||||
);
|
);
|
||||||
app.add_systems(XrPreSetup, init_subaction_path);
|
app.add_systems(XrPreSetup, init_subaction_path);
|
||||||
app.add_systems(XrSetup, setup_xr_cameras);
|
app.add_systems(XrSetup, setup_xr_cameras);
|
||||||
|
app.add_plugins(ExtractComponentPlugin::<XrCameraType>::default());
|
||||||
|
app.add_plugins(ExtractComponentPlugin::<XRProjection>::default());
|
||||||
|
app.add_plugins(ExtractComponentPlugin::<TransformExtract>::default());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
use crate::xr_input::{QuatConv, Vec3Conv};
|
use crate::xr_input::{QuatConv, Vec3Conv};
|
||||||
use crate::{LEFT_XR_TEXTURE_HANDLE, RIGHT_XR_TEXTURE_HANDLE};
|
use crate::{LEFT_XR_TEXTURE_HANDLE, RIGHT_XR_TEXTURE_HANDLE};
|
||||||
use bevy::core_pipeline::tonemapping::{DebandDither, Tonemapping};
|
use bevy::core_pipeline::tonemapping::{DebandDither, Tonemapping};
|
||||||
|
use bevy::ecs::system::lifetimeless::Read;
|
||||||
use bevy::math::Vec3A;
|
use bevy::math::Vec3A;
|
||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
use bevy::render::camera::{CameraProjection, CameraRenderGraph, RenderTarget};
|
use bevy::render::camera::{CameraProjection, CameraRenderGraph, RenderTarget};
|
||||||
|
use bevy::render::extract_component::ExtractComponent;
|
||||||
use bevy::render::primitives::Frustum;
|
use bevy::render::primitives::Frustum;
|
||||||
use bevy::render::view::{ColorGrading, VisibleEntities};
|
use bevy::render::view::{ColorGrading, VisibleEntities};
|
||||||
use openxr::Fovf;
|
use openxr::Fovf;
|
||||||
@@ -48,6 +50,35 @@ pub enum XrCameraType {
|
|||||||
Flatscreen,
|
Flatscreen,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[derive(Component)]
|
||||||
|
pub(super) struct TransformExtract;
|
||||||
|
|
||||||
|
|
||||||
|
impl ExtractComponent for TransformExtract {
|
||||||
|
type Query = Read<Transform>;
|
||||||
|
|
||||||
|
type Filter = ();
|
||||||
|
|
||||||
|
type Out = Transform;
|
||||||
|
|
||||||
|
fn extract_component(item: bevy::ecs::query::QueryItem<'_, Self::Query>) -> Option<Self::Out> {
|
||||||
|
Some(*item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ExtractComponent for XrCameraType {
|
||||||
|
type Query = Read<Self>;
|
||||||
|
|
||||||
|
type Filter = ();
|
||||||
|
|
||||||
|
type Out = Self;
|
||||||
|
|
||||||
|
fn extract_component(item: bevy::ecs::query::QueryItem<'_, Self::Query>) -> Option<Self::Out> {
|
||||||
|
Some(*item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)]
|
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)]
|
||||||
pub enum Eye {
|
pub enum Eye {
|
||||||
Left = 0,
|
Left = 0,
|
||||||
@@ -81,7 +112,7 @@ impl XrCameraBundle {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Component, Reflect)]
|
#[derive(Debug, Clone, Component, Reflect, ExtractComponent)]
|
||||||
#[reflect(Component, Default)]
|
#[reflect(Component, Default)]
|
||||||
pub struct XRProjection {
|
pub struct XRProjection {
|
||||||
pub near: f32,
|
pub near: f32,
|
||||||
@@ -241,24 +272,21 @@ impl CameraProjection for XRProjection {
|
|||||||
|
|
||||||
pub fn xr_camera_head_sync(
|
pub fn xr_camera_head_sync(
|
||||||
views: ResMut<crate::resources::XrViews>,
|
views: ResMut<crate::resources::XrViews>,
|
||||||
query: Query<(&mut Transform, &XrCameraType, &mut XRProjection)>,
|
mut query: Query<(&mut Transform, &XrCameraType, &mut XRProjection)>,
|
||||||
) {
|
) {
|
||||||
fn f(
|
//TODO calculate HMD position
|
||||||
views: ResMut<crate::resources::XrViews>,
|
for (mut transform, camera_type, mut xr_projection) in query.iter_mut() {
|
||||||
mut query: Query<(&mut Transform, &XrCameraType, &mut XRProjection)>,
|
let view_idx = match camera_type {
|
||||||
) -> Option<()> {
|
XrCameraType::Xr(eye) => *eye as usize,
|
||||||
//TODO calculate HMD position
|
// I don't belive we need a flatscrenn cam, that's just a cam without this component
|
||||||
for (mut transform, camera_type, mut xr_projection) in query.iter_mut() {
|
XrCameraType::Flatscreen => continue,
|
||||||
let view_idx = match camera_type {
|
};
|
||||||
XrCameraType::Xr(eye) => *eye as usize,
|
let view = match views.get(view_idx) {
|
||||||
XrCameraType::Flatscreen => return None,
|
Some(views) => views,
|
||||||
};
|
None => continue,
|
||||||
let view = views.get(view_idx)?;
|
};
|
||||||
xr_projection.fov = view.fov;
|
xr_projection.fov = view.fov;
|
||||||
transform.rotation = view.pose.orientation.to_quat();
|
transform.rotation = view.pose.orientation.to_quat();
|
||||||
transform.translation = view.pose.position.to_vec3();
|
transform.translation = view.pose.position.to_vec3();
|
||||||
}
|
|
||||||
Some(())
|
|
||||||
}
|
}
|
||||||
let _ = f(views, query);
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user