add interaction profile changed event, support velocities and expose Space(Location/Velocity)Flags as components
Signed-off-by: Schmarni <marnistromer@gmail.com>
This commit is contained in:
@@ -1,17 +1,18 @@
|
|||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
use bevy_mod_xr::hands::{LeftHand, RightHand, XrHandBoneEntities, HAND_JOINT_COUNT};
|
use bevy_mod_xr::hands::{LeftHand, RightHand, XrHandBoneEntities, HAND_JOINT_COUNT};
|
||||||
use bevy_mod_xr::session::{XrPreDestroySession, XrSessionCreated, XrTrackingRoot};
|
use bevy_mod_xr::session::{XrPreDestroySession, XrSessionCreated, XrTrackingRoot};
|
||||||
use bevy_mod_xr::spaces::{XrPrimaryReferenceSpace, XrReferenceSpace};
|
use bevy_mod_xr::spaces::{XrPrimaryReferenceSpace, XrReferenceSpace, XrVelocity};
|
||||||
use bevy_mod_xr::{
|
use bevy_mod_xr::{
|
||||||
hands::{HandBone, HandBoneRadius},
|
hands::{HandBone, HandBoneRadius},
|
||||||
session::session_running,
|
session::session_running,
|
||||||
};
|
};
|
||||||
use openxr::SpaceLocationFlags;
|
use openxr::SpaceLocationFlags;
|
||||||
|
|
||||||
use crate::init::create_xr_session;
|
use crate::helper_traits::ToVec3;
|
||||||
use crate::resources::OxrFrameState;
|
use crate::resources::OxrFrameState;
|
||||||
use crate::resources::Pipelined;
|
use crate::resources::Pipelined;
|
||||||
use crate::session::OxrSession;
|
use crate::session::OxrSession;
|
||||||
|
use crate::spaces::{OxrSpaceLocationFlags, OxrSpaceVelocityFlags};
|
||||||
|
|
||||||
pub struct HandTrackingPlugin {
|
pub struct HandTrackingPlugin {
|
||||||
default_hands: bool,
|
default_hands: bool,
|
||||||
@@ -43,7 +44,12 @@ pub fn spawn_hand_bones<T: Bundle + Clone>(
|
|||||||
#[allow(clippy::needless_range_loop)]
|
#[allow(clippy::needless_range_loop)]
|
||||||
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((SpatialBundle::default(), bone, HandBoneRadius(0.0)))
|
.spawn((
|
||||||
|
SpatialBundle::default(),
|
||||||
|
bone,
|
||||||
|
HandBoneRadius(0.0),
|
||||||
|
OxrSpaceLocationFlags(openxr::SpaceLocationFlags::default()),
|
||||||
|
))
|
||||||
.insert(bundle.clone())
|
.insert(bundle.clone())
|
||||||
.id();
|
.id();
|
||||||
}
|
}
|
||||||
@@ -101,9 +107,9 @@ fn spawn_default_hands(
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Component, Clone, Copy)]
|
#[derive(Component, Clone, Copy)]
|
||||||
struct DefaultHandTracker;
|
pub struct DefaultHandTracker;
|
||||||
#[derive(Component, Clone, Copy)]
|
#[derive(Component, Clone, Copy)]
|
||||||
struct DefaultHandBone;
|
pub struct DefaultHandBone;
|
||||||
|
|
||||||
#[allow(clippy::type_complexity)]
|
#[allow(clippy::type_complexity)]
|
||||||
fn clean_up_default_hands(
|
fn clean_up_default_hands(
|
||||||
@@ -128,34 +134,60 @@ fn locate_hands(
|
|||||||
&XrHandBoneEntities,
|
&XrHandBoneEntities,
|
||||||
)>,
|
)>,
|
||||||
session: Res<OxrSession>,
|
session: Res<OxrSession>,
|
||||||
mut bone_query: Query<(&HandBone, &mut HandBoneRadius, &mut Transform)>,
|
mut bone_query: Query<(
|
||||||
|
&HandBone,
|
||||||
|
&mut HandBoneRadius,
|
||||||
|
&mut Transform,
|
||||||
|
Option<&mut XrVelocity>,
|
||||||
|
&mut OxrSpaceLocationFlags,
|
||||||
|
Option<&mut OxrSpaceVelocityFlags>,
|
||||||
|
)>,
|
||||||
pipelined: Option<Res<Pipelined>>,
|
pipelined: Option<Res<Pipelined>>,
|
||||||
) {
|
) {
|
||||||
for (tracker, ref_space, hand_entities) in &tracker_query {
|
for (tracker, ref_space, hand_entities) in &tracker_query {
|
||||||
|
let wants_velocities = hand_entities
|
||||||
|
.0
|
||||||
|
.iter()
|
||||||
|
.filter_map(|e| bone_query.get(*e).ok())
|
||||||
|
.any(|v| v.3.is_some());
|
||||||
|
let time = if pipelined.is_some() {
|
||||||
|
openxr::Time::from_nanos(
|
||||||
|
frame_state.predicted_display_time.as_nanos()
|
||||||
|
+ frame_state.predicted_display_period.as_nanos(),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
frame_state.predicted_display_time
|
||||||
|
};
|
||||||
let ref_space = ref_space.map(|v| &v.0).unwrap_or(&default_ref_space.0);
|
let ref_space = ref_space.map(|v| &v.0).unwrap_or(&default_ref_space.0);
|
||||||
// relate_hand_joints also provides velocities
|
let (joints, vels) = if wants_velocities {
|
||||||
let joints = match session.locate_hand_joints(
|
let (loc, vel) =
|
||||||
tracker,
|
match session.locate_hand_joints_with_velocities(tracker, ref_space, time) {
|
||||||
ref_space,
|
Ok(Some(v)) => v,
|
||||||
if pipelined.is_some() {
|
Ok(None) => continue,
|
||||||
openxr::Time::from_nanos(
|
Err(openxr::sys::Result::ERROR_EXTENSION_NOT_PRESENT) => {
|
||||||
frame_state.predicted_display_time.as_nanos()
|
error!("HandTracking Extension not loaded");
|
||||||
+ frame_state.predicted_display_period.as_nanos(),
|
continue;
|
||||||
)
|
}
|
||||||
} else {
|
Err(err) => {
|
||||||
frame_state.predicted_display_time
|
warn!("Error while locating hand joints: {}", err.to_string());
|
||||||
},
|
continue;
|
||||||
) {
|
}
|
||||||
Ok(Some(v)) => v,
|
};
|
||||||
Ok(None) => continue,
|
(loc, Some(vel))
|
||||||
Err(openxr::sys::Result::ERROR_EXTENSION_NOT_PRESENT) => {
|
} else {
|
||||||
error!("HandTracking Extension not loaded");
|
let space = match session.locate_hand_joints(tracker, ref_space, time) {
|
||||||
continue;
|
Ok(Some(v)) => v,
|
||||||
}
|
Ok(None) => continue,
|
||||||
Err(err) => {
|
Err(openxr::sys::Result::ERROR_EXTENSION_NOT_PRESENT) => {
|
||||||
warn!("Error while locating hand joints: {}", err.to_string());
|
error!("HandTracking Extension not loaded");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
Err(err) => {
|
||||||
|
warn!("Error while locating hand joints: {}", err.to_string());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
(space, None)
|
||||||
};
|
};
|
||||||
let bone_entities = match bone_query.get_many_mut(hand_entities.0) {
|
let bone_entities = match bone_query.get_many_mut(hand_entities.0) {
|
||||||
Ok(v) => v,
|
Ok(v) => v,
|
||||||
@@ -164,28 +196,45 @@ fn locate_hands(
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
for (bone, mut bone_radius, mut transform) in bone_entities {
|
for (bone, mut bone_radius, mut transform, velocity, mut location_flags, velocity_flags) in
|
||||||
|
bone_entities
|
||||||
|
{
|
||||||
let joint = joints[*bone as usize];
|
let joint = joints[*bone as usize];
|
||||||
**bone_radius = joint.radius;
|
if let Some(mut velocity) = velocity {
|
||||||
|
let Some(vels) = vels.as_ref() else {
|
||||||
|
error!("somehow got a hand bone with an XrVelocity component, but there are no velocities");
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
let Some(mut vel_flags) = velocity_flags else {
|
||||||
|
error!("somehow got a hand bone with an XrVelocity component, but without velocity flags");
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
let vel = vels[*bone as usize];
|
||||||
|
let flags = OxrSpaceVelocityFlags(vel.velocity_flags);
|
||||||
|
if flags.linear_valid() {
|
||||||
|
velocity.linear = vel.linear_velocity.to_vec3();
|
||||||
|
}
|
||||||
|
if flags.angular_valid() {
|
||||||
|
velocity.angular = vel.angular_velocity.to_vec3();
|
||||||
|
}
|
||||||
|
*vel_flags = flags;
|
||||||
|
}
|
||||||
|
|
||||||
if joint
|
**bone_radius = joint.radius;
|
||||||
.location_flags
|
let flags = OxrSpaceLocationFlags(joint.location_flags);
|
||||||
.contains(SpaceLocationFlags::POSITION_VALID)
|
if flags.pos_valid() {
|
||||||
{
|
|
||||||
transform.translation.x = joint.pose.position.x;
|
transform.translation.x = joint.pose.position.x;
|
||||||
transform.translation.y = joint.pose.position.y;
|
transform.translation.y = joint.pose.position.y;
|
||||||
transform.translation.z = joint.pose.position.z;
|
transform.translation.z = joint.pose.position.z;
|
||||||
}
|
}
|
||||||
|
|
||||||
if joint
|
if flags.rot_valid() {
|
||||||
.location_flags
|
|
||||||
.contains(SpaceLocationFlags::ORIENTATION_VALID)
|
|
||||||
{
|
|
||||||
transform.rotation.x = joint.pose.orientation.x;
|
transform.rotation.x = joint.pose.orientation.x;
|
||||||
transform.rotation.y = joint.pose.orientation.y;
|
transform.rotation.y = joint.pose.orientation.y;
|
||||||
transform.rotation.z = joint.pose.orientation.z;
|
transform.rotation.z = joint.pose.orientation.z;
|
||||||
transform.rotation.w = joint.pose.orientation.w;
|
transform.rotation.w = joint.pose.orientation.w;
|
||||||
}
|
}
|
||||||
|
*location_flags = flags;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ use bevy::render::RenderPlugin;
|
|||||||
use bevy::winit::UpdateMode;
|
use bevy::winit::UpdateMode;
|
||||||
use bevy::winit::WinitSettings;
|
use bevy::winit::WinitSettings;
|
||||||
use bevy_mod_xr::session::*;
|
use bevy_mod_xr::session::*;
|
||||||
|
use openxr::Event;
|
||||||
|
|
||||||
use crate::error::OxrError;
|
use crate::error::OxrError;
|
||||||
use crate::features::overlay::OxrOverlaySessionEvent;
|
use crate::features::overlay::OxrOverlaySessionEvent;
|
||||||
@@ -80,6 +81,7 @@ impl Default for OxrInitPlugin {
|
|||||||
|
|
||||||
impl Plugin for OxrInitPlugin {
|
impl Plugin for OxrInitPlugin {
|
||||||
fn build(&self, app: &mut App) {
|
fn build(&self, app: &mut App) {
|
||||||
|
app.add_event::<OxrInteractionProfileChanged>();
|
||||||
match self.init_xr() {
|
match self.init_xr() {
|
||||||
Ok((
|
Ok((
|
||||||
instance,
|
instance,
|
||||||
@@ -260,12 +262,15 @@ impl OxrInitPlugin {
|
|||||||
))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#[derive(Event, Clone, Copy, Debug, Default)]
|
||||||
|
pub struct OxrInteractionProfileChanged;
|
||||||
|
|
||||||
/// Polls any OpenXR events and handles them accordingly
|
/// Polls any OpenXR events and handles them accordingly
|
||||||
pub fn poll_events(
|
pub fn poll_events(
|
||||||
instance: Res<OxrInstance>,
|
instance: Res<OxrInstance>,
|
||||||
mut status: ResMut<XrState>,
|
mut status: ResMut<XrState>,
|
||||||
mut changed_event: EventWriter<XrStateChanged>,
|
mut changed_event: EventWriter<XrStateChanged>,
|
||||||
|
mut interaction_profile_changed_event: EventWriter<OxrInteractionProfileChanged>,
|
||||||
mut overlay_writer: Option<ResMut<Events<OxrOverlaySessionEvent>>>,
|
mut overlay_writer: Option<ResMut<Events<OxrOverlaySessionEvent>>>,
|
||||||
) {
|
) {
|
||||||
let _span = info_span!("xr_poll_events");
|
let _span = info_span!("xr_poll_events");
|
||||||
@@ -313,6 +318,10 @@ pub fn poll_events(
|
|||||||
warn!("Overlay Event Recieved without the OverlayPlugin being added!");
|
warn!("Overlay Event Recieved without the OverlayPlugin being added!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// we might want to check if this is the correct session?
|
||||||
|
Event::InteractionProfileChanged(_) => {
|
||||||
|
interaction_profile_changed_event.send_default();
|
||||||
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,12 +3,12 @@ use std::{mem::MaybeUninit, ptr, sync::Mutex};
|
|||||||
use bevy::{prelude::*, utils::hashbrown::HashSet};
|
use bevy::{prelude::*, utils::hashbrown::HashSet};
|
||||||
use bevy_mod_xr::{
|
use bevy_mod_xr::{
|
||||||
session::{session_available, session_running, XrFirst, XrHandleEvents},
|
session::{session_available, session_running, XrFirst, XrHandleEvents},
|
||||||
spaces::{XrDestroySpace, XrPrimaryReferenceSpace, XrReferenceSpace, XrSpace, XrSpatialOffset},
|
spaces::{XrDestroySpace, XrPrimaryReferenceSpace, XrReferenceSpace, XrSpace, XrVelocity},
|
||||||
types::XrPose,
|
types::XrPose,
|
||||||
};
|
};
|
||||||
use openxr::{
|
use openxr::{
|
||||||
sys, HandJointLocation, HandJointLocations, HandJointVelocities, HandJointVelocity,
|
sys, HandJointLocation, HandJointLocations, HandJointVelocities, HandJointVelocity,
|
||||||
ReferenceSpaceType, SpaceLocationFlags, HAND_JOINT_COUNT,
|
ReferenceSpaceType, SpaceLocationFlags, SpaceVelocityFlags, HAND_JOINT_COUNT,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
@@ -27,6 +27,7 @@ impl Plugin for OxrSpacePatchingPlugin {
|
|||||||
app.add_systems(Startup, patch_destroy_space.run_if(session_available));
|
app.add_systems(Startup, patch_destroy_space.run_if(session_available));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct OxrSpatialPlugin;
|
pub struct OxrSpatialPlugin;
|
||||||
impl Plugin for OxrSpatialPlugin {
|
impl Plugin for OxrSpatialPlugin {
|
||||||
fn build(&self, app: &mut App) {
|
fn build(&self, app: &mut App) {
|
||||||
@@ -42,10 +43,29 @@ impl Plugin for OxrSpatialPlugin {
|
|||||||
update_space_transforms
|
update_space_transforms
|
||||||
.in_set(OxrSpaceSyncSet)
|
.in_set(OxrSpaceSyncSet)
|
||||||
.run_if(session_running),
|
.run_if(session_running),
|
||||||
);
|
)
|
||||||
|
.observe(add_location_flags)
|
||||||
|
.observe(add_velocity_flags);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn add_velocity_flags(event: Trigger<OnAdd, XrVelocity>, mut cmds: Commands) {
|
||||||
|
if event.entity() == Entity::PLACEHOLDER {
|
||||||
|
error!("called add_location_flags observer without entity");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
cmds.entity(event.entity())
|
||||||
|
.insert(OxrSpaceLocationFlags(openxr::SpaceLocationFlags::default()));
|
||||||
|
}
|
||||||
|
fn add_location_flags(event: Trigger<OnAdd, XrSpace>, mut cmds: Commands) {
|
||||||
|
if event.entity() == Entity::PLACEHOLDER {
|
||||||
|
error!("called add_location_flags observer without entity");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
cmds.entity(event.entity())
|
||||||
|
.insert(OxrSpaceLocationFlags(openxr::SpaceLocationFlags::default()));
|
||||||
|
}
|
||||||
|
|
||||||
fn destroy_space_event(instance: Res<OxrInstance>, mut events: EventReader<XrDestroySpace>) {
|
fn destroy_space_event(instance: Res<OxrInstance>, mut events: EventReader<XrDestroySpace>) {
|
||||||
for space in events.read() {
|
for space in events.read() {
|
||||||
match instance.destroy_space(space.0) {
|
match instance.destroy_space(space.0) {
|
||||||
@@ -92,6 +112,34 @@ unsafe extern "system" fn patched_destroy_space(space: openxr::sys::Space) -> op
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Component)]
|
||||||
|
pub struct OxrSpaceLocationFlags(pub openxr::SpaceLocationFlags);
|
||||||
|
impl OxrSpaceLocationFlags {
|
||||||
|
pub fn pos_valid(&self) -> bool {
|
||||||
|
self.0.contains(SpaceLocationFlags::POSITION_VALID)
|
||||||
|
}
|
||||||
|
pub fn pos_tracked(&self) -> bool {
|
||||||
|
self.0.contains(SpaceLocationFlags::POSITION_TRACKED)
|
||||||
|
}
|
||||||
|
pub fn rot_valid(&self) -> bool {
|
||||||
|
self.0.contains(SpaceLocationFlags::ORIENTATION_VALID)
|
||||||
|
}
|
||||||
|
pub fn rot_tracked(&self) -> bool {
|
||||||
|
self.0.contains(SpaceLocationFlags::ORIENTATION_TRACKED)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[derive(Clone, Copy, Component)]
|
||||||
|
pub struct OxrSpaceVelocityFlags(pub openxr::SpaceVelocityFlags);
|
||||||
|
impl OxrSpaceVelocityFlags {
|
||||||
|
pub fn linear_valid(&self) -> bool {
|
||||||
|
self.0.contains(SpaceVelocityFlags::LINEAR_VALID)
|
||||||
|
}
|
||||||
|
pub fn angular_valid(&self) -> bool {
|
||||||
|
self.0.contains(SpaceVelocityFlags::ANGULAR_VALID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::type_complexity)]
|
||||||
fn update_space_transforms(
|
fn update_space_transforms(
|
||||||
session: Res<OxrSession>,
|
session: Res<OxrSession>,
|
||||||
default_ref_space: Res<XrPrimaryReferenceSpace>,
|
default_ref_space: Res<XrPrimaryReferenceSpace>,
|
||||||
@@ -100,39 +148,61 @@ fn update_space_transforms(
|
|||||||
mut query: Query<(
|
mut query: Query<(
|
||||||
&mut Transform,
|
&mut Transform,
|
||||||
&XrSpace,
|
&XrSpace,
|
||||||
Option<&XrSpatialOffset>,
|
Option<&mut XrVelocity>,
|
||||||
Option<&XrReferenceSpace>,
|
Option<&XrReferenceSpace>,
|
||||||
|
&mut OxrSpaceLocationFlags,
|
||||||
|
Option<&mut OxrSpaceVelocityFlags>,
|
||||||
)>,
|
)>,
|
||||||
) {
|
) {
|
||||||
for (mut transform, space, offset, ref_space) in &mut query {
|
for (
|
||||||
let offset = offset.copied().unwrap_or_default();
|
mut transform,
|
||||||
|
space,
|
||||||
|
velocity,
|
||||||
|
ref_space,
|
||||||
|
mut space_location_flags,
|
||||||
|
space_velocity_flags,
|
||||||
|
) in &mut query
|
||||||
|
{
|
||||||
let ref_space = ref_space.unwrap_or(&default_ref_space);
|
let ref_space = ref_space.unwrap_or(&default_ref_space);
|
||||||
if let Ok(space_location) = session.locate_space(
|
let time = if pipelined.is_some() {
|
||||||
space,
|
openxr::Time::from_nanos(
|
||||||
ref_space,
|
frame_state.predicted_display_time.as_nanos()
|
||||||
if pipelined.is_some() {
|
+ frame_state.predicted_display_period.as_nanos(),
|
||||||
openxr::Time::from_nanos(
|
)
|
||||||
frame_state.predicted_display_time.as_nanos()
|
} else {
|
||||||
+ frame_state.predicted_display_period.as_nanos(),
|
frame_state.predicted_display_time
|
||||||
)
|
};
|
||||||
} else {
|
let space_location = if let Some(mut velocity) = velocity {
|
||||||
frame_state.predicted_display_time
|
match session.locate_space_with_velocity(space, ref_space, time) {
|
||||||
},
|
Ok((location, space_velocity)) => {
|
||||||
) {
|
let flags = OxrSpaceVelocityFlags(space_velocity.velocity_flags);
|
||||||
if space_location
|
if flags.linear_valid() {
|
||||||
.location_flags
|
velocity.linear = space_velocity.linear_velocity.to_vec3();
|
||||||
.contains(SpaceLocationFlags::POSITION_VALID)
|
}
|
||||||
{
|
if flags.linear_valid() {
|
||||||
transform.translation = offset
|
velocity.linear = space_velocity.linear_velocity.to_vec3();
|
||||||
.to_transform()
|
}
|
||||||
.transform_point(space_location.pose.position.to_vec3())
|
let Some(mut vel_flags) = space_velocity_flags else {
|
||||||
|
error!("XrVelocity without OxrSpaceVelocityFlags");
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
*vel_flags = flags;
|
||||||
|
Ok(location)
|
||||||
|
}
|
||||||
|
Err(err) => Err(err),
|
||||||
}
|
}
|
||||||
if space_location
|
} else {
|
||||||
.location_flags
|
session.locate_space(space, ref_space, time)
|
||||||
.contains(SpaceLocationFlags::ORIENTATION_VALID)
|
};
|
||||||
{
|
if let Ok(space_location) = space_location {
|
||||||
transform.rotation = offset.rotation * space_location.pose.orientation.to_quat();
|
let flags = OxrSpaceLocationFlags(space_location.location_flags);
|
||||||
|
if flags.pos_valid() {
|
||||||
|
transform.translation = space_location.pose.position.to_vec3();
|
||||||
}
|
}
|
||||||
|
if flags.rot_valid() {
|
||||||
|
transform.rotation = space_location.pose.orientation.to_quat();
|
||||||
|
}
|
||||||
|
*space_location_flags = flags;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,19 +3,29 @@ use bevy::{
|
|||||||
render::{extract_component::ExtractComponent, extract_resource::ExtractResource},
|
render::{extract_component::ExtractComponent, extract_resource::ExtractResource},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::types::XrPose;
|
|
||||||
|
|
||||||
/// 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, Component, ExtractComponent)]
|
#[derive(Clone, Copy, Hash, PartialEq, Eq, Reflect, Debug, Component, ExtractComponent)]
|
||||||
pub struct XrSpace(u64);
|
pub struct XrSpace(u64);
|
||||||
|
|
||||||
// Does repr(transparent) even make sense here?
|
#[derive(Clone, Copy, Reflect, Debug, Component, ExtractComponent, Default)]
|
||||||
#[repr(transparent)]
|
pub struct XrVelocity {
|
||||||
#[derive(
|
/// Velocity of a space relative to it's reference space
|
||||||
Clone, Copy, PartialEq, Reflect, Debug, Component, ExtractComponent, Default, Deref, DerefMut,
|
pub linear: Vec3,
|
||||||
)]
|
/// Angular Velocity of a space relative to it's reference space
|
||||||
pub struct XrSpatialOffset(pub XrPose);
|
/// the direction of the vector is parrelel to the axis of rotation,
|
||||||
|
/// the magnitude is the relative angular speed in radians per second
|
||||||
|
/// the vector follows the right-hand rule for torque/rotation
|
||||||
|
pub angular: Vec3,
|
||||||
|
}
|
||||||
|
impl XrVelocity {
|
||||||
|
pub const fn new() -> XrVelocity {
|
||||||
|
XrVelocity {
|
||||||
|
linear: Vec3::ZERO,
|
||||||
|
angular: Vec3::ZERO,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Event, Clone, Copy, Deref, DerefMut)]
|
#[derive(Event, Clone, Copy, Deref, DerefMut)]
|
||||||
pub struct XrDestroySpace(pub XrSpace);
|
pub struct XrDestroySpace(pub XrSpace);
|
||||||
|
|||||||
Reference in New Issue
Block a user