diff --git a/examples/demo/src/lib.rs b/examples/demo/src/lib.rs index 314f488..484b666 100644 --- a/examples/demo/src/lib.rs +++ b/examples/demo/src/lib.rs @@ -19,7 +19,7 @@ use bevy_oxr::{ resources::{XrFrameState, XrInstance, XrSession}, xr_input::{ debug_gizmos::OpenXrDebugRenderer, - hand::{ HandInputDebugRenderer, HandResource, HandsResource, OpenXrHandInput}, + hands::common::{ HandInputDebugRenderer, HandResource, HandsResource, OpenXrHandInput}, hands::HandBone, interactions::{ draw_interaction_gizmos, draw_socket_gizmos, interactions, socket_interactions, diff --git a/examples/xr.rs b/examples/xr.rs index 148bac6..79e1c90 100644 --- a/examples/xr.rs +++ b/examples/xr.rs @@ -3,10 +3,10 @@ use bevy::diagnostic::{FrameTimeDiagnosticsPlugin, LogDiagnosticsPlugin}; use bevy::prelude::*; use bevy::transform::components::Transform; use bevy_oxr::input::XrInput; -use bevy_oxr::resources::{XrFrameState, XrInstance, XrSession}; +use bevy_oxr::resources::{XrFrameState, XrSession}; use bevy_oxr::xr_input::actions::XrActionSets; -use bevy_oxr::xr_input::hand::{HandInputDebugRenderer, OpenXrHandInput}; +use bevy_oxr::xr_input::hands::common::{HandInputDebugRenderer, OpenXrHandInput}; use bevy_oxr::xr_input::interactions::{ draw_interaction_gizmos, draw_socket_gizmos, interactions, socket_interactions, update_interactable_states, InteractionEvent, Touched, XRDirectInteractor, XRInteractable, diff --git a/src/lib.rs b/src/lib.rs index d17c37e..001d658 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -5,7 +5,6 @@ pub mod resources; pub mod xr_input; use std::sync::{Arc, Mutex}; -use std::time::Duration; use crate::xr_input::hands::hand_tracking::DisableHandTracking; use crate::xr_input::oculus_touch::ActionSets; @@ -23,7 +22,7 @@ use openxr as xr; use resources::*; use xr::FormFactor; use xr_input::controllers::XrControllerType; -use xr_input::hands::emulated::EmulatedHandsPlugin; +use xr_input::hands::emulated::HandEmulationPlugin; use xr_input::hands::hand_tracking::{HandTrackingData, HandTrackingPlugin}; use xr_input::OpenXrInput; @@ -228,7 +227,7 @@ impl PluginGroup for DefaultXrPlugins { .disable::() .add_before::(OpenXrPlugin::default()) .add_after::(OpenXrInput::new(XrControllerType::OculusTouch)) - .add(EmulatedHandsPlugin) + .add(HandEmulationPlugin) .add(HandTrackingPlugin) .set(WindowPlugin { #[cfg(not(target_os = "android"))] diff --git a/src/xr_input/debug_gizmos.rs b/src/xr_input/debug_gizmos.rs index 87e3ce4..e2e8227 100644 --- a/src/xr_input/debug_gizmos.rs +++ b/src/xr_input/debug_gizmos.rs @@ -16,7 +16,6 @@ use crate::xr_input::{ use super::{ actions::XrActionSets, - hands::hand_tracking::HandTrackingData, trackers::{OpenXRLeftController, OpenXRRightController, OpenXRTrackingRoot}, }; @@ -54,43 +53,38 @@ pub fn draw_gizmos( Without, Without, )>, - hand_tracking: Option>, action_sets: Res, ) { - if let Some(hand_tracking) = hand_tracking { - let handtracking_ref = hand_tracking.get_ref(&xr_input, &frame_state); - if let Some(joints) = handtracking_ref.get_poses(Hand::Left) { - for joint in joints.inner() { - let trans = Transform::from_rotation(joint.orientation); - gizmos.circle( - joint.position, - trans.forward(), - joint.radius, - Color::ORANGE_RED, - ); - } - } else { - info!("left_hand_poses returned None"); - } - if let Some(joints) = handtracking_ref.get_poses(Hand::Right) { - for joint in joints.inner() { - let trans = Transform::from_rotation(joint.orientation); - gizmos.circle( - joint.position, - trans.forward(), - joint.radius, - Color::LIME_GREEN, - ); - } - return; - } - } + // if let Some(hand_tracking) = hand_tracking { + // let handtracking_ref = hand_tracking.get_ref(&xr_input, &frame_state); + // if let Some(joints) = handtracking_ref.get_poses(Hand::Left) { + // for joint in joints.inner() { + // let trans = Transform::from_rotation(joint.orientation); + // gizmos.circle( + // joint.position, + // trans.forward(), + // joint.radius, + // Color::ORANGE_RED, + // ); + // } + // } + // if let Some(joints) = handtracking_ref.get_poses(Hand::Right) { + // for joint in joints.inner() { + // let trans = Transform::from_rotation(joint.orientation); + // gizmos.circle( + // joint.position, + // trans.forward(), + // joint.radius, + // Color::LIME_GREEN, + // ); + // } + // return; + // } + // } //lock frame let frame_state = *frame_state.lock().unwrap(); //get controller let controller = oculus_controller.get_ref(&session, &frame_state, &xr_input, &action_sets); - //tracking root? - let mut tracking_transform = &Transform::IDENTITY; let root = tracking_root_query.get_single(); match root { Ok(position) => { @@ -105,7 +99,6 @@ pub fn draw_gizmos( 0.2, Color::RED, ); - tracking_transform = position.0; } Err(_) => info!("too many tracking roots"), } diff --git a/src/xr_input/hand.rs b/src/xr_input/hand.rs deleted file mode 100644 index 2c18844..0000000 --- a/src/xr_input/hand.rs +++ /dev/null @@ -1,1018 +0,0 @@ -use std::f32::consts::PI; - -use bevy::log::info; -use bevy::prelude::{ - default, Color, Commands, Component, Deref, DerefMut, Entity, Gizmos, GlobalTransform, Plugin, - PostUpdate, Quat, Query, Res, ResMut, Resource, SpatialBundle, Startup, Transform, - Vec3, With, Without, -}; -use openxr::{HandJoint, Posef}; - -use crate::{ - input::XrInput, - resources::{XrFrameState, XrInstance, XrSession}, - xr_input::Vec3Conv, -}; - -use super::{ - actions::XrActionSets, - hand_poses::get_simulated_open_hand_transforms, - hands::{BoneTrackingStatus, HandBone}, - oculus_touch::OculusController, - trackers::{OpenXRLeftController, OpenXRRightController, OpenXRTracker, OpenXRTrackingRoot}, - Hand, -}; - -/// add debug renderer for controllers -#[derive(Default)] -pub struct OpenXrHandInput; - -impl Plugin for OpenXrHandInput { - fn build(&self, app: &mut bevy::prelude::App) { - app - // .add_systems(Update, update_hand_skeletons) - // .add_systems(PreUpdate, update_hand_states) - .add_systems(Startup, spawn_hand_entities); - // .insert_resource(HandStatesResource::default()) - // .insert_resource(HandInputSource::default()); - } -} - -/// add debug renderer for controllers -#[derive(Default)] -pub struct HandInputDebugRenderer; - -impl Plugin for HandInputDebugRenderer { - fn build(&self, app: &mut bevy::prelude::App) { - app.add_systems(PostUpdate, draw_hand_entities); - } -} - -#[derive(Resource)] -pub enum HandInputSource { - Emulated, - OpenXr, -} - -impl Default for HandInputSource { - fn default() -> Self { - HandInputSource::OpenXr - } -} - -#[derive(Resource, Default, Clone, Copy)] -pub struct HandsResource { - pub left: HandResource, - pub right: HandResource, -} -#[derive(Clone, Copy)] -pub struct HandResource { - pub palm: Entity, - pub wrist: Entity, - pub thumb: ThumbResource, - pub index: IndexResource, - pub middle: MiddleResource, - pub ring: RingResource, - pub little: LittleResource, -} - -impl Default for HandResource { - fn default() -> Self { - Self { - palm: Entity::PLACEHOLDER, - wrist: Entity::PLACEHOLDER, - thumb: Default::default(), - index: Default::default(), - middle: Default::default(), - ring: Default::default(), - little: Default::default(), - } - } -} -#[derive(Clone, Copy)] -pub struct ThumbResource { - pub metacarpal: Entity, - pub proximal: Entity, - pub distal: Entity, - pub tip: Entity, -} - -impl Default for ThumbResource { - fn default() -> Self { - Self { - metacarpal: Entity::PLACEHOLDER, - proximal: Entity::PLACEHOLDER, - distal: Entity::PLACEHOLDER, - tip: Entity::PLACEHOLDER, - } - } -} -#[derive(Clone, Copy)] -pub struct IndexResource { - pub metacarpal: Entity, - pub proximal: Entity, - pub intermediate: Entity, - pub distal: Entity, - pub tip: Entity, -} - -impl Default for IndexResource { - fn default() -> Self { - Self { - metacarpal: Entity::PLACEHOLDER, - proximal: Entity::PLACEHOLDER, - intermediate: Entity::PLACEHOLDER, - distal: Entity::PLACEHOLDER, - tip: Entity::PLACEHOLDER, - } - } -} -#[derive(Clone, Copy)] -pub struct MiddleResource { - pub metacarpal: Entity, - pub proximal: Entity, - pub intermediate: Entity, - pub distal: Entity, - pub tip: Entity, -} -impl Default for MiddleResource { - fn default() -> Self { - Self { - metacarpal: Entity::PLACEHOLDER, - proximal: Entity::PLACEHOLDER, - intermediate: Entity::PLACEHOLDER, - distal: Entity::PLACEHOLDER, - tip: Entity::PLACEHOLDER, - } - } -} -#[derive(Clone, Copy)] -pub struct RingResource { - pub metacarpal: Entity, - pub proximal: Entity, - pub intermediate: Entity, - pub distal: Entity, - pub tip: Entity, -} -impl Default for RingResource { - fn default() -> Self { - Self { - metacarpal: Entity::PLACEHOLDER, - proximal: Entity::PLACEHOLDER, - intermediate: Entity::PLACEHOLDER, - distal: Entity::PLACEHOLDER, - tip: Entity::PLACEHOLDER, - } - } -} -#[derive(Clone, Copy)] -pub struct LittleResource { - pub metacarpal: Entity, - pub proximal: Entity, - pub intermediate: Entity, - pub distal: Entity, - pub tip: Entity, -} -impl Default for LittleResource { - fn default() -> Self { - Self { - metacarpal: Entity::PLACEHOLDER, - proximal: Entity::PLACEHOLDER, - intermediate: Entity::PLACEHOLDER, - distal: Entity::PLACEHOLDER, - tip: Entity::PLACEHOLDER, - } - } -} - -pub fn spawn_hand_entities(mut commands: Commands) { - let hands = [Hand::Left, Hand::Right]; - let bones = HandBone::get_all_bones(); - //hand resource - let mut hand_resource = HandsResource { ..default() }; - for hand in hands.iter() { - for bone in bones.iter() { - let boneid = commands - .spawn(( - SpatialBundle::default(), - bone.clone(), - OpenXRTracker, - hand.clone(), - BoneTrackingStatus::Emulated, - HandBoneRadius(1.0), - )) - .id(); - match hand { - Hand::Left => match bone { - HandBone::Palm => hand_resource.left.palm = boneid, - HandBone::Wrist => hand_resource.left.wrist = boneid, - HandBone::ThumbMetacarpal => hand_resource.left.thumb.metacarpal = boneid, - HandBone::ThumbProximal => hand_resource.left.thumb.proximal = boneid, - HandBone::ThumbDistal => hand_resource.left.thumb.distal = boneid, - HandBone::ThumbTip => hand_resource.left.thumb.tip = boneid, - HandBone::IndexMetacarpal => hand_resource.left.index.metacarpal = boneid, - HandBone::IndexProximal => hand_resource.left.index.proximal = boneid, - HandBone::IndexIntermediate => hand_resource.left.index.intermediate = boneid, - HandBone::IndexDistal => hand_resource.left.index.distal = boneid, - HandBone::IndexTip => hand_resource.left.index.tip = boneid, - HandBone::MiddleMetacarpal => hand_resource.left.middle.metacarpal = boneid, - HandBone::MiddleProximal => hand_resource.left.middle.proximal = boneid, - HandBone::MiddleIntermediate => hand_resource.left.middle.intermediate = boneid, - HandBone::MiddleDistal => hand_resource.left.middle.distal = boneid, - HandBone::MiddleTip => hand_resource.left.middle.tip = boneid, - HandBone::RingMetacarpal => hand_resource.left.ring.metacarpal = boneid, - HandBone::RingProximal => hand_resource.left.ring.proximal = boneid, - HandBone::RingIntermediate => hand_resource.left.ring.intermediate = boneid, - HandBone::RingDistal => hand_resource.left.ring.distal = boneid, - HandBone::RingTip => hand_resource.left.ring.tip = boneid, - HandBone::LittleMetacarpal => hand_resource.left.little.metacarpal = boneid, - HandBone::LittleProximal => hand_resource.left.little.proximal = boneid, - HandBone::LittleIntermediate => hand_resource.left.little.intermediate = boneid, - HandBone::LittleDistal => hand_resource.left.little.distal = boneid, - HandBone::LittleTip => hand_resource.left.little.tip = boneid, - }, - Hand::Right => match bone { - HandBone::Palm => hand_resource.right.palm = boneid, - HandBone::Wrist => hand_resource.right.wrist = boneid, - HandBone::ThumbMetacarpal => hand_resource.right.thumb.metacarpal = boneid, - HandBone::ThumbProximal => hand_resource.right.thumb.proximal = boneid, - HandBone::ThumbDistal => hand_resource.right.thumb.distal = boneid, - HandBone::ThumbTip => hand_resource.right.thumb.tip = boneid, - HandBone::IndexMetacarpal => hand_resource.right.index.metacarpal = boneid, - HandBone::IndexProximal => hand_resource.right.index.proximal = boneid, - HandBone::IndexIntermediate => hand_resource.right.index.intermediate = boneid, - HandBone::IndexDistal => hand_resource.right.index.distal = boneid, - HandBone::IndexTip => hand_resource.right.index.tip = boneid, - HandBone::MiddleMetacarpal => hand_resource.right.middle.metacarpal = boneid, - HandBone::MiddleProximal => hand_resource.right.middle.proximal = boneid, - HandBone::MiddleIntermediate => { - hand_resource.right.middle.intermediate = boneid - } - HandBone::MiddleDistal => hand_resource.right.middle.distal = boneid, - HandBone::MiddleTip => hand_resource.right.middle.tip = boneid, - HandBone::RingMetacarpal => hand_resource.right.ring.metacarpal = boneid, - HandBone::RingProximal => hand_resource.right.ring.proximal = boneid, - HandBone::RingIntermediate => hand_resource.right.ring.intermediate = boneid, - HandBone::RingDistal => hand_resource.right.ring.distal = boneid, - HandBone::RingTip => hand_resource.right.ring.tip = boneid, - HandBone::LittleMetacarpal => hand_resource.right.little.metacarpal = boneid, - HandBone::LittleProximal => hand_resource.right.little.proximal = boneid, - HandBone::LittleIntermediate => { - hand_resource.right.little.intermediate = boneid - } - HandBone::LittleDistal => hand_resource.right.little.distal = boneid, - HandBone::LittleTip => hand_resource.right.little.tip = boneid, - }, - } - } - } - commands.insert_resource(hand_resource); -} - -pub fn update_hand_states( - oculus_controller: Res, - hand_states_option: Option>, - frame_state: Res, - xr_input: Res, - instance: Res, - session: Res, - action_sets: Res, -) { - match hand_states_option { - Some(mut hands) => { - //lock frame - let frame_state = *frame_state.lock().unwrap(); - //get controller - let controller = - oculus_controller.get_ref(&session, &frame_state, &xr_input, &action_sets); - - //right hand - let squeeze = controller.squeeze(Hand::Right); - let trigger_state = controller.trigger(Hand::Right); - let calc_trigger_state = match controller.trigger_touched(Hand::Right) { - true => match trigger_state > 0.0 { - true => TriggerState::PULLED, - false => TriggerState::TOUCHED, - }, - false => TriggerState::OFF, - }; - //button a - let mut a_state = ButtonState::OFF; - if controller.a_button_touched() { - a_state = ButtonState::TOUCHED; - } - if controller.a_button() { - a_state = ButtonState::PRESSED; - } - - //button b - let mut b_state = ButtonState::OFF; - if controller.b_button_touched() { - b_state = ButtonState::TOUCHED; - } - if controller.b_button() { - b_state = ButtonState::PRESSED; - } - - let thumbstick_state = controller.thumbstick(Hand::Right); - let calc_thumbstick_state = match controller.thumbstick_touch(Hand::Right) { - true => match thumbstick_state.x > 0.0 || thumbstick_state.y > 0.0 { - true => ThumbstickState::PRESSED, - false => ThumbstickState::TOUCHED, - }, - false => ThumbstickState::OFF, - }; - - let right_state = HandState { - grip: squeeze, - trigger_state: calc_trigger_state, - a_button: a_state, - b_button: b_state, - thumbstick: calc_thumbstick_state, - }; - - //left - let squeeze = controller.squeeze(Hand::Left); - let trigger_state = controller.trigger(Hand::Left); - let calc_trigger_state = match controller.trigger_touched(Hand::Left) { - true => match trigger_state > 0.0 { - true => TriggerState::PULLED, - false => TriggerState::TOUCHED, - }, - false => TriggerState::OFF, - }; - //button a - let mut a_state = ButtonState::OFF; - if controller.x_button_touched() { - a_state = ButtonState::TOUCHED; - } - if controller.x_button() { - a_state = ButtonState::PRESSED; - } - - //button b - let mut b_state = ButtonState::OFF; - if controller.y_button_touched() { - b_state = ButtonState::TOUCHED; - } - if controller.y_button() { - b_state = ButtonState::PRESSED; - } - - let thumbstick_state = controller.thumbstick(Hand::Left); - let calc_thumbstick_state = match controller.thumbstick_touch(Hand::Left) { - true => match thumbstick_state.x > 0.0 || thumbstick_state.y > 0.0 { - true => ThumbstickState::PRESSED, - false => ThumbstickState::TOUCHED, - }, - false => ThumbstickState::OFF, - }; - - let left_state = HandState { - grip: squeeze, - trigger_state: calc_trigger_state, - a_button: a_state, - b_button: b_state, - thumbstick: calc_thumbstick_state, - }; - - hands.left = left_state; - hands.right = right_state; - } - None => info!("hand states resource not init yet"), - } -} - -#[derive(Clone, Copy)] -pub enum ButtonState { - OFF, - TOUCHED, - PRESSED, -} - -impl Default for ButtonState { - fn default() -> Self { - ButtonState::OFF - } -} -#[derive(Clone, Copy)] -pub enum ThumbstickState { - OFF, - TOUCHED, - PRESSED, -} - -impl Default for ThumbstickState { - fn default() -> Self { - ThumbstickState::OFF - } -} -#[derive(Clone, Copy)] -pub enum TriggerState { - OFF, - TOUCHED, - PULLED, -} - -impl Default for TriggerState { - fn default() -> Self { - TriggerState::OFF - } -} - -#[derive(Default, Resource)] -pub struct HandStatesResource { - pub left: HandState, - pub right: HandState, -} - -#[derive(Clone, Copy)] -pub struct HandState { - pub grip: f32, - pub trigger_state: TriggerState, - pub a_button: ButtonState, - pub b_button: ButtonState, - pub thumbstick: ThumbstickState, -} - -impl HandState { - pub fn get_index_curl(&self) -> f32 { - match self.trigger_state { - TriggerState::OFF => 0.0, - TriggerState::TOUCHED => 0.50, - TriggerState::PULLED => 1.0, - } - } - - pub fn get_thumb_curl(&self) -> f32 { - match self.thumbstick { - ThumbstickState::OFF => (), - ThumbstickState::TOUCHED => return 0.25, - ThumbstickState::PRESSED => return 0.25, - }; - - match self.a_button { - ButtonState::OFF => (), - ButtonState::TOUCHED => return 0.25, - ButtonState::PRESSED => return 0.25, - }; - - match self.b_button { - ButtonState::OFF => (), - ButtonState::TOUCHED => return 0.25, - ButtonState::PRESSED => return 0.25, - }; - //if no thumb actions taken return open position - return 0.0; - } -} - -impl Default for HandState { - fn default() -> Self { - Self { - grip: Default::default(), - trigger_state: Default::default(), - a_button: Default::default(), - b_button: Default::default(), - thumbstick: Default::default(), - } - } -} - -pub fn update_hand_bones_emulated( - controller_transform: Transform, - hand: Hand, - hand_state: HandState, - - hand_bone_query: &mut Query<( - Entity, - &mut Transform, - &HandBone, - &Hand, - Option<&mut HandBoneRadius>, - Without, - )>, -) { - let left_hand_rot = Quat::from_rotation_y(180.0 * PI / 180.0); - let hand_translation: Vec3 = match hand { - Hand::Left => controller_transform.translation, - Hand::Right => controller_transform.translation, - }; - - let controller_quat: Quat = match hand { - Hand::Left => controller_transform.rotation.mul_quat(left_hand_rot), - Hand::Right => controller_transform.rotation, - }; - - let splay_direction = match hand { - Hand::Left => -1.0, - Hand::Right => 1.0, - }; - //lets make a structure to hold our calculated transforms for now - let mut calc_transforms = [Transform::default(); 26]; - - //curl represents how closed the hand is from 0 to 1; - let grip_curl = hand_state.grip; - let index_curl = hand_state.get_index_curl(); - let thumb_curl = hand_state.get_thumb_curl(); - //get palm quat - let y = Quat::from_rotation_y(-90.0 * PI / 180.0); - let x = Quat::from_rotation_x(-90.0 * PI / 180.0); - let palm_quat = controller_quat.mul_quat(y).mul_quat(x); - //get simulated bones - let hand_transform_array: [Transform; 26] = get_simulated_open_hand_transforms(hand); - //palm - let palm = hand_transform_array[HandJoint::PALM]; - calc_transforms[HandJoint::PALM] = Transform { - translation: hand_translation + palm.translation, - ..default() - }; - //wrist - let wrist = hand_transform_array[HandJoint::WRIST]; - calc_transforms[HandJoint::WRIST] = Transform { - translation: hand_translation + palm.translation + palm_quat.mul_vec3(wrist.translation), - ..default() - }; - - //thumb - let thumb_joints = [ - HandJoint::THUMB_METACARPAL, - HandJoint::THUMB_PROXIMAL, - HandJoint::THUMB_DISTAL, - HandJoint::THUMB_TIP, - ]; - let mut prior_start: Option = None; - let mut prior_quat: Option = None; - let mut prior_vector: Option = None; - let splay = Quat::from_rotation_y(splay_direction * 30.0 * PI / 180.0); - let huh = Quat::from_rotation_x(-35.0 * PI / 180.0); - let splay_quat = palm_quat.mul_quat(huh).mul_quat(splay); - for bone in thumb_joints.iter() { - match prior_start { - Some(start) => { - let curl_angle: f32 = get_bone_curl_angle(*bone, thumb_curl); - let tp_lrot = Quat::from_rotation_y(splay_direction * curl_angle * PI / 180.0); - let tp_quat = prior_quat.unwrap().mul_quat(tp_lrot); - let thumb_prox = hand_transform_array[*bone]; - let tp_start = start + prior_vector.unwrap(); - let tp_vector = tp_quat.mul_vec3(thumb_prox.translation); - prior_start = Some(tp_start); - prior_quat = Some(tp_quat); - prior_vector = Some(tp_vector); - //store it - calc_transforms[*bone] = Transform { - translation: tp_start + tp_vector, - ..default() - }; - } - None => { - let thumb_meta = hand_transform_array[*bone]; - let tm_start = hand_translation - + palm_quat.mul_vec3(palm.translation) - + palm_quat.mul_vec3(wrist.translation); - let tm_vector = palm_quat.mul_vec3(thumb_meta.translation); - prior_start = Some(tm_start); - prior_quat = Some(splay_quat); - prior_vector = Some(tm_vector); - //store it - calc_transforms[*bone] = Transform { - translation: tm_start + tm_vector, - ..default() - }; - } - } - } - - //index - let thumb_joints = [ - HandJoint::INDEX_METACARPAL, - HandJoint::INDEX_PROXIMAL, - HandJoint::INDEX_INTERMEDIATE, - HandJoint::INDEX_DISTAL, - HandJoint::INDEX_TIP, - ]; - let mut prior_start: Option = None; - let mut prior_quat: Option = None; - let mut prior_vector: Option = None; - let splay = Quat::from_rotation_y(splay_direction * 10.0 * PI / 180.0); - let splay_quat = palm_quat.mul_quat(splay); - for bone in thumb_joints.iter() { - match prior_start { - Some(start) => { - let curl_angle: f32 = get_bone_curl_angle(*bone, index_curl); - let tp_lrot = Quat::from_rotation_x(curl_angle * PI / 180.0); - let tp_quat = prior_quat.unwrap().mul_quat(tp_lrot); - let thumb_prox = hand_transform_array[*bone]; - let tp_start = start + prior_vector.unwrap(); - let tp_vector = tp_quat.mul_vec3(thumb_prox.translation); - prior_start = Some(tp_start); - prior_quat = Some(tp_quat); - prior_vector = Some(tp_vector); - //store it - calc_transforms[*bone] = Transform { - translation: tp_start + tp_vector, - ..default() - }; - } - None => { - let thumb_meta = hand_transform_array[*bone]; - let tm_start = hand_translation - + palm_quat.mul_vec3(palm.translation) - + palm_quat.mul_vec3(wrist.translation); - let tm_vector = palm_quat.mul_vec3(thumb_meta.translation); - prior_start = Some(tm_start); - prior_quat = Some(splay_quat); - prior_vector = Some(tm_vector); - //store it - calc_transforms[*bone] = Transform { - translation: tm_start + tm_vector, - ..default() - }; - } - } - } - - //middle - let thumb_joints = [ - HandJoint::MIDDLE_METACARPAL, - HandJoint::MIDDLE_PROXIMAL, - HandJoint::MIDDLE_INTERMEDIATE, - HandJoint::MIDDLE_DISTAL, - HandJoint::MIDDLE_TIP, - ]; - let mut prior_start: Option = None; - let mut prior_quat: Option = None; - let mut prior_vector: Option = None; - let splay = Quat::from_rotation_y(splay_direction * 0.0 * PI / 180.0); - let splay_quat = palm_quat.mul_quat(splay); - for bone in thumb_joints.iter() { - match prior_start { - Some(start) => { - let curl_angle: f32 = get_bone_curl_angle(*bone, grip_curl); - let tp_lrot = Quat::from_rotation_x(curl_angle * PI / 180.0); - let tp_quat = prior_quat.unwrap().mul_quat(tp_lrot); - let thumb_prox = hand_transform_array[*bone]; - let tp_start = start + prior_vector.unwrap(); - let tp_vector = tp_quat.mul_vec3(thumb_prox.translation); - prior_start = Some(tp_start); - prior_quat = Some(tp_quat); - prior_vector = Some(tp_vector); - //store it - calc_transforms[*bone] = Transform { - translation: tp_start + tp_vector, - ..default() - }; - } - None => { - let thumb_meta = hand_transform_array[*bone]; - let tm_start = hand_translation - + palm_quat.mul_vec3(palm.translation) - + palm_quat.mul_vec3(wrist.translation); - let tm_vector = palm_quat.mul_vec3(thumb_meta.translation); - prior_start = Some(tm_start); - prior_quat = Some(splay_quat); - prior_vector = Some(tm_vector); - //store it - calc_transforms[*bone] = Transform { - translation: tm_start + tm_vector, - ..default() - }; - } - } - } - //ring - let thumb_joints = [ - HandJoint::RING_METACARPAL, - HandJoint::RING_PROXIMAL, - HandJoint::RING_INTERMEDIATE, - HandJoint::RING_DISTAL, - HandJoint::RING_TIP, - ]; - let mut prior_start: Option = None; - let mut prior_quat: Option = None; - let mut prior_vector: Option = None; - let splay = Quat::from_rotation_y(splay_direction * -10.0 * PI / 180.0); - let splay_quat = palm_quat.mul_quat(splay); - for bone in thumb_joints.iter() { - match prior_start { - Some(start) => { - let curl_angle: f32 = get_bone_curl_angle(*bone, grip_curl); - let tp_lrot = Quat::from_rotation_x(curl_angle * PI / 180.0); - let tp_quat = prior_quat.unwrap().mul_quat(tp_lrot); - let thumb_prox = hand_transform_array[*bone]; - let tp_start = start + prior_vector.unwrap(); - let tp_vector = tp_quat.mul_vec3(thumb_prox.translation); - prior_start = Some(tp_start); - prior_quat = Some(tp_quat); - prior_vector = Some(tp_vector); - //store it - calc_transforms[*bone] = Transform { - translation: tp_start + tp_vector, - ..default() - }; - } - None => { - let thumb_meta = hand_transform_array[*bone]; - let tm_start = hand_translation - + palm_quat.mul_vec3(palm.translation) - + palm_quat.mul_vec3(wrist.translation); - let tm_vector = palm_quat.mul_vec3(thumb_meta.translation); - prior_start = Some(tm_start); - prior_quat = Some(splay_quat); - prior_vector = Some(tm_vector); - //store it - calc_transforms[*bone] = Transform { - translation: tm_start + tm_vector, - ..default() - }; - } - } - } - - //little - let thumb_joints = [ - HandJoint::LITTLE_METACARPAL, - HandJoint::LITTLE_PROXIMAL, - HandJoint::LITTLE_INTERMEDIATE, - HandJoint::LITTLE_DISTAL, - HandJoint::LITTLE_TIP, - ]; - let mut prior_start: Option = None; - let mut prior_quat: Option = None; - let mut prior_vector: Option = None; - let splay = Quat::from_rotation_y(splay_direction * -20.0 * PI / 180.0); - let splay_quat = palm_quat.mul_quat(splay); - for bone in thumb_joints.iter() { - match prior_start { - Some(start) => { - let curl_angle: f32 = get_bone_curl_angle(*bone, grip_curl); - let tp_lrot = Quat::from_rotation_x(curl_angle * PI / 180.0); - let tp_quat = prior_quat.unwrap().mul_quat(tp_lrot); - let thumb_prox = hand_transform_array[*bone]; - let tp_start = start + prior_vector.unwrap(); - let tp_vector = tp_quat.mul_vec3(thumb_prox.translation); - prior_start = Some(tp_start); - prior_quat = Some(tp_quat); - prior_vector = Some(tp_vector); - //store it - calc_transforms[*bone] = Transform { - translation: tp_start + tp_vector, - ..default() - }; - } - None => { - let thumb_meta = hand_transform_array[*bone]; - let tm_start = hand_translation - + palm_quat.mul_vec3(palm.translation) - + palm_quat.mul_vec3(wrist.translation); - let tm_vector = palm_quat.mul_vec3(thumb_meta.translation); - prior_start = Some(tm_start); - prior_quat = Some(splay_quat); - prior_vector = Some(tm_vector); - //store it - calc_transforms[*bone] = Transform { - translation: tm_start + tm_vector, - ..default() - }; - } - } - } - - //now that we have all the transforms lets assign them - for (_, mut transform, handbone, bonehand, _, _) in hand_bone_query.iter_mut() { - if *bonehand == hand { - //if the hands match lets go - let index = match_index(handbone); - *transform = calc_transforms[index]; - } - } -} - -fn match_index(handbone: &HandBone) -> HandJoint { - match handbone { - HandBone::Palm => HandJoint::PALM, - HandBone::Wrist => HandJoint::WRIST, - HandBone::ThumbMetacarpal => HandJoint::THUMB_METACARPAL, - HandBone::ThumbProximal => HandJoint::THUMB_PROXIMAL, - HandBone::ThumbDistal => HandJoint::THUMB_DISTAL, - HandBone::ThumbTip => HandJoint::THUMB_TIP, - HandBone::IndexMetacarpal => HandJoint::INDEX_METACARPAL, - HandBone::IndexProximal => HandJoint::INDEX_PROXIMAL, - HandBone::IndexIntermediate => HandJoint::INDEX_INTERMEDIATE, - HandBone::IndexDistal => HandJoint::INDEX_DISTAL, - HandBone::IndexTip => HandJoint::INDEX_TIP, - HandBone::MiddleMetacarpal => HandJoint::MIDDLE_METACARPAL, - HandBone::MiddleProximal => HandJoint::MIDDLE_PROXIMAL, - HandBone::MiddleIntermediate => HandJoint::MIDDLE_INTERMEDIATE, - HandBone::MiddleDistal => HandJoint::MIDDLE_DISTAL, - HandBone::MiddleTip => HandJoint::MIDDLE_TIP, - HandBone::RingMetacarpal => HandJoint::RING_METACARPAL, - HandBone::RingProximal => HandJoint::RING_PROXIMAL, - HandBone::RingIntermediate => HandJoint::RING_INTERMEDIATE, - HandBone::RingDistal => HandJoint::RING_DISTAL, - HandBone::RingTip => HandJoint::RING_TIP, - HandBone::LittleMetacarpal => HandJoint::LITTLE_METACARPAL, - HandBone::LittleProximal => HandJoint::LITTLE_PROXIMAL, - HandBone::LittleIntermediate => HandJoint::LITTLE_INTERMEDIATE, - HandBone::LittleDistal => HandJoint::LITTLE_DISTAL, - HandBone::LittleTip => HandJoint::LITTLE_TIP, - } -} - -fn get_bone_curl_angle(bone: HandJoint, curl: f32) -> f32 { - let mul: f32 = match bone { - HandJoint::INDEX_PROXIMAL => 0.0, - HandJoint::MIDDLE_PROXIMAL => 0.0, - HandJoint::RING_PROXIMAL => 0.0, - HandJoint::LITTLE_PROXIMAL => 0.0, - HandJoint::THUMB_PROXIMAL => 0.0, - _ => 1.0, - }; - let curl_angle = -((mul * curl * 80.0) + 5.0); - return curl_angle; -} - -fn log_hand(hand_pose: [Posef; 26]) { - let _palm_wrist = hand_pose[HandJoint::WRIST].position.to_vec3() - - hand_pose[HandJoint::PALM].position.to_vec3(); - info!( - "palm-wrist: {}", - hand_pose[HandJoint::WRIST].position.to_vec3() - - hand_pose[HandJoint::PALM].position.to_vec3() - ); - - info!( - "wrist-tm: {}", - hand_pose[HandJoint::THUMB_METACARPAL].position.to_vec3() - - hand_pose[HandJoint::WRIST].position.to_vec3() - ); - info!( - "tm-tp: {}", - hand_pose[HandJoint::THUMB_PROXIMAL].position.to_vec3() - - hand_pose[HandJoint::THUMB_METACARPAL].position.to_vec3() - ); - info!( - "tp-td: {}", - hand_pose[HandJoint::THUMB_DISTAL].position.to_vec3() - - hand_pose[HandJoint::THUMB_PROXIMAL].position.to_vec3() - ); - info!( - "td-tt: {}", - hand_pose[HandJoint::THUMB_TIP].position.to_vec3() - - hand_pose[HandJoint::THUMB_DISTAL].position.to_vec3() - ); - - info!( - "wrist-im: {}", - hand_pose[HandJoint::INDEX_METACARPAL].position.to_vec3() - - hand_pose[HandJoint::WRIST].position.to_vec3() - ); - info!( - "im-ip: {}", - hand_pose[HandJoint::INDEX_PROXIMAL].position.to_vec3() - - hand_pose[HandJoint::INDEX_METACARPAL].position.to_vec3() - ); - info!( - "ip-ii: {}", - hand_pose[HandJoint::INDEX_INTERMEDIATE].position.to_vec3() - - hand_pose[HandJoint::INDEX_PROXIMAL].position.to_vec3() - ); - info!( - "ii-id: {}", - hand_pose[HandJoint::INDEX_DISTAL].position.to_vec3() - - hand_pose[HandJoint::INDEX_INTERMEDIATE].position.to_vec3() - ); - info!( - "id-it: {}", - hand_pose[HandJoint::INDEX_TIP].position.to_vec3() - - hand_pose[HandJoint::INDEX_DISTAL].position.to_vec3() - ); - - info!( - "wrist-mm: {}", - hand_pose[HandJoint::MIDDLE_METACARPAL].position.to_vec3() - - hand_pose[HandJoint::WRIST].position.to_vec3() - ); - info!( - "mm-mp: {}", - hand_pose[HandJoint::MIDDLE_PROXIMAL].position.to_vec3() - - hand_pose[HandJoint::MIDDLE_METACARPAL].position.to_vec3() - ); - info!( - "mp-mi: {}", - hand_pose[HandJoint::MIDDLE_INTERMEDIATE].position.to_vec3() - - hand_pose[HandJoint::MIDDLE_PROXIMAL].position.to_vec3() - ); - info!( - "mi-md: {}", - hand_pose[HandJoint::MIDDLE_DISTAL].position.to_vec3() - - hand_pose[HandJoint::MIDDLE_INTERMEDIATE].position.to_vec3() - ); - info!( - "md-mt: {}", - hand_pose[HandJoint::MIDDLE_TIP].position.to_vec3() - - hand_pose[HandJoint::MIDDLE_DISTAL].position.to_vec3() - ); - - info!( - "wrist-rm: {}", - hand_pose[HandJoint::RING_METACARPAL].position.to_vec3() - - hand_pose[HandJoint::WRIST].position.to_vec3() - ); - info!( - "rm-rp: {}", - hand_pose[HandJoint::RING_PROXIMAL].position.to_vec3() - - hand_pose[HandJoint::RING_METACARPAL].position.to_vec3() - ); - info!( - "rp-ri: {}", - hand_pose[HandJoint::RING_INTERMEDIATE].position.to_vec3() - - hand_pose[HandJoint::RING_PROXIMAL].position.to_vec3() - ); - info!( - "ri-rd: {}", - hand_pose[HandJoint::RING_DISTAL].position.to_vec3() - - hand_pose[HandJoint::RING_INTERMEDIATE].position.to_vec3() - ); - info!( - "rd-rt: {}", - hand_pose[HandJoint::RING_TIP].position.to_vec3() - - hand_pose[HandJoint::RING_DISTAL].position.to_vec3() - ); - - info!( - "wrist-lm: {}", - hand_pose[HandJoint::LITTLE_METACARPAL].position.to_vec3() - - hand_pose[HandJoint::WRIST].position.to_vec3() - ); - info!( - "lm-lp: {}", - hand_pose[HandJoint::LITTLE_PROXIMAL].position.to_vec3() - - hand_pose[HandJoint::LITTLE_METACARPAL].position.to_vec3() - ); - info!( - "lp-li: {}", - hand_pose[HandJoint::LITTLE_INTERMEDIATE].position.to_vec3() - - hand_pose[HandJoint::LITTLE_PROXIMAL].position.to_vec3() - ); - info!( - "li-ld: {}", - hand_pose[HandJoint::LITTLE_DISTAL].position.to_vec3() - - hand_pose[HandJoint::LITTLE_INTERMEDIATE].position.to_vec3() - ); - info!( - "ld-lt: {}", - hand_pose[HandJoint::LITTLE_TIP].position.to_vec3() - - hand_pose[HandJoint::LITTLE_DISTAL].position.to_vec3() - ); -} - - -#[derive(Debug, Component, DerefMut, Deref)] -pub struct HandBoneRadius(pub f32); - -pub fn draw_hand_entities( - mut gizmos: Gizmos, - query: Query<(&Transform, &HandBone, &HandBoneRadius)>, -) { - for (transform, hand_bone, hand_bone_radius) in query.iter() { - let (_, color) = get_bone_gizmo_style(hand_bone); - gizmos.sphere( - transform.translation, - transform.rotation, - hand_bone_radius.0, - color, - ); - } -} - -pub(crate) fn get_bone_gizmo_style(hand_bone: &HandBone) -> (f32, Color) { - match hand_bone { - HandBone::Palm => (0.01, Color::WHITE), - HandBone::Wrist => (0.01, Color::GRAY), - HandBone::ThumbMetacarpal => (0.01, Color::RED), - HandBone::ThumbProximal => (0.008, Color::RED), - HandBone::ThumbDistal => (0.006, Color::RED), - HandBone::ThumbTip => (0.004, Color::RED), - HandBone::IndexMetacarpal => (0.01, Color::ORANGE), - HandBone::IndexProximal => (0.008, Color::ORANGE), - HandBone::IndexIntermediate => (0.006, Color::ORANGE), - HandBone::IndexDistal => (0.004, Color::ORANGE), - HandBone::IndexTip => (0.002, Color::ORANGE), - HandBone::MiddleMetacarpal => (0.01, Color::YELLOW), - HandBone::MiddleProximal => (0.008, Color::YELLOW), - HandBone::MiddleIntermediate => (0.006, Color::YELLOW), - HandBone::MiddleDistal => (0.004, Color::YELLOW), - HandBone::MiddleTip => (0.002, Color::YELLOW), - HandBone::RingMetacarpal => (0.01, Color::GREEN), - HandBone::RingProximal => (0.008, Color::GREEN), - HandBone::RingIntermediate => (0.006, Color::GREEN), - HandBone::RingDistal => (0.004, Color::GREEN), - HandBone::RingTip => (0.002, Color::GREEN), - HandBone::LittleMetacarpal => (0.01, Color::BLUE), - HandBone::LittleProximal => (0.008, Color::BLUE), - HandBone::LittleIntermediate => (0.006, Color::BLUE), - HandBone::LittleDistal => (0.004, Color::BLUE), - HandBone::LittleTip => (0.002, Color::BLUE), - } -} diff --git a/src/xr_input/hands/common.rs b/src/xr_input/hands/common.rs new file mode 100644 index 0000000..2c88b08 --- /dev/null +++ b/src/xr_input/hands/common.rs @@ -0,0 +1,286 @@ +use bevy::prelude::{ + default, Color, Commands, Component, Deref, DerefMut, Entity, Gizmos, Plugin, PostUpdate, + Query, Resource, SpatialBundle, Startup, Transform, +}; + +use crate::xr_input::{Hand, trackers::OpenXRTracker}; + +use super::{HandBone, BoneTrackingStatus}; + +/// add debug renderer for controllers +#[derive(Default)] +pub struct OpenXrHandInput; + +impl Plugin for OpenXrHandInput { + fn build(&self, app: &mut bevy::prelude::App) { + app.add_systems(Startup, spawn_hand_entities); + } +} + +/// add debug renderer for controllers +#[derive(Default)] +pub struct HandInputDebugRenderer; + +impl Plugin for HandInputDebugRenderer { + fn build(&self, app: &mut bevy::prelude::App) { + app.add_systems(PostUpdate, draw_hand_entities); + } +} + +#[derive(Resource, Default, Clone, Copy)] +pub struct HandsResource { + pub left: HandResource, + pub right: HandResource, +} +#[derive(Clone, Copy)] +pub struct HandResource { + pub palm: Entity, + pub wrist: Entity, + pub thumb: ThumbResource, + pub index: IndexResource, + pub middle: MiddleResource, + pub ring: RingResource, + pub little: LittleResource, +} + +impl Default for HandResource { + fn default() -> Self { + Self { + palm: Entity::PLACEHOLDER, + wrist: Entity::PLACEHOLDER, + thumb: Default::default(), + index: Default::default(), + middle: Default::default(), + ring: Default::default(), + little: Default::default(), + } + } +} +#[derive(Clone, Copy)] +pub struct ThumbResource { + pub metacarpal: Entity, + pub proximal: Entity, + pub distal: Entity, + pub tip: Entity, +} + +impl Default for ThumbResource { + fn default() -> Self { + Self { + metacarpal: Entity::PLACEHOLDER, + proximal: Entity::PLACEHOLDER, + distal: Entity::PLACEHOLDER, + tip: Entity::PLACEHOLDER, + } + } +} +#[derive(Clone, Copy)] +pub struct IndexResource { + pub metacarpal: Entity, + pub proximal: Entity, + pub intermediate: Entity, + pub distal: Entity, + pub tip: Entity, +} + +impl Default for IndexResource { + fn default() -> Self { + Self { + metacarpal: Entity::PLACEHOLDER, + proximal: Entity::PLACEHOLDER, + intermediate: Entity::PLACEHOLDER, + distal: Entity::PLACEHOLDER, + tip: Entity::PLACEHOLDER, + } + } +} +#[derive(Clone, Copy)] +pub struct MiddleResource { + pub metacarpal: Entity, + pub proximal: Entity, + pub intermediate: Entity, + pub distal: Entity, + pub tip: Entity, +} +impl Default for MiddleResource { + fn default() -> Self { + Self { + metacarpal: Entity::PLACEHOLDER, + proximal: Entity::PLACEHOLDER, + intermediate: Entity::PLACEHOLDER, + distal: Entity::PLACEHOLDER, + tip: Entity::PLACEHOLDER, + } + } +} +#[derive(Clone, Copy)] +pub struct RingResource { + pub metacarpal: Entity, + pub proximal: Entity, + pub intermediate: Entity, + pub distal: Entity, + pub tip: Entity, +} +impl Default for RingResource { + fn default() -> Self { + Self { + metacarpal: Entity::PLACEHOLDER, + proximal: Entity::PLACEHOLDER, + intermediate: Entity::PLACEHOLDER, + distal: Entity::PLACEHOLDER, + tip: Entity::PLACEHOLDER, + } + } +} +#[derive(Clone, Copy)] +pub struct LittleResource { + pub metacarpal: Entity, + pub proximal: Entity, + pub intermediate: Entity, + pub distal: Entity, + pub tip: Entity, +} +impl Default for LittleResource { + fn default() -> Self { + Self { + metacarpal: Entity::PLACEHOLDER, + proximal: Entity::PLACEHOLDER, + intermediate: Entity::PLACEHOLDER, + distal: Entity::PLACEHOLDER, + tip: Entity::PLACEHOLDER, + } + } +} + +pub fn spawn_hand_entities(mut commands: Commands) { + let hands = [Hand::Left, Hand::Right]; + let bones = HandBone::get_all_bones(); + //hand resource + let mut hand_resource = HandsResource { ..default() }; + for hand in hands.iter() { + for bone in bones.iter() { + let boneid = commands + .spawn(( + SpatialBundle::default(), + bone.clone(), + OpenXRTracker, + hand.clone(), + BoneTrackingStatus::Emulated, + HandBoneRadius(0.1), + )) + .id(); + match hand { + Hand::Left => match bone { + HandBone::Palm => hand_resource.left.palm = boneid, + HandBone::Wrist => hand_resource.left.wrist = boneid, + HandBone::ThumbMetacarpal => hand_resource.left.thumb.metacarpal = boneid, + HandBone::ThumbProximal => hand_resource.left.thumb.proximal = boneid, + HandBone::ThumbDistal => hand_resource.left.thumb.distal = boneid, + HandBone::ThumbTip => hand_resource.left.thumb.tip = boneid, + HandBone::IndexMetacarpal => hand_resource.left.index.metacarpal = boneid, + HandBone::IndexProximal => hand_resource.left.index.proximal = boneid, + HandBone::IndexIntermediate => hand_resource.left.index.intermediate = boneid, + HandBone::IndexDistal => hand_resource.left.index.distal = boneid, + HandBone::IndexTip => hand_resource.left.index.tip = boneid, + HandBone::MiddleMetacarpal => hand_resource.left.middle.metacarpal = boneid, + HandBone::MiddleProximal => hand_resource.left.middle.proximal = boneid, + HandBone::MiddleIntermediate => hand_resource.left.middle.intermediate = boneid, + HandBone::MiddleDistal => hand_resource.left.middle.distal = boneid, + HandBone::MiddleTip => hand_resource.left.middle.tip = boneid, + HandBone::RingMetacarpal => hand_resource.left.ring.metacarpal = boneid, + HandBone::RingProximal => hand_resource.left.ring.proximal = boneid, + HandBone::RingIntermediate => hand_resource.left.ring.intermediate = boneid, + HandBone::RingDistal => hand_resource.left.ring.distal = boneid, + HandBone::RingTip => hand_resource.left.ring.tip = boneid, + HandBone::LittleMetacarpal => hand_resource.left.little.metacarpal = boneid, + HandBone::LittleProximal => hand_resource.left.little.proximal = boneid, + HandBone::LittleIntermediate => hand_resource.left.little.intermediate = boneid, + HandBone::LittleDistal => hand_resource.left.little.distal = boneid, + HandBone::LittleTip => hand_resource.left.little.tip = boneid, + }, + Hand::Right => match bone { + HandBone::Palm => hand_resource.right.palm = boneid, + HandBone::Wrist => hand_resource.right.wrist = boneid, + HandBone::ThumbMetacarpal => hand_resource.right.thumb.metacarpal = boneid, + HandBone::ThumbProximal => hand_resource.right.thumb.proximal = boneid, + HandBone::ThumbDistal => hand_resource.right.thumb.distal = boneid, + HandBone::ThumbTip => hand_resource.right.thumb.tip = boneid, + HandBone::IndexMetacarpal => hand_resource.right.index.metacarpal = boneid, + HandBone::IndexProximal => hand_resource.right.index.proximal = boneid, + HandBone::IndexIntermediate => hand_resource.right.index.intermediate = boneid, + HandBone::IndexDistal => hand_resource.right.index.distal = boneid, + HandBone::IndexTip => hand_resource.right.index.tip = boneid, + HandBone::MiddleMetacarpal => hand_resource.right.middle.metacarpal = boneid, + HandBone::MiddleProximal => hand_resource.right.middle.proximal = boneid, + HandBone::MiddleIntermediate => { + hand_resource.right.middle.intermediate = boneid + } + HandBone::MiddleDistal => hand_resource.right.middle.distal = boneid, + HandBone::MiddleTip => hand_resource.right.middle.tip = boneid, + HandBone::RingMetacarpal => hand_resource.right.ring.metacarpal = boneid, + HandBone::RingProximal => hand_resource.right.ring.proximal = boneid, + HandBone::RingIntermediate => hand_resource.right.ring.intermediate = boneid, + HandBone::RingDistal => hand_resource.right.ring.distal = boneid, + HandBone::RingTip => hand_resource.right.ring.tip = boneid, + HandBone::LittleMetacarpal => hand_resource.right.little.metacarpal = boneid, + HandBone::LittleProximal => hand_resource.right.little.proximal = boneid, + HandBone::LittleIntermediate => { + hand_resource.right.little.intermediate = boneid + } + HandBone::LittleDistal => hand_resource.right.little.distal = boneid, + HandBone::LittleTip => hand_resource.right.little.tip = boneid, + }, + } + } + } + commands.insert_resource(hand_resource); +} + +#[derive(Debug, Component, DerefMut, Deref)] +pub struct HandBoneRadius(pub f32); + +pub fn draw_hand_entities( + mut gizmos: Gizmos, + query: Query<(&Transform, &HandBone, &HandBoneRadius)>, +) { + for (transform, hand_bone, hand_bone_radius) in query.iter() { + let (_, color) = get_bone_gizmo_style(hand_bone); + gizmos.sphere( + transform.translation, + transform.rotation, + hand_bone_radius.0, + color, + ); + } +} + +pub(crate) fn get_bone_gizmo_style(hand_bone: &HandBone) -> (f32, Color) { + match hand_bone { + HandBone::Palm => (0.01, Color::WHITE), + HandBone::Wrist => (0.01, Color::GRAY), + HandBone::ThumbMetacarpal => (0.01, Color::RED), + HandBone::ThumbProximal => (0.008, Color::RED), + HandBone::ThumbDistal => (0.006, Color::RED), + HandBone::ThumbTip => (0.004, Color::RED), + HandBone::IndexMetacarpal => (0.01, Color::ORANGE), + HandBone::IndexProximal => (0.008, Color::ORANGE), + HandBone::IndexIntermediate => (0.006, Color::ORANGE), + HandBone::IndexDistal => (0.004, Color::ORANGE), + HandBone::IndexTip => (0.002, Color::ORANGE), + HandBone::MiddleMetacarpal => (0.01, Color::YELLOW), + HandBone::MiddleProximal => (0.008, Color::YELLOW), + HandBone::MiddleIntermediate => (0.006, Color::YELLOW), + HandBone::MiddleDistal => (0.004, Color::YELLOW), + HandBone::MiddleTip => (0.002, Color::YELLOW), + HandBone::RingMetacarpal => (0.01, Color::GREEN), + HandBone::RingProximal => (0.008, Color::GREEN), + HandBone::RingIntermediate => (0.006, Color::GREEN), + HandBone::RingDistal => (0.004, Color::GREEN), + HandBone::RingTip => (0.002, Color::GREEN), + HandBone::LittleMetacarpal => (0.01, Color::BLUE), + HandBone::LittleProximal => (0.008, Color::BLUE), + HandBone::LittleIntermediate => (0.006, Color::BLUE), + HandBone::LittleDistal => (0.004, Color::BLUE), + HandBone::LittleTip => (0.002, Color::BLUE), + } +} diff --git a/src/xr_input/hands/emulated.rs b/src/xr_input/hands/emulated.rs index e1cb915..7c0187b 100644 --- a/src/xr_input/hands/emulated.rs +++ b/src/xr_input/hands/emulated.rs @@ -1,20 +1,18 @@ use std::f32::consts::PI; use bevy::prelude::*; -use openxr::{Action, ActionTy, Binding, HandJoint}; +use openxr::{ActionTy, HandJoint}; +use super::common::{get_bone_gizmo_style, HandBoneRadius}; use crate::{ resources::{XrInstance, XrSession}, xr_input::{ actions::{ ActionHandednes, ActionType, SetupActionSet, SetupActionSets, XrActionSets, XrBinding, }, - controllers::Touchable, - hand::{get_bone_gizmo_style, HandBoneRadius}, hand_poses::get_simulated_open_hand_transforms, - oculus_touch::ActionSets, trackers::{OpenXRLeftController, OpenXRRightController, OpenXRTrackingRoot}, - Hand, InteractionProfileBindings, + Hand, }, }; @@ -25,22 +23,16 @@ pub enum TouchValue { Touched(T), } -// #[derive(Deref, DerefMut, Resource)] -// pub struct EmulatedHandPoseFunctions { -// pub get_base_pose: Box [Transform; 26] + Send + Sync>, -// pub map_data: Box [Transform; 26] + Send + Sync>, -// } +pub struct HandEmulationPlugin; -pub struct EmulatedHandsPlugin; - -impl Plugin for EmulatedHandsPlugin { +impl Plugin for HandEmulationPlugin { fn build(&self, app: &mut App) { app.add_systems(PreUpdate, update_hand_skeleton_from_emulated); app.add_systems(Startup, setup_hand_emulation_action_set); } } -const HAND_ACTION_SET: &'static str = "hand_pose_approx"; +const HAND_ACTION_SET: &str = "hand_pose_approx"; fn setup_hand_emulation_action_set(mut action_sets: ResMut) { let mut action_set = action_sets.add_action_set(HAND_ACTION_SET, "Hand Pose Approximaiton", 0); diff --git a/src/xr_input/hands/hand_tracking.rs b/src/xr_input/hands/hand_tracking.rs index d51bcf2..4e6fa13 100644 --- a/src/xr_input/hands/hand_tracking.rs +++ b/src/xr_input/hands/hand_tracking.rs @@ -3,12 +3,14 @@ use openxr::{HandTracker, Result, SpaceLocationFlags}; use crate::{ input::XrInput, + resources::{XrFrameState, XrSession}, xr_input::{ - hand::HandBoneRadius, hands::HandBone, trackers::OpenXRTrackingRoot, Hand, QuatConv, + hands::HandBone, trackers::OpenXRTrackingRoot, Hand, QuatConv, Vec3Conv, }, }; +use super::common::HandBoneRadius; use super::BoneTrackingStatus; @@ -123,13 +125,35 @@ impl Plugin for HandTrackingPlugin { fn build(&self, app: &mut App) { app.add_systems( PreUpdate, - (update_hand_bones).run_if(|dh: Option>| { - !dh.is_some_and(|v| *v == DisableHandTracking::Both) - }), + ( + update_hand_bones.run_if(|dh: Option>| { + !dh.is_some_and(|v| *v == DisableHandTracking::Both) + }), + update_tracking_state_on_disable, + ), ); } } +fn update_tracking_state_on_disable( + mut is_off: Local, + disabled_tracking: Option>, + mut tracking_states: Query<&mut BoneTrackingStatus>, +) { + if !*is_off + && disabled_tracking + .as_ref() + .is_some_and(|t| **t == DisableHandTracking::Both) + { + tracking_states + .par_iter_mut() + .for_each(|mut state| *state = BoneTrackingStatus::Emulated); + } + *is_off = disabled_tracking + .as_ref() + .is_some_and(|t| **t == DisableHandTracking::Both); +} + pub fn update_hand_bones( disabled_tracking: Option>, hand_tracking: Option>, diff --git a/src/xr_input/hands/mod.rs b/src/xr_input/hands/mod.rs index 1d41844..db760dc 100644 --- a/src/xr_input/hands/mod.rs +++ b/src/xr_input/hands/mod.rs @@ -1,12 +1,20 @@ -use bevy::prelude::*; +use bevy::{app::PluginGroupBuilder, prelude::*}; + +use self::{emulated::HandEmulationPlugin, hand_tracking::HandTrackingPlugin}; pub mod emulated; pub mod hand_tracking; +pub mod common; -pub struct HandsPlugin; +pub struct XrHandPlugins; -impl Plugin for HandsPlugin { - fn build(&self, app: &mut bevy::prelude::App) {} +impl PluginGroup for XrHandPlugins { + fn build(self) -> PluginGroupBuilder { + PluginGroupBuilder::start::() + .add(HandTrackingPlugin) + .add(HandEmulationPlugin) + .build() + } } #[derive(Component, Debug, Clone, Copy, PartialEq)] diff --git a/src/xr_input/interactions.rs b/src/xr_input/interactions.rs index 5d7463b..30e434b 100644 --- a/src/xr_input/interactions.rs +++ b/src/xr_input/interactions.rs @@ -1,7 +1,8 @@ use std::f32::consts::PI; +use bevy::log::info; use bevy::prelude::{ - info, Color, Component, Entity, Event, EventReader, EventWriter, Gizmos, GlobalTransform, Quat, + Color, Component, Entity, Event, EventReader, EventWriter, Gizmos, GlobalTransform, Quat, Query, Transform, Vec3, With, Without, }; @@ -45,7 +46,7 @@ impl Default for XRInteractorState { #[derive(Component)] pub enum XRSelection { Empty, - Full(Entity) + Full(Entity), } impl Default for XRSelection { fn default() -> Self { diff --git a/src/xr_input/mod.rs b/src/xr_input/mod.rs index 863edb5..cfc80c0 100644 --- a/src/xr_input/mod.rs +++ b/src/xr_input/mod.rs @@ -1,7 +1,6 @@ pub mod actions; pub mod controllers; pub mod debug_gizmos; -pub mod hand; pub mod hand_poses; pub mod hands; pub mod interactions; diff --git a/src/xr_input/oculus_touch.rs b/src/xr_input/oculus_touch.rs index 689583f..abd501f 100644 --- a/src/xr_input/oculus_touch.rs +++ b/src/xr_input/oculus_touch.rs @@ -1,17 +1,16 @@ use crate::input::XrInput; use crate::resources::{XrInstance, XrSession}; -use crate::xr_input::controllers::{Handed, Touchable}; +use crate::xr_input::controllers::Handed; use crate::xr_input::Hand; use bevy::prelude::{Commands, Res, ResMut, Resource}; use openxr::{ - Action, ActionSet, AnyGraphics, Binding, FrameState, Haptic, Instance, Path, Posef, Session, - Space, SpaceLocation, SpaceVelocity, + ActionSet, AnyGraphics, FrameState, Instance, Path, Posef, Session, Space, SpaceLocation, + SpaceVelocity, }; -use std::convert::identity; use std::sync::OnceLock; -use super::actions::{ActionHandednes, XrActionSets, ActionType, SetupActionSets, XrBinding}; +use super::actions::{ActionHandednes, ActionType, SetupActionSets, XrActionSets, XrBinding}; pub fn post_action_setup_oculus_controller( action_sets: Res, @@ -30,34 +29,18 @@ pub fn post_action_setup_oculus_controller( .unwrap(); controller.grip_space = Some(Handed { left: grip_action - .create_space( - s.clone(), - left_path, - Posef::IDENTITY, - ) + .create_space(s.clone(), left_path, Posef::IDENTITY) .unwrap(), right: grip_action - .create_space( - s.clone(), - right_path, - Posef::IDENTITY, - ) + .create_space(s.clone(), right_path, Posef::IDENTITY) .unwrap(), }); controller.aim_space = Some(Handed { left: aim_action - .create_space( - s.clone(), - left_path, - Posef::IDENTITY, - ) + .create_space(s.clone(), left_path, Posef::IDENTITY) .unwrap(), right: aim_action - .create_space( - s.clone(), - right_path, - Posef::IDENTITY, - ) + .create_space(s.clone(), right_path, Posef::IDENTITY) .unwrap(), }) } @@ -100,27 +83,51 @@ pub fn subaction_path(hand: Hand) -> Path { impl OculusControllerRef<'_> { pub fn grip_space(&self, hand: Hand) -> (SpaceLocation, SpaceVelocity) { match hand { - Hand::Left => self.oculus_controller.grip_space.as_ref().unwrap().left.relate( - &self.xr_input.stage, - self.frame_state.predicted_display_time, - ), - Hand::Right => self.oculus_controller.grip_space.as_ref().unwrap().right.relate( - &self.xr_input.stage, - self.frame_state.predicted_display_time, - ), + Hand::Left => self + .oculus_controller + .grip_space + .as_ref() + .unwrap() + .left + .relate( + &self.xr_input.stage, + self.frame_state.predicted_display_time, + ), + Hand::Right => self + .oculus_controller + .grip_space + .as_ref() + .unwrap() + .right + .relate( + &self.xr_input.stage, + self.frame_state.predicted_display_time, + ), } .unwrap() } pub fn aim_space(&self, hand: Hand) -> (SpaceLocation, SpaceVelocity) { match hand { - Hand::Left => self.oculus_controller.aim_space.as_ref().unwrap().left.relate( - &self.xr_input.stage, - self.frame_state.predicted_display_time, - ), - Hand::Right => self.oculus_controller.aim_space.as_ref().unwrap().right.relate( - &self.xr_input.stage, - self.frame_state.predicted_display_time, - ), + Hand::Left => self + .oculus_controller + .aim_space + .as_ref() + .unwrap() + .left + .relate( + &self.xr_input.stage, + self.frame_state.predicted_display_time, + ), + Hand::Right => self + .oculus_controller + .aim_space + .as_ref() + .unwrap() + .right + .relate( + &self.xr_input.stage, + self.frame_state.predicted_display_time, + ), } .unwrap() } diff --git a/src/xr_input/trackers.rs b/src/xr_input/trackers.rs index 9200b13..bd61977 100644 --- a/src/xr_input/trackers.rs +++ b/src/xr_input/trackers.rs @@ -1,11 +1,11 @@ +use bevy::log::info; use bevy::prelude::{ - info, Added, BuildChildren, Commands, Component, Entity, Query, Res, Transform, Vec3, With, - Without, + Added, BuildChildren, Commands, Component, Entity, Query, Res, Transform, Vec3, With, Without, }; use crate::{ input::XrInput, - resources::{XrFrameState, XrInstance, XrSession}, + resources::{XrFrameState, XrSession}, }; use super::{actions::XrActionSets, oculus_touch::OculusController, Hand, QuatConv, Vec3Conv};