add XrTracker component that auto parents the entity to the XrTrackingRoot, XrSpace requires XrTracker

Signed-off-by: Schmarni <marnistromer@gmail.com>
This commit is contained in:
Schmarni
2024-11-20 11:46:24 +01:00
parent d1cc160cac
commit a04ebb8426
10 changed files with 128 additions and 203 deletions

View File

@@ -11,7 +11,7 @@ use bevy_mod_openxr::{
spaces::OxrSpaceExt, spaces::OxrSpaceExt,
}; };
use bevy_mod_xr::{ use bevy_mod_xr::{
session::{session_available, session_running, XrSessionCreated, XrTrackingRoot}, session::{session_available, session_running, XrSessionCreated},
spaces::XrSpace, spaces::XrSpace,
}; };
use openxr::Posef; use openxr::Posef;
@@ -108,7 +108,6 @@ fn create_actions(instance: Res<OxrInstance>, mut cmds: Commands) {
fn spawn_hands( fn spawn_hands(
actions: Res<ControllerActions>, actions: Res<ControllerActions>,
mut cmds: Commands, mut cmds: Commands,
root: Query<Entity, With<XrTrackingRoot>>,
session: Res<OxrSession>, session: Res<OxrSession>,
mut meshes: ResMut<Assets<Mesh>>, mut meshes: ResMut<Assets<Mesh>>,
mut materials: ResMut<Assets<StandardMaterial>>, mut materials: ResMut<Assets<StandardMaterial>>,
@@ -128,26 +127,18 @@ fn spawn_hands(
let right_space = session let right_space = session
.create_action_space(&actions.right, openxr::Path::NULL, Isometry3d::IDENTITY) .create_action_space(&actions.right, openxr::Path::NULL, Isometry3d::IDENTITY)
.unwrap(); .unwrap();
let left = cmds cmds.spawn((
.spawn((
Mesh3d(meshes.add(Cuboid::new(0.1, 0.1, 0.05))), Mesh3d(meshes.add(Cuboid::new(0.1, 0.1, 0.05))),
MeshMaterial3d(materials.add(Color::srgb_u8(124, 144, 255))), MeshMaterial3d(materials.add(Color::srgb_u8(124, 144, 255))),
Transform::from_xyz(0.0, 0.5, 0.0),
left_space, left_space,
Controller, Controller,
)) ));
.id(); cmds.spawn((
let right = cmds
.spawn((
Mesh3d(meshes.add(Cuboid::new(0.1, 0.1, 0.05))), Mesh3d(meshes.add(Cuboid::new(0.1, 0.1, 0.05))),
MeshMaterial3d(materials.add(Color::srgb_u8(124, 144, 255))), MeshMaterial3d(materials.add(Color::srgb_u8(124, 144, 255))),
Transform::from_xyz(0.0, 0.5, 0.0),
right_space, right_space,
Controller, Controller,
)) ));
.id();
cmds.entity(root.single()).add_children(&[left, right]);
} }
#[derive(Component)] #[derive(Component)]

View File

@@ -2,7 +2,7 @@
use bevy::prelude::*; use bevy::prelude::*;
use bevy_mod_openxr::add_xr_plugins; use bevy_mod_openxr::add_xr_plugins;
use bevy_mod_xr::session::XrSessionCreated; use bevy_mod_xr::session::{XrSessionCreated, XrTracker};
use bevy_xr_utils::tracking_utils::{ use bevy_xr_utils::tracking_utils::{
TrackingUtilitiesPlugin, XrTrackedLeftGrip, XrTrackedLocalFloor, XrTrackedRightGrip, TrackingUtilitiesPlugin, XrTrackedLeftGrip, XrTrackedLocalFloor, XrTrackedRightGrip,
XrTrackedStage, XrTrackedView, XrTrackedStage, XrTrackedView,
@@ -53,50 +53,42 @@ fn spawn_hands(
mut meshes: ResMut<Assets<Mesh>>, mut meshes: ResMut<Assets<Mesh>>,
mut materials: ResMut<Assets<StandardMaterial>>, mut materials: ResMut<Assets<StandardMaterial>>,
) { ) {
let left = cmds cmds.spawn((
.spawn((
Mesh3d(meshes.add(Cuboid::new(0.1, 0.1, 0.05))), Mesh3d(meshes.add(Cuboid::new(0.1, 0.1, 0.05))),
MeshMaterial3d(materials.add(Color::srgb_u8(124, 144, 255))), MeshMaterial3d(materials.add(Color::srgb_u8(124, 144, 255))),
Transform::from_xyz(0.0, 0.5, 0.0), Transform::from_xyz(0.0, 0.5, 0.0),
XrTrackedLeftGrip, XrTrackedLeftGrip,
)) XrTracker,
.id(); ));
let bundle = ( cmds.spawn((
Mesh3d(meshes.add(Cuboid::new(0.1, 0.1, 0.05))), Mesh3d(meshes.add(Cuboid::new(0.1, 0.1, 0.05))),
MeshMaterial3d(materials.add(Color::srgb_u8(124, 144, 255))), MeshMaterial3d(materials.add(Color::srgb_u8(124, 144, 255))),
Transform::from_xyz(0.0, 0.5, 0.0), Transform::from_xyz(0.0, 0.5, 0.0),
XrTrackedRightGrip, XrTrackedRightGrip,
); XrTracker,
let right = cmds.spawn(bundle).id(); ));
//head //head
cmds.spawn((
let head = cmds
.spawn((
Mesh3d(meshes.add(Cuboid::new(0.2, 0.2, 0.2))), Mesh3d(meshes.add(Cuboid::new(0.2, 0.2, 0.2))),
MeshMaterial3d(materials.add(Color::srgb_u8(255, 144, 144))), MeshMaterial3d(materials.add(Color::srgb_u8(255, 144, 144))),
Transform::from_xyz(0.0, 0.0, 0.0), Transform::from_xyz(0.0, 0.0, 0.0),
XrTrackedView, XrTrackedView,
)) XrTracker,
.id(); ));
//local_floor emulated //local_floor emulated
let local_floor = cmds cmds.spawn((
.spawn((
Mesh3d(meshes.add(Cuboid::new(0.5, 0.1, 0.5))), Mesh3d(meshes.add(Cuboid::new(0.5, 0.1, 0.5))),
MeshMaterial3d(materials.add(Color::srgb_u8(144, 255, 144))), MeshMaterial3d(materials.add(Color::srgb_u8(144, 255, 144))),
Transform::from_xyz(0.0, 0.0, 0.0), Transform::from_xyz(0.0, 0.0, 0.0),
XrTrackedLocalFloor, XrTrackedLocalFloor,
)) XrTracker,
.id(); ));
let stage = cmds cmds.spawn((
.spawn((
Mesh3d(meshes.add(Cuboid::new(0.5, 0.1, 0.5))), Mesh3d(meshes.add(Cuboid::new(0.5, 0.1, 0.5))),
MeshMaterial3d(materials.add(Color::srgb_u8(144, 255, 255))), MeshMaterial3d(materials.add(Color::srgb_u8(144, 255, 255))),
Transform::from_xyz(0.0, 0.0, 0.0), Transform::from_xyz(0.0, 0.0, 0.0),
XrTrackedStage, XrTrackedStage,
)) XrTracker,
.id(); ));
cmds.entity(stage)
.add_children(&[left, right, head, local_floor]);
} }

View File

@@ -1,10 +1,10 @@
use bevy::prelude::*; use bevy::prelude::*;
use bevy_mod_xr::hands::{ use bevy_mod_xr::hands::{
spawn_hand_bones, HandBone, HandBoneRadius, HandSide, SpawnHandTracker, spawn_hand_bones, HandBone, HandSide, SpawnHandTracker, SpawnHandTrackerCommandExecutor,
SpawnHandTrackerCommandExecutor, XrHandBoneRadius,
}; };
use bevy_mod_xr::hands::{LeftHand, RightHand, XrHandBoneEntities}; use bevy_mod_xr::hands::{LeftHand, RightHand, XrHandBoneEntities};
use bevy_mod_xr::session::{XrPreDestroySession, XrSessionCreated, XrTrackingRoot}; use bevy_mod_xr::session::{XrPreDestroySession, XrSessionCreated};
use bevy_mod_xr::spaces::{ use bevy_mod_xr::spaces::{
XrPrimaryReferenceSpace, XrReferenceSpace, XrSpaceLocationFlags, XrSpaceVelocityFlags, XrPrimaryReferenceSpace, XrReferenceSpace, XrSpaceLocationFlags, XrSpaceVelocityFlags,
XrVelocity, XrVelocity,
@@ -70,11 +70,7 @@ fn handle_tracker_spawn(world: &mut World, tracker: Entity, side: HandSide) {
.insert(OxrHandTracker(oxr_tracker)); .insert(OxrHandTracker(oxr_tracker));
} }
fn spawn_default_hands(mut cmds: Commands, root: Query<Entity, With<XrTrackingRoot>>) { fn spawn_default_hands(mut cmds: Commands) {
let Ok(root) = root.get_single() else {
error!("unable to get tracking root, skipping handtracker creation");
return;
};
debug!("spawning default hands"); debug!("spawning default hands");
let left_bones = spawn_hand_bones(&mut cmds, |_| { let left_bones = spawn_hand_bones(&mut cmds, |_| {
( (
@@ -90,8 +86,6 @@ fn spawn_default_hands(mut cmds: Commands, root: Query<Entity, With<XrTrackingRo
OxrSpaceLocationFlags(openxr::SpaceLocationFlags::default()), OxrSpaceLocationFlags(openxr::SpaceLocationFlags::default()),
) )
}); });
cmds.entity(root).add_children(&left_bones);
cmds.entity(root).add_children(&right_bones);
cmds.queue(SpawnHandTracker { cmds.queue(SpawnHandTracker {
joints: XrHandBoneEntities(left_bones), joints: XrHandBoneEntities(left_bones),
tracker_bundle: DefaultHandTracker, tracker_bundle: DefaultHandTracker,
@@ -134,7 +128,7 @@ fn locate_hands(
session: Res<OxrSession>, session: Res<OxrSession>,
mut bone_query: Query<( mut bone_query: Query<(
&HandBone, &HandBone,
&mut HandBoneRadius, &mut XrHandBoneRadius,
&mut Transform, &mut Transform,
Option<&mut XrVelocity>, Option<&mut XrVelocity>,
&mut OxrSpaceLocationFlags, &mut OxrSpaceLocationFlags,

View File

@@ -1,5 +1,4 @@
use bevy::{ use bevy::{
ecs::query::QuerySingleError,
prelude::*, prelude::*,
render::{ render::{
camera::{ManualTextureView, ManualTextureViewHandle, ManualTextureViews, RenderTarget}, camera::{ManualTextureView, ManualTextureViewHandle, ManualTextureViews, RenderTarget},
@@ -12,9 +11,7 @@ use bevy::{
}; };
use bevy_mod_xr::{ use bevy_mod_xr::{
camera::{XrCamera, XrProjection}, camera::{XrCamera, XrProjection},
session::{ session::{XrFirst, XrHandleEvents, XrPreDestroySession, XrRenderSet, XrRootTransform},
XrFirst, XrHandleEvents, XrPreDestroySession, XrRenderSet, XrRootTransform, XrTrackingRoot,
},
spaces::XrPrimaryReferenceSpace, spaces::XrPrimaryReferenceSpace,
}; };
use openxr::ViewStateFlags; use openxr::ViewStateFlags;
@@ -34,10 +31,6 @@ impl Plugin for OxrRenderPlugin {
fn build(&self, app: &mut App) { fn build(&self, app: &mut App) {
if app.is_plugin_added::<PipelinedRenderingPlugin>() { if app.is_plugin_added::<PipelinedRenderingPlugin>() {
app.init_resource::<Pipelined>(); app.init_resource::<Pipelined>();
// if let Some(sub_app) = app.remove_sub_app(RenderExtractApp) {
// app.insert_sub_app(RenderExtractApp, SubApp::new(sub_app.app, update_rendering));
// }
} }
app.add_plugins(( app.add_plugins((
@@ -140,7 +133,6 @@ pub fn init_views(
graphics_info: Res<OxrGraphicsInfo>, graphics_info: Res<OxrGraphicsInfo>,
mut manual_texture_views: ResMut<ManualTextureViews>, mut manual_texture_views: ResMut<ManualTextureViews>,
swapchain_images: Res<OxrSwapchainImages>, swapchain_images: Res<OxrSwapchainImages>,
root: Query<Entity, With<XrTrackingRoot>>,
mut commands: Commands, mut commands: Commands,
) { ) {
let _span = info_span!("xr_init_views"); let _span = info_span!("xr_init_views");
@@ -150,27 +142,13 @@ pub fn init_views(
info!("XrCamera resolution: {}", graphics_info.resolution); info!("XrCamera resolution: {}", graphics_info.resolution);
let view_handle = let view_handle =
add_texture_view(&mut manual_texture_views, temp_tex, &graphics_info, index); add_texture_view(&mut manual_texture_views, temp_tex, &graphics_info, index);
let cam = commands commands.spawn((
.spawn((
Camera { Camera {
target: RenderTarget::TextureView(view_handle), target: RenderTarget::TextureView(view_handle),
..Default::default() ..Default::default()
}, },
XrCamera(index), XrCamera(index),
)) ));
.remove::<Projection>()
.id();
match root.get_single() {
Ok(root) => {
commands.entity(root).add_child(cam);
}
Err(QuerySingleError::NoEntities(_)) => {
warn!("No XrTrackingRoot!");
}
Err(QuerySingleError::MultipleEntities(_)) => {
warn!("Multiple XrTrackingRoots! this is not allowed");
}
}
} }
} }

View File

@@ -1,7 +1,6 @@
use core::panic; use core::panic;
use bevy::app::{App, Plugin, PostUpdate}; use bevy::app::{App, Plugin, PostUpdate};
use bevy::core_pipeline::core_3d::graph::Core3d;
use bevy::core_pipeline::core_3d::Camera3d; use bevy::core_pipeline::core_3d::Camera3d;
use bevy::ecs::component::{Component, StorageType}; use bevy::ecs::component::{Component, StorageType};
use bevy::ecs::reflect::ReflectComponent; use bevy::ecs::reflect::ReflectComponent;
@@ -18,6 +17,8 @@ use bevy::render::extract_component::{ExtractComponent, ExtractComponentPlugin};
use bevy::render::view::{update_frusta, VisibilitySystems}; use bevy::render::view::{update_frusta, VisibilitySystems};
use bevy::transform::TransformSystem; use bevy::transform::TransformSystem;
use crate::session::XrTracker;
pub struct XrCameraPlugin; pub struct XrCameraPlugin;
impl Plugin for XrCameraPlugin { impl Plugin for XrCameraPlugin {
@@ -69,7 +70,7 @@ impl Default for XrProjection {
/// Marker component for an XR view. It is the backends responsibility to update this. /// Marker component for an XR view. It is the backends responsibility to update this.
#[derive(Clone, Copy, Component, ExtractComponent, Debug, Default)] #[derive(Clone, Copy, Component, ExtractComponent, Debug, Default)]
#[require(Camera3d, XrProjection)] #[require(Camera3d, XrProjection, XrTracker)]
pub struct XrCamera(pub u32); pub struct XrCamera(pub u32);
impl CameraProjection for XrProjection { impl CameraProjection for XrProjection {

View File

@@ -1,11 +1,11 @@
use bevy::{ use bevy::{
ecs::{component::Component, entity::Entity, world::Command}, ecs::{component::Component, entity::Entity, world::Command},
log::{error, warn}, log::warn,
math::bool, math::bool,
prelude::{BuildChildren, Bundle, Commands, Deref, DerefMut, Resource, Transform, Visibility, With, World}, prelude::{Bundle, Commands, Deref, DerefMut, Resource, Transform, Visibility, World},
}; };
use crate::{session::XrTrackingRoot, spaces::XrSpaceLocationFlags}; use crate::{session::XrTracker, spaces::XrSpaceLocationFlags};
pub const HAND_JOINT_COUNT: usize = 26; pub const HAND_JOINT_COUNT: usize = 26;
pub fn spawn_hand_bones<T: Bundle>( pub fn spawn_hand_bones<T: Bundle>(
@@ -14,16 +14,7 @@ pub fn spawn_hand_bones<T: Bundle>(
) -> [Entity; HAND_JOINT_COUNT] { ) -> [Entity; HAND_JOINT_COUNT] {
let mut bones: [Entity; HAND_JOINT_COUNT] = [Entity::PLACEHOLDER; HAND_JOINT_COUNT]; let mut bones: [Entity; HAND_JOINT_COUNT] = [Entity::PLACEHOLDER; HAND_JOINT_COUNT];
for bone in HandBone::get_all_bones().into_iter() { for bone in HandBone::get_all_bones().into_iter() {
bones[bone as usize] = cmds bones[bone as usize] = cmds.spawn((bone, (get_bundle)(bone))).id();
.spawn((
Transform::default(),
Visibility::default(),
bone,
HandBoneRadius(0.0),
XrSpaceLocationFlags::default(),
))
.insert((get_bundle)(bone))
.id();
} }
bones bones
} }
@@ -45,11 +36,18 @@ pub struct RightHand;
pub struct XrHandBoneEntities(pub [Entity; HAND_JOINT_COUNT]); pub struct XrHandBoneEntities(pub [Entity; HAND_JOINT_COUNT]);
#[repr(transparent)] #[repr(transparent)]
#[derive(Clone, Copy, Component, Debug, DerefMut, Deref)] #[derive(Clone, Copy, Component, Debug, DerefMut, Deref, Default)]
pub struct HandBoneRadius(pub f32); pub struct XrHandBoneRadius(pub f32);
#[repr(u8)] #[repr(u8)]
#[derive(Clone, Copy, Component, Debug)] #[derive(Clone, Copy, Component, Debug)]
#[require(
XrSpaceLocationFlags,
XrHandBoneRadius,
Transform,
Visibility,
XrTracker
)]
pub enum HandBone { pub enum HandBone {
Palm = 0, Palm = 0,
Wrist = 1, Wrist = 1,
@@ -189,20 +187,12 @@ impl<B: Bundle> Command for SpawnHandTracker<B> {
warn!("no SpawnHandTracker executor defined, skipping handtracker creation"); warn!("no SpawnHandTracker executor defined, skipping handtracker creation");
return; return;
}; };
let Ok(root) = world
.query_filtered::<Entity, With<XrTrackingRoot>>()
.get_single(world)
else {
error!("unable to get tracking root, skipping handtracker creation");
return;
};
let mut tracker = world.spawn(self.joints); let mut tracker = world.spawn(self.joints);
match &self.side { match &self.side {
HandSide::Left => tracker.insert(LeftHand), HandSide::Left => tracker.insert((XrTracker, LeftHand)),
HandSide::Right => tracker.insert(LeftHand), HandSide::Right => tracker.insert((XrTracker, RightHand)),
}; };
let tracker = tracker.id(); let tracker = tracker.id();
world.entity_mut(root).add_children(&[tracker]);
executor.0(world, tracker, self.side); executor.0(world, tracker, self.side);
if let Ok(mut tracker) = world.get_entity_mut(tracker) { if let Ok(mut tracker) = world.get_entity_mut(tracker) {
tracker.insert(self.side); tracker.insert(self.side);

View File

@@ -2,6 +2,7 @@ use std::sync::atomic::AtomicBool;
use std::sync::Arc; use std::sync::Arc;
use bevy::app::{AppExit, MainScheduleOrder}; use bevy::app::{AppExit, MainScheduleOrder};
use bevy::ecs::component::StorageType;
use bevy::ecs::schedule::ScheduleLabel; use bevy::ecs::schedule::ScheduleLabel;
use bevy::prelude::*; use bevy::prelude::*;
use bevy::render::extract_resource::{ExtractResource, ExtractResourcePlugin}; use bevy::render::extract_resource::{ExtractResource, ExtractResourcePlugin};
@@ -84,7 +85,29 @@ pub struct XrRootTransform(pub GlobalTransform);
/// Component used to specify the entity we should use as the tracking root. /// Component used to specify the entity we should use as the tracking root.
#[derive(Component)] #[derive(Component)]
#[require(Transform, Visibility)]
pub struct XrTrackingRoot; pub struct XrTrackingRoot;
#[derive(Resource)]
struct TrackingRootRes(Entity);
/// Makes the entity a child of the XrTrackingRoot if the entity has no parent
#[derive(Clone, Copy, Hash, PartialEq, Eq, Reflect, Debug, Default)]
pub struct XrTracker;
impl Component for XrTracker {
const STORAGE_TYPE: StorageType = StorageType::SparseSet;
fn register_component_hooks(hooks: &mut bevy::ecs::component::ComponentHooks) {
hooks.on_add(|mut world, entity, _| {
if world.entity(entity).components::<Has<Parent>>() {
return;
}
let Some(root) = world.get_resource::<TrackingRootRes>().map(|r| r.0) else {
return;
};
world.commands().entity(root).add_child(entity);
});
}
}
pub struct XrSessionPlugin { pub struct XrSessionPlugin {
pub auto_handle: bool, pub auto_handle: bool,
@@ -125,12 +148,12 @@ impl Plugin for XrSessionPlugin {
.run_if(session_created) .run_if(session_created)
.in_set(XrHandleEvents::ExitEvents), .in_set(XrHandleEvents::ExitEvents),
); );
let root = app.world_mut().spawn(XrTrackingRoot).id();
app.world_mut().insert_resource(TrackingRootRes(root));
app.world_mut() app.world_mut()
.resource_mut::<MainScheduleOrder>() .resource_mut::<MainScheduleOrder>()
.labels .labels
.insert(0, XrFirst.intern()); .insert(0, XrFirst.intern());
app.world_mut()
.spawn((Transform::default(), Visibility::default(), XrTrackingRoot));
if self.auto_handle { if self.auto_handle {
app.add_systems(PreUpdate, auto_handle_session); app.add_systems(PreUpdate, auto_handle_session);

View File

@@ -1,15 +1,18 @@
use bevy::{ use bevy::{
ecs::component::StorageType,
prelude::*, prelude::*,
render::{extract_component::ExtractComponent, extract_resource::ExtractResource}, render::{extract_component::ExtractComponent, extract_resource::ExtractResource},
}; };
use crate::session::XrTracker;
/// Any Spaces will be invalid after the owning session exits /// Any Spaces will be invalid after the owning session exits
#[repr(transparent)] #[repr(transparent)]
#[derive(Clone, Copy, Hash, PartialEq, Eq, Reflect, Debug, ExtractComponent)] #[derive(Component, Clone, Copy, Hash, PartialEq, Eq, Reflect, Debug, ExtractComponent)]
#[require(XrSpaceLocationFlags, Transform, Visibility, XrTracker)]
pub struct XrSpace(u64); pub struct XrSpace(u64);
#[derive(Clone, Copy, Reflect, Debug, ExtractComponent, Default)] #[derive(Component, Clone, Copy, Reflect, Debug, ExtractComponent, Default)]
#[require(XrSpaceVelocityFlags)]
pub struct XrVelocity { pub struct XrVelocity {
/// Velocity of a space relative to it's reference space /// Velocity of a space relative to it's reference space
pub linear: Vec3, pub linear: Vec3,
@@ -69,28 +72,3 @@ impl XrSpace {
self.0 self.0
} }
} }
impl Component for XrSpace {
const STORAGE_TYPE: StorageType = StorageType::Table;
fn register_component_hooks(hooks: &mut bevy::ecs::component::ComponentHooks) {
hooks.on_add(|mut world, entity, _| {
world
.commands()
.entity(entity)
.insert(XrSpaceLocationFlags::default());
});
}
}
impl Component for XrVelocity {
const STORAGE_TYPE: StorageType = StorageType::Table;
fn register_component_hooks(hooks: &mut bevy::ecs::component::ComponentHooks) {
hooks.on_add(|mut world, entity, _| {
world
.commands()
.entity(entity)
.insert(XrSpaceVelocityFlags::default());
});
}
}

View File

@@ -1,6 +1,6 @@
use bevy::color::palettes::css; use bevy::color::palettes::css;
use bevy::{prelude::*, transform::TransformSystem}; use bevy::{prelude::*, transform::TransformSystem};
use bevy_mod_xr::hands::{HandBone, HandBoneRadius}; use bevy_mod_xr::hands::{HandBone, XrHandBoneRadius};
use bevy_mod_xr::spaces::XrSpaceLocationFlags; use bevy_mod_xr::spaces::XrSpaceLocationFlags;
pub struct HandGizmosPlugin; pub struct HandGizmosPlugin;
impl Plugin for HandGizmosPlugin { impl Plugin for HandGizmosPlugin {
@@ -16,7 +16,7 @@ fn draw_hand_gizmos(
query: Query<( query: Query<(
&GlobalTransform, &GlobalTransform,
&HandBone, &HandBone,
&HandBoneRadius, &XrHandBoneRadius,
&XrSpaceLocationFlags, &XrSpaceLocationFlags,
)>, )>,
) { ) {

View File

@@ -10,7 +10,7 @@ use bevy_mod_openxr::{
spaces::{OxrSpaceLocationFlags, OxrSpaceSyncSet}, spaces::{OxrSpaceLocationFlags, OxrSpaceSyncSet},
}; };
use bevy_mod_xr::{ use bevy_mod_xr::{
session::{XrSessionCreated, XrTrackingRoot}, session::{XrSessionCreated, XrTracker, XrTrackingRoot},
spaces::{XrPrimaryReferenceSpace, XrReferenceSpace}, spaces::{XrPrimaryReferenceSpace, XrReferenceSpace},
}; };
use openxr::Posef; use openxr::Posef;
@@ -80,11 +80,10 @@ impl Plugin for TrackingUtilitiesPlugin {
//stage //stage
fn update_stage( fn update_stage(
mut root_query: Query<&mut Transform, (With<XrTrackingRoot>, Without<XrTrackedStage>)>, root_query: Query<&Transform, (With<XrTrackingRoot>, Without<XrTrackedStage>)>,
mut stage_query: Query<&mut Transform, (With<XrTrackedStage>, Without<XrTrackingRoot>)>, mut stage_query: Query<&mut Transform, (With<XrTrackedStage>, Without<XrTrackingRoot>)>,
) { ) {
let tracking_root_transform = root_query.get_single_mut(); if let Ok(root) = root_query.get_single() {
if let Ok(root) = tracking_root_transform {
for mut transform in &mut stage_query { for mut transform in &mut stage_query {
*transform = *root; *transform = *root;
} }
@@ -148,10 +147,10 @@ fn update_local_floor_transforms(
let mut calc_floor = *head; let mut calc_floor = *head;
calc_floor.translation.y = 0.0; calc_floor.translation.y = 0.0;
//TODO: use yaw //TODO: use yaw
let (y, x, z) = calc_floor.rotation.to_euler(EulerRot::YXZ); let (y, _, _) = calc_floor.rotation.to_euler(EulerRot::YXZ);
let new_rot = Quat::from_rotation_y(y); let new_rot = Quat::from_rotation_y(y);
calc_floor.rotation = new_rot; calc_floor.rotation = new_rot;
for (mut transform) in &mut local_floor { for mut transform in &mut local_floor {
*transform = calc_floor; *transform = calc_floor;
} }
} }
@@ -166,14 +165,11 @@ fn update_left_grip(
mut tracked_left_grip: Query<&mut Transform, (With<XrTrackedLeftGrip>, Without<LeftGrip>)>, mut tracked_left_grip: Query<&mut Transform, (With<XrTrackedLeftGrip>, Without<LeftGrip>)>,
) { ) {
let head_transform = left_grip.get_single_mut(); let head_transform = left_grip.get_single_mut();
match head_transform { if let Ok(head) = head_transform {
Ok(head) => { for mut transform in &mut tracked_left_grip {
for (mut transform) in &mut tracked_left_grip { *transform = *head;
*transform = head.clone();
} }
} }
Err(_) => (),
}
} }
//right grip //right grip
@@ -185,14 +181,11 @@ fn update_right_grip(
mut tracked_right_grip: Query<&mut Transform, (With<XrTrackedRightGrip>, Without<RightGrip>)>, mut tracked_right_grip: Query<&mut Transform, (With<XrTrackedRightGrip>, Without<RightGrip>)>,
) { ) {
let head_transform = right_grip.get_single_mut(); let head_transform = right_grip.get_single_mut();
match head_transform { if let Ok(head) = head_transform {
Ok(head) => { for mut transform in &mut tracked_right_grip {
for (mut transform) in &mut tracked_right_grip { *transform = *head;
*transform = head.clone();
} }
} }
Err(_) => (),
}
} }
//tracking rig //tracking rig
@@ -206,16 +199,18 @@ struct ControllerActions {
fn spawn_tracking_rig( fn spawn_tracking_rig(
actions: Res<ControllerActions>, actions: Res<ControllerActions>,
mut cmds: Commands, mut cmds: Commands,
root: Query<Entity, With<XrTrackingRoot>>,
session: Res<OxrSession>, session: Res<OxrSession>,
) { ) {
//head //head
let head_space = session let head_space = session
.create_reference_space(openxr::ReferenceSpaceType::VIEW, Transform::IDENTITY) .create_reference_space(openxr::ReferenceSpaceType::VIEW, Transform::IDENTITY)
.unwrap(); .unwrap();
let head = cmds cmds.spawn((
.spawn((SpatialBundle::default(), HeadXRSpace(head_space))) Transform::default(),
.id(); Visibility::default(),
XrTracker,
HeadXRSpace(head_space),
));
// let local_floor = cmds.spawn((SpatialBundle::default(), LocalFloor)).id(); // let local_floor = cmds.spawn((SpatialBundle::default(), LocalFloor)).id();
let left_space = session let left_space = session
@@ -224,25 +219,8 @@ fn spawn_tracking_rig(
let right_space = session let right_space = session
.create_action_space(&actions.right, openxr::Path::NULL, Isometry3d::IDENTITY) .create_action_space(&actions.right, openxr::Path::NULL, Isometry3d::IDENTITY)
.unwrap(); .unwrap();
let left = cmds cmds.spawn((left_space, LeftGrip));
.spawn(( cmds.spawn((right_space, RightGrip));
Transform::default(),
Visibility::default(),
left_space,
LeftGrip,
))
.id();
let right = cmds
.spawn((
Transform::default(),
Visibility::default(),
right_space,
RightGrip,
))
.id();
cmds.entity(root.single())
.add_children(&[head, left, right]);
} }
//bindings //bindings