Skip to content

Commit

Permalink
Fix VR player orientation and controls
Browse files Browse the repository at this point in the history
The VR player was not oriented to the earth surface, but to the global coordinate system
  • Loading branch information
oli-obk committed Nov 30, 2023
1 parent f768d42 commit ceb6bc6
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 17 deletions.
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ web-sys = { version = "0.3.22", default-features = false, features = [
] }

[target.'cfg(not(any(target_os="macos", target_arch = "wasm32")))'.dependencies]
bevy_oxr = { git = "https://github.com/awtterpip/bevy_openxr", optional = true }
bevy_oxr = { git = "https://github.com/oli-obk/vrtest", branch = "arbitrary_up", optional = true }

[features]
xr = ["dep:bevy_oxr"]
Expand Down
43 changes: 40 additions & 3 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@ use bevy::{
diagnostic::{DiagnosticsStore, FrameTimeDiagnosticsPlugin},
prelude::*,
};
use bevy_flycam::FlyCam;
use bevy_flycam::{FlyCam, MovementSettings};
#[cfg(all(feature = "xr", not(any(target_os = "macos", target_arch = "wasm32"))))]
use bevy_oxr::xr_input::trackers::OpenXRTrackingRoot;
use bevy_screen_diagnostics::{
Aggregate, ScreenDiagnostics, ScreenDiagnosticsPlugin, ScreenEntityDiagnosticsPlugin,
ScreenFrameDiagnosticsPlugin,
};
use geopos::GeoPos;
use geopos::{GeoPos, EARTH_RADIUS};
use http_assets::HttpAssetReaderPlugin;
use sun::Sky;
use tilemap::TileMap;
Expand Down Expand Up @@ -53,13 +53,16 @@ pub fn main() {
lon: 11.55741,
};

let mut xr = false;

for arg in args {
let (k, v) = arg
.split_once('=')
.expect("arguments must be `key=value` pairs");
match k {
"lat" => pos.lat = v.parse().unwrap(),
"lon" => pos.lon = v.parse().unwrap(),
"xr" => xr = v.parse().unwrap(),
other => panic!("unknown key `{other}`"),
}
}
Expand All @@ -69,9 +72,10 @@ pub fn main() {
app.add_plugins(HttpAssetReaderPlugin {
base_url: "gltiles.osm2world.org/glb/".into(),
});
if std::env::args().any(|arg| arg == "xr") {
if xr {
#[cfg(all(feature = "xr", not(any(target_os = "macos", target_arch = "wasm32"))))]
app.add_plugins(xr::Plugin);
app.add_systems(Update, pull_to_ground);
} else {
app.add_plugins(DefaultPlugins);
}
Expand All @@ -86,6 +90,7 @@ pub fn main() {
.add_plugins(flycam::Plugin)
.add_systems(Startup, setup)
.add_systems(Update, (load_next_tile, TileMap::update))
.add_systems(Update, update_camera_orientations)
.run();
}

Expand Down Expand Up @@ -190,3 +195,35 @@ fn load_next_tile(
radius,
);
}

fn update_camera_orientations(
mut movement_settings: ResMut<MovementSettings>,
fly_cam: Query<&Transform, (With<FlyCam>, Without<TileMap>)>,
tilemap: Query<&Transform, (With<TileMap>, Without<FlyCam>)>,
) {
movement_settings.up =
(fly_cam.single().translation - tilemap.single().translation).normalize();
}

fn pull_to_ground(
time: Res<Time>,
mut tracking_root_query: Query<&mut Transform, (With<OpenXRTrackingRoot>, Without<TileMap>)>,
tilemap: Query<&Transform, (With<TileMap>, Without<OpenXRTrackingRoot>)>,
) {
let Ok(mut root) = tracking_root_query.get_single_mut() else {
return;
};
let tilemap = tilemap.single();

let adjustment_rate = (time.delta_seconds() * 10.0).min(1.0);

// Lower player onto sphere
let real_pos = root.translation.as_dvec3() - tilemap.translation.as_dvec3();
let up = real_pos.normalize();
let diff = up * EARTH_RADIUS as f64 - real_pos;
root.translation += diff.as_vec3() * adjustment_rate;

// Rotate player to be upright on sphere
let angle_diff = Quat::from_rotation_arc(root.up(), up.as_vec3());
root.rotate(Quat::IDENTITY.slerp(angle_diff, adjustment_rate));
}
12 changes: 0 additions & 12 deletions src/xr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ use bevy_oxr::xr_input::prototype_locomotion::{
};
use bevy_oxr::xr_input::trackers::{
AimPose, OpenXRController, OpenXRLeftController, OpenXRRightController, OpenXRTracker,
OpenXRTrackingRoot,
};
use bevy_oxr::xr_input::Hand;
use bevy_oxr::xr_input::{
Expand All @@ -29,7 +28,6 @@ impl bevy::prelude::Plugin for Plugin {
fn build(&self, app: &mut App) {
app.add_plugins(DefaultXrPlugins)
.add_systems(Update, proto_locomotion)
.add_systems(Startup, setup_initial_position)
.insert_resource(PrototypeLocomotionConfig {
locomotion_speed: 10.0,
rotation_type: RotationType::Snap,
Expand Down Expand Up @@ -61,16 +59,6 @@ impl bevy::prelude::Plugin for Plugin {
}
}

fn setup_initial_position(
mut tracking_root_query: Query<&mut Transform, With<OpenXRTrackingRoot>>,
) {
tracking_root_query.single_mut().translation.x = 3.;
tracking_root_query.single_mut().translation.z = 400.0;
// FIXME: attach the camera bundle to the world, so when we move the world, the player is automatically moved with it.
// We'll need this when the player moves very far or teleports to another place, as we need to ensure we don't go into
// regions where the floating point numbers become imprecise.
}

fn spawn_controllers_example(mut commands: Commands) {
//left hand
commands.spawn((
Expand Down

0 comments on commit ceb6bc6

Please sign in to comment.