diff --git a/.gitignore b/.gitignore index 1f0c08d..77a7bd1 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ -/target -/Cargo.lock +**/target +**/Cargo.lock +**/runtime_libs/arm64-v8a/* \.DS_Store diff --git a/examples/demo/Cargo.toml b/examples/demo/Cargo.toml index e472750..d38d7d5 100644 --- a/examples/demo/Cargo.toml +++ b/examples/demo/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [lib] -crate-type = ["lib", "cdylib"] +crate-type = ["rlib", "cdylib"] # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/examples/demo/Cargo_back.toml b/examples/demo/Cargo_back.toml new file mode 100644 index 0000000..0423b99 --- /dev/null +++ b/examples/demo/Cargo_back.toml @@ -0,0 +1,24 @@ +[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/Readme.md b/examples/demo/Readme.md new file mode 100644 index 0000000..6b16a29 --- /dev/null +++ b/examples/demo/Readme.md @@ -0,0 +1,11 @@ +## setup +install xbuild ```cargo install --git https://github.com/rust-mobile/xbuild``` +run ```x doctor``` and install all required depencencies +download the [openxr loader](https://developer.oculus.com/downloads/package/oculus-openxr-mobile-sdk/) and put it in the runtime_libs/arm64-v8a folder + +## how to run +run ```x devices``` + +and get the device name that looks something like this ```adb:1WD523S``` (probably a bit longer) + +then ```run x run --release``` diff --git a/examples/demo/src/lib.rs b/examples/demo/src/lib.rs index 98c7056..484b666 100644 --- a/examples/demo/src/lib.rs +++ b/examples/demo/src/lib.rs @@ -18,9 +18,9 @@ use bevy_oxr::{ input::XrInput, resources::{XrFrameState, XrInstance, XrSession}, xr_input::{ - actions::XrActionSets, debug_gizmos::OpenXrDebugRenderer, - hand::{HandBone, HandInputDebugRenderer, HandResource, HandsResource, OpenXrHandInput}, + hands::common::{ HandInputDebugRenderer, HandResource, HandsResource, OpenXrHandInput}, + hands::HandBone, interactions::{ draw_interaction_gizmos, draw_socket_gizmos, interactions, socket_interactions, update_interactable_states, InteractionEvent, Touched, XRDirectInteractor, @@ -29,7 +29,7 @@ use bevy_oxr::{ oculus_touch::OculusController, prototype_locomotion::{proto_locomotion, PrototypeLocomotionConfig}, trackers::{OpenXRController, OpenXRLeftController, OpenXRRightController, OpenXRTracker}, - Hand, + Hand, actions::XrActionSets, }, DefaultXrPlugins, }; diff --git a/examples/demo/src/lib_bak.rs b/examples/demo/src/lib_bak.rs new file mode 100644 index 0000000..54d9766 --- /dev/null +++ b/examples/demo/src/lib_bak.rs @@ -0,0 +1,609 @@ +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