From 28008f79641357c2fd1be1292de15169fcd80cf7 Mon Sep 17 00:00:00 2001 From: Schmarni <51007916+Schmarni-Dev@users.noreply.github.com> Date: Sat, 9 Dec 2023 06:09:48 +0100 Subject: [PATCH] Fallback to flat when no oxr runtime is found (#51) * basics done? now to the fun part: changing the ENTIRE lib to work with xr and non xr * updated stuff and renamed file * actually add the renamed file into git lol :3 * made lib fallback to flat when no runtime is found but can't compile with default settings under those circumstances --- Cargo.toml | 1 + examples/demo/Cargo.toml | 1 + examples/demo/Cargo_back.toml | 24 -- examples/demo/src/lib.rs | 31 +- examples/demo/src/lib_bak.rs | 609 ---------------------------- examples/demo/src/setup.rs | 18 +- src/graphics/mod.rs | 6 +- src/graphics/vulkan.rs | 4 +- src/lib.rs | 196 ++++----- src/xr_init.rs | 354 ++++++++++++++++ src/xr_input/actions.rs | 5 +- src/xr_input/debug_gizmos.rs | 47 ++- src/xr_input/hands/emulated.rs | 10 +- src/xr_input/hands/hand_tracking.rs | 4 +- src/xr_input/mod.rs | 20 +- 15 files changed, 547 insertions(+), 783 deletions(-) delete mode 100644 examples/demo/Cargo_back.toml delete mode 100644 examples/demo/src/lib_bak.rs create mode 100644 src/xr_init.rs diff --git a/Cargo.toml b/Cargo.toml index 4286be2f..73996b7c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,6 +18,7 @@ members = ["examples/android", "examples/demo"] anyhow = "1.0.75" ash = "0.37.3" bevy = "0.12" +futures-lite = "2.1.0" mint = "0.5.9" wgpu = "0.17.1" wgpu-core = { version = "0.17.1", features = ["vulkan"] } diff --git a/examples/demo/Cargo.toml b/examples/demo/Cargo.toml index d38d7d5b..a6abbf91 100644 --- a/examples/demo/Cargo.toml +++ b/examples/demo/Cargo.toml @@ -17,4 +17,5 @@ color-eyre = "0.6.2" [target.'cfg(not(target_os="android"))'.dependencies.bevy_oxr] path = "../../" +# May need to be more specific. needs to be false at least on linux without an active runtime to run in flat default-features = true diff --git a/examples/demo/Cargo_back.toml b/examples/demo/Cargo_back.toml deleted file mode 100644 index 0423b999..00000000 --- a/examples/demo/Cargo_back.toml +++ /dev/null @@ -1,24 +0,0 @@ -[package] -name = "demo" -version = "0.1.0" -edition = "2021" - - -[lib] -crate-type = ["cdylib", "lib"] -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[dependencies] -bevy = { git = "https://github.com/bevyengine/bevy.git" } -# bevy = "0.11.3" -# default-features is false because it for some reason complains when trying to statically link openxr -bevy_oxr = { path = "../../" } -# bevy_openxr = { git = "https://github.com/Schmarni-Dev/bevy_openxr", default-features = false, branch = "demo"} -bevy_rapier3d = { git = "https://github.com/devil-ira/bevy_rapier", version = "0.22.0", branch = "bevy-0.12" } -# bevy_rapier3d = { git = "https://github.com/Schmarni-Dev/bevy_rapier" } -color-eyre = "0.6.2" - -[profile.release] -lto = "fat" -codegen-units = 1 -panic = "abort" diff --git a/examples/demo/src/lib.rs b/examples/demo/src/lib.rs index 8be09a49..9ce50002 100644 --- a/examples/demo/src/lib.rs +++ b/examples/demo/src/lib.rs @@ -3,6 +3,7 @@ use std::{f32::consts::PI, ops::Mul, time::Duration}; use bevy::{ diagnostic::{FrameTimeDiagnosticsPlugin, LogDiagnosticsPlugin}, ecs::schedule::ScheduleLabel, + input::{keyboard::KeyCode, Input}, log::info, prelude::{ bevy_main, default, shape, App, Assets, Color, Commands, Component, Entity, Event, @@ -16,10 +17,12 @@ use bevy::{ }; use bevy_oxr::{ input::XrInput, + xr_init::{XrEnableRequest, XrEnableStatus, xr_only}, resources::{XrFrameState, XrInstance, XrSession}, xr_input::{ + actions::XrActionSets, debug_gizmos::OpenXrDebugRenderer, - hands::common::{ HandInputDebugRenderer, HandResource, HandsResource, OpenXrHandInput}, + hands::common::{HandInputDebugRenderer, HandResource, HandsResource, OpenXrHandInput}, hands::HandBone, interactions::{ draw_interaction_gizmos, draw_socket_gizmos, interactions, socket_interactions, @@ -29,11 +32,25 @@ use bevy_oxr::{ oculus_touch::OculusController, prototype_locomotion::{proto_locomotion, PrototypeLocomotionConfig}, trackers::{OpenXRController, OpenXRLeftController, OpenXRRightController, OpenXRTracker}, - Hand, actions::XrActionSets, + Hand, }, DefaultXrPlugins, }; +fn input_stuff( + keys: Res>, + status: Res, + mut request: EventWriter, +) { + if keys.just_pressed(KeyCode::Space) { + match status.into_inner() { + XrEnableStatus::Enabled => request.send(XrEnableRequest::TryDisable), + XrEnableStatus::Disabled => request.send(XrEnableRequest::TryEnable), + XrEnableStatus::Waiting => (), + } + } +} + mod setup; use crate::setup::setup_scene; use bevy_rapier3d::prelude::*; @@ -45,7 +62,7 @@ pub fn main() { info!("Running bevy_openxr demo"); let mut app = App::new(); - app + app.add_systems(Update, input_stuff) //lets get the usual diagnostic stuff added .add_plugins(LogDiagnosticsPlugin::default()) .add_plugins(FrameTimeDiagnosticsPlugin) @@ -60,11 +77,11 @@ pub fn main() { .add_systems(Startup, setup_scene) .add_systems(Startup, spawn_controllers_example) //you need to spawn controllers or it crashes TODO:: Fix this //add locomotion - .add_systems(Update, proto_locomotion) + .add_systems(Update, proto_locomotion.run_if(xr_only())) .insert_resource(PrototypeLocomotionConfig::default()) //lets add the interaction systems .add_event::() - .add_systems(Update, prototype_interaction_input) + .add_systems(Update, prototype_interaction_input.run_if(xr_only())) .add_systems(Update, interactions.before(update_interactable_states)) .add_systems(Update, update_interactable_states) .add_systems( @@ -76,7 +93,7 @@ pub fn main() { //draw the interaction gizmos .add_systems( Update, - draw_interaction_gizmos.after(update_interactable_states), + draw_interaction_gizmos.run_if(xr_only()).after(update_interactable_states), ) .add_systems(Update, draw_socket_gizmos.after(update_interactable_states)) //add our cube spawning system @@ -85,7 +102,7 @@ pub fn main() { 0.25, bevy::time::TimerMode::Once, ))) - .add_systems(Update, request_cube_spawn) + .add_systems(Update, request_cube_spawn.run_if(xr_only())) .add_systems(Update, cube_spawner.after(request_cube_spawn)) //test capsule .add_systems(Startup, spawn_capsule) diff --git a/examples/demo/src/lib_bak.rs b/examples/demo/src/lib_bak.rs deleted file mode 100644 index 54d97662..00000000 --- a/examples/demo/src/lib_bak.rs +++ /dev/null @@ -1,609 +0,0 @@ -use bevy::{ - diagnostic::{FrameTimeDiagnosticsPlugin, LogDiagnosticsPlugin}, - log::info, - prelude::{ - *, - bevy_main, default, shape, App, Assets, Color, Commands, Component, Event, EventReader, - EventWriter, GlobalTransform, IntoSystemConfigs, IntoSystemSetConfigs, Mesh, PbrBundle, - PostUpdate, Query, Res, ResMut, Resource, SpatialBundle, StandardMaterial, Startup, - Transform, Update, With, Without, - }, - time::{Time, Timer}, - transform::TransformSystem, -}; -use bevy_openxr::{ - input::XrInput, - resources::{XrFrameState, XrInstance, XrSession}, - xr_input::{ - debug_gizmos::OpenXrDebugRenderer, - hand::{HandBone, HandInputDebugRenderer, HandResource, HandsResource, OpenXrHandInput}, - interactions::{ - draw_interaction_gizmos, draw_socket_gizmos, interactions, socket_interactions, - update_interactable_states, InteractionEvent, Touched, XRDirectInteractor, - XRInteractable, XRInteractableState, XRInteractorState, XRSelection, - }, - oculus_touch::OculusController, - prototype_locomotion::{proto_locomotion, PrototypeLocomotionConfig}, - trackers::{OpenXRController, OpenXRLeftController, OpenXRRightController, OpenXRTracker}, - Hand, - }, - DefaultXrPlugins, -}; - -mod setup; -use crate::setup::setup_scene; -use bevy_rapier3d::prelude::*; - -#[bevy_main] -pub fn main() { - color_eyre::install().unwrap(); - - info!("Running bevy_openxr demo"); - let mut app = App::new(); - - app - //lets get the usual diagnostic stuff added - .add_plugins(LogDiagnosticsPlugin::default()) - .add_plugins(FrameTimeDiagnosticsPlugin) - //lets get the xr defaults added - .add_plugins(DefaultXrPlugins) - //lets add the debug renderer for the controllers - .add_plugins(OpenXrDebugRenderer) - //rapier goes here - .add_plugins(RapierPhysicsPlugin::::default().with_default_system_setup(false)) - .add_plugins(RapierDebugRenderPlugin::default()) - //lets setup the starting scene - .add_systems(Startup, setup_scene) - .add_systems(Startup, spawn_controllers_example) //you need to spawn controllers or it crashes TODO:: Fix this - //add locomotion - .add_systems(Update, proto_locomotion) - .insert_resource(PrototypeLocomotionConfig::default()) - //lets add the interaction systems - .add_event::() - .add_systems(Update, prototype_interaction_input) - .add_systems(Update, interactions.before(update_interactable_states)) - .add_systems(Update, update_interactable_states) - .add_systems( - Update, - socket_interactions.before(update_interactable_states), - ) - //add the grabbable system - .add_systems(Update, update_grabbables.after(update_interactable_states)) - //draw the interaction gizmos - .add_systems( - Update, - draw_interaction_gizmos.after(update_interactable_states), - ) - .add_systems(Update, draw_socket_gizmos.after(update_interactable_states)) - //add our cube spawning system - .add_event::() - .insert_resource(SpawnCubeTimer(Timer::from_seconds( - 0.25, - bevy::time::TimerMode::Once, - ))) - .add_systems(Update, request_cube_spawn) - .add_systems(Update, cube_spawner.after(request_cube_spawn)) - //test capsule - .add_systems(Startup, spawn_capsule) - //physics hands - .add_plugins(OpenXrHandInput) - .add_plugins(HandInputDebugRenderer) - .add_systems(Startup, spawn_physics_hands) - .add_systems(Update, update_physics_hands); - - //configure rapier sets - app.configure_sets( - PostUpdate, - ( - PhysicsSet::SyncBackend, - PhysicsSet::StepSimulation, - PhysicsSet::Writeback, - ) - .chain() - .before(TransformSystem::TransformPropagate), - ); - //add rapier systems - app.add_systems( - PostUpdate, - ( - RapierPhysicsPlugin::::get_systems(PhysicsSet::SyncBackend) - .in_set(PhysicsSet::SyncBackend), - ( - RapierPhysicsPlugin::::get_systems(PhysicsSet::StepSimulation), - // despawn_one_box, - ) - .in_set(PhysicsSet::StepSimulation), - RapierPhysicsPlugin::::get_systems(PhysicsSet::Writeback) - .in_set(PhysicsSet::Writeback), - ), - ); - - app.run(); -} - -fn spawn_controllers_example(mut commands: Commands) { - //left hand - commands.spawn(( - OpenXRLeftController, - OpenXRController, - OpenXRTracker, - SpatialBundle::default(), - XRDirectInteractor, - XRInteractorState::default(), - XRSelection::default(), - )); - //right hand - commands.spawn(( - OpenXRRightController, - OpenXRController, - OpenXRTracker, - SpatialBundle::default(), - XRDirectInteractor, - XRInteractorState::default(), - XRSelection::default(), - )); -} - -fn spawn_capsule( - mut commands: Commands, - mut meshes: ResMut>, - mut materials: ResMut>, -) { - commands.spawn(( - PbrBundle { - mesh: meshes.add(Mesh::from(shape::Capsule { - radius: 0.033, - depth: 0.115, - ..default() - })), - material: materials.add(Color::rgb(0.8, 0.7, 0.6).into()), - transform: Transform::from_xyz(0.0, 2.0, 0.0), - ..default() - }, - // Collider::capsule_y(0.0575, 0.034), - Collider::capsule( - Vec3 { - x: 0.0, - y: -0.0575, - z: 0.0, - }, - Vec3 { - x: 0.0, - y: 0.0575, - z: 0.0, - }, - 0.034, - ), - RigidBody::Dynamic, - )); -} - -#[derive(Component, PartialEq, Debug, Clone, Copy)] -pub enum PhysicsHandBone { - Palm, - Wrist, - ThumbMetacarpal, - ThumbProximal, - ThumbDistal, - ThumbTip, - IndexMetacarpal, - IndexProximal, - IndexIntermediate, - IndexDistal, - IndexTip, - MiddleMetacarpal, - MiddleProximal, - MiddleIntermediate, - MiddleDistal, - MiddleTip, - RingMetacarpal, - RingProximal, - RingIntermediate, - RingDistal, - RingTip, - LittleMetacarpal, - LittleProximal, - LittleIntermediate, - LittleDistal, - LittleTip, -} -#[derive(Component, PartialEq)] -pub enum BoneInitState { - True, - False, -} - -fn spawn_physics_hands(mut commands: Commands) { - //here we go - let hands = [Hand::Left, Hand::Right]; - let bones = [ - PhysicsHandBone::Palm, - PhysicsHandBone::Wrist, - PhysicsHandBone::ThumbMetacarpal, - PhysicsHandBone::ThumbProximal, - PhysicsHandBone::ThumbDistal, - PhysicsHandBone::ThumbTip, - PhysicsHandBone::IndexMetacarpal, - PhysicsHandBone::IndexProximal, - PhysicsHandBone::IndexIntermediate, - PhysicsHandBone::IndexDistal, - PhysicsHandBone::IndexTip, - PhysicsHandBone::MiddleMetacarpal, - PhysicsHandBone::MiddleProximal, - PhysicsHandBone::MiddleIntermediate, - PhysicsHandBone::MiddleDistal, - PhysicsHandBone::MiddleTip, - PhysicsHandBone::RingMetacarpal, - PhysicsHandBone::RingProximal, - PhysicsHandBone::RingIntermediate, - PhysicsHandBone::RingDistal, - PhysicsHandBone::RingTip, - PhysicsHandBone::LittleMetacarpal, - PhysicsHandBone::LittleProximal, - PhysicsHandBone::LittleIntermediate, - PhysicsHandBone::LittleDistal, - PhysicsHandBone::LittleTip, - ]; - //lets just do the Right ThumbMetacarpal for now - //i dont understand the groups yet - let self_group = Group::GROUP_1; - let interaction_group = Group::ALL; - let radius = 0.010; - - for hand in hands.iter() { - for bone in bones.iter() { - //spawn the thing - commands.spawn(( - SpatialBundle::default(), - Collider::capsule( - Vec3 { - x: 0.0, - y: -0.0575, - z: 0.0, - }, - Vec3 { - x: 0.0, - y: 0.0575, - z: 0.0, - }, - radius, - ), - RigidBody::KinematicPositionBased, - // CollisionGroups::new(self_group, interaction_group), - // SolverGroups::new(self_group, interaction_group), - bone.clone(), - BoneInitState::False, - hand.clone(), - )); - } - } -} - -fn update_physics_hands( - hands_res: Option>, - mut bone_query: Query<( - &mut Transform, - &mut Collider, - &PhysicsHandBone, - &mut BoneInitState, - &Hand, - )>, - hand_query: Query<(&Transform, &HandBone, &Hand, Without)>, -) { - //sanity check do we even have hands? - match hands_res { - Some(res) => { - //config stuff - let radius = 0.010; - for mut bone in bone_query.iter_mut() { - let hand_res = match bone.4 { - Hand::Left => res.left, - Hand::Right => res.right, - }; - - //lets just do the Right ThumbMetacarpal for now - let result = get_start_and_end_entities(hand_res, bone.2); - if let Some((start_entity, end_entity)) = result { - //now we need their transforms - let start_components = hand_query.get(start_entity); - let end_components = hand_query.get(end_entity); - let direction = end_components.unwrap().0.translation - - start_components.unwrap().0.translation; - if direction.length() < 0.001 { - //i hate this but we need to skip init if the length is zero - return; - } - - match *bone.3 { - BoneInitState::True => { - //if we are init then we just move em? - *bone.0 = start_components - .unwrap() - .0 - .clone() - .looking_at(end_components.unwrap().0.translation, Vec3::Y); - } - BoneInitState::False => { - //build a new collider? - *bone.1 = Collider::capsule( - Vec3::splat(0.0), - Vec3 { - x: 0.0, - y: 0.0, - z: -direction.length(), - }, - radius, - ); - *bone.3 = BoneInitState::True; - } - } - } - } - } - None => info!("hand states resource not initialized yet"), - } -} - -fn get_start_and_end_entities( - hand_res: HandResource, - bone: &PhysicsHandBone, -) -> Option<(Entity, Entity)> { - match bone { - PhysicsHandBone::Palm => return None, - PhysicsHandBone::Wrist => return None, - PhysicsHandBone::ThumbMetacarpal => { - return Some((hand_res.thumb.metacarpal, hand_res.thumb.proximal)) - } - PhysicsHandBone::ThumbProximal => { - return Some((hand_res.thumb.proximal, hand_res.thumb.distal)) - } - PhysicsHandBone::ThumbDistal => return Some((hand_res.thumb.distal, hand_res.thumb.tip)), - PhysicsHandBone::ThumbTip => return None, - PhysicsHandBone::IndexMetacarpal => { - return Some((hand_res.index.metacarpal, hand_res.index.proximal)) - } - PhysicsHandBone::IndexProximal => { - return Some((hand_res.index.proximal, hand_res.index.intermediate)) - } - PhysicsHandBone::IndexIntermediate => { - return Some((hand_res.index.intermediate, hand_res.index.distal)) - } - PhysicsHandBone::IndexDistal => return Some((hand_res.index.distal, hand_res.index.tip)), - PhysicsHandBone::IndexTip => return None, - PhysicsHandBone::MiddleMetacarpal => { - return Some((hand_res.middle.metacarpal, hand_res.middle.proximal)) - } - PhysicsHandBone::MiddleProximal => { - return Some((hand_res.middle.proximal, hand_res.middle.intermediate)) - } - PhysicsHandBone::MiddleIntermediate => { - return Some((hand_res.middle.intermediate, hand_res.middle.distal)) - } - PhysicsHandBone::MiddleDistal => { - return Some((hand_res.middle.distal, hand_res.middle.tip)) - } - PhysicsHandBone::MiddleTip => return None, - PhysicsHandBone::RingMetacarpal => { - return Some((hand_res.ring.metacarpal, hand_res.ring.proximal)) - } - PhysicsHandBone::RingProximal => { - return Some((hand_res.ring.proximal, hand_res.ring.intermediate)) - } - PhysicsHandBone::RingIntermediate => { - return Some((hand_res.ring.intermediate, hand_res.ring.distal)) - } - PhysicsHandBone::RingDistal => return Some((hand_res.ring.distal, hand_res.ring.tip)), - PhysicsHandBone::RingTip => return None, - PhysicsHandBone::LittleMetacarpal => { - return Some((hand_res.little.metacarpal, hand_res.little.proximal)) - } - PhysicsHandBone::LittleProximal => { - return Some((hand_res.little.proximal, hand_res.little.intermediate)) - } - PhysicsHandBone::LittleIntermediate => { - return Some((hand_res.little.intermediate, hand_res.little.distal)) - } - PhysicsHandBone::LittleDistal => { - return Some((hand_res.little.distal, hand_res.little.tip)) - } - PhysicsHandBone::LittleTip => return None, - }; -} - -fn get_hand_res(res: &Res<'_, HandsResource>, hand: Hand) -> HandResource { - match hand { - Hand::Left => res.left.clone(), - Hand::Right => res.right.clone(), - } -} - -#[derive(Event, Default)] -pub struct SpawnCubeRequest; - -#[derive(Resource)] -pub struct SpawnCubeTimer(Timer); - -fn request_cube_spawn( - oculus_controller: Res, - frame_state: Res, - xr_input: Res, - instance: Res, - session: Res, - mut writer: EventWriter, - time: Res