From 43215f622126bea8733b6bcdd7e339fc8e019cd3 Mon Sep 17 00:00:00 2001 From: Jay Christy Date: Thu, 19 Oct 2023 16:27:22 -0400 Subject: [PATCH] I have achieved a throwable cube --- examples/demo/src/main.rs | 183 ++++++++++++++++++++++++++----------- examples/demo/src/setup.rs | 99 +++++++++++++++++--- 2 files changed, 215 insertions(+), 67 deletions(-) diff --git a/examples/demo/src/main.rs b/examples/demo/src/main.rs index 3e53a10..b28cc57 100644 --- a/examples/demo/src/main.rs +++ b/examples/demo/src/main.rs @@ -1,11 +1,25 @@ use bevy::{ diagnostic::{FrameTimeDiagnosticsPlugin, LogDiagnosticsPlugin}, - prelude::{info, App, Commands, SpatialBundle, Startup, PostUpdate, IntoSystemSetConfigs, IntoSystemConfigs, Transform, Color}, transform::{TransformSystem, TransformBundle}, + log::info, + prelude::{ + App, Commands, IntoSystemConfigs, IntoSystemSetConfigs, PostUpdate, Query, Res, + SpatialBundle, Startup, Update, With, Without, Component, EventReader, Transform, GlobalTransform, + }, + transform::TransformSystem, }; use bevy_openxr::{ + input::XrInput, + resources::{XrFrameState, XrInstance, XrSession}, xr_input::{ debug_gizmos::OpenXrDebugRenderer, + interactions::{ + interactions, update_interactable_states, XRDirectInteractor, XRInteractorState, + XRRayInteractor, draw_interaction_gizmos, draw_socket_gizmos, socket_interactions, InteractionEvent, + }, + oculus_touch::OculusController, + prototype_locomotion::{proto_locomotion, PrototypeLocomotionConfig}, trackers::{OpenXRController, OpenXRLeftController, OpenXRRightController, OpenXRTracker}, + Hand, }, DefaultXrPlugins, }; @@ -34,8 +48,26 @@ fn main() { //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 - //spawn rapier test physics - .add_systems(Startup, setup_physics) + //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)) ; //configure rapier sets @@ -75,9 +107,8 @@ fn spawn_controllers_example(mut commands: Commands) { OpenXRController, OpenXRTracker, SpatialBundle::default(), - // XRRayInteractor, - // AimPose(Transform::default()), - // XRInteractorState::default(), + XRDirectInteractor, + XRInteractorState::default(), )); //right hand commands.spawn(( @@ -85,59 +116,103 @@ fn spawn_controllers_example(mut commands: Commands) { OpenXRController, OpenXRTracker, SpatialBundle::default(), - // XRDirectInteractor, - // XRInteractorState::default(), + XRDirectInteractor, + XRInteractorState::default(), )); } -pub fn setup_physics(mut commands: Commands) { - /* - * Ground - */ - let ground_size = 200.1; - let ground_height = 0.1; +//TODO: find a real place for this +fn prototype_interaction_input( + oculus_controller: Res, + frame_state: Res, + xr_input: Res, + instance: Res, + session: Res, + mut right_interactor_query: Query< + (&mut XRInteractorState), + ( + With, + With, + Without, + ), + >, + mut left_interactor_query: Query< + (&mut XRInteractorState), + ( + With, + With, + Without, + ), + >, +) { + //lock frame + let frame_state = *frame_state.lock().unwrap(); + //get controller + let controller = oculus_controller.get_ref(&instance, &session, &frame_state, &xr_input); + //get controller triggers + let left_trigger = controller.trigger(Hand::Left); + let right_trigger = controller.trigger(Hand::Right); + //get the interactors and do state stuff + let mut left_state = left_interactor_query.single_mut(); + if left_trigger > 0.8 { + *left_state = XRInteractorState::Selecting; + } else { + *left_state = XRInteractorState::Idle; + } + let mut right_state = right_interactor_query.single_mut(); + if right_trigger > 0.8 { + *right_state = XRInteractorState::Selecting; + } else { + *right_state = XRInteractorState::Idle; + } +} - commands.spawn(( - TransformBundle::from(Transform::from_xyz(0.0, -ground_height, 0.0)), - Collider::cuboid(ground_size, ground_height, ground_size), - )); +#[derive(Component)] +pub struct Grabbable; - /* - * Create the cubes - */ - let num = 8; - let rad = 1.0; - - let shift = rad * 2.0 + rad; - let centerx = shift * (num / 2) as f32; - let centery = shift / 2.0; - let centerz = shift * (num / 2) as f32; - - let mut offset = -(num as f32) * (rad * 2.0 + rad) * 0.5; - let mut color = 0; - let colors = [ - Color::hsl(220.0, 1.0, 0.3), - Color::hsl(180.0, 1.0, 0.3), - Color::hsl(260.0, 1.0, 0.7), - ]; - - for j in 0usize..20 { - for i in 0..num { - for k in 0usize..num { - let x = i as f32 * shift - centerx + offset; - let y = j as f32 * shift + centery + 3.0; - let z = k as f32 * shift - centerz + offset; - color += 1; - - commands.spawn(( - TransformBundle::from(Transform::from_xyz(x, y, z)), - RigidBody::Dynamic, - Collider::cuboid(rad, rad, rad), - ColliderDebugColor(colors[color % 3]), - )); +pub fn update_grabbables( + mut events: EventReader, + mut grabbable_query: Query<(&mut Transform, With, Without, Option<&mut RigidBody>)>, + interactor_query: Query<(&GlobalTransform, &XRInteractorState, Without)>, +) { + //so basically the idea is to try all the events? + for event in events.read() { + // info!("some event"); + match grabbable_query.get_mut(event.interactable) { + Ok(mut grabbable_transform) => { + // info!("we got a grabbable"); + //now we need the location of our interactor + match interactor_query.get(event.interactor) { + Ok(interactor_transform) => { + match interactor_transform.1 { + XRInteractorState::Idle => { + match grabbable_transform.3 { + Some(mut thing) => { + *thing = RigidBody::Dynamic; + }, + None => (), + } + }, + XRInteractorState::Selecting => { + // info!("its a direct interactor?"); + match grabbable_transform.3 { + Some(mut thing) => { + *thing = RigidBody::KinematicPositionBased; + }, + None => (), + } + *grabbable_transform.0 = interactor_transform.0.compute_transform(); + } + } + } + Err(_) => { + // info!("not a direct interactor") + } + } + } + Err(_) => { + // info!("not a grabbable?") } } - - offset -= 0.05 * rad * (num as f32 - 1.0); } -} \ No newline at end of file +} diff --git a/examples/demo/src/setup.rs b/examples/demo/src/setup.rs index 458fbb1..d4da2c8 100644 --- a/examples/demo/src/setup.rs +++ b/examples/demo/src/setup.rs @@ -1,4 +1,18 @@ -use bevy::{prelude::{Commands, ResMut, Assets, Mesh, StandardMaterial, PbrBundle, shape, Color, Transform, SpatialBundle, Camera3dBundle, Vec3, PointLight, PointLightBundle}, utils::default}; +use bevy::{ + prelude::{ + shape, Assets, Camera3dBundle, Color, Commands, Mesh, PbrBundle, PointLight, + PointLightBundle, ResMut, SpatialBundle, StandardMaterial, Transform, Vec3, + }, + transform::TransformBundle, + utils::default, +}; +use bevy_openxr::xr_input::interactions::{Touched, XRInteractable, XRInteractableState}; +use bevy_rapier3d::{ + prelude::{Collider, RigidBody}, + render::ColliderDebugColor, +}; + +use crate::Grabbable; /// set up a simple 3D scene pub fn setup_scene( @@ -6,19 +20,37 @@ pub fn setup_scene( mut meshes: ResMut>, mut materials: ResMut>, ) { + /* + * Ground + */ + let ground_size = 2.5; + let ground_height = 0.1; // plane - commands.spawn(PbrBundle { - mesh: meshes.add(shape::Plane::from_size(5.0).into()), - material: materials.add(Color::rgb(0.3, 0.5, 0.3).into()), - ..default() - }); + commands.spawn(( + PbrBundle { + mesh: meshes.add(shape::Plane::from_size(5.0).into()), + material: materials.add(Color::rgb(0.3, 0.5, 0.3).into()), + transform: Transform::from_xyz(0.0, -ground_height, 0.0), + ..default() + }, + Collider::cuboid(ground_size, ground_height, ground_size), + )); // cube - commands.spawn(PbrBundle { - mesh: meshes.add(Mesh::from(shape::Cube { size: 0.1 })), - material: materials.add(Color::rgb(0.8, 0.7, 0.6).into()), - transform: Transform::from_xyz(0.0, 0.5, 0.0), - ..default() - }); + commands.spawn(( + PbrBundle { + mesh: meshes.add(Mesh::from(shape::Cube { size: 0.1 })), + material: materials.add(Color::rgb(0.8, 0.7, 0.6).into()), + transform: Transform::from_xyz(0.0, 0.5, 0.0), + ..default() + }, + RigidBody::Dynamic, + Collider::cuboid(0.05, 0.05, 0.05), + ColliderDebugColor(Color::hsl(220.0, 1.0, 0.3)), + XRInteractable, + XRInteractableState::default(), + Grabbable, + Touched(false), + )); // light commands.spawn(PointLightBundle { @@ -42,4 +74,45 @@ pub fn setup_scene( ), ..default() },)); -} \ No newline at end of file +} + +pub fn setup_physics(mut commands: Commands) { + /* + * Create the cubes + */ + let num = 8; + let rad = 1.0; + + let shift = rad * 2.0 + rad; + let centerx = shift * (num / 2) as f32; + let centery = shift / 2.0; + let centerz = shift * (num / 2) as f32; + + let mut offset = -(num as f32) * (rad * 2.0 + rad) * 0.5; + let mut color = 0; + let colors = [ + Color::hsl(220.0, 1.0, 0.3), + Color::hsl(180.0, 1.0, 0.3), + Color::hsl(260.0, 1.0, 0.7), + ]; + + for j in 0usize..20 { + for i in 0..num { + for k in 0usize..num { + let x = i as f32 * shift - centerx + offset; + let y = j as f32 * shift + centery + 3.0; + let z = k as f32 * shift - centerz + offset; + color += 1; + + commands.spawn(( + TransformBundle::from(Transform::from_xyz(x, y, z)), + RigidBody::Dynamic, + Collider::cuboid(rad, rad, rad), + ColliderDebugColor(colors[color % 3]), + )); + } + } + + offset -= 0.05 * rad * (num as f32 - 1.0); + } +}