feat(objects): implement hmd spatial again (i forgor)
Signed-off-by: Schmarni <marnistromer@gmail.com>
This commit is contained in:
@@ -52,6 +52,7 @@ use nodes::drawable::lines::LinesNodePlugin;
|
||||
use nodes::drawable::model::ModelNodePlugin;
|
||||
use nodes::drawable::text::TextNodePlugin;
|
||||
use nodes::spatial::SpatialNodePlugin;
|
||||
use objects::hmd::HmdPlugin;
|
||||
use objects::input::mouse_pointer::FlatscreenInputPlugin;
|
||||
use objects::input::oxr_controller::ControllerPlugin;
|
||||
use objects::input::oxr_hand::HandPlugin;
|
||||
@@ -173,6 +174,8 @@ async fn main() -> Result<AppExit, JoinError> {
|
||||
let dbus_connection = Connection::session()
|
||||
.await
|
||||
.expect("Could not open dbus session");
|
||||
// why is this requested here? should there be a specific server bus name that we check
|
||||
// instead?
|
||||
dbus_connection
|
||||
.request_name("org.stardustxr.HMD")
|
||||
.await
|
||||
@@ -393,7 +396,7 @@ fn bevy_loop(
|
||||
AudioNodePlugin,
|
||||
));
|
||||
// object plugins
|
||||
app.add_plugins((PlaySpacePlugin, HandPlugin, ControllerPlugin));
|
||||
app.add_plugins((PlaySpacePlugin, HandPlugin, ControllerPlugin, HmdPlugin));
|
||||
// feature plugins
|
||||
app.add_plugins(WaylandPlugin);
|
||||
app.add_systems(PostStartup, move || {
|
||||
|
||||
108
src/objects/hmd.rs
Normal file
108
src/objects/hmd.rs
Normal file
@@ -0,0 +1,108 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use bevy::prelude::*;
|
||||
use bevy_mod_openxr::{
|
||||
helper_traits::{ToQuat as _, ToVec3 as _},
|
||||
resources::OxrFrameState,
|
||||
session::OxrSession,
|
||||
};
|
||||
use bevy_mod_xr::{
|
||||
session::{XrPreDestroySession, XrSessionCreated, session_running},
|
||||
spaces::{XrPrimaryReferenceSpace, XrSpace},
|
||||
};
|
||||
use openxr::SpaceLocationFlags;
|
||||
|
||||
use crate::{DbusConnection, PreFrameWait, nodes::spatial::Spatial};
|
||||
|
||||
use super::{ObjectHandle, SpatialRef, input::mouse_pointer::FlatscreenCam};
|
||||
|
||||
pub struct HmdPlugin;
|
||||
impl Plugin for HmdPlugin {
|
||||
fn build(&self, app: &mut App) {
|
||||
app.add_systems(XrPreDestroySession, destroy_view_space);
|
||||
app.add_systems(XrSessionCreated, create_view_space);
|
||||
app.add_systems(PreFrameWait, update_xr.run_if(session_running));
|
||||
app.add_systems(PreFrameWait, update_flat.run_if(not(session_running)));
|
||||
app.add_systems(Startup, setup);
|
||||
}
|
||||
}
|
||||
|
||||
fn setup(connection: Res<DbusConnection>, mut cmds: Commands) {
|
||||
let (spatial, _spatial_handle) = SpatialRef::create(&connection, "/org/stardustxr/HMD");
|
||||
let hmd = Hmd {
|
||||
spatial,
|
||||
_spatial_handle,
|
||||
space: None,
|
||||
};
|
||||
cmds.insert_resource(hmd);
|
||||
}
|
||||
|
||||
fn create_view_space(session: Res<OxrSession>, mut hmd: ResMut<Hmd>) {
|
||||
let space = session
|
||||
.create_reference_space(openxr::ReferenceSpaceType::VIEW, Transform::IDENTITY)
|
||||
.inspect_err(|err| error!("failed to create View XrSpace"))
|
||||
.ok();
|
||||
hmd.space = space.map(|v| v.0);
|
||||
}
|
||||
fn destroy_view_space(session: Res<OxrSession>, mut cmds: Commands, mut hmd: ResMut<Hmd>) {
|
||||
let Some(space) = hmd.space.take() else {
|
||||
return;
|
||||
};
|
||||
session.destroy_space(space);
|
||||
}
|
||||
|
||||
#[derive(Resource)]
|
||||
struct Hmd {
|
||||
spatial: Arc<Spatial>,
|
||||
_spatial_handle: ObjectHandle<SpatialRef>,
|
||||
space: Option<XrSpace>,
|
||||
}
|
||||
|
||||
fn update_flat(cam: Single<&GlobalTransform, With<FlatscreenCam>>, hmd: Res<Hmd>) {
|
||||
// this shouldn't be parented to anything, so global and local spaces should be the same
|
||||
hmd.spatial.set_local_transform(cam.compute_matrix());
|
||||
}
|
||||
|
||||
fn update_xr(
|
||||
session: Option<Res<OxrSession>>,
|
||||
ref_space: Option<Res<XrPrimaryReferenceSpace>>,
|
||||
hmd: Res<Hmd>,
|
||||
state: Option<Res<OxrFrameState>>,
|
||||
) {
|
||||
let (Some(session), Some(view), Some(ref_space), Some(state)) =
|
||||
(session, hmd.space, ref_space, state)
|
||||
else {
|
||||
// tokio::task::spawn({
|
||||
// let handle = hmd.tracked_handle.clone();
|
||||
// async move {
|
||||
// handle.set_tracked(false);
|
||||
// }
|
||||
// });
|
||||
return;
|
||||
};
|
||||
// this won't be correct with pipelined rendering
|
||||
let location = session
|
||||
.locate_space(&view, &ref_space, state.predicted_display_time)
|
||||
.inspect_err(|err| error!("Error while Locating OpenXR Stage Space {err}"));
|
||||
if let Ok(location) = location {
|
||||
let is_tracked = location
|
||||
.location_flags
|
||||
.contains(SpaceLocationFlags::POSITION_VALID | SpaceLocationFlags::POSITION_TRACKED)
|
||||
|| location.location_flags.contains(
|
||||
SpaceLocationFlags::ORIENTATION_VALID | SpaceLocationFlags::ORIENTATION_TRACKED,
|
||||
);
|
||||
// tokio::task::spawn({
|
||||
// let handle = play_space.tracked_handle.clone();
|
||||
// async move {
|
||||
// handle.set_tracked(is_tracked);
|
||||
// }
|
||||
// });
|
||||
if is_tracked {
|
||||
hmd.spatial
|
||||
.set_local_transform(Mat4::from_rotation_translation(
|
||||
location.pose.orientation.to_quat(),
|
||||
location.pose.position.to_vec3(),
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -46,7 +46,7 @@ impl Plugin for FlatscreenInputPlugin {
|
||||
|
||||
#[derive(Component)]
|
||||
#[require(Camera3d)]
|
||||
struct FlatscreenCam;
|
||||
pub struct FlatscreenCam;
|
||||
|
||||
fn setup(mut cmds: Commands) {
|
||||
let Ok(pointer) =
|
||||
|
||||
@@ -24,6 +24,7 @@ use zbus::{Connection, interface, object_server::Interface, zvariant::OwnedObjec
|
||||
|
||||
pub mod input;
|
||||
pub mod play_space;
|
||||
pub mod hmd;
|
||||
|
||||
pub struct ObjectHandle<I: Interface>(Connection, OwnedObjectPath, PhantomData<I>);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user