1528
Cargo.lock
generated
1528
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@@ -10,10 +10,17 @@ resolver = "2"
|
|||||||
members = ["crates/*", "crates/bevy_openxr/examples/android"]
|
members = ["crates/*", "crates/bevy_openxr/examples/android"]
|
||||||
|
|
||||||
[workspace.dependencies]
|
[workspace.dependencies]
|
||||||
bevy = { version = "0.14.0", default-features = false, features = [
|
bevy = { version = "0.15", default-features = false, features = [
|
||||||
"bevy_render",
|
"bevy_render",
|
||||||
"bevy_core_pipeline",
|
"bevy_core_pipeline",
|
||||||
"bevy_winit",
|
"bevy_winit",
|
||||||
"bevy_pbr",
|
"bevy_pbr",
|
||||||
"x11",
|
"x11",
|
||||||
] }
|
] }
|
||||||
|
bevy_mod_xr.path = "crates/bevy_xr"
|
||||||
|
bevy_mod_openxr.path = "crates/bevy_openxr"
|
||||||
|
bevy_xr_utils.path = "crates/bevy_xr_utils"
|
||||||
|
openxr = "0.19.0"
|
||||||
|
thiserror = "2.0.3"
|
||||||
|
wgpu = "23"
|
||||||
|
wgpu-hal = "23"
|
||||||
|
|||||||
@@ -10,11 +10,11 @@ keywords = ["gamedev", "bevy", "Xr", "Vr", "OpenXR"]
|
|||||||
[features]
|
[features]
|
||||||
default = ["vulkan", "d3d12", "passthrough"]
|
default = ["vulkan", "d3d12", "passthrough"]
|
||||||
vulkan = ["dep:ash"]
|
vulkan = ["dep:ash"]
|
||||||
d3d12 = ["wgpu/dx12", "wgpu-hal/dx12", "dep:winapi", "dep:d3d12"]
|
d3d12 = ["wgpu/dx12", "wgpu-hal/dx12", "dep:winapi"]
|
||||||
passthrough = []
|
passthrough = []
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
bevy_xr_utils.path = "../bevy_xr_utils"
|
bevy_xr_utils.workspace = true
|
||||||
bevy = { workspace = true, default-features = true }
|
bevy = { workspace = true, default-features = true }
|
||||||
|
|
||||||
[target.'cfg(target_os = "android")'.dependencies]
|
[target.'cfg(target_os = "android")'.dependencies]
|
||||||
@@ -27,22 +27,20 @@ bevy.workspace = true
|
|||||||
|
|
||||||
# all other dependencies are placed under this since on wasm, this crate is completely empty
|
# all other dependencies are placed under this since on wasm, this crate is completely empty
|
||||||
[target.'cfg(not(target_family = "wasm"))'.dependencies]
|
[target.'cfg(not(target_family = "wasm"))'.dependencies]
|
||||||
openxr = "0.18.0"
|
bevy_mod_xr.workspace = true
|
||||||
thiserror = "1.0.57"
|
openxr.workspace = true
|
||||||
wgpu = "0.20"
|
thiserror.workspace = true
|
||||||
wgpu-hal = "0.21"
|
wgpu.workspace = true
|
||||||
bevy_mod_xr = { path = "../bevy_xr", version = "0.1.0" }
|
wgpu-hal.workspace = true
|
||||||
|
ash = { version = "0.38", optional = true }
|
||||||
ash = { version = "0.37.3", optional = true }
|
|
||||||
|
|
||||||
[target.'cfg(target_family = "unix")'.dependencies]
|
[target.'cfg(target_family = "unix")'.dependencies]
|
||||||
openxr = { version = "0.18.0", features = ["mint"] }
|
openxr = { workspace = true, features = ["mint"] }
|
||||||
wgpu = { version = "0.20", features = ["vulkan-portability"] }
|
wgpu = { workspace = true, features = ["vulkan-portability"] }
|
||||||
|
|
||||||
[target.'cfg(target_family = "windows")'.dependencies]
|
[target.'cfg(target_family = "windows")'.dependencies]
|
||||||
openxr = { version = "0.18.0", features = ["mint", "static"] }
|
openxr = { workspace=true, features = ["mint", "static"] }
|
||||||
winapi = { version = "0.3.9", optional = true }
|
winapi = { version = "0.3.9", optional = true }
|
||||||
d3d12 = { version = "0.20", features = ["libloading"], optional = true }
|
|
||||||
|
|
||||||
[lints.clippy]
|
[lints.clippy]
|
||||||
too_many_arguments = "allow"
|
too_many_arguments = "allow"
|
||||||
|
|||||||
@@ -1,13 +1,25 @@
|
|||||||
//! A simple 3D scene with light shining over a cube sitting on a plane.
|
//! A simple 3D scene with light shining over a cube sitting on a plane.
|
||||||
|
|
||||||
use bevy::prelude::*;
|
use bevy::{prelude::*, render::pipelined_rendering::PipelinedRenderingPlugin};
|
||||||
use bevy_mod_openxr::add_xr_plugins;
|
use bevy_mod_openxr::{add_xr_plugins, init::OxrInitPlugin};
|
||||||
|
use openxr::EnvironmentBlendMode;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
App::new()
|
App::new()
|
||||||
.add_plugins(add_xr_plugins(DefaultPlugins))
|
.add_plugins(
|
||||||
|
add_xr_plugins(DefaultPlugins.build().disable::<PipelinedRenderingPlugin>()).set(
|
||||||
|
OxrInitPlugin {
|
||||||
|
blend_modes: Some(vec![
|
||||||
|
EnvironmentBlendMode::ALPHA_BLEND,
|
||||||
|
EnvironmentBlendMode::ADDITIVE,
|
||||||
|
]),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
.add_plugins(bevy_xr_utils::hand_gizmos::HandGizmosPlugin)
|
.add_plugins(bevy_xr_utils::hand_gizmos::HandGizmosPlugin)
|
||||||
.add_systems(Startup, setup)
|
.add_systems(Startup, setup)
|
||||||
|
.insert_resource(ClearColor(Color::NONE))
|
||||||
.run();
|
.run();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -18,30 +30,27 @@ fn setup(
|
|||||||
mut materials: ResMut<Assets<StandardMaterial>>,
|
mut materials: ResMut<Assets<StandardMaterial>>,
|
||||||
) {
|
) {
|
||||||
// circular base
|
// circular base
|
||||||
commands.spawn(PbrBundle {
|
commands.spawn((
|
||||||
mesh: meshes.add(Circle::new(4.0)),
|
Mesh3d(meshes.add(Circle::new(4.0))),
|
||||||
material: materials.add(Color::WHITE),
|
MeshMaterial3d(materials.add(Color::WHITE)),
|
||||||
transform: Transform::from_rotation(Quat::from_rotation_x(-std::f32::consts::FRAC_PI_2)),
|
Transform::from_rotation(Quat::from_rotation_x(-std::f32::consts::FRAC_PI_2)),
|
||||||
..default()
|
));
|
||||||
});
|
|
||||||
// cube
|
// cube
|
||||||
commands.spawn(PbrBundle {
|
commands.spawn((
|
||||||
mesh: meshes.add(Cuboid::new(1.0, 1.0, 1.0)),
|
Mesh3d(meshes.add(Cuboid::new(1.0, 1.0, 1.0))),
|
||||||
material: materials.add(Color::srgb_u8(124, 144, 255)),
|
MeshMaterial3d(materials.add(Color::srgb_u8(124, 144, 255))),
|
||||||
transform: Transform::from_xyz(0.0, 0.5, 0.0),
|
Transform::from_xyz(0.0, 0.5, 0.0),
|
||||||
..default()
|
));
|
||||||
});
|
|
||||||
// light
|
// light
|
||||||
commands.spawn(PointLightBundle {
|
commands.spawn((
|
||||||
point_light: PointLight {
|
PointLight {
|
||||||
shadows_enabled: true,
|
shadows_enabled: true,
|
||||||
..default()
|
..default()
|
||||||
},
|
},
|
||||||
transform: Transform::from_xyz(4.0, 8.0, 4.0),
|
Transform::from_xyz(4.0, 8.0, 4.0),
|
||||||
..default()
|
));
|
||||||
});
|
commands.spawn((
|
||||||
commands.spawn(Camera3dBundle {
|
Camera3d::default(),
|
||||||
transform: Transform::from_xyz(-2.5, 4.5, 9.0).looking_at(Vec3::ZERO, Vec3::Y),
|
Transform::from_xyz(-2.5, 4.5, 9.0).looking_at(Vec3::ZERO, Vec3::Y),
|
||||||
..default()
|
));
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,24 +34,22 @@ fn setup_scene(
|
|||||||
mut materials: ResMut<Assets<StandardMaterial>>,
|
mut materials: ResMut<Assets<StandardMaterial>>,
|
||||||
) {
|
) {
|
||||||
// circular base
|
// circular base
|
||||||
commands.spawn(PbrBundle {
|
commands.spawn((
|
||||||
mesh: meshes.add(Circle::new(4.0)),
|
Mesh3d(meshes.add(Circle::new(4.0))),
|
||||||
material: materials.add(Color::WHITE),
|
MeshMaterial3d(materials.add(Color::WHITE)),
|
||||||
transform: Transform::from_rotation(Quat::from_rotation_x(-std::f32::consts::FRAC_PI_2)),
|
Transform::from_rotation(Quat::from_rotation_x(-std::f32::consts::FRAC_PI_2)),
|
||||||
..default()
|
));
|
||||||
});
|
|
||||||
// cube
|
// cube
|
||||||
commands.spawn(PbrBundle {
|
commands.spawn((
|
||||||
mesh: meshes.add(Cuboid::new(1.0, 1.0, 1.0)),
|
Mesh3d(meshes.add(Cuboid::new(1.0, 1.0, 1.0))),
|
||||||
material: materials.add(Color::srgb_u8(124, 144, 255)),
|
MeshMaterial3d(materials.add(Color::srgb_u8(124, 144, 255))),
|
||||||
transform: Transform::from_xyz(0.0, 0.5, 0.0),
|
Transform::from_xyz(0.0, 0.5, 0.0),
|
||||||
..default()
|
));
|
||||||
});
|
|
||||||
|
|
||||||
commands.spawn(Camera3dBundle {
|
commands.spawn((
|
||||||
transform: Transform::from_xyz(-2.5, 4.5, 9.0).looking_at(Vec3::ZERO, Vec3::Y),
|
Camera3d::default(),
|
||||||
..default()
|
Transform::from_xyz(-2.5, 4.5, 9.0).looking_at(Vec3::ZERO, Vec3::Y),
|
||||||
});
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Component)]
|
#[derive(Component)]
|
||||||
@@ -145,7 +143,7 @@ fn handle_flight_input(
|
|||||||
let locomotion_vector = reference_quat.mul_vec3(input_vector);
|
let locomotion_vector = reference_quat.mul_vec3(input_vector);
|
||||||
|
|
||||||
root_position.translation +=
|
root_position.translation +=
|
||||||
locomotion_vector * speed * time.delta_seconds();
|
locomotion_vector * speed * time.delta_secs();
|
||||||
}
|
}
|
||||||
None => return,
|
None => return,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,9 +7,9 @@ publish = false
|
|||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
bevy_mod_openxr.path = "../.."
|
bevy_mod_openxr.workspace = true
|
||||||
bevy = { workspace = true, default-features = true }
|
bevy = { workspace = true, default-features = true }
|
||||||
bevy_xr_utils.path = "../../../bevy_xr_utils"
|
bevy_xr_utils.workspace = true
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
reqwest = { version = "0.12", features = ["blocking"] }
|
reqwest = { version = "0.12", features = ["blocking"] }
|
||||||
|
|||||||
@@ -21,8 +21,8 @@ fn main() {
|
|||||||
synchronous_pipeline_compilation: default(),
|
synchronous_pipeline_compilation: default(),
|
||||||
}))
|
}))
|
||||||
.add_plugins(bevy_xr_utils::hand_gizmos::HandGizmosPlugin)
|
.add_plugins(bevy_xr_utils::hand_gizmos::HandGizmosPlugin)
|
||||||
.insert_resource(Msaa::Off)
|
|
||||||
.add_systems(Startup, setup)
|
.add_systems(Startup, setup)
|
||||||
|
.add_systems(Update, modify_msaa)
|
||||||
.insert_resource(AmbientLight {
|
.insert_resource(AmbientLight {
|
||||||
color: Default::default(),
|
color: Default::default(),
|
||||||
brightness: 500.0,
|
brightness: 500.0,
|
||||||
@@ -31,6 +31,15 @@ fn main() {
|
|||||||
.run();
|
.run();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Component)]
|
||||||
|
struct MsaaModified;
|
||||||
|
|
||||||
|
fn modify_msaa(cams: Query<Entity, (With<Camera>, Without<MsaaModified>)>, mut commands: Commands) {
|
||||||
|
for cam in &cams {
|
||||||
|
commands.entity(cam).insert(Msaa::Off).insert(MsaaModified);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// set up a simple 3D scene
|
/// set up a simple 3D scene
|
||||||
fn setup(
|
fn setup(
|
||||||
mut commands: Commands,
|
mut commands: Commands,
|
||||||
@@ -40,19 +49,17 @@ fn setup(
|
|||||||
let mut white: StandardMaterial = Color::WHITE.into();
|
let mut white: StandardMaterial = Color::WHITE.into();
|
||||||
white.unlit = true;
|
white.unlit = true;
|
||||||
// circular base
|
// circular base
|
||||||
commands.spawn(PbrBundle {
|
commands.spawn((
|
||||||
mesh: meshes.add(Circle::new(4.0)),
|
Mesh3d(meshes.add(Circle::new(4.0))),
|
||||||
material: materials.add(white),
|
MeshMaterial3d(materials.add(white)),
|
||||||
transform: Transform::from_rotation(Quat::from_rotation_x(-std::f32::consts::FRAC_PI_2)),
|
Transform::from_rotation(Quat::from_rotation_x(-std::f32::consts::FRAC_PI_2)),
|
||||||
..default()
|
));
|
||||||
});
|
|
||||||
let mut cube_mat: StandardMaterial = Color::srgb_u8(124, 144, 255).into();
|
let mut cube_mat: StandardMaterial = Color::srgb_u8(124, 144, 255).into();
|
||||||
cube_mat.unlit = true;
|
cube_mat.unlit = true;
|
||||||
// cube
|
// cube
|
||||||
commands.spawn(PbrBundle {
|
commands.spawn((
|
||||||
mesh: meshes.add(Cuboid::new(1.0, 1.0, 1.0)),
|
Mesh3d(meshes.add(Cuboid::new(1.0, 1.0, 1.0))),
|
||||||
material: materials.add(cube_mat),
|
MeshMaterial3d(materials.add(cube_mat)),
|
||||||
transform: Transform::from_xyz(0.0, 0.5, 0.0),
|
Transform::from_xyz(0.0, 0.5, 0.0),
|
||||||
..default()
|
));
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
//! A simple 3D scene with light shining over a cube sitting on a plane.
|
//! A simple 3D scene with light shining over a cube sitting on a plane.
|
||||||
|
|
||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
use bevy_mod_openxr::{add_xr_plugins, init::OxrInitPlugin, types::OxrExtensions};
|
use bevy_mod_openxr::{
|
||||||
use bevy_mod_xr::session::XrState;
|
add_xr_plugins, features::overlay::OxrOverlaySessionEvent, init::OxrInitPlugin,
|
||||||
// use openxr::EnvironmentBlendMode;
|
types::OxrExtensions,
|
||||||
// use wgpu::TextureFormat;
|
};
|
||||||
|
use openxr::EnvironmentBlendMode;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
App::new()
|
App::new()
|
||||||
@@ -12,32 +13,32 @@ fn main() {
|
|||||||
exts: {
|
exts: {
|
||||||
let mut exts = OxrExtensions::default();
|
let mut exts = OxrExtensions::default();
|
||||||
exts.enable_hand_tracking();
|
exts.enable_hand_tracking();
|
||||||
exts.other.push("XR_EXTX_overlay\0".into());
|
exts.extx_overlay = true;
|
||||||
exts
|
exts
|
||||||
},
|
},
|
||||||
// blend_modes: Some({
|
blend_modes: Some({
|
||||||
// let mut v = Vec::new();
|
vec![
|
||||||
// v.push(EnvironmentBlendMode::ALPHA_BLEND);
|
EnvironmentBlendMode::ALPHA_BLEND,
|
||||||
// v.push(EnvironmentBlendMode::ADDITIVE);
|
EnvironmentBlendMode::OPAQUE,
|
||||||
// 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()
|
..OxrInitPlugin::default()
|
||||||
}))
|
}))
|
||||||
.insert_resource(ClearColor(Color::NONE))
|
.insert_resource(ClearColor(Color::NONE))
|
||||||
.add_plugins(bevy_xr_utils::hand_gizmos::HandGizmosPlugin)
|
.add_plugins(bevy_xr_utils::hand_gizmos::HandGizmosPlugin)
|
||||||
.add_systems(Startup, setup)
|
.add_systems(Startup, setup)
|
||||||
.add_systems(Update, handle_input)
|
.add_systems(Update, handle_input)
|
||||||
|
.add_systems(Update, print_main_session_changes)
|
||||||
.run();
|
.run();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn print_main_session_changes(mut events: EventReader<OxrOverlaySessionEvent>) {
|
||||||
|
for event in events.read() {
|
||||||
|
let OxrOverlaySessionEvent::MainSessionVisibilityChanged { visible, flags: _ } = event;
|
||||||
|
info!("main session visible: {visible}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn handle_input(
|
fn handle_input(
|
||||||
keys: Res<ButtonInput<KeyCode>>,
|
keys: Res<ButtonInput<KeyCode>>,
|
||||||
mut end: EventWriter<bevy_mod_xr::session::XrEndSessionEvent>,
|
mut end: EventWriter<bevy_mod_xr::session::XrEndSessionEvent>,
|
||||||
@@ -45,7 +46,6 @@ fn handle_input(
|
|||||||
mut begin: EventWriter<bevy_mod_xr::session::XrBeginSessionEvent>,
|
mut begin: EventWriter<bevy_mod_xr::session::XrBeginSessionEvent>,
|
||||||
mut create: EventWriter<bevy_mod_xr::session::XrCreateSessionEvent>,
|
mut create: EventWriter<bevy_mod_xr::session::XrCreateSessionEvent>,
|
||||||
mut request_exit: EventWriter<bevy_mod_xr::session::XrRequestExitEvent>,
|
mut request_exit: EventWriter<bevy_mod_xr::session::XrRequestExitEvent>,
|
||||||
state: Res<XrState>,
|
|
||||||
) {
|
) {
|
||||||
if keys.just_pressed(KeyCode::KeyE) {
|
if keys.just_pressed(KeyCode::KeyE) {
|
||||||
info!("sending end");
|
info!("sending end");
|
||||||
@@ -67,9 +67,6 @@ fn handle_input(
|
|||||||
info!("sending request exit");
|
info!("sending request exit");
|
||||||
request_exit.send_default();
|
request_exit.send_default();
|
||||||
}
|
}
|
||||||
if keys.just_pressed(KeyCode::KeyI) {
|
|
||||||
info!("current state: {:?}", *state);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// set up a simple 3D scene
|
/// set up a simple 3D scene
|
||||||
@@ -78,31 +75,22 @@ fn setup(
|
|||||||
mut meshes: ResMut<Assets<Mesh>>,
|
mut meshes: ResMut<Assets<Mesh>>,
|
||||||
mut materials: ResMut<Assets<StandardMaterial>>,
|
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
|
// cube
|
||||||
commands.spawn(PbrBundle {
|
commands.spawn((
|
||||||
mesh: meshes.add(Cuboid::new(1.0, 1.0, 1.0)),
|
Mesh3d(meshes.add(Cuboid::new(1.0, 1.0, 1.0))),
|
||||||
material: materials.add(Color::srgb_u8(124, 144, 255)),
|
MeshMaterial3d(materials.add(Color::srgb_u8(124, 144, 255))),
|
||||||
transform: Transform::from_xyz(0.0, 2.5, 0.0),
|
Transform::from_xyz(0.0, 2.5, 0.0),
|
||||||
..default()
|
));
|
||||||
});
|
|
||||||
// light
|
// light
|
||||||
commands.spawn(PointLightBundle {
|
commands.spawn((
|
||||||
point_light: PointLight {
|
PointLight {
|
||||||
shadows_enabled: true,
|
shadows_enabled: true,
|
||||||
..default()
|
..default()
|
||||||
},
|
},
|
||||||
transform: Transform::from_xyz(4.0, 8.0, 4.0),
|
Transform::from_xyz(4.0, 8.0, 4.0),
|
||||||
..default()
|
));
|
||||||
});
|
commands.spawn((
|
||||||
commands.spawn(Camera3dBundle {
|
Camera3d::default(),
|
||||||
transform: Transform::from_xyz(-2.5, 4.5, 9.0).looking_at(Vec3::ZERO, Vec3::Y),
|
Transform::from_xyz(-2.5, 4.5, 9.0).looking_at(Vec3::ZERO, Vec3::Y),
|
||||||
..default()
|
));
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,15 +5,14 @@ use bevy_mod_openxr::{
|
|||||||
action_binding::{OxrSendActionBindings, OxrSuggestActionBinding},
|
action_binding::{OxrSendActionBindings, OxrSuggestActionBinding},
|
||||||
action_set_attaching::OxrAttachActionSet,
|
action_set_attaching::OxrAttachActionSet,
|
||||||
action_set_syncing::{OxrActionSetSyncSet, OxrSyncActionSet},
|
action_set_syncing::{OxrActionSetSyncSet, OxrSyncActionSet},
|
||||||
add_xr_plugins,
|
add_xr_plugins, openxr_session_running,
|
||||||
resources::OxrInstance,
|
resources::OxrInstance,
|
||||||
session::OxrSession,
|
session::OxrSession,
|
||||||
spaces::OxrSpaceExt,
|
spaces::OxrSpaceExt,
|
||||||
};
|
};
|
||||||
use bevy_mod_xr::{
|
use bevy_mod_xr::{
|
||||||
session::{session_available, session_running, XrSessionCreated, XrTrackingRoot},
|
session::{session_available, XrSessionCreated},
|
||||||
spaces::XrSpace,
|
spaces::XrSpace,
|
||||||
types::XrPose,
|
|
||||||
};
|
};
|
||||||
use openxr::Posef;
|
use openxr::Posef;
|
||||||
|
|
||||||
@@ -26,7 +25,7 @@ fn main() {
|
|||||||
PreUpdate,
|
PreUpdate,
|
||||||
sync_actions
|
sync_actions
|
||||||
.before(OxrActionSetSyncSet)
|
.before(OxrActionSetSyncSet)
|
||||||
.run_if(session_running),
|
.run_if(openxr_session_running),
|
||||||
);
|
);
|
||||||
app.add_systems(OxrSendActionBindings, suggest_action_bindings);
|
app.add_systems(OxrSendActionBindings, suggest_action_bindings);
|
||||||
app.add_systems(Startup, create_actions.run_if(session_available));
|
app.add_systems(Startup, create_actions.run_if(session_available));
|
||||||
@@ -55,32 +54,29 @@ fn setup(
|
|||||||
mut materials: ResMut<Assets<StandardMaterial>>,
|
mut materials: ResMut<Assets<StandardMaterial>>,
|
||||||
) {
|
) {
|
||||||
// circular base
|
// circular base
|
||||||
commands.spawn(PbrBundle {
|
commands.spawn((
|
||||||
mesh: meshes.add(Circle::new(4.0)),
|
Mesh3d(meshes.add(Circle::new(4.0))),
|
||||||
material: materials.add(Color::WHITE),
|
MeshMaterial3d(materials.add(Color::WHITE)),
|
||||||
transform: Transform::from_rotation(Quat::from_rotation_x(-std::f32::consts::FRAC_PI_2)),
|
Transform::from_rotation(Quat::from_rotation_x(-std::f32::consts::FRAC_PI_2)),
|
||||||
..default()
|
));
|
||||||
});
|
|
||||||
// cube
|
// cube
|
||||||
commands.spawn(PbrBundle {
|
commands.spawn((
|
||||||
mesh: meshes.add(Cuboid::new(1.0, 1.0, 1.0)),
|
Mesh3d(meshes.add(Cuboid::new(1.0, 1.0, 1.0))),
|
||||||
material: materials.add(Color::srgb_u8(124, 144, 255)),
|
MeshMaterial3d(materials.add(Color::srgb_u8(124, 144, 255))),
|
||||||
transform: Transform::from_xyz(0.0, 0.5, 0.0),
|
Transform::from_xyz(0.0, 0.5, 0.0),
|
||||||
..default()
|
));
|
||||||
});
|
|
||||||
// light
|
// light
|
||||||
commands.spawn(PointLightBundle {
|
commands.spawn((
|
||||||
point_light: PointLight {
|
PointLight {
|
||||||
shadows_enabled: true,
|
shadows_enabled: true,
|
||||||
..default()
|
..default()
|
||||||
},
|
},
|
||||||
transform: Transform::from_xyz(4.0, 8.0, 4.0),
|
Transform::from_xyz(4.0, 8.0, 4.0),
|
||||||
..default()
|
));
|
||||||
});
|
commands.spawn((
|
||||||
commands.spawn(Camera3dBundle {
|
Camera3d::default(),
|
||||||
transform: Transform::from_xyz(-2.5, 4.5, 9.0).looking_at(Vec3::ZERO, Vec3::Y),
|
Transform::from_xyz(-2.5, 4.5, 9.0).looking_at(Vec3::ZERO, Vec3::Y),
|
||||||
..default()
|
));
|
||||||
});
|
|
||||||
}
|
}
|
||||||
fn suggest_action_bindings(
|
fn suggest_action_bindings(
|
||||||
actions: Res<ControllerActions>,
|
actions: Res<ControllerActions>,
|
||||||
@@ -112,7 +108,6 @@ fn create_actions(instance: Res<OxrInstance>, mut cmds: Commands) {
|
|||||||
fn spawn_hands(
|
fn spawn_hands(
|
||||||
actions: Res<ControllerActions>,
|
actions: Res<ControllerActions>,
|
||||||
mut cmds: Commands,
|
mut cmds: Commands,
|
||||||
root: Query<Entity, With<XrTrackingRoot>>,
|
|
||||||
session: Res<OxrSession>,
|
session: Res<OxrSession>,
|
||||||
mut meshes: ResMut<Assets<Mesh>>,
|
mut meshes: ResMut<Assets<Mesh>>,
|
||||||
mut materials: ResMut<Assets<StandardMaterial>>,
|
mut materials: ResMut<Assets<StandardMaterial>>,
|
||||||
@@ -130,34 +125,20 @@ fn spawn_hands(
|
|||||||
.unwrap(),
|
.unwrap(),
|
||||||
);
|
);
|
||||||
let right_space = session
|
let right_space = session
|
||||||
.create_action_space(&actions.right, openxr::Path::NULL, XrPose::IDENTITY)
|
.create_action_space(&actions.right, openxr::Path::NULL, Isometry3d::IDENTITY)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let left = cmds
|
cmds.spawn((
|
||||||
.spawn((
|
Mesh3d(meshes.add(Cuboid::new(0.1, 0.1, 0.05))),
|
||||||
PbrBundle {
|
MeshMaterial3d(materials.add(Color::srgb_u8(124, 144, 255))),
|
||||||
mesh: meshes.add(Cuboid::new(0.1, 0.1, 0.05)),
|
left_space,
|
||||||
material: materials.add(Color::srgb_u8(124, 144, 255)),
|
Controller,
|
||||||
transform: Transform::from_xyz(0.0, 0.5, 0.0),
|
));
|
||||||
..default()
|
cmds.spawn((
|
||||||
},
|
Mesh3d(meshes.add(Cuboid::new(0.1, 0.1, 0.05))),
|
||||||
left_space,
|
MeshMaterial3d(materials.add(Color::srgb_u8(124, 144, 255))),
|
||||||
Controller,
|
right_space,
|
||||||
))
|
Controller,
|
||||||
.id();
|
));
|
||||||
let right = cmds
|
|
||||||
.spawn((
|
|
||||||
PbrBundle {
|
|
||||||
mesh: meshes.add(Cuboid::new(0.1, 0.1, 0.05)),
|
|
||||||
material: materials.add(Color::srgb_u8(124, 144, 255)),
|
|
||||||
transform: Transform::from_xyz(0.0, 0.5, 0.0),
|
|
||||||
..default()
|
|
||||||
},
|
|
||||||
right_space,
|
|
||||||
Controller,
|
|
||||||
))
|
|
||||||
.id();
|
|
||||||
|
|
||||||
cmds.entity(root.single()).push_children(&[left, right]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Component)]
|
#[derive(Component)]
|
||||||
|
|||||||
@@ -1,12 +1,19 @@
|
|||||||
//! A simple 3D scene with light shining over a cube sitting on a plane.
|
//! A simple 3D scene with light shining over a cube sitting on a plane.
|
||||||
|
|
||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
use bevy_mod_openxr::add_xr_plugins;
|
use bevy_mod_openxr::{add_xr_plugins, init::OxrInitPlugin};
|
||||||
use bevy_mod_xr::session::{XrSessionPlugin, XrState};
|
use bevy_mod_xr::session::{XrSessionPlugin, XrState};
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
App::new()
|
App::new()
|
||||||
.add_plugins(add_xr_plugins(DefaultPlugins).set(XrSessionPlugin { auto_handle: true }))
|
.add_plugins(
|
||||||
|
add_xr_plugins(DefaultPlugins)
|
||||||
|
.set(XrSessionPlugin { auto_handle: true })
|
||||||
|
.set(OxrInitPlugin {
|
||||||
|
blend_modes: Some(vec![openxr::EnvironmentBlendMode::OPAQUE]),
|
||||||
|
..Default::default()
|
||||||
|
}),
|
||||||
|
)
|
||||||
.add_plugins(bevy_xr_utils::hand_gizmos::HandGizmosPlugin)
|
.add_plugins(bevy_xr_utils::hand_gizmos::HandGizmosPlugin)
|
||||||
.add_systems(Startup, setup)
|
.add_systems(Startup, setup)
|
||||||
.add_systems(Update, handle_input)
|
.add_systems(Update, handle_input)
|
||||||
@@ -55,21 +62,19 @@ fn setup(
|
|||||||
mut materials: ResMut<Assets<StandardMaterial>>,
|
mut materials: ResMut<Assets<StandardMaterial>>,
|
||||||
) {
|
) {
|
||||||
// circular base
|
// circular base
|
||||||
commands.spawn(PbrBundle {
|
commands.spawn((
|
||||||
mesh: meshes.add(Circle::new(4.0)),
|
Mesh3d(meshes.add(Circle::new(4.0))),
|
||||||
material: materials.add(Color::WHITE),
|
MeshMaterial3d(materials.add(Color::WHITE)),
|
||||||
transform: Transform::from_rotation(Quat::from_rotation_x(-std::f32::consts::FRAC_PI_2)),
|
Transform::from_rotation(Quat::from_rotation_x(-std::f32::consts::FRAC_PI_2)),
|
||||||
..default()
|
));
|
||||||
});
|
|
||||||
// cube
|
// cube
|
||||||
commands.spawn(PbrBundle {
|
commands.spawn((
|
||||||
mesh: meshes.add(Cuboid::new(1.0, 1.0, 1.0)),
|
Mesh3d(meshes.add(Cuboid::new(1.0, 1.0, 1.0))),
|
||||||
material: materials.add(Color::srgb_u8(124, 144, 255)),
|
MeshMaterial3d(materials.add(Color::srgb_u8(124, 144, 255))),
|
||||||
transform: Transform::from_xyz(0.0, 0.5, 0.0),
|
Transform::from_xyz(0.0, 0.5, 0.0),
|
||||||
..default()
|
));
|
||||||
});
|
commands.spawn((
|
||||||
commands.spawn(Camera3dBundle {
|
Camera3d::default(),
|
||||||
transform: Transform::from_xyz(-2.5, 4.5, 9.0).looking_at(Vec3::ZERO, Vec3::Y),
|
Transform::from_xyz(-2.5, 4.5, 9.0).looking_at(Vec3::ZERO, Vec3::Y),
|
||||||
..default()
|
));
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
use bevy_mod_openxr::{action_binding::OxrSendActionBindings, add_xr_plugins};
|
use bevy_mod_openxr::{action_binding::OxrSendActionBindings, add_xr_plugins};
|
||||||
use bevy_mod_xr::session::XrSessionCreated;
|
use bevy_mod_xr::session::{XrSessionCreated, XrTracker};
|
||||||
use bevy_xr_utils::tracking_utils::{
|
use bevy_xr_utils::tracking_utils::{
|
||||||
suggest_action_bindings, TrackingUtilitiesPlugin, XrTrackedLeftGrip, XrTrackedLocalFloor, XrTrackedRightGrip, XrTrackedStage, XrTrackedView
|
suggest_action_bindings, TrackingUtilitiesPlugin, XrTrackedLeftGrip, XrTrackedLocalFloor, XrTrackedRightGrip, XrTrackedStage, XrTrackedView
|
||||||
};
|
};
|
||||||
@@ -30,25 +30,23 @@ fn setup(
|
|||||||
mut materials: ResMut<Assets<StandardMaterial>>,
|
mut materials: ResMut<Assets<StandardMaterial>>,
|
||||||
) {
|
) {
|
||||||
// circular base
|
// circular base
|
||||||
commands.spawn(PbrBundle {
|
commands.spawn((
|
||||||
mesh: meshes.add(Circle::new(4.0)),
|
Mesh3d(meshes.add(Circle::new(4.0))),
|
||||||
material: materials.add(Color::WHITE),
|
MeshMaterial3d(materials.add(Color::WHITE)),
|
||||||
transform: Transform::from_rotation(Quat::from_rotation_x(-std::f32::consts::FRAC_PI_2)),
|
Transform::from_rotation(Quat::from_rotation_x(-std::f32::consts::FRAC_PI_2)),
|
||||||
..default()
|
));
|
||||||
});
|
|
||||||
// light
|
// light
|
||||||
commands.spawn(PointLightBundle {
|
commands.spawn((
|
||||||
point_light: PointLight {
|
PointLight {
|
||||||
shadows_enabled: true,
|
shadows_enabled: true,
|
||||||
..default()
|
..default()
|
||||||
},
|
},
|
||||||
transform: Transform::from_xyz(4.0, 8.0, 4.0),
|
Transform::from_xyz(4.0, 8.0, 4.0),
|
||||||
..default()
|
));
|
||||||
});
|
commands.spawn((
|
||||||
commands.spawn(Camera3dBundle {
|
Camera3d::default(),
|
||||||
transform: Transform::from_xyz(-2.5, 4.5, 9.0).looking_at(Vec3::ZERO, Vec3::Y),
|
Transform::from_xyz(-2.5, 4.5, 9.0).looking_at(Vec3::ZERO, Vec3::Y),
|
||||||
..default()
|
));
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn spawn_hands(
|
fn spawn_hands(
|
||||||
@@ -56,65 +54,42 @@ fn spawn_hands(
|
|||||||
mut meshes: ResMut<Assets<Mesh>>,
|
mut meshes: ResMut<Assets<Mesh>>,
|
||||||
mut materials: ResMut<Assets<StandardMaterial>>,
|
mut materials: ResMut<Assets<StandardMaterial>>,
|
||||||
) {
|
) {
|
||||||
let left = cmds
|
cmds.spawn((
|
||||||
.spawn((
|
Mesh3d(meshes.add(Cuboid::new(0.1, 0.1, 0.05))),
|
||||||
PbrBundle {
|
MeshMaterial3d(materials.add(Color::srgb_u8(124, 144, 255))),
|
||||||
mesh: meshes.add(Cuboid::new(0.1, 0.1, 0.05)),
|
Transform::from_xyz(0.0, 0.5, 0.0),
|
||||||
material: materials.add(Color::srgb_u8(124, 144, 255)),
|
XrTrackedLeftGrip,
|
||||||
transform: Transform::from_xyz(0.0, 0.5, 0.0),
|
XrTracker,
|
||||||
..default()
|
));
|
||||||
},
|
cmds.spawn((
|
||||||
XrTrackedLeftGrip,
|
Mesh3d(meshes.add(Cuboid::new(0.1, 0.1, 0.05))),
|
||||||
))
|
MeshMaterial3d(materials.add(Color::srgb_u8(124, 144, 255))),
|
||||||
.id();
|
Transform::from_xyz(0.0, 0.5, 0.0),
|
||||||
let bundle = (
|
|
||||||
PbrBundle {
|
|
||||||
mesh: meshes.add(Cuboid::new(0.1, 0.1, 0.05)),
|
|
||||||
material: materials.add(Color::srgb_u8(124, 144, 255)),
|
|
||||||
transform: Transform::from_xyz(0.0, 0.5, 0.0),
|
|
||||||
..default()
|
|
||||||
},
|
|
||||||
XrTrackedRightGrip,
|
XrTrackedRightGrip,
|
||||||
);
|
XrTracker,
|
||||||
let right = cmds.spawn(bundle).id();
|
));
|
||||||
//head
|
//head
|
||||||
|
cmds.spawn((
|
||||||
let head = cmds
|
Mesh3d(meshes.add(Cuboid::new(0.2, 0.2, 0.2))),
|
||||||
.spawn((
|
MeshMaterial3d(materials.add(Color::srgb_u8(255, 144, 144))),
|
||||||
PbrBundle {
|
Transform::from_xyz(0.0, 0.0, 0.0),
|
||||||
mesh: meshes.add(Cuboid::new(0.2, 0.2, 0.2)),
|
XrTrackedView,
|
||||||
material: materials.add(Color::srgb_u8(255, 144, 144)),
|
XrTracker,
|
||||||
transform: Transform::from_xyz(0.0, 0.0, 0.0),
|
));
|
||||||
..default()
|
|
||||||
},
|
|
||||||
XrTrackedView,
|
|
||||||
))
|
|
||||||
.id();
|
|
||||||
//local_floor emulated
|
//local_floor emulated
|
||||||
let local_floor = cmds
|
cmds.spawn((
|
||||||
.spawn((
|
Mesh3d(meshes.add(Cuboid::new(0.5, 0.1, 0.5))),
|
||||||
PbrBundle {
|
MeshMaterial3d(materials.add(Color::srgb_u8(144, 255, 144))),
|
||||||
mesh: meshes.add(Cuboid::new(0.5, 0.1, 0.5)),
|
Transform::from_xyz(0.0, 0.0, 0.0),
|
||||||
material: materials.add(Color::srgb_u8(144, 255, 144)),
|
XrTrackedLocalFloor,
|
||||||
transform: Transform::from_xyz(0.0, 0.0, 0.0),
|
XrTracker,
|
||||||
..default()
|
));
|
||||||
},
|
|
||||||
XrTrackedLocalFloor,
|
|
||||||
))
|
|
||||||
.id();
|
|
||||||
|
|
||||||
let stage = cmds
|
cmds.spawn((
|
||||||
.spawn((
|
Mesh3d(meshes.add(Cuboid::new(0.5, 0.1, 0.5))),
|
||||||
PbrBundle {
|
MeshMaterial3d(materials.add(Color::srgb_u8(144, 255, 255))),
|
||||||
mesh: meshes.add(Cuboid::new(0.5, 0.1, 0.5)),
|
Transform::from_xyz(0.0, 0.0, 0.0),
|
||||||
material: materials.add(Color::srgb_u8(144, 255, 255)),
|
XrTrackedStage,
|
||||||
transform: Transform::from_xyz(0.0, 0.0, 0.0),
|
XrTracker,
|
||||||
..default()
|
));
|
||||||
},
|
|
||||||
XrTrackedStage,
|
|
||||||
))
|
|
||||||
.id();
|
|
||||||
|
|
||||||
cmds.entity(stage)
|
|
||||||
.push_children(&[left, right, head, local_floor]);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,52 +41,46 @@ fn setup(
|
|||||||
mut materials: ResMut<Assets<StandardMaterial>>,
|
mut materials: ResMut<Assets<StandardMaterial>>,
|
||||||
) {
|
) {
|
||||||
// circular base
|
// circular base
|
||||||
commands.spawn(PbrBundle {
|
commands.spawn((
|
||||||
mesh: meshes.add(Circle::new(4.0)),
|
Mesh3d(meshes.add(Circle::new(4.0))),
|
||||||
material: materials.add(Color::WHITE),
|
MeshMaterial3d(materials.add(Color::WHITE)),
|
||||||
transform: Transform::from_rotation(Quat::from_rotation_x(-std::f32::consts::FRAC_PI_2)),
|
Transform::from_rotation(Quat::from_rotation_x(-std::f32::consts::FRAC_PI_2)),
|
||||||
..default()
|
));
|
||||||
});
|
|
||||||
// red cube
|
// red cube
|
||||||
commands.spawn(PbrBundle {
|
commands.spawn((
|
||||||
mesh: meshes.add(Cuboid::new(1.0, 1.0, 1.0)),
|
Mesh3d(meshes.add(Cuboid::new(1.0, 1.0, 1.0))),
|
||||||
material: materials.add(Color::srgb_u8(252, 44, 3)),
|
MeshMaterial3d(materials.add(Color::srgb_u8(252, 44, 3))),
|
||||||
transform: Transform::from_xyz(4.0, 0.5, 0.0).with_scale(Vec3::splat(0.5)),
|
Transform::from_xyz(4.0, 0.5, 0.0).with_scale(Vec3::splat(0.5)),
|
||||||
..default()
|
));
|
||||||
});
|
|
||||||
// blue cube
|
// blue cube
|
||||||
commands.spawn(PbrBundle {
|
commands.spawn((
|
||||||
mesh: meshes.add(Cuboid::new(1.0, 1.0, 1.0)),
|
Mesh3d(meshes.add(Cuboid::new(1.0, 1.0, 1.0))),
|
||||||
material: materials.add(Color::srgb_u8(3, 28, 252)),
|
MeshMaterial3d(materials.add(Color::srgb_u8(3, 28, 252))),
|
||||||
transform: Transform::from_xyz(-4.0, 0.5, 0.0).with_scale(Vec3::splat(0.5)),
|
Transform::from_xyz(-4.0, 0.5, 0.0).with_scale(Vec3::splat(0.5)),
|
||||||
..default()
|
));
|
||||||
});
|
|
||||||
// green cube
|
// green cube
|
||||||
commands.spawn(PbrBundle {
|
commands.spawn((
|
||||||
mesh: meshes.add(Cuboid::new(1.0, 1.0, 1.0)),
|
Mesh3d(meshes.add(Cuboid::new(1.0, 1.0, 1.0))),
|
||||||
material: materials.add(Color::srgb_u8(3, 252, 32)),
|
MeshMaterial3d(materials.add(Color::srgb_u8(3, 252, 32))),
|
||||||
transform: Transform::from_xyz(0.0, 0.5, 4.0).with_scale(Vec3::splat(0.5)),
|
Transform::from_xyz(0.0, 0.5, 4.0).with_scale(Vec3::splat(0.5)),
|
||||||
..default()
|
));
|
||||||
});
|
|
||||||
// white cube
|
// white cube
|
||||||
commands.spawn(PbrBundle {
|
commands.spawn((
|
||||||
mesh: meshes.add(Cuboid::new(1.0, 1.0, 1.0)),
|
Mesh3d(meshes.add(Cuboid::new(1.0, 1.0, 1.0))),
|
||||||
material: materials.add(Color::srgb_u8(250, 250, 250)),
|
MeshMaterial3d(materials.add(Color::srgb_u8(250, 250, 250))),
|
||||||
transform: Transform::from_xyz(0.0, 0.5, -4.0).with_scale(Vec3::splat(0.5)),
|
Transform::from_xyz(0.0, 0.5, -4.0).with_scale(Vec3::splat(0.5)),
|
||||||
..default()
|
));
|
||||||
});
|
|
||||||
// black cube
|
// black cube
|
||||||
commands.spawn(PbrBundle {
|
commands.spawn((
|
||||||
mesh: meshes.add(Cuboid::new(1.0, 1.0, 1.0)),
|
Mesh3d(meshes.add(Cuboid::new(1.0, 1.0, 1.0))),
|
||||||
material: materials.add(Color::srgb_u8(0, 0, 0)),
|
MeshMaterial3d(materials.add(Color::srgb_u8(0, 0, 0))),
|
||||||
transform: Transform::from_xyz(0.0, 0.1, 0.0).with_scale(Vec3::splat(0.2)),
|
Transform::from_xyz(0.0, 0.1, 0.0).with_scale(Vec3::splat(0.2)),
|
||||||
..default()
|
));
|
||||||
});
|
|
||||||
|
|
||||||
commands.spawn(Camera3dBundle {
|
commands.spawn((
|
||||||
transform: Transform::from_xyz(-2.5, 4.5, 9.0).looking_at(Vec3::ZERO, Vec3::Y),
|
Camera3d::default(),
|
||||||
..default()
|
Transform::from_xyz(-2.5, 4.5, 9.0).looking_at(Vec3::ZERO, Vec3::Y),
|
||||||
});
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Component)]
|
#[derive(Component)]
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ impl Plugin for OxrActionBindingPlugin {
|
|||||||
app.add_event::<OxrSuggestActionBinding>();
|
app.add_event::<OxrSuggestActionBinding>();
|
||||||
app.add_systems(
|
app.add_systems(
|
||||||
Update,
|
Update,
|
||||||
run_action_binding_sugestion.run_if(on_event::<XrSessionCreatedEvent>()),
|
run_action_binding_sugestion.run_if(on_event::<XrSessionCreatedEvent>),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -25,7 +25,7 @@ impl Plugin for OxrActionBindingPlugin {
|
|||||||
// Event to allow requesting binding suggestion for new actions
|
// Event to allow requesting binding suggestion for new actions
|
||||||
pub(crate) fn run_action_binding_sugestion(world: &mut World) {
|
pub(crate) fn run_action_binding_sugestion(world: &mut World) {
|
||||||
world.run_schedule(OxrSendActionBindings);
|
world.run_schedule(OxrSendActionBindings);
|
||||||
world.run_system_once(bind_actions);
|
_ = world.run_system_once(bind_actions);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bind_actions(instance: Res<OxrInstance>, mut actions: EventReader<OxrSuggestActionBinding>) {
|
fn bind_actions(instance: Res<OxrInstance>, mut actions: EventReader<OxrSuggestActionBinding>) {
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ impl Plugin for OxrActionAttachingPlugin {
|
|||||||
app.add_systems(
|
app.add_systems(
|
||||||
PostUpdate,
|
PostUpdate,
|
||||||
attach_sets
|
attach_sets
|
||||||
.run_if(on_event::<XrSessionCreatedEvent>())
|
.run_if(on_event::<XrSessionCreatedEvent>)
|
||||||
.after(run_action_binding_sugestion),
|
.after(run_action_binding_sugestion),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ fn sync_sets(session: Res<OxrSession>, mut events: EventReader<OxrSyncActionSet>
|
|||||||
.map(|v| &v.0)
|
.map(|v| &v.0)
|
||||||
.map(openxr::ActiveActionSet::new)
|
.map(openxr::ActiveActionSet::new)
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
if sets.is_empty() {
|
if sets.is_empty() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
use bevy::{ecs::system::Resource, 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)]
|
#[derive(Clone, Debug, Eq, PartialEq, Deref, DerefMut, Resource)]
|
||||||
@@ -29,6 +32,10 @@ impl OxrExtensions {
|
|||||||
self.0.ext_hand_tracking = false;
|
self.0.ext_hand_tracking = false;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
pub fn enable_extx_overlay(&mut self) -> &mut Self {
|
||||||
|
self.0.extx_overlay = true;
|
||||||
|
self
|
||||||
|
}
|
||||||
/// returns true if all of the extensions enabled are also available in `available_exts`
|
/// returns true if all of the extensions enabled are also available in `available_exts`
|
||||||
pub fn is_available(&self, available_exts: &OxrExtensions) -> bool {
|
pub fn is_available(&self, available_exts: &OxrExtensions) -> bool {
|
||||||
self.clone() & available_exts.clone() == *self
|
self.clone() & available_exts.clone() == *self
|
||||||
@@ -192,6 +199,8 @@ macro_rules! impl_ext {
|
|||||||
ext_local_floor,
|
ext_local_floor,
|
||||||
ext_hand_tracking_data_source,
|
ext_hand_tracking_data_source,
|
||||||
ext_plane_detection,
|
ext_plane_detection,
|
||||||
|
ext_future,
|
||||||
|
ext_user_presence,
|
||||||
fb_composition_layer_image_layout,
|
fb_composition_layer_image_layout,
|
||||||
fb_composition_layer_alpha_blend,
|
fb_composition_layer_alpha_blend,
|
||||||
#[cfg(target_os = "android")]
|
#[cfg(target_os = "android")]
|
||||||
@@ -234,6 +243,7 @@ macro_rules! impl_ext {
|
|||||||
fb_composition_layer_depth_test,
|
fb_composition_layer_depth_test,
|
||||||
fb_spatial_entity_storage_batch,
|
fb_spatial_entity_storage_batch,
|
||||||
fb_spatial_entity_user,
|
fb_spatial_entity_user,
|
||||||
|
fb_face_tracking2,
|
||||||
htc_vive_cosmos_controller_interaction,
|
htc_vive_cosmos_controller_interaction,
|
||||||
htc_facial_tracking,
|
htc_facial_tracking,
|
||||||
htc_vive_focus3_controller_interaction,
|
htc_vive_focus3_controller_interaction,
|
||||||
@@ -241,6 +251,7 @@ macro_rules! impl_ext {
|
|||||||
htc_vive_wrist_tracker_interaction,
|
htc_vive_wrist_tracker_interaction,
|
||||||
htc_passthrough,
|
htc_passthrough,
|
||||||
htc_foveation,
|
htc_foveation,
|
||||||
|
htc_anchor,
|
||||||
huawei_controller_interaction,
|
huawei_controller_interaction,
|
||||||
#[cfg(target_os = "android")]
|
#[cfg(target_os = "android")]
|
||||||
khr_android_thread_settings,
|
khr_android_thread_settings,
|
||||||
@@ -272,6 +283,8 @@ macro_rules! impl_ext {
|
|||||||
khr_composition_layer_equirect2,
|
khr_composition_layer_equirect2,
|
||||||
khr_binding_modification,
|
khr_binding_modification,
|
||||||
khr_swapchain_usage_input_attachment_bit,
|
khr_swapchain_usage_input_attachment_bit,
|
||||||
|
khr_locate_spaces,
|
||||||
|
khr_maintenance1,
|
||||||
meta_foveation_eye_tracked,
|
meta_foveation_eye_tracked,
|
||||||
meta_local_dimming,
|
meta_local_dimming,
|
||||||
meta_passthrough_preferences,
|
meta_passthrough_preferences,
|
||||||
@@ -279,11 +292,18 @@ macro_rules! impl_ext {
|
|||||||
meta_vulkan_swapchain_create_info,
|
meta_vulkan_swapchain_create_info,
|
||||||
meta_performance_metrics,
|
meta_performance_metrics,
|
||||||
meta_headset_id,
|
meta_headset_id,
|
||||||
|
meta_recommended_layer_resolution,
|
||||||
meta_passthrough_color_lut,
|
meta_passthrough_color_lut,
|
||||||
|
meta_spatial_entity_mesh,
|
||||||
|
meta_automatic_layer_filter,
|
||||||
|
meta_touch_controller_plus,
|
||||||
|
meta_environment_depth,
|
||||||
ml_ml2_controller_interaction,
|
ml_ml2_controller_interaction,
|
||||||
ml_frame_end_info,
|
ml_frame_end_info,
|
||||||
ml_global_dimmer,
|
ml_global_dimmer,
|
||||||
ml_compat,
|
ml_compat,
|
||||||
|
ml_marker_understanding,
|
||||||
|
ml_localization_map,
|
||||||
ml_user_calibration,
|
ml_user_calibration,
|
||||||
mnd_headless,
|
mnd_headless,
|
||||||
mnd_swapchain_usage_input_attachment_bit,
|
mnd_swapchain_usage_input_attachment_bit,
|
||||||
@@ -315,7 +335,12 @@ macro_rules! impl_ext {
|
|||||||
varjo_environment_depth_estimation,
|
varjo_environment_depth_estimation,
|
||||||
varjo_marker_tracking,
|
varjo_marker_tracking,
|
||||||
varjo_view_offset,
|
varjo_view_offset,
|
||||||
|
varjo_xr4_controller_interaction,
|
||||||
yvr_controller_interaction,
|
yvr_controller_interaction,
|
||||||
|
extx_overlay,
|
||||||
|
mndx_egl_enable,
|
||||||
|
mndx_force_feedback_curl,
|
||||||
|
htcx_vive_tracker_interaction,
|
||||||
}
|
}
|
||||||
)*
|
)*
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
use bevy_mod_xr::hands::{
|
use bevy_mod_xr::hands::{
|
||||||
spawn_hand_bones, HandBone, HandBoneRadius, HandSide, SpawnHandTracker,
|
spawn_hand_bones, HandBone, HandSide, SpawnHandTracker, SpawnHandTrackerCommandExecutor,
|
||||||
SpawnHandTrackerCommandExecutor,
|
XrHandBoneRadius,
|
||||||
};
|
};
|
||||||
use bevy_mod_xr::hands::{LeftHand, RightHand, XrHandBoneEntities};
|
use bevy_mod_xr::hands::{LeftHand, RightHand, XrHandBoneEntities};
|
||||||
use bevy_mod_xr::session::{XrPreDestroySession, XrSessionCreated, XrTrackingRoot};
|
use bevy_mod_xr::session::{XrPreDestroySession, XrSessionCreated};
|
||||||
use bevy_mod_xr::spaces::{
|
use bevy_mod_xr::spaces::{
|
||||||
XrPrimaryReferenceSpace, XrReferenceSpace, XrSpaceLocationFlags, XrSpaceVelocityFlags,
|
XrPrimaryReferenceSpace, XrReferenceSpace, XrSpaceLocationFlags, XrSpaceVelocityFlags,
|
||||||
XrVelocity,
|
XrVelocity,
|
||||||
@@ -70,11 +70,7 @@ fn handle_tracker_spawn(world: &mut World, tracker: Entity, side: HandSide) {
|
|||||||
.insert(OxrHandTracker(oxr_tracker));
|
.insert(OxrHandTracker(oxr_tracker));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn spawn_default_hands(mut cmds: Commands, root: Query<Entity, With<XrTrackingRoot>>) {
|
fn spawn_default_hands(mut cmds: Commands) {
|
||||||
let Ok(root) = root.get_single() else {
|
|
||||||
error!("unable to get tracking root, skipping handtracker creation");
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
debug!("spawning default hands");
|
debug!("spawning default hands");
|
||||||
let left_bones = spawn_hand_bones(&mut cmds, |_| {
|
let left_bones = spawn_hand_bones(&mut cmds, |_| {
|
||||||
(
|
(
|
||||||
@@ -90,14 +86,12 @@ fn spawn_default_hands(mut cmds: Commands, root: Query<Entity, With<XrTrackingRo
|
|||||||
OxrSpaceLocationFlags(openxr::SpaceLocationFlags::default()),
|
OxrSpaceLocationFlags(openxr::SpaceLocationFlags::default()),
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
cmds.entity(root).push_children(&left_bones);
|
cmds.queue(SpawnHandTracker {
|
||||||
cmds.entity(root).push_children(&right_bones);
|
|
||||||
cmds.push(SpawnHandTracker {
|
|
||||||
joints: XrHandBoneEntities(left_bones),
|
joints: XrHandBoneEntities(left_bones),
|
||||||
tracker_bundle: DefaultHandTracker,
|
tracker_bundle: DefaultHandTracker,
|
||||||
side: HandSide::Left,
|
side: HandSide::Left,
|
||||||
});
|
});
|
||||||
cmds.push(SpawnHandTracker {
|
cmds.queue(SpawnHandTracker {
|
||||||
joints: XrHandBoneEntities(right_bones),
|
joints: XrHandBoneEntities(right_bones),
|
||||||
tracker_bundle: DefaultHandTracker,
|
tracker_bundle: DefaultHandTracker,
|
||||||
side: HandSide::Right,
|
side: HandSide::Right,
|
||||||
@@ -134,7 +128,7 @@ fn locate_hands(
|
|||||||
session: Res<OxrSession>,
|
session: Res<OxrSession>,
|
||||||
mut bone_query: Query<(
|
mut bone_query: Query<(
|
||||||
&HandBone,
|
&HandBone,
|
||||||
&mut HandBoneRadius,
|
&mut XrHandBoneRadius,
|
||||||
&mut Transform,
|
&mut Transform,
|
||||||
Option<&mut XrVelocity>,
|
Option<&mut XrVelocity>,
|
||||||
&mut OxrSpaceLocationFlags,
|
&mut OxrSpaceLocationFlags,
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ fn add_overlay_info_to_chain(
|
|||||||
exts: Res<OxrEnabledExtensions>,
|
exts: Res<OxrEnabledExtensions>,
|
||||||
settings: Res<OxrOverlaySettings>,
|
settings: Res<OxrOverlaySettings>,
|
||||||
) {
|
) {
|
||||||
if exts.other.contains(&"XR_EXTX_overlay\0".to_string()) {
|
if exts.extx_overlay {
|
||||||
chain.push(OxrSessionCreateInfoOverlay::new(
|
chain.push(OxrSessionCreateInfoOverlay::new(
|
||||||
settings.flags,
|
settings.flags,
|
||||||
settings.session_layer_placement,
|
settings.session_layer_placement,
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#[cfg(all(feature = "d3d12", windows))]
|
// #[cfg(all(feature = "d3d12", windows))]
|
||||||
mod d3d12;
|
// mod d3d12;
|
||||||
#[cfg(feature = "vulkan")]
|
#[cfg(feature = "vulkan")]
|
||||||
pub mod vulkan;
|
pub mod vulkan;
|
||||||
|
|
||||||
@@ -8,7 +8,10 @@ use std::any::TypeId;
|
|||||||
use bevy::math::UVec2;
|
use bevy::math::UVec2;
|
||||||
use openxr::{FrameStream, FrameWaiter, Session};
|
use openxr::{FrameStream, FrameWaiter, Session};
|
||||||
|
|
||||||
use crate::{session::OxrSessionCreateNextChain, types::{AppInfo, OxrExtensions, Result, WgpuGraphics}};
|
use crate::{
|
||||||
|
session::OxrSessionCreateNextChain,
|
||||||
|
types::{AppInfo, OxrExtensions, Result, WgpuGraphics},
|
||||||
|
};
|
||||||
|
|
||||||
/// This is an extension trait to the [`Graphics`](openxr::Graphics) trait and is how the graphics API should be interacted with.
|
/// This is an extension trait to the [`Graphics`](openxr::Graphics) trait and is how the graphics API should be interacted with.
|
||||||
pub unsafe trait GraphicsExt: openxr::Graphics {
|
pub unsafe trait GraphicsExt: openxr::Graphics {
|
||||||
@@ -37,7 +40,7 @@ pub unsafe trait GraphicsExt: openxr::Graphics {
|
|||||||
instance: &openxr::Instance,
|
instance: &openxr::Instance,
|
||||||
system_id: openxr::SystemId,
|
system_id: openxr::SystemId,
|
||||||
) -> Result<(WgpuGraphics, Self::SessionCreateInfo)>;
|
) -> Result<(WgpuGraphics, Self::SessionCreateInfo)>;
|
||||||
unsafe fn create_session(
|
unsafe fn create_session(
|
||||||
instance: &openxr::Instance,
|
instance: &openxr::Instance,
|
||||||
system_id: openxr::SystemId,
|
system_id: openxr::SystemId,
|
||||||
info: &Self::SessionCreateInfo,
|
info: &Self::SessionCreateInfo,
|
||||||
@@ -74,8 +77,8 @@ impl GraphicsBackend {
|
|||||||
const ALL: &'static [Self] = &[
|
const ALL: &'static [Self] = &[
|
||||||
#[cfg(feature = "vulkan")]
|
#[cfg(feature = "vulkan")]
|
||||||
Self::Vulkan(()),
|
Self::Vulkan(()),
|
||||||
#[cfg(all(feature = "d3d12", windows))]
|
// #[cfg(all(feature = "d3d12", windows))]
|
||||||
Self::D3D12(()),
|
// Self::D3D12(()),
|
||||||
];
|
];
|
||||||
|
|
||||||
pub fn available_backends(exts: &OxrExtensions) -> Vec<Self> {
|
pub fn available_backends(exts: &OxrExtensions) -> Vec<Self> {
|
||||||
@@ -103,8 +106,8 @@ impl GraphicsBackend {
|
|||||||
pub enum GraphicsWrap<T: GraphicsType> {
|
pub enum GraphicsWrap<T: GraphicsType> {
|
||||||
#[cfg(feature = "vulkan")]
|
#[cfg(feature = "vulkan")]
|
||||||
Vulkan(T::Inner<openxr::Vulkan>),
|
Vulkan(T::Inner<openxr::Vulkan>),
|
||||||
#[cfg(all(feature = "d3d12", windows))]
|
// #[cfg(all(feature = "d3d12", windows))]
|
||||||
D3D12(T::Inner<openxr::D3D12>),
|
// D3D12(T::Inner<openxr::D3D12>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: GraphicsType> GraphicsWrap<T> {
|
impl<T: GraphicsType> GraphicsWrap<T> {
|
||||||
@@ -173,12 +176,12 @@ macro_rules! graphics_match {
|
|||||||
type Api = openxr::Vulkan;
|
type Api = openxr::Vulkan;
|
||||||
graphics_match!(@arm_impl Vulkan; $expr $(=> $($return)*)?)
|
graphics_match!(@arm_impl Vulkan; $expr $(=> $($return)*)?)
|
||||||
},
|
},
|
||||||
#[cfg(all(feature = "d3d12", windows))]
|
// #[cfg(all(feature = "d3d12", windows))]
|
||||||
$crate::graphics::GraphicsWrap::D3D12($var) => {
|
// $crate::graphics::GraphicsWrap::D3D12($var) => {
|
||||||
#[allow(unused)]
|
// #[allow(unused)]
|
||||||
type Api = openxr::D3D12;
|
// type Api = openxr::D3D12;
|
||||||
graphics_match!(@arm_impl D3D12; $expr $(=> $($return)*)?)
|
// graphics_match!(@arm_impl D3D12; $expr $(=> $($return)*)?)
|
||||||
},
|
// },
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ const VK_TARGET_VERSION_ASH: u32 = ash::vk::make_api_version(
|
|||||||
0,
|
0,
|
||||||
VK_TARGET_VERSION.major() as u32,
|
VK_TARGET_VERSION.major() as u32,
|
||||||
VK_TARGET_VERSION.minor() as u32,
|
VK_TARGET_VERSION.minor() as u32,
|
||||||
VK_TARGET_VERSION.patch() as u32,
|
VK_TARGET_VERSION.patch(),
|
||||||
);
|
);
|
||||||
|
|
||||||
unsafe impl GraphicsExt for openxr::Vulkan {
|
unsafe impl GraphicsExt for openxr::Vulkan {
|
||||||
@@ -63,7 +63,7 @@ unsafe impl GraphicsExt for openxr::Vulkan {
|
|||||||
mip_level_count: 1,
|
mip_level_count: 1,
|
||||||
sample_count: 1,
|
sample_count: 1,
|
||||||
dimension: wgpu::TextureDimension::D2,
|
dimension: wgpu::TextureDimension::D2,
|
||||||
format: format,
|
format,
|
||||||
usage: wgpu_hal::TextureUses::COLOR_TARGET | wgpu_hal::TextureUses::COPY_DST,
|
usage: wgpu_hal::TextureUses::COLOR_TARGET | wgpu_hal::TextureUses::COPY_DST,
|
||||||
memory_flags: wgpu_hal::MemoryFlags::empty(),
|
memory_flags: wgpu_hal::MemoryFlags::empty(),
|
||||||
view_formats: vec![],
|
view_formats: vec![],
|
||||||
@@ -84,7 +84,7 @@ unsafe impl GraphicsExt for openxr::Vulkan {
|
|||||||
mip_level_count: 1,
|
mip_level_count: 1,
|
||||||
sample_count: 1,
|
sample_count: 1,
|
||||||
dimension: wgpu::TextureDimension::D2,
|
dimension: wgpu::TextureDimension::D2,
|
||||||
format: format,
|
format,
|
||||||
usage: wgpu::TextureUsages::RENDER_ATTACHMENT | wgpu::TextureUsages::COPY_DST,
|
usage: wgpu::TextureUsages::RENDER_ATTACHMENT | wgpu::TextureUsages::COPY_DST,
|
||||||
view_formats: &[],
|
view_formats: &[],
|
||||||
},
|
},
|
||||||
@@ -113,20 +113,20 @@ unsafe impl GraphicsExt for openxr::Vulkan {
|
|||||||
let flags = wgpu::InstanceFlags::empty();
|
let flags = wgpu::InstanceFlags::empty();
|
||||||
let extensions =
|
let extensions =
|
||||||
<Vulkan as Api>::Instance::desired_extensions(&vk_entry, VK_TARGET_VERSION_ASH, flags)?;
|
<Vulkan as Api>::Instance::desired_extensions(&vk_entry, VK_TARGET_VERSION_ASH, flags)?;
|
||||||
let device_extensions = vec![
|
let device_extensions = [
|
||||||
ash::extensions::khr::Swapchain::name(),
|
ash::khr::swapchain::NAME,
|
||||||
ash::extensions::khr::DrawIndirectCount::name(),
|
ash::khr::draw_indirect_count::NAME,
|
||||||
#[cfg(target_os = "android")]
|
// #[cfg(target_os = "android")]
|
||||||
ash::extensions::khr::TimelineSemaphore::name(),
|
ash::khr::timeline_semaphore::NAME,
|
||||||
ash::vk::KhrImagelessFramebufferFn::name(),
|
ash::khr::imageless_framebuffer::NAME,
|
||||||
ash::vk::KhrImageFormatListFn::name(),
|
ash::khr::image_format_list::NAME,
|
||||||
];
|
];
|
||||||
|
|
||||||
let vk_instance = unsafe {
|
let vk_instance = unsafe {
|
||||||
let extensions_cchar: Vec<_> = extensions.iter().map(|s| s.as_ptr()).collect();
|
let extensions_cchar: Vec<_> = extensions.iter().map(|s| s.as_ptr()).collect();
|
||||||
|
|
||||||
let app_name = CString::new(app_info.name.clone().into_owned())?;
|
let app_name = CString::new(app_info.name.clone().into_owned())?;
|
||||||
let vk_app_info = ash::vk::ApplicationInfo::builder()
|
let vk_app_info = ash::vk::ApplicationInfo::default()
|
||||||
.application_name(&app_name)
|
.application_name(&app_name)
|
||||||
.application_version(1)
|
.application_version(1)
|
||||||
.engine_name(&app_name)
|
.engine_name(&app_name)
|
||||||
@@ -136,8 +136,9 @@ unsafe impl GraphicsExt for openxr::Vulkan {
|
|||||||
let vk_instance = instance
|
let vk_instance = instance
|
||||||
.create_vulkan_instance(
|
.create_vulkan_instance(
|
||||||
system_id,
|
system_id,
|
||||||
|
#[allow(clippy::missing_transmute_annotations)]
|
||||||
std::mem::transmute(vk_entry.static_fn().get_instance_proc_addr),
|
std::mem::transmute(vk_entry.static_fn().get_instance_proc_addr),
|
||||||
&ash::vk::InstanceCreateInfo::builder()
|
&ash::vk::InstanceCreateInfo::default()
|
||||||
.application_info(&vk_app_info)
|
.application_info(&vk_app_info)
|
||||||
.enabled_extension_names(&extensions_cchar) as *const _
|
.enabled_extension_names(&extensions_cchar) as *const _
|
||||||
as *const _,
|
as *const _,
|
||||||
@@ -181,7 +182,7 @@ unsafe impl GraphicsExt for openxr::Vulkan {
|
|||||||
extensions,
|
extensions,
|
||||||
flags,
|
flags,
|
||||||
false,
|
false,
|
||||||
Some(Box::new(())),
|
None,
|
||||||
)?
|
)?
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -205,26 +206,26 @@ unsafe impl GraphicsExt for openxr::Vulkan {
|
|||||||
.adapter
|
.adapter
|
||||||
.physical_device_features(&enabled_extensions, wgpu_features);
|
.physical_device_features(&enabled_extensions, wgpu_features);
|
||||||
let family_index = 0;
|
let family_index = 0;
|
||||||
let family_info = ash::vk::DeviceQueueCreateInfo::builder()
|
let family_info = ash::vk::DeviceQueueCreateInfo::default()
|
||||||
.queue_family_index(family_index)
|
.queue_family_index(family_index)
|
||||||
.queue_priorities(&[1.0])
|
.queue_priorities(&[1.0]);
|
||||||
.build();
|
|
||||||
let family_infos = [family_info];
|
let family_infos = [family_info];
|
||||||
|
let mut physical_device_multiview_features = ash::vk::PhysicalDeviceMultiviewFeatures {
|
||||||
|
multiview: ash::vk::TRUE,
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
let info = enabled_phd_features
|
let info = enabled_phd_features
|
||||||
.add_to_device_create_builder(
|
.add_to_device_create(
|
||||||
ash::vk::DeviceCreateInfo::builder()
|
ash::vk::DeviceCreateInfo::default()
|
||||||
.queue_create_infos(&family_infos)
|
.queue_create_infos(&family_infos)
|
||||||
.push_next(&mut ash::vk::PhysicalDeviceMultiviewFeatures {
|
.push_next(&mut physical_device_multiview_features),
|
||||||
multiview: ash::vk::TRUE,
|
|
||||||
..Default::default()
|
|
||||||
}),
|
|
||||||
)
|
)
|
||||||
.enabled_extension_names(&extensions_cchar)
|
.enabled_extension_names(&extensions_cchar);
|
||||||
.build();
|
|
||||||
let vk_device = unsafe {
|
let vk_device = unsafe {
|
||||||
let vk_device = instance
|
let vk_device = instance
|
||||||
.create_vulkan_device(
|
.create_vulkan_device(
|
||||||
system_id,
|
system_id,
|
||||||
|
#[allow(clippy::missing_transmute_annotations)]
|
||||||
std::mem::transmute(vk_entry.static_fn().get_instance_proc_addr),
|
std::mem::transmute(vk_entry.static_fn().get_instance_proc_addr),
|
||||||
vk_physical_device.as_raw() as _,
|
vk_physical_device.as_raw() as _,
|
||||||
&info as *const _ as *const _,
|
&info as *const _ as *const _,
|
||||||
@@ -241,9 +242,10 @@ unsafe impl GraphicsExt for openxr::Vulkan {
|
|||||||
let wgpu_open_device = unsafe {
|
let wgpu_open_device = unsafe {
|
||||||
wgpu_exposed_adapter.adapter.device_from_raw(
|
wgpu_exposed_adapter.adapter.device_from_raw(
|
||||||
vk_device,
|
vk_device,
|
||||||
true,
|
None,
|
||||||
&enabled_extensions,
|
&enabled_extensions,
|
||||||
wgpu_features,
|
wgpu_features,
|
||||||
|
&wgpu::MemoryHints::Performance,
|
||||||
family_info.queue_family_index,
|
family_info.queue_family_index,
|
||||||
0,
|
0,
|
||||||
)
|
)
|
||||||
@@ -273,6 +275,7 @@ unsafe impl GraphicsExt for openxr::Vulkan {
|
|||||||
max_push_constant_size: 4,
|
max_push_constant_size: 4,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
|
memory_hints: wgpu::MemoryHints::Performance,
|
||||||
},
|
},
|
||||||
None,
|
None,
|
||||||
)
|
)
|
||||||
@@ -320,7 +323,7 @@ unsafe impl GraphicsExt for openxr::Vulkan {
|
|||||||
ty: sys::SessionCreateInfo::TYPE,
|
ty: sys::SessionCreateInfo::TYPE,
|
||||||
next: &binding as *const _ as *const _,
|
next: &binding as *const _ as *const _,
|
||||||
create_flags: Default::default(),
|
create_flags: Default::default(),
|
||||||
system_id: system_id,
|
system_id,
|
||||||
};
|
};
|
||||||
let mut out = sys::Session::NULL;
|
let mut out = sys::Session::NULL;
|
||||||
cvt((instance.fp().create_session)(
|
cvt((instance.fp().create_session)(
|
||||||
@@ -379,7 +382,7 @@ fn vulkan_to_wgpu(format: ash::vk::Format) -> Option<wgpu::TextureFormat> {
|
|||||||
F::R8G8B8A8_SINT => Tf::Rgba8Sint,
|
F::R8G8B8A8_SINT => Tf::Rgba8Sint,
|
||||||
F::A2B10G10R10_UINT_PACK32 => Tf::Rgb10a2Uint,
|
F::A2B10G10R10_UINT_PACK32 => Tf::Rgb10a2Uint,
|
||||||
F::A2B10G10R10_UNORM_PACK32 => Tf::Rgb10a2Unorm,
|
F::A2B10G10R10_UNORM_PACK32 => Tf::Rgb10a2Unorm,
|
||||||
F::B10G11R11_UFLOAT_PACK32 => Tf::Rg11b10Float,
|
F::B10G11R11_UFLOAT_PACK32 => Tf::Rg11b10Ufloat,
|
||||||
F::R32G32_UINT => Tf::Rg32Uint,
|
F::R32G32_UINT => Tf::Rg32Uint,
|
||||||
F::R32G32_SINT => Tf::Rg32Sint,
|
F::R32G32_SINT => Tf::Rg32Sint,
|
||||||
F::R32G32_SFLOAT => Tf::Rg32Float,
|
F::R32G32_SFLOAT => Tf::Rg32Float,
|
||||||
@@ -630,7 +633,7 @@ fn wgpu_to_vulkan(format: wgpu::TextureFormat) -> Option<ash::vk::Format> {
|
|||||||
Tf::Rgba8Sint => F::R8G8B8A8_SINT,
|
Tf::Rgba8Sint => F::R8G8B8A8_SINT,
|
||||||
Tf::Rgb10a2Uint => F::A2B10G10R10_UINT_PACK32,
|
Tf::Rgb10a2Uint => F::A2B10G10R10_UINT_PACK32,
|
||||||
Tf::Rgb10a2Unorm => F::A2B10G10R10_UNORM_PACK32,
|
Tf::Rgb10a2Unorm => F::A2B10G10R10_UNORM_PACK32,
|
||||||
Tf::Rg11b10Float => F::B10G11R11_UFLOAT_PACK32,
|
Tf::Rg11b10Ufloat => F::B10G11R11_UFLOAT_PACK32,
|
||||||
Tf::Rg32Uint => F::R32G32_UINT,
|
Tf::Rg32Uint => F::R32G32_UINT,
|
||||||
Tf::Rg32Sint => F::R32G32_SINT,
|
Tf::Rg32Sint => F::R32G32_SINT,
|
||||||
Tf::Rg32Float => F::R32G32_SFLOAT,
|
Tf::Rg32Float => F::R32G32_SFLOAT,
|
||||||
@@ -724,4 +727,3 @@ fn wgpu_to_vulkan(format: wgpu::TextureFormat) -> Option<ash::vk::Format> {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
use bevy::prelude::*;
|
use bevy::{math::Vec3A, prelude::*};
|
||||||
use bevy_mod_xr::types::XrPose;
|
|
||||||
|
|
||||||
pub trait ToPosef {
|
pub trait ToPosef {
|
||||||
fn to_posef(&self) -> openxr::Posef;
|
fn to_posef(&self) -> openxr::Posef;
|
||||||
@@ -7,8 +6,8 @@ pub trait ToPosef {
|
|||||||
pub trait ToTransform {
|
pub trait ToTransform {
|
||||||
fn to_transform(&self) -> Transform;
|
fn to_transform(&self) -> Transform;
|
||||||
}
|
}
|
||||||
pub trait ToXrPose {
|
pub trait ToIsometry3d {
|
||||||
fn to_xr_pose(&self) -> XrPose;
|
fn to_xr_pose(&self) -> Isometry3d;
|
||||||
}
|
}
|
||||||
pub trait ToQuaternionf {
|
pub trait ToQuaternionf {
|
||||||
fn to_quaternionf(&self) -> openxr::Quaternionf;
|
fn to_quaternionf(&self) -> openxr::Quaternionf;
|
||||||
@@ -42,15 +41,15 @@ impl ToTransform for openxr::Posef {
|
|||||||
.with_rotation(self.orientation.to_quat())
|
.with_rotation(self.orientation.to_quat())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl ToXrPose for openxr::Posef {
|
impl ToIsometry3d for openxr::Posef {
|
||||||
fn to_xr_pose(&self) -> XrPose {
|
fn to_xr_pose(&self) -> Isometry3d {
|
||||||
XrPose {
|
Isometry3d {
|
||||||
translation: self.position.to_vec3(),
|
translation: self.position.to_vec3().into(),
|
||||||
rotation: self.orientation.to_quat(),
|
rotation: self.orientation.to_quat(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl ToPosef for XrPose {
|
impl ToPosef for Isometry3d {
|
||||||
fn to_posef(&self) -> openxr::Posef {
|
fn to_posef(&self) -> openxr::Posef {
|
||||||
openxr::Posef {
|
openxr::Posef {
|
||||||
orientation: self.rotation.to_quaternionf(),
|
orientation: self.rotation.to_quaternionf(),
|
||||||
@@ -90,6 +89,15 @@ impl ToVector3f for Vec3 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
impl ToVector3f for Vec3A {
|
||||||
|
fn to_vector3f(&self) -> openxr::Vector3f {
|
||||||
|
openxr::Vector3f {
|
||||||
|
x: self.x,
|
||||||
|
y: self.y,
|
||||||
|
z: self.z,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
impl ToVec3 for openxr::Vector3f {
|
impl ToVec3 for openxr::Vector3f {
|
||||||
fn to_vec3(&self) -> Vec3 {
|
fn to_vec3(&self) -> Vec3 {
|
||||||
Vec3 {
|
Vec3 {
|
||||||
|
|||||||
@@ -113,7 +113,7 @@ impl Plugin for OxrInitPlugin {
|
|||||||
(
|
(
|
||||||
create_xr_session
|
create_xr_session
|
||||||
.run_if(state_equals(XrState::Available))
|
.run_if(state_equals(XrState::Available))
|
||||||
.run_if(on_event::<XrCreateSessionEvent>()),
|
.run_if(on_event::<XrCreateSessionEvent>),
|
||||||
(
|
(
|
||||||
destroy_xr_session,
|
destroy_xr_session,
|
||||||
(|v: Res<XrDestroySessionRender>| {
|
(|v: Res<XrDestroySessionRender>| {
|
||||||
@@ -122,16 +122,16 @@ impl Plugin for OxrInitPlugin {
|
|||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
.run_if(state_matches!(XrState::Exiting { .. }))
|
.run_if(state_matches!(XrState::Exiting { .. }))
|
||||||
.run_if(on_event::<XrDestroySessionEvent>()),
|
.run_if(on_event::<XrDestroySessionEvent>),
|
||||||
begin_xr_session
|
begin_xr_session
|
||||||
.run_if(state_equals(XrState::Ready))
|
.run_if(state_equals(XrState::Ready))
|
||||||
.run_if(on_event::<XrBeginSessionEvent>()),
|
.run_if(on_event::<XrBeginSessionEvent>),
|
||||||
end_xr_session
|
end_xr_session
|
||||||
.run_if(state_equals(XrState::Stopping))
|
.run_if(state_equals(XrState::Stopping))
|
||||||
.run_if(on_event::<XrEndSessionEvent>()),
|
.run_if(on_event::<XrEndSessionEvent>),
|
||||||
request_exit_xr_session
|
request_exit_xr_session
|
||||||
.run_if(session_created)
|
.run_if(session_created)
|
||||||
.run_if(on_event::<XrRequestExitEvent>()),
|
.run_if(on_event::<XrRequestExitEvent>),
|
||||||
)
|
)
|
||||||
.in_set(XrHandleEvents::SessionStateUpdateEvents),
|
.in_set(XrHandleEvents::SessionStateUpdateEvents),
|
||||||
)
|
)
|
||||||
@@ -146,9 +146,6 @@ impl Plugin for OxrInitPlugin {
|
|||||||
.insert_non_send_resource(session_create_info)
|
.insert_non_send_resource(session_create_info)
|
||||||
.init_non_send_resource::<OxrSessionCreateNextChain>();
|
.init_non_send_resource::<OxrSessionCreateNextChain>();
|
||||||
|
|
||||||
app.world_mut()
|
|
||||||
.spawn((SpatialBundle::default(), XrTrackingRoot));
|
|
||||||
|
|
||||||
app.world_mut()
|
app.world_mut()
|
||||||
.resource_mut::<Events<XrStateChanged>>()
|
.resource_mut::<Events<XrStateChanged>>()
|
||||||
.send(XrStateChanged(XrState::Available));
|
.send(XrStateChanged(XrState::Available));
|
||||||
@@ -178,7 +175,7 @@ impl Plugin for OxrInitPlugin {
|
|||||||
})
|
})
|
||||||
.run_if(
|
.run_if(
|
||||||
resource_exists::<XrDestroySessionRender>
|
resource_exists::<XrDestroySessionRender>
|
||||||
.and_then(|v: Res<XrDestroySessionRender>| v.0.load(Ordering::Relaxed)),
|
.and(|v: Res<XrDestroySessionRender>| v.0.load(Ordering::Relaxed)),
|
||||||
)
|
)
|
||||||
.chain(),
|
.chain(),
|
||||||
);
|
);
|
||||||
@@ -467,7 +464,7 @@ pub fn create_xr_session(world: &mut World) {
|
|||||||
let system_id = world.resource::<OxrSystemId>();
|
let system_id = world.resource::<OxrSystemId>();
|
||||||
match init_xr_session(
|
match init_xr_session(
|
||||||
device.wgpu_device(),
|
device.wgpu_device(),
|
||||||
&instance,
|
instance,
|
||||||
**system_id,
|
**system_id,
|
||||||
&mut chain,
|
&mut chain,
|
||||||
create_info.clone(),
|
create_info.clone(),
|
||||||
@@ -475,8 +472,8 @@ pub fn create_xr_session(world: &mut World) {
|
|||||||
Ok((session, frame_waiter, frame_stream, swapchain, images, graphics_info)) => {
|
Ok((session, frame_waiter, frame_stream, swapchain, images, graphics_info)) => {
|
||||||
world.insert_resource(session.clone());
|
world.insert_resource(session.clone());
|
||||||
world.insert_resource(frame_waiter);
|
world.insert_resource(frame_waiter);
|
||||||
world.insert_resource(images.clone());
|
world.insert_resource(images);
|
||||||
world.insert_resource(graphics_info.clone());
|
world.insert_resource(graphics_info);
|
||||||
world.insert_resource(OxrRenderResources {
|
world.insert_resource(OxrRenderResources {
|
||||||
session,
|
session,
|
||||||
frame_stream,
|
frame_stream,
|
||||||
@@ -511,12 +508,13 @@ pub fn begin_xr_session(
|
|||||||
world: &mut World,
|
world: &mut World,
|
||||||
// session: Res<OxrSession>, mut session_started: ResMut<OxrSessionStarted>
|
// session: Res<OxrSession>, mut session_started: ResMut<OxrSessionStarted>
|
||||||
) {
|
) {
|
||||||
let _span = info_span!("xr_begin_session");
|
let _span = debug_span!("xr_begin_session").entered();
|
||||||
world
|
world
|
||||||
.get_resource::<OxrSession>()
|
.get_resource::<OxrSession>()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.begin(openxr::ViewConfigurationType::PRIMARY_STEREO)
|
.begin(openxr::ViewConfigurationType::PRIMARY_STEREO)
|
||||||
.expect("Failed to begin session");
|
.expect("Failed to begin session");
|
||||||
|
drop(_span);
|
||||||
world.get_resource_mut::<OxrSessionStarted>().unwrap().0 = true;
|
world.get_resource_mut::<OxrSessionStarted>().unwrap().0 = true;
|
||||||
world.run_schedule(XrPostSessionBegin);
|
world.run_schedule(XrPostSessionBegin);
|
||||||
}
|
}
|
||||||
@@ -527,7 +525,7 @@ pub fn end_xr_session(
|
|||||||
) {
|
) {
|
||||||
// Maybe this could be an event?
|
// Maybe this could be an event?
|
||||||
world.run_schedule(XrPreSessionEnd);
|
world.run_schedule(XrPreSessionEnd);
|
||||||
let _span = info_span!("xr_end_session");
|
let _span = debug_span!("xr_end_session").entered();
|
||||||
world
|
world
|
||||||
.get_resource::<OxrSession>()
|
.get_resource::<OxrSession>()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
|
|||||||
@@ -37,14 +37,14 @@ impl LayerProvider for ProjectionLayer {
|
|||||||
Some(Box::new(
|
Some(Box::new(
|
||||||
CompositionLayerProjection::new()
|
CompositionLayerProjection::new()
|
||||||
.layer_flags(CompositionLayerFlags::BLEND_TEXTURE_SOURCE_ALPHA)
|
.layer_flags(CompositionLayerFlags::BLEND_TEXTURE_SOURCE_ALPHA)
|
||||||
.space(&stage)
|
.space(stage)
|
||||||
.views(&[
|
.views(&[
|
||||||
CompositionLayerProjectionView::new()
|
CompositionLayerProjectionView::new()
|
||||||
.pose(openxr_views.0[0].pose)
|
.pose(openxr_views.0[0].pose)
|
||||||
.fov(openxr_views.0[0].fov)
|
.fov(openxr_views.0[0].fov)
|
||||||
.sub_image(
|
.sub_image(
|
||||||
SwapchainSubImage::new()
|
SwapchainSubImage::new()
|
||||||
.swapchain(&swapchain)
|
.swapchain(swapchain)
|
||||||
.image_array_index(0)
|
.image_array_index(0)
|
||||||
.image_rect(rect),
|
.image_rect(rect),
|
||||||
),
|
),
|
||||||
@@ -53,7 +53,7 @@ impl LayerProvider for ProjectionLayer {
|
|||||||
.fov(openxr_views.0[1].fov)
|
.fov(openxr_views.0[1].fov)
|
||||||
.sub_image(
|
.sub_image(
|
||||||
SwapchainSubImage::new()
|
SwapchainSubImage::new()
|
||||||
.swapchain(&swapchain)
|
.swapchain(swapchain)
|
||||||
.image_array_index(1)
|
.image_array_index(1)
|
||||||
.image_rect(rect),
|
.image_rect(rect),
|
||||||
),
|
),
|
||||||
@@ -235,9 +235,15 @@ impl<'a> Default for CompositionLayerProjection<'a> {
|
|||||||
pub struct CompositionLayerPassthrough {
|
pub struct CompositionLayerPassthrough {
|
||||||
inner: sys::CompositionLayerPassthroughFB,
|
inner: sys::CompositionLayerPassthroughFB,
|
||||||
}
|
}
|
||||||
|
impl Default for CompositionLayerPassthrough {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl CompositionLayerPassthrough {
|
impl CompositionLayerPassthrough {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn new() -> Self {
|
pub const fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
inner: openxr::sys::CompositionLayerPassthroughFB {
|
inner: openxr::sys::CompositionLayerPassthroughFB {
|
||||||
ty: openxr::sys::CompositionLayerPassthroughFB::TYPE,
|
ty: openxr::sys::CompositionLayerPassthroughFB::TYPE,
|
||||||
|
|||||||
@@ -60,8 +60,8 @@ pub fn add_xr_plugins<G: PluginGroup>(plugins: G) -> PluginGroupBuilder {
|
|||||||
.build()
|
.build()
|
||||||
.disable::<RenderPlugin>()
|
.disable::<RenderPlugin>()
|
||||||
// .disable::<PipelinedRenderingPlugin>()
|
// .disable::<PipelinedRenderingPlugin>()
|
||||||
.add_before::<RenderPlugin, _>(XrSessionPlugin { auto_handle: true })
|
.add_before::<RenderPlugin>(XrSessionPlugin { auto_handle: true })
|
||||||
.add_before::<RenderPlugin, _>(OxrInitPlugin::default())
|
.add_before::<RenderPlugin>(OxrInitPlugin::default())
|
||||||
.add(OxrEventsPlugin)
|
.add(OxrEventsPlugin)
|
||||||
.add(OxrReferenceSpacePlugin::default())
|
.add(OxrReferenceSpacePlugin::default())
|
||||||
.add(OxrRenderPlugin)
|
.add(OxrRenderPlugin)
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ impl Plugin for OxrEventsPlugin {
|
|||||||
}
|
}
|
||||||
/// Polls any OpenXR events and handles them accordingly
|
/// Polls any OpenXR events and handles them accordingly
|
||||||
pub fn poll_events(world: &mut World) {
|
pub fn poll_events(world: &mut World) {
|
||||||
let _span = info_span!("xr_poll_events");
|
let _span = debug_span!("xr_poll_events").entered();
|
||||||
let instance = world.resource::<OxrInstance>().clone();
|
let instance = world.resource::<OxrInstance>().clone();
|
||||||
let handlers = world.remove_resource::<OxrEventHandlers>().unwrap();
|
let handlers = world.remove_resource::<OxrEventHandlers>().unwrap();
|
||||||
let mut buffer = EventDataBuffer::default();
|
let mut buffer = EventDataBuffer::default();
|
||||||
@@ -45,15 +45,16 @@ use super::{openxr_session_available, resources::OxrInstance};
|
|||||||
pub struct OxrEventHandlers {
|
pub struct OxrEventHandlers {
|
||||||
pub handlers: Vec<OxrEventHandler>,
|
pub handlers: Vec<OxrEventHandler>,
|
||||||
}
|
}
|
||||||
pub type OxrEventHandler = SystemId<OxrEvent, ()>;
|
pub type OxrEventHandler = SystemId<In<OxrEvent>, ()>;
|
||||||
|
|
||||||
pub struct OxrEvent {
|
pub struct OxrEvent {
|
||||||
event: Rc<RefCell<Option<Event<'static>>>>,
|
event: Rc<RefCell<Option<Event<'static>>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl OxrEvent {
|
impl OxrEvent {
|
||||||
pub(crate) fn new<'a>(event: Rc<RefCell<Option<Event<'a>>>>) -> Self {
|
pub(crate) fn new(event: Rc<RefCell<Option<Event<'_>>>>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
#[allow(clippy::missing_transmute_annotations)]
|
||||||
event: unsafe { mem::transmute(event) },
|
event: unsafe { mem::transmute(event) },
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -63,19 +64,19 @@ impl OxrEvent {
|
|||||||
/// don't Store the [Event] anywhere!!
|
/// don't Store the [Event] anywhere!!
|
||||||
#[allow(clippy::needless_lifetimes)]
|
#[allow(clippy::needless_lifetimes)]
|
||||||
pub unsafe fn get<'a>(&'a self) -> Option<Event<'a>> {
|
pub unsafe fn get<'a>(&'a self) -> Option<Event<'a>> {
|
||||||
self.event.borrow().clone()
|
*self.event.borrow()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub trait OxrEventHandlerExt {
|
pub trait OxrEventHandlerExt {
|
||||||
fn add_oxr_event_handler<M>(
|
fn add_oxr_event_handler<M>(
|
||||||
&mut self,
|
&mut self,
|
||||||
system: impl IntoSystem<OxrEvent, (), M> + 'static,
|
system: impl IntoSystem<In<OxrEvent>, (), M> + 'static,
|
||||||
) -> &mut Self;
|
) -> &mut Self;
|
||||||
}
|
}
|
||||||
impl OxrEventHandlerExt for App {
|
impl OxrEventHandlerExt for App {
|
||||||
fn add_oxr_event_handler<M>(
|
fn add_oxr_event_handler<M>(
|
||||||
&mut self,
|
&mut self,
|
||||||
system: impl IntoSystem<OxrEvent, (), M> + 'static,
|
system: impl IntoSystem<In<OxrEvent>, (), M> + 'static,
|
||||||
) -> &mut Self {
|
) -> &mut Self {
|
||||||
self.init_resource::<OxrEventHandlers>();
|
self.init_resource::<OxrEventHandlers>();
|
||||||
let id = self.register_system(system);
|
let id = self.register_system(system);
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
use bevy::{
|
use bevy::{
|
||||||
ecs::query::QuerySingleError,
|
|
||||||
prelude::*,
|
prelude::*,
|
||||||
render::{
|
render::{
|
||||||
camera::{ManualTextureView, ManualTextureViewHandle, ManualTextureViews, RenderTarget},
|
camera::{ManualTextureView, ManualTextureViewHandle, ManualTextureViews, RenderTarget},
|
||||||
@@ -11,10 +10,8 @@ use bevy::{
|
|||||||
transform::TransformSystem,
|
transform::TransformSystem,
|
||||||
};
|
};
|
||||||
use bevy_mod_xr::{
|
use bevy_mod_xr::{
|
||||||
camera::{XrCamera, XrCameraBundle, XrProjection},
|
camera::{XrCamera, XrProjection},
|
||||||
session::{
|
session::{XrFirst, XrHandleEvents, XrPreDestroySession, XrRenderSet, XrRootTransform},
|
||||||
XrFirst, XrHandleEvents, XrPreDestroySession, XrRenderSet, XrRootTransform, XrTrackingRoot,
|
|
||||||
},
|
|
||||||
spaces::XrPrimaryReferenceSpace,
|
spaces::XrPrimaryReferenceSpace,
|
||||||
};
|
};
|
||||||
use openxr::ViewStateFlags;
|
use openxr::ViewStateFlags;
|
||||||
@@ -34,10 +31,6 @@ impl Plugin for OxrRenderPlugin {
|
|||||||
fn build(&self, app: &mut App) {
|
fn build(&self, app: &mut App) {
|
||||||
if app.is_plugin_added::<PipelinedRenderingPlugin>() {
|
if app.is_plugin_added::<PipelinedRenderingPlugin>() {
|
||||||
app.init_resource::<Pipelined>();
|
app.init_resource::<Pipelined>();
|
||||||
|
|
||||||
// if let Some(sub_app) = app.remove_sub_app(RenderExtractApp) {
|
|
||||||
// app.insert_sub_app(RenderExtractApp, SubApp::new(sub_app.app, update_rendering));
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
app.add_plugins((
|
app.add_plugins((
|
||||||
@@ -140,43 +133,26 @@ pub fn init_views(
|
|||||||
graphics_info: Res<OxrGraphicsInfo>,
|
graphics_info: Res<OxrGraphicsInfo>,
|
||||||
mut manual_texture_views: ResMut<ManualTextureViews>,
|
mut manual_texture_views: ResMut<ManualTextureViews>,
|
||||||
swapchain_images: Res<OxrSwapchainImages>,
|
swapchain_images: Res<OxrSwapchainImages>,
|
||||||
root: Query<Entity, With<XrTrackingRoot>>,
|
|
||||||
mut commands: Commands,
|
mut commands: Commands,
|
||||||
) {
|
) {
|
||||||
let _span = info_span!("xr_init_views");
|
|
||||||
let temp_tex = swapchain_images.first().unwrap();
|
let temp_tex = swapchain_images.first().unwrap();
|
||||||
// this for loop is to easily add support for quad or mono views in the future.
|
// this for loop is to easily add support for quad or mono views in the future.
|
||||||
for index in 0..2 {
|
for index in 0..2 {
|
||||||
info!("{}", graphics_info.resolution);
|
let _span = debug_span!("xr_init_view").entered();
|
||||||
|
info!("XrCamera resolution: {}", graphics_info.resolution);
|
||||||
let view_handle =
|
let view_handle =
|
||||||
add_texture_view(&mut manual_texture_views, temp_tex, &graphics_info, index);
|
add_texture_view(&mut manual_texture_views, temp_tex, &graphics_info, index);
|
||||||
|
commands.spawn((
|
||||||
let cam = commands
|
Camera {
|
||||||
.spawn((XrCameraBundle {
|
target: RenderTarget::TextureView(view_handle),
|
||||||
camera: Camera {
|
|
||||||
target: RenderTarget::TextureView(view_handle),
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
view: XrCamera(index),
|
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},))
|
},
|
||||||
.id();
|
XrCamera(index),
|
||||||
match root.get_single() {
|
));
|
||||||
Ok(root) => {
|
|
||||||
commands.entity(root).add_child(cam);
|
|
||||||
}
|
|
||||||
Err(QuerySingleError::NoEntities(_)) => {
|
|
||||||
warn!("No XrTrackingRoot!");
|
|
||||||
}
|
|
||||||
Err(QuerySingleError::MultipleEntities(_)) => {
|
|
||||||
warn!("Multiple XrTrackingRoots! this is not allowed");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn wait_frame(mut frame_waiter: ResMut<OxrFrameWaiter>, mut commands: Commands) {
|
pub fn wait_frame(mut frame_waiter: ResMut<OxrFrameWaiter>, mut commands: Commands) {
|
||||||
let _span = info_span!("xr_wait_frame");
|
|
||||||
let state = frame_waiter.wait().expect("Failed to wait frame");
|
let state = frame_waiter.wait().expect("Failed to wait frame");
|
||||||
commands.insert_resource(OxrFrameState(state));
|
commands.insert_resource(OxrFrameState(state));
|
||||||
}
|
}
|
||||||
@@ -385,11 +361,11 @@ pub fn insert_texture_views(
|
|||||||
mut manual_texture_views: ResMut<ManualTextureViews>,
|
mut manual_texture_views: ResMut<ManualTextureViews>,
|
||||||
graphics_info: Res<OxrGraphicsInfo>,
|
graphics_info: Res<OxrGraphicsInfo>,
|
||||||
) {
|
) {
|
||||||
let _span = info_span!("xr_insert_texture_views");
|
|
||||||
let index = swapchain.acquire_image().expect("Failed to acquire image");
|
let index = swapchain.acquire_image().expect("Failed to acquire image");
|
||||||
let image = &swapchain_images[index as usize];
|
let image = &swapchain_images[index as usize];
|
||||||
|
|
||||||
for i in 0..2 {
|
for i in 0..2 {
|
||||||
|
let _span = debug_span!("xr_insert_texture_view").entered();
|
||||||
add_texture_view(&mut manual_texture_views, image, &graphics_info, i);
|
add_texture_view(&mut manual_texture_views, image, &graphics_info, i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -423,23 +399,21 @@ pub fn add_texture_view(
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn begin_frame(mut frame_stream: ResMut<OxrFrameStream>) {
|
pub fn begin_frame(mut frame_stream: ResMut<OxrFrameStream>) {
|
||||||
let _span = info_span!("xr_begin_frame");
|
|
||||||
frame_stream.begin().expect("Failed to begin frame");
|
frame_stream.begin().expect("Failed to begin frame");
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn release_image(mut swapchain: ResMut<OxrSwapchain>) {
|
pub fn release_image(mut swapchain: ResMut<OxrSwapchain>) {
|
||||||
let _span = info_span!("xr_release_image");
|
|
||||||
#[cfg(target_os = "android")]
|
#[cfg(target_os = "android")]
|
||||||
{
|
{
|
||||||
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();
|
||||||
}
|
}
|
||||||
|
let _span = debug_span!("xr_release_image").entered();
|
||||||
swapchain.release_image().unwrap();
|
swapchain.release_image().unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn end_frame(world: &mut World) {
|
pub fn end_frame(world: &mut World) {
|
||||||
let _span = info_span!("xr_end_frame");
|
|
||||||
#[cfg(target_os = "android")]
|
#[cfg(target_os = "android")]
|
||||||
{
|
{
|
||||||
let ctx = ndk_context::android_context();
|
let ctx = ndk_context::android_context();
|
||||||
@@ -449,6 +423,7 @@ pub fn end_frame(world: &mut World) {
|
|||||||
world.resource_scope::<OxrFrameStream, ()>(|world, mut frame_stream| {
|
world.resource_scope::<OxrFrameStream, ()>(|world, mut frame_stream| {
|
||||||
let mut layers = vec![];
|
let mut layers = vec![];
|
||||||
let frame_state = world.resource::<OxrFrameState>();
|
let frame_state = world.resource::<OxrFrameState>();
|
||||||
|
let _span = debug_span!("get layers").entered();
|
||||||
if frame_state.should_render {
|
if frame_state.should_render {
|
||||||
for layer in world.resource::<OxrRenderLayers>().iter() {
|
for layer in world.resource::<OxrRenderLayers>().iter() {
|
||||||
if let Some(layer) = layer.get(world) {
|
if let Some(layer) = layer.get(world) {
|
||||||
@@ -456,7 +431,9 @@ pub fn end_frame(world: &mut World) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
drop(_span);
|
||||||
let layers: Vec<_> = layers.iter().map(Box::as_ref).collect();
|
let layers: Vec<_> = layers.iter().map(Box::as_ref).collect();
|
||||||
|
let _span = debug_span!("xr_end_frame").entered();
|
||||||
if let Err(e) = frame_stream.end(
|
if let Err(e) = frame_stream.end(
|
||||||
frame_state.predicted_display_time,
|
frame_state.predicted_display_time,
|
||||||
world.resource::<OxrGraphicsInfo>().blend_mode,
|
world.resource::<OxrGraphicsInfo>().blend_mode,
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ impl OxrEntry {
|
|||||||
application_version: app_info.version.to_u32(),
|
application_version: app_info.version.to_u32(),
|
||||||
engine_name: "Bevy",
|
engine_name: "Bevy",
|
||||||
engine_version: Version::BEVY.to_u32(),
|
engine_version: Version::BEVY.to_u32(),
|
||||||
|
api_version: openxr::Version::new(1, 1, 36),
|
||||||
},
|
},
|
||||||
&required_exts.into(),
|
&required_exts.into(),
|
||||||
layers,
|
layers,
|
||||||
@@ -108,7 +109,7 @@ impl OxrInstance {
|
|||||||
graphics_match!(
|
graphics_match!(
|
||||||
self.1;
|
self.1;
|
||||||
_ => {
|
_ => {
|
||||||
let (graphics, session_info) = Api::init_graphics(&self.2, &self, system_id)?;
|
let (graphics, session_info) = Api::init_graphics(&self.2, self, system_id)?;
|
||||||
|
|
||||||
Ok((graphics, SessionCreateInfo(Api::wrap(session_info))))
|
Ok((graphics, SessionCreateInfo(Api::wrap(session_info))))
|
||||||
}
|
}
|
||||||
@@ -185,7 +186,7 @@ impl OxrFrameStream {
|
|||||||
stream => {
|
stream => {
|
||||||
let mut new_layers = vec![];
|
let mut new_layers = vec![];
|
||||||
|
|
||||||
for (i, layer) in layers.into_iter().enumerate() {
|
for (i, layer) in layers.iter().enumerate() {
|
||||||
if let Some(swapchain) = layer.swapchain() {
|
if let Some(swapchain) = layer.swapchain() {
|
||||||
if !swapchain.0.using_graphics::<Api>() {
|
if !swapchain.0.using_graphics::<Api>() {
|
||||||
error!(
|
error!(
|
||||||
@@ -196,7 +197,10 @@ impl OxrFrameStream {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
new_layers.push(unsafe { std::mem::transmute(layer.header()) });
|
new_layers.push(unsafe {
|
||||||
|
#[allow(clippy::missing_transmute_annotations)]
|
||||||
|
std::mem::transmute(layer.header())
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(stream.end(display_time, environment_blend_mode, new_layers.as_slice())?)
|
Ok(stream.end(display_time, environment_blend_mode, new_layers.as_slice())?)
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ use bevy_mod_xr::{
|
|||||||
XrDestroySpace, XrPrimaryReferenceSpace, XrReferenceSpace, XrSpace, XrSpaceLocationFlags,
|
XrDestroySpace, XrPrimaryReferenceSpace, XrReferenceSpace, XrSpace, XrSpaceLocationFlags,
|
||||||
XrSpaceVelocityFlags, XrVelocity,
|
XrSpaceVelocityFlags, XrVelocity,
|
||||||
},
|
},
|
||||||
types::XrPose,
|
|
||||||
};
|
};
|
||||||
use openxr::{
|
use openxr::{
|
||||||
sys, HandJointLocation, HandJointLocations, HandJointVelocities, HandJointVelocity,
|
sys, HandJointLocation, HandJointLocations, HandJointVelocities, HandJointVelocity,
|
||||||
@@ -51,28 +50,11 @@ impl Plugin for OxrSpatialPlugin {
|
|||||||
.in_set(OxrSpaceSyncSet)
|
.in_set(OxrSpaceSyncSet)
|
||||||
.run_if(openxr_session_running),
|
.run_if(openxr_session_running),
|
||||||
)
|
)
|
||||||
.observe(add_location_flags)
|
.register_required_components::<XrSpaceLocationFlags, OxrSpaceLocationFlags>()
|
||||||
.observe(add_velocity_flags);
|
.register_required_components::<XrSpaceVelocityFlags, OxrSpaceVelocityFlags>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_velocity_flags(event: Trigger<OnAdd, XrVelocity>, mut cmds: Commands) {
|
|
||||||
if event.entity() == Entity::PLACEHOLDER {
|
|
||||||
error!("called add_location_flags observer without entity");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
cmds.entity(event.entity())
|
|
||||||
.insert(OxrSpaceLocationFlags(openxr::SpaceLocationFlags::default()));
|
|
||||||
}
|
|
||||||
fn add_location_flags(event: Trigger<OnAdd, XrSpace>, mut cmds: Commands) {
|
|
||||||
if event.entity() == Entity::PLACEHOLDER {
|
|
||||||
error!("called add_location_flags observer without entity");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
cmds.entity(event.entity())
|
|
||||||
.insert(OxrSpaceLocationFlags(openxr::SpaceLocationFlags::default()));
|
|
||||||
}
|
|
||||||
|
|
||||||
fn destroy_space_event(instance: Res<OxrInstance>, mut events: EventReader<XrDestroySpace>) {
|
fn destroy_space_event(instance: Res<OxrInstance>, mut events: EventReader<XrDestroySpace>) {
|
||||||
for space in events.read() {
|
for space in events.read() {
|
||||||
match instance.destroy_space(space.0) {
|
match instance.destroy_space(space.0) {
|
||||||
@@ -119,7 +101,7 @@ unsafe extern "system" fn patched_destroy_space(space: openxr::sys::Space) -> op
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Component)]
|
#[derive(Clone, Copy, Component, Default)]
|
||||||
pub struct OxrSpaceLocationFlags(pub openxr::SpaceLocationFlags);
|
pub struct OxrSpaceLocationFlags(pub openxr::SpaceLocationFlags);
|
||||||
impl OxrSpaceLocationFlags {
|
impl OxrSpaceLocationFlags {
|
||||||
pub fn pos_valid(&self) -> bool {
|
pub fn pos_valid(&self) -> bool {
|
||||||
@@ -135,7 +117,7 @@ impl OxrSpaceLocationFlags {
|
|||||||
self.0.contains(SpaceLocationFlags::ORIENTATION_TRACKED)
|
self.0.contains(SpaceLocationFlags::ORIENTATION_TRACKED)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[derive(Clone, Copy, Component)]
|
#[derive(Clone, Copy, Component, Default)]
|
||||||
pub struct OxrSpaceVelocityFlags(pub openxr::SpaceVelocityFlags);
|
pub struct OxrSpaceVelocityFlags(pub openxr::SpaceVelocityFlags);
|
||||||
impl OxrSpaceVelocityFlags {
|
impl OxrSpaceVelocityFlags {
|
||||||
pub fn linear_valid(&self) -> bool {
|
pub fn linear_valid(&self) -> bool {
|
||||||
@@ -231,7 +213,7 @@ impl OxrSession {
|
|||||||
&self,
|
&self,
|
||||||
action: &openxr::Action<T>,
|
action: &openxr::Action<T>,
|
||||||
subaction_path: openxr::Path,
|
subaction_path: openxr::Path,
|
||||||
pose_in_space: XrPose,
|
pose_in_space: Isometry3d,
|
||||||
) -> openxr::Result<XrSpace> {
|
) -> openxr::Result<XrSpace> {
|
||||||
let info = sys::ActionSpaceCreateInfo {
|
let info = sys::ActionSpaceCreateInfo {
|
||||||
ty: sys::ActionSpaceCreateInfo::TYPE,
|
ty: sys::ActionSpaceCreateInfo::TYPE,
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ pub struct Version(pub u8, pub u8, pub u16);
|
|||||||
|
|
||||||
impl Version {
|
impl Version {
|
||||||
/// Bevy's version number
|
/// Bevy's version number
|
||||||
pub const BEVY: Self = Self(0, 13, 0);
|
pub const BEVY: Self = Self(0, 15, 0);
|
||||||
|
|
||||||
pub const fn to_u32(self) -> u32 {
|
pub const fn to_u32(self) -> u32 {
|
||||||
let major = (self.0 as u32) << 24;
|
let major = (self.0 as u32) << 24;
|
||||||
|
|||||||
@@ -12,11 +12,11 @@ bevy.workspace = true
|
|||||||
|
|
||||||
# all dependencies are placed under this since on anything but wasm, this crate is completely empty
|
# all dependencies are placed under this since on anything but wasm, this crate is completely empty
|
||||||
[target.'cfg(target_family = "wasm")'.dependencies]
|
[target.'cfg(target_family = "wasm")'.dependencies]
|
||||||
thiserror = "1.0.57"
|
thiserror.workspace = true
|
||||||
wgpu = "0.19.3"
|
wgpu.workspace = true
|
||||||
wgpu-hal = "0.19.3"
|
wgpu-hal.workspace = true
|
||||||
|
|
||||||
bevy_mod_xr = { path = "../bevy_xr", version = "0.1.0-rc1" }
|
bevy_mod_xr.workspace = true
|
||||||
|
|
||||||
[lints.clippy]
|
[lints.clippy]
|
||||||
too_many_arguments = "allow"
|
too_many_arguments = "allow"
|
||||||
|
|||||||
@@ -94,11 +94,11 @@ impl<A: Action<ActionType = bool>> ActionState<A> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn just_pressed(&self) -> bool {
|
pub fn just_pressed(&self) -> bool {
|
||||||
self.previous_state == false && self.current_state == true
|
!self.previous_state && self.current_state
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn just_released(&self) -> bool {
|
pub fn just_released(&self) -> bool {
|
||||||
self.previous_state == true && self.current_state == false
|
self.previous_state && !self.current_state
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn press(&mut self) {
|
pub fn press(&mut self) {
|
||||||
|
|||||||
@@ -1,25 +1,24 @@
|
|||||||
|
use core::panic;
|
||||||
|
|
||||||
use bevy::app::{App, Plugin, PostUpdate};
|
use bevy::app::{App, Plugin, PostUpdate};
|
||||||
use bevy::core_pipeline::core_3d::graph::Core3d;
|
|
||||||
use bevy::core_pipeline::core_3d::Camera3d;
|
use bevy::core_pipeline::core_3d::Camera3d;
|
||||||
use bevy::core_pipeline::tonemapping::{DebandDither, Tonemapping};
|
use bevy::ecs::component::{Component, StorageType};
|
||||||
use bevy::ecs::bundle::Bundle;
|
|
||||||
use bevy::ecs::component::Component;
|
|
||||||
use bevy::ecs::reflect::ReflectComponent;
|
use bevy::ecs::reflect::ReflectComponent;
|
||||||
use bevy::ecs::schedule::IntoSystemConfigs;
|
use bevy::ecs::schedule::IntoSystemConfigs;
|
||||||
use bevy::math::{Mat4, Vec3A};
|
use bevy::math::{Mat4, Vec3A};
|
||||||
use bevy::pbr::{build_directional_light_cascades, clear_directional_light_cascades, SimulationLightSystems};
|
use bevy::pbr::{
|
||||||
|
build_directional_light_cascades, clear_directional_light_cascades, SimulationLightSystems,
|
||||||
|
};
|
||||||
|
use bevy::prelude::Projection;
|
||||||
use bevy::reflect::std_traits::ReflectDefault;
|
use bevy::reflect::std_traits::ReflectDefault;
|
||||||
use bevy::reflect::Reflect;
|
use bevy::reflect::Reflect;
|
||||||
use bevy::render::camera::{
|
use bevy::render::camera::{CameraProjection, CameraProjectionPlugin};
|
||||||
Camera, CameraMainTextureUsages, CameraProjection, CameraProjectionPlugin, CameraRenderGraph,
|
|
||||||
Exposure,
|
|
||||||
};
|
|
||||||
use bevy::render::extract_component::{ExtractComponent, ExtractComponentPlugin};
|
use bevy::render::extract_component::{ExtractComponent, ExtractComponentPlugin};
|
||||||
use bevy::render::primitives::Frustum;
|
use bevy::render::view::{update_frusta, VisibilitySystems};
|
||||||
use bevy::render::view::{update_frusta, ColorGrading, VisibilitySystems, VisibleEntities};
|
|
||||||
use bevy::transform::components::{GlobalTransform, Transform};
|
|
||||||
use bevy::transform::TransformSystem;
|
use bevy::transform::TransformSystem;
|
||||||
|
|
||||||
|
use crate::session::XrTracker;
|
||||||
|
|
||||||
pub struct XrCameraPlugin;
|
pub struct XrCameraPlugin;
|
||||||
|
|
||||||
impl Plugin for XrCameraPlugin {
|
impl Plugin for XrCameraPlugin {
|
||||||
@@ -44,12 +43,21 @@ impl Plugin for XrCameraPlugin {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Component, Reflect, ExtractComponent)]
|
#[derive(Debug, Clone, Reflect, ExtractComponent)]
|
||||||
#[reflect(Component, Default)]
|
#[reflect(Component, Default)]
|
||||||
pub struct XrProjection {
|
pub struct XrProjection {
|
||||||
pub projection_matrix: Mat4,
|
pub projection_matrix: Mat4,
|
||||||
pub near: f32,
|
pub near: f32,
|
||||||
}
|
}
|
||||||
|
impl Component for XrProjection {
|
||||||
|
const STORAGE_TYPE: StorageType = StorageType::Table;
|
||||||
|
|
||||||
|
fn register_component_hooks(hooks: &mut bevy::ecs::component::ComponentHooks) {
|
||||||
|
hooks.on_add(|mut world, entity, _| {
|
||||||
|
world.commands().entity(entity).remove::<Projection>();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Default for XrProjection {
|
impl Default for XrProjection {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
@@ -62,16 +70,15 @@ 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, ExtractComponent, Debug, Default)]
|
#[derive(Clone, Copy, Component, ExtractComponent, Debug, Default)]
|
||||||
|
#[require(Camera3d, XrProjection, XrTracker)]
|
||||||
pub struct XrCamera(pub u32);
|
pub struct XrCamera(pub u32);
|
||||||
|
|
||||||
impl CameraProjection for XrProjection {
|
impl CameraProjection for XrProjection {
|
||||||
fn update(&mut self, _width: f32, _height: f32) {}
|
fn update(&mut self, _width: f32, _height: f32) {}
|
||||||
|
|
||||||
fn far(&self) -> f32 {
|
fn far(&self) -> f32 {
|
||||||
let far = self.projection_matrix.to_cols_array()[14]
|
self.projection_matrix.to_cols_array()[14]
|
||||||
/ (self.projection_matrix.to_cols_array()[10] + 1.0);
|
/ (self.projection_matrix.to_cols_array()[10] + 1.0)
|
||||||
|
|
||||||
far
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO calculate this properly
|
// TODO calculate this properly
|
||||||
@@ -99,43 +106,8 @@ impl CameraProjection for XrProjection {
|
|||||||
fn get_clip_from_view(&self) -> Mat4 {
|
fn get_clip_from_view(&self) -> Mat4 {
|
||||||
self.projection_matrix
|
self.projection_matrix
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Bundle)]
|
fn get_clip_from_view_for_sub(&self, _sub_view: &bevy::render::camera::SubCameraView) -> Mat4 {
|
||||||
pub struct XrCameraBundle {
|
panic!("sub view not supported for xr camera");
|
||||||
pub camera: Camera,
|
|
||||||
pub camera_render_graph: CameraRenderGraph,
|
|
||||||
pub projection: XrProjection,
|
|
||||||
pub visible_entities: VisibleEntities,
|
|
||||||
pub frustum: Frustum,
|
|
||||||
pub transform: Transform,
|
|
||||||
pub global_transform: GlobalTransform,
|
|
||||||
pub camera_3d: Camera3d,
|
|
||||||
pub tonemapping: Tonemapping,
|
|
||||||
pub dither: DebandDither,
|
|
||||||
pub color_grading: ColorGrading,
|
|
||||||
pub exposure: Exposure,
|
|
||||||
pub main_texture_usages: CameraMainTextureUsages,
|
|
||||||
pub view: XrCamera,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for XrCameraBundle {
|
|
||||||
fn default() -> Self {
|
|
||||||
Self {
|
|
||||||
camera_render_graph: CameraRenderGraph::new(Core3d),
|
|
||||||
camera: Default::default(),
|
|
||||||
projection: Default::default(),
|
|
||||||
visible_entities: Default::default(),
|
|
||||||
frustum: Default::default(),
|
|
||||||
transform: Default::default(),
|
|
||||||
global_transform: Default::default(),
|
|
||||||
camera_3d: Default::default(),
|
|
||||||
tonemapping: Default::default(),
|
|
||||||
color_grading: Default::default(),
|
|
||||||
exposure: Default::default(),
|
|
||||||
main_texture_usages: Default::default(),
|
|
||||||
dither: DebandDither::Enabled,
|
|
||||||
view: XrCamera(0),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,15 +1,11 @@
|
|||||||
use bevy::{
|
use bevy::{
|
||||||
ecs::{component::Component, entity::Entity, world::Command},
|
ecs::{component::Component, entity::Entity, world::Command},
|
||||||
hierarchy::BuildWorldChildren,
|
log::warn,
|
||||||
log::{error, warn},
|
|
||||||
math::bool,
|
math::bool,
|
||||||
prelude::{Bundle, Commands, Deref, DerefMut, Resource, SpatialBundle, With, World},
|
prelude::{Bundle, Commands, Deref, DerefMut, Resource, Transform, Visibility, World},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{session::XrTracker, spaces::XrSpaceLocationFlags};
|
||||||
session:: XrTrackingRoot,
|
|
||||||
spaces::XrSpaceLocationFlags,
|
|
||||||
};
|
|
||||||
pub const HAND_JOINT_COUNT: usize = 26;
|
pub const HAND_JOINT_COUNT: usize = 26;
|
||||||
|
|
||||||
pub fn spawn_hand_bones<T: Bundle>(
|
pub fn spawn_hand_bones<T: Bundle>(
|
||||||
@@ -18,15 +14,7 @@ pub fn spawn_hand_bones<T: Bundle>(
|
|||||||
) -> [Entity; HAND_JOINT_COUNT] {
|
) -> [Entity; HAND_JOINT_COUNT] {
|
||||||
let mut bones: [Entity; HAND_JOINT_COUNT] = [Entity::PLACEHOLDER; HAND_JOINT_COUNT];
|
let mut bones: [Entity; HAND_JOINT_COUNT] = [Entity::PLACEHOLDER; HAND_JOINT_COUNT];
|
||||||
for bone in HandBone::get_all_bones().into_iter() {
|
for bone in HandBone::get_all_bones().into_iter() {
|
||||||
bones[bone as usize] = cmds
|
bones[bone as usize] = cmds.spawn((bone, (get_bundle)(bone))).id();
|
||||||
.spawn((
|
|
||||||
SpatialBundle::default(),
|
|
||||||
bone,
|
|
||||||
HandBoneRadius(0.0),
|
|
||||||
XrSpaceLocationFlags::default(),
|
|
||||||
))
|
|
||||||
.insert((get_bundle)(bone))
|
|
||||||
.id();
|
|
||||||
}
|
}
|
||||||
bones
|
bones
|
||||||
}
|
}
|
||||||
@@ -48,11 +36,18 @@ pub struct RightHand;
|
|||||||
pub struct XrHandBoneEntities(pub [Entity; HAND_JOINT_COUNT]);
|
pub struct XrHandBoneEntities(pub [Entity; HAND_JOINT_COUNT]);
|
||||||
|
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
#[derive(Clone, Copy, Component, Debug, DerefMut, Deref)]
|
#[derive(Clone, Copy, Component, Debug, DerefMut, Deref, Default)]
|
||||||
pub struct HandBoneRadius(pub f32);
|
pub struct XrHandBoneRadius(pub f32);
|
||||||
|
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
#[derive(Clone, Copy, Component, Debug)]
|
#[derive(Clone, Copy, Component, Debug)]
|
||||||
|
#[require(
|
||||||
|
XrSpaceLocationFlags,
|
||||||
|
XrHandBoneRadius,
|
||||||
|
Transform,
|
||||||
|
Visibility,
|
||||||
|
XrTracker
|
||||||
|
)]
|
||||||
pub enum HandBone {
|
pub enum HandBone {
|
||||||
Palm = 0,
|
Palm = 0,
|
||||||
Wrist = 1,
|
Wrist = 1,
|
||||||
@@ -192,22 +187,14 @@ impl<B: Bundle> Command for SpawnHandTracker<B> {
|
|||||||
warn!("no SpawnHandTracker executor defined, skipping handtracker creation");
|
warn!("no SpawnHandTracker executor defined, skipping handtracker creation");
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
let Ok(root) = world
|
|
||||||
.query_filtered::<Entity, With<XrTrackingRoot>>()
|
|
||||||
.get_single(world)
|
|
||||||
else {
|
|
||||||
error!("unable to get tracking root, skipping handtracker creation");
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
let mut tracker = world.spawn(self.joints);
|
let mut tracker = world.spawn(self.joints);
|
||||||
match &self.side {
|
match &self.side {
|
||||||
HandSide::Left => tracker.insert(LeftHand),
|
HandSide::Left => tracker.insert((XrTracker, LeftHand)),
|
||||||
HandSide::Right => tracker.insert(RightHand),
|
HandSide::Right => tracker.insert((XrTracker, RightHand)),
|
||||||
};
|
};
|
||||||
let tracker = tracker.id();
|
let tracker = tracker.id();
|
||||||
world.entity_mut(root).push_children(&[tracker]);
|
|
||||||
executor.0(world, tracker, self.side);
|
executor.0(world, tracker, self.side);
|
||||||
if let Some(mut tracker) = world.get_entity_mut(tracker) {
|
if let Ok(mut tracker) = world.get_entity_mut(tracker) {
|
||||||
tracker.insert(self.side);
|
tracker.insert(self.side);
|
||||||
tracker.insert(self.tracker_bundle);
|
tracker.insert(self.tracker_bundle);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
|
use std::convert::identity;
|
||||||
use std::sync::atomic::AtomicBool;
|
use std::sync::atomic::AtomicBool;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use bevy::app::{AppExit, MainScheduleOrder};
|
use bevy::app::{AppExit, MainScheduleOrder};
|
||||||
|
use bevy::ecs::component::StorageType;
|
||||||
use bevy::ecs::schedule::ScheduleLabel;
|
use bevy::ecs::schedule::ScheduleLabel;
|
||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
use bevy::render::extract_resource::{ExtractResource, ExtractResourcePlugin};
|
use bevy::render::extract_resource::{ExtractResource, ExtractResourcePlugin};
|
||||||
@@ -84,7 +86,33 @@ pub struct XrRootTransform(pub GlobalTransform);
|
|||||||
|
|
||||||
/// Component used to specify the entity we should use as the tracking root.
|
/// Component used to specify the entity we should use as the tracking root.
|
||||||
#[derive(Component)]
|
#[derive(Component)]
|
||||||
|
#[require(Transform, Visibility)]
|
||||||
pub struct XrTrackingRoot;
|
pub struct XrTrackingRoot;
|
||||||
|
#[derive(Resource)]
|
||||||
|
struct TrackingRootRes(Entity);
|
||||||
|
|
||||||
|
/// Makes the entity a child of the XrTrackingRoot if the entity has no parent
|
||||||
|
#[derive(Clone, Copy, Hash, PartialEq, Eq, Reflect, Debug, Default)]
|
||||||
|
pub struct XrTracker;
|
||||||
|
impl Component for XrTracker {
|
||||||
|
const STORAGE_TYPE: StorageType = StorageType::SparseSet;
|
||||||
|
|
||||||
|
fn register_component_hooks(hooks: &mut bevy::ecs::component::ComponentHooks) {
|
||||||
|
hooks.on_add(|mut world, entity, _| {
|
||||||
|
if world
|
||||||
|
.entity(entity)
|
||||||
|
.get_components::<Has<Parent>>()
|
||||||
|
.is_some_and(identity)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let Some(root) = world.get_resource::<TrackingRootRes>().map(|r| r.0) else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
world.commands().entity(root).add_child(entity);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct XrSessionPlugin {
|
pub struct XrSessionPlugin {
|
||||||
pub auto_handle: bool,
|
pub auto_handle: bool,
|
||||||
@@ -121,10 +149,12 @@ impl Plugin for XrSessionPlugin {
|
|||||||
.add_systems(
|
.add_systems(
|
||||||
XrFirst,
|
XrFirst,
|
||||||
exits_session_on_app_exit
|
exits_session_on_app_exit
|
||||||
.run_if(on_event::<AppExit>())
|
.run_if(on_event::<AppExit>)
|
||||||
.run_if(session_created)
|
.run_if(session_created)
|
||||||
.in_set(XrHandleEvents::ExitEvents),
|
.in_set(XrHandleEvents::ExitEvents),
|
||||||
);
|
);
|
||||||
|
let root = app.world_mut().spawn(XrTrackingRoot).id();
|
||||||
|
app.world_mut().insert_resource(TrackingRootRes(root));
|
||||||
app.world_mut()
|
app.world_mut()
|
||||||
.resource_mut::<MainScheduleOrder>()
|
.resource_mut::<MainScheduleOrder>()
|
||||||
.labels
|
.labels
|
||||||
@@ -153,7 +183,7 @@ impl Plugin for XrSessionPlugin {
|
|||||||
XrFirst,
|
XrFirst,
|
||||||
exits_session_on_app_exit
|
exits_session_on_app_exit
|
||||||
.before(XrHandleEvents::ExitEvents)
|
.before(XrHandleEvents::ExitEvents)
|
||||||
.run_if(on_event::<AppExit>().and_then(session_running)),
|
.run_if(on_event::<AppExit>.and(session_running)),
|
||||||
);
|
);
|
||||||
|
|
||||||
let render_app = app.sub_app_mut(RenderApp);
|
let render_app = app.sub_app_mut(RenderApp);
|
||||||
|
|||||||
@@ -1,15 +1,18 @@
|
|||||||
use bevy::{
|
use bevy::{
|
||||||
ecs::component::StorageType,
|
|
||||||
prelude::*,
|
prelude::*,
|
||||||
render::{extract_component::ExtractComponent, extract_resource::ExtractResource},
|
render::{extract_component::ExtractComponent, extract_resource::ExtractResource},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use crate::session::XrTracker;
|
||||||
|
|
||||||
/// Any Spaces will be invalid after the owning session exits
|
/// Any Spaces will be invalid after the owning session exits
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
#[derive(Clone, Copy, Hash, PartialEq, Eq, Reflect, Debug, ExtractComponent)]
|
#[derive(Component, Clone, Copy, Hash, PartialEq, Eq, Reflect, Debug, ExtractComponent)]
|
||||||
|
#[require(XrSpaceLocationFlags, Transform, Visibility, XrTracker)]
|
||||||
pub struct XrSpace(u64);
|
pub struct XrSpace(u64);
|
||||||
|
|
||||||
#[derive(Clone, Copy, Reflect, Debug, ExtractComponent, Default)]
|
#[derive(Component, Clone, Copy, Reflect, Debug, ExtractComponent, Default)]
|
||||||
|
#[require(XrSpaceVelocityFlags)]
|
||||||
pub struct XrVelocity {
|
pub struct XrVelocity {
|
||||||
/// Velocity of a space relative to it's reference space
|
/// Velocity of a space relative to it's reference space
|
||||||
pub linear: Vec3,
|
pub linear: Vec3,
|
||||||
@@ -69,28 +72,3 @@ impl XrSpace {
|
|||||||
self.0
|
self.0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Component for XrSpace {
|
|
||||||
const STORAGE_TYPE: StorageType = StorageType::Table;
|
|
||||||
|
|
||||||
fn register_component_hooks(hooks: &mut bevy::ecs::component::ComponentHooks) {
|
|
||||||
hooks.on_add(|mut world, entity, _| {
|
|
||||||
world
|
|
||||||
.commands()
|
|
||||||
.entity(entity)
|
|
||||||
.insert(XrSpaceLocationFlags::default());
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl Component for XrVelocity {
|
|
||||||
const STORAGE_TYPE: StorageType = StorageType::Table;
|
|
||||||
|
|
||||||
fn register_component_hooks(hooks: &mut bevy::ecs::component::ComponentHooks) {
|
|
||||||
hooks.on_add(|mut world, entity, _| {
|
|
||||||
world
|
|
||||||
.commands()
|
|
||||||
.entity(entity)
|
|
||||||
.insert(XrSpaceVelocityFlags::default());
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,26 +1,4 @@
|
|||||||
use bevy::{
|
use bevy::math::Isometry3d;
|
||||||
math::{Quat, Vec3},
|
|
||||||
reflect::Reflect,
|
|
||||||
transform::components::Transform,
|
|
||||||
};
|
|
||||||
|
|
||||||
#[derive(Clone, Copy, PartialEq, Reflect, Debug)]
|
#[deprecated = "Use Isometry3d instead"]
|
||||||
pub struct XrPose {
|
pub type XrPose = Isometry3d;
|
||||||
pub translation: Vec3,
|
|
||||||
pub rotation: Quat,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for XrPose {
|
|
||||||
fn default() -> Self {
|
|
||||||
Self::IDENTITY
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl XrPose {
|
|
||||||
pub const IDENTITY: XrPose = XrPose {
|
|
||||||
translation: Vec3::ZERO,
|
|
||||||
rotation: Quat::IDENTITY,
|
|
||||||
};
|
|
||||||
pub const fn to_transform(self) -> Transform {
|
|
||||||
Transform::from_translation(self.translation).with_rotation(self.rotation)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -10,11 +10,11 @@ description = "utils for bevy_mod_xr and bevy_mod_openxr"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
bevy = { workspace = true, features = ["bevy_gizmos"] }
|
bevy = { workspace = true, features = ["bevy_gizmos"] }
|
||||||
bevy_mod_xr = { path = "../bevy_xr", version = "0.1.0" }
|
bevy_mod_xr.workspace = true
|
||||||
bevy_mod_openxr = { path = "../bevy_openxr", version = "0.1.0" }
|
bevy_mod_openxr.workspace = true
|
||||||
|
|
||||||
[target.'cfg(not(target_family = "wasm"))'.dependencies]
|
[target.'cfg(not(target_family = "wasm"))'.dependencies]
|
||||||
openxr = "0.18.0"
|
openxr.workspace = true
|
||||||
|
|
||||||
[lints.clippy]
|
[lints.clippy]
|
||||||
too_many_arguments = "allow"
|
too_many_arguments = "allow"
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
use bevy::color::palettes::css;
|
use bevy::color::palettes::css;
|
||||||
use bevy::{prelude::*, transform::TransformSystem};
|
use bevy::{prelude::*, transform::TransformSystem};
|
||||||
use bevy_mod_xr::hands::{HandBone, HandBoneRadius};
|
use bevy_mod_xr::hands::{HandBone, XrHandBoneRadius};
|
||||||
|
use bevy_mod_xr::spaces::XrSpaceLocationFlags;
|
||||||
pub struct HandGizmosPlugin;
|
pub struct HandGizmosPlugin;
|
||||||
impl Plugin for HandGizmosPlugin {
|
impl Plugin for HandGizmosPlugin {
|
||||||
fn build(&self, app: &mut App) {
|
fn build(&self, app: &mut App) {
|
||||||
@@ -12,11 +13,24 @@ impl Plugin for HandGizmosPlugin {
|
|||||||
}
|
}
|
||||||
fn draw_hand_gizmos(
|
fn draw_hand_gizmos(
|
||||||
mut gizmos: Gizmos,
|
mut gizmos: Gizmos,
|
||||||
query: Query<(&GlobalTransform, &HandBone, &HandBoneRadius)>,
|
query: Query<(
|
||||||
|
&GlobalTransform,
|
||||||
|
&HandBone,
|
||||||
|
&XrHandBoneRadius,
|
||||||
|
&XrSpaceLocationFlags,
|
||||||
|
)>,
|
||||||
) {
|
) {
|
||||||
for (transform, bone, radius) in &query {
|
for (transform, bone, radius, flags) in &query {
|
||||||
|
if (!flags.position_tracked) || (!flags.rotation_tracked) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
let pose = transform.compute_transform();
|
let pose = transform.compute_transform();
|
||||||
gizmos.sphere(pose.translation, pose.rotation, **radius, gizmo_color(bone));
|
let pose = Isometry3d {
|
||||||
|
translation: pose.translation.into(),
|
||||||
|
rotation: pose.rotation,
|
||||||
|
};
|
||||||
|
gizmos.sphere(pose, **radius, gizmo_color(bone));
|
||||||
|
gizmos.axes(pose, **radius);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,17 @@
|
|||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
use bevy_mod_openxr::{
|
use bevy_mod_openxr::{
|
||||||
action_binding::{OxrSendActionBindings, OxrSuggestActionBinding}, action_set_attaching::OxrAttachActionSet, action_set_syncing::{OxrActionSetSyncSet, OxrSyncActionSet}, helper_traits::{ToQuat, ToVec3}, openxr_session_available, openxr_session_running, resources::{OxrFrameState, OxrInstance, Pipelined}, session::OxrSession, spaces::{OxrSpaceLocationFlags, OxrSpaceSyncSet}
|
action_binding::OxrSuggestActionBinding,
|
||||||
|
action_set_attaching::OxrAttachActionSet,
|
||||||
|
action_set_syncing::{OxrActionSetSyncSet, OxrSyncActionSet},
|
||||||
|
helper_traits::{ToQuat, ToVec3},
|
||||||
|
openxr_session_available, openxr_session_running,
|
||||||
|
resources::{OxrFrameState, OxrInstance, Pipelined},
|
||||||
|
session::OxrSession,
|
||||||
|
spaces::{OxrSpaceLocationFlags, OxrSpaceSyncSet},
|
||||||
};
|
};
|
||||||
use bevy_mod_xr::{
|
use bevy_mod_xr::{
|
||||||
session::{session_available, session_running, XrSessionCreated, XrTrackingRoot},
|
session::{XrSessionCreated, XrTracker, XrTrackingRoot},
|
||||||
spaces::{XrPrimaryReferenceSpace, XrReferenceSpace},
|
spaces::{XrPrimaryReferenceSpace, XrReferenceSpace},
|
||||||
types::XrPose,
|
|
||||||
};
|
};
|
||||||
use openxr::Posef;
|
use openxr::Posef;
|
||||||
|
|
||||||
@@ -74,17 +80,13 @@ impl Plugin for TrackingUtilitiesPlugin {
|
|||||||
|
|
||||||
//stage
|
//stage
|
||||||
fn update_stage(
|
fn update_stage(
|
||||||
mut root_query: Query<&mut Transform, (With<XrTrackingRoot>, Without<XrTrackedStage>)>,
|
root_query: Query<&Transform, (With<XrTrackingRoot>, Without<XrTrackedStage>)>,
|
||||||
mut stage_query: Query<&mut Transform, (With<XrTrackedStage>, Without<XrTrackingRoot>)>,
|
mut stage_query: Query<&mut Transform, (With<XrTrackedStage>, Without<XrTrackingRoot>)>,
|
||||||
) {
|
) {
|
||||||
let tracking_root_transform = root_query.get_single_mut();
|
if let Ok(root) = root_query.get_single() {
|
||||||
match tracking_root_transform {
|
for mut transform in &mut stage_query {
|
||||||
Ok(root) => {
|
*transform = *root;
|
||||||
for (mut transform) in &mut stage_query {
|
|
||||||
*transform = root.clone();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Err(_) => (),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -128,13 +130,10 @@ fn update_view(
|
|||||||
mut view_query: Query<&mut Transform, (With<XrTrackedView>, Without<HeadXRSpace>)>,
|
mut view_query: Query<&mut Transform, (With<XrTrackedView>, Without<HeadXRSpace>)>,
|
||||||
) {
|
) {
|
||||||
let head_transform = head_query.get_single_mut();
|
let head_transform = head_query.get_single_mut();
|
||||||
match head_transform {
|
if let Ok(root) = head_transform {
|
||||||
Ok(root) => {
|
for mut transform in &mut view_query {
|
||||||
for (mut transform) in &mut view_query {
|
*transform = *root;
|
||||||
*transform = root.clone();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Err(_) => (),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -144,19 +143,16 @@ fn update_local_floor_transforms(
|
|||||||
mut local_floor: Query<&mut Transform, (With<XrTrackedLocalFloor>, Without<HeadXRSpace>)>,
|
mut local_floor: Query<&mut Transform, (With<XrTrackedLocalFloor>, Without<HeadXRSpace>)>,
|
||||||
) {
|
) {
|
||||||
let head_transform = head_space.get_single_mut();
|
let head_transform = head_space.get_single_mut();
|
||||||
match head_transform {
|
if let Ok(head) = head_transform {
|
||||||
Ok(head) => {
|
let mut calc_floor = *head;
|
||||||
let mut calc_floor = head.clone();
|
calc_floor.translation.y = 0.0;
|
||||||
calc_floor.translation.y = 0.0;
|
//TODO: use yaw
|
||||||
//TODO: use yaw
|
let (y, _, _) = calc_floor.rotation.to_euler(EulerRot::YXZ);
|
||||||
let (y, x, z) = calc_floor.rotation.to_euler(EulerRot::YXZ);
|
let new_rot = Quat::from_rotation_y(y);
|
||||||
let new_rot = Quat::from_rotation_y(y);
|
calc_floor.rotation = new_rot;
|
||||||
calc_floor.rotation = new_rot;
|
for mut transform in &mut local_floor {
|
||||||
for (mut transform) in &mut local_floor {
|
*transform = calc_floor;
|
||||||
*transform = calc_floor;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Err(_) => (),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -169,13 +165,10 @@ fn update_left_grip(
|
|||||||
mut tracked_left_grip: Query<&mut Transform, (With<XrTrackedLeftGrip>, Without<LeftGrip>)>,
|
mut tracked_left_grip: Query<&mut Transform, (With<XrTrackedLeftGrip>, Without<LeftGrip>)>,
|
||||||
) {
|
) {
|
||||||
let head_transform = left_grip.get_single_mut();
|
let head_transform = left_grip.get_single_mut();
|
||||||
match head_transform {
|
if let Ok(head) = head_transform {
|
||||||
Ok(head) => {
|
for mut transform in &mut tracked_left_grip {
|
||||||
for (mut transform) in &mut tracked_left_grip {
|
*transform = *head;
|
||||||
*transform = head.clone();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Err(_) => (),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -188,13 +181,10 @@ fn update_right_grip(
|
|||||||
mut tracked_right_grip: Query<&mut Transform, (With<XrTrackedRightGrip>, Without<RightGrip>)>,
|
mut tracked_right_grip: Query<&mut Transform, (With<XrTrackedRightGrip>, Without<RightGrip>)>,
|
||||||
) {
|
) {
|
||||||
let head_transform = right_grip.get_single_mut();
|
let head_transform = right_grip.get_single_mut();
|
||||||
match head_transform {
|
if let Ok(head) = head_transform {
|
||||||
Ok(head) => {
|
for mut transform in &mut tracked_right_grip {
|
||||||
for (mut transform) in &mut tracked_right_grip {
|
*transform = *head;
|
||||||
*transform = head.clone();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Err(_) => (),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -209,33 +199,28 @@ pub struct ControllerActions {
|
|||||||
fn spawn_tracking_rig(
|
fn spawn_tracking_rig(
|
||||||
actions: Res<ControllerActions>,
|
actions: Res<ControllerActions>,
|
||||||
mut cmds: Commands,
|
mut cmds: Commands,
|
||||||
root: Query<Entity, With<XrTrackingRoot>>,
|
|
||||||
session: Res<OxrSession>,
|
session: Res<OxrSession>,
|
||||||
) {
|
) {
|
||||||
//head
|
//head
|
||||||
let head_space = session
|
let head_space = session
|
||||||
.create_reference_space(openxr::ReferenceSpaceType::VIEW, Transform::IDENTITY)
|
.create_reference_space(openxr::ReferenceSpaceType::VIEW, Transform::IDENTITY)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let head = cmds
|
cmds.spawn((
|
||||||
.spawn((SpatialBundle::default(), HeadXRSpace(head_space)))
|
Transform::default(),
|
||||||
.id();
|
Visibility::default(),
|
||||||
|
XrTracker,
|
||||||
|
HeadXRSpace(head_space),
|
||||||
|
));
|
||||||
// let local_floor = cmds.spawn((SpatialBundle::default(), LocalFloor)).id();
|
// let local_floor = cmds.spawn((SpatialBundle::default(), LocalFloor)).id();
|
||||||
|
|
||||||
let left_space = session
|
let left_space = session
|
||||||
.create_action_space(&actions.left, openxr::Path::NULL, XrPose::IDENTITY)
|
.create_action_space(&actions.left, openxr::Path::NULL, Isometry3d::IDENTITY)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let right_space = session
|
let right_space = session
|
||||||
.create_action_space(&actions.right, openxr::Path::NULL, XrPose::IDENTITY)
|
.create_action_space(&actions.right, openxr::Path::NULL, Isometry3d::IDENTITY)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let left = cmds
|
cmds.spawn((left_space, LeftGrip));
|
||||||
.spawn((SpatialBundle::default(), left_space, LeftGrip))
|
cmds.spawn((right_space, RightGrip));
|
||||||
.id();
|
|
||||||
let right = cmds
|
|
||||||
.spawn((SpatialBundle::default(), right_space, RightGrip))
|
|
||||||
.id();
|
|
||||||
|
|
||||||
cmds.entity(root.single())
|
|
||||||
.push_children(&[head, left, right]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//bindings
|
//bindings
|
||||||
|
|||||||
Reference in New Issue
Block a user