feat(objects): implement hmd spatial again (i forgor)

Signed-off-by: Schmarni <marnistromer@gmail.com>
This commit is contained in:
Schmarni
2025-07-16 03:05:45 +02:00
parent a8144dbd22
commit a8b5ff47a6
4 changed files with 114 additions and 2 deletions

View File

@@ -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
View 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(),
));
}
}
}

View File

@@ -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) =

View File

@@ -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>);