Add the cockpit and hand-steering settings, docs and credits

F10 > VR (and the headset panel) gains a Seat choice (cockpit or custom,
with the cockpit scale or the existing custom sliders), "Turn the steering
wheel", "Use the vehicle's own wheel", "Hand steering (by heurazy)" and its
tuning, plus a line saying which wheel the cockpit found and how many
draws took the animated copy. "Reset first-person defaults" covers the
seat and wheel keys; hand steering keeps its own choice.

OPENXR.md documents the seats and a new "Steering wheel and hand
steering" section, fixes the stale first-person defaults in the sample
configuration, and lists the headset validation still owed. README and
THIRD-PARTY-NOTICES credit heurazy's mario-kart-wii-VR-port (GPL-3.0) and
the references it credits.
This commit is contained in:
iChris4 committed 2026-09-22 03:56:30 +02:00
1 parent 9b61715ab9
commit 0d07df14c9
4 files changed
+250 -12

No files matched your search

+100 -8
View File
@@ -48,16 +48,24 @@ hud_virtual_screen = true
stop_at_display_copy = true
skip_copy_clears = true
first_person = false
first_person_units_per_meter = 30.0
first_person_head_up_meters = 3.0
first_person_seat = "cockpit"
cockpit_units_per_meter = 100.0
first_person_units_per_meter = 50.0
first_person_head_up_meters = 1.5
first_person_head_forward_meters = 0.0
first_person_head_right_meters = 0.0
first_person_hide_driver = true
first_person_hidden_model = 0
first_person_rotation = "yaw"
steering_wheel = true
native_steering_wheel = true
hand_steering = false
performance_level = "boost"
```
The seven `wheel_*` hand-steering tuning keys are described in
[Steering wheel and hand steering](#steering-wheel-and-hand-steering).
To play this installation on the desktop instead, set `enabled = false`, close the game completely,
and start it again. These settings are read only at launch. The in-game F10 settings bar also
exposes the enable switch, but a restart is still required.
@@ -203,6 +211,12 @@ Raw IR camera dots in `KPADGetUnifiedWpadStatus` stay invalid; the game reads th
**Settings in the headset.** Left Y opens the settings panel described below; while it is open the
controllers operate the panel and the game sees them idle.
**Hand steering.** With `hand_steering` on, in the first-person cockpit, a grip squeezed near the
steering wheel takes hold of it, and while held the wheel steers through the Nunchuk stick's X axis
and that grip stops pressing C; see [Steering wheel and hand
steering](#steering-wheel-and-hand-steering). Turning the wheel moves the controllers, and the game's
own motion detection still reads them, so a sharp enough turn can read as a shake.
`"gamepad"` keeps the controllers one ordinary gamepad read through PAD as a GameCube controller:
A/B → South/East, X/Y → West/North, index triggers → trigger axes, grips → shoulders, thumbsticks
→ sticks (clicks → stick buttons), left menu → Start. Every binding in the F10 controller menu
@@ -257,9 +271,23 @@ selection, scrolling and the canvas mapping; `gx_fifo_tests` covers where the pa
By default the headset sits where Mario Kart's own chase camera sits, and `world_units_per_meter`
of 500 presents the race as a small diorama on a table. Turning on `first_person` moves the camera
to the local driver's head instead, and switches the world scale to
`first_person_units_per_meter`, whose default of 30 is what makes the race read life-size from the
seat. It is a matter of taste rather than a property of the game, so the F10 bar exposes it.
to the local driver's head instead, at one of two seats:
- `first_person_seat = "cockpit"`, the default, sits you at the driver's own eyes, behind the
steering wheel, at a life-size scale, so the wheel or handlebar is within reach of your hands.
The eye is measured once per race from the character's head bone, while the kart drives straight,
undamaged and at normal size, and then frozen; until then the bind pose, or the vehicle's authored
seat height, stands in. It is kept at least 0.45 m behind the wheel so a long face or a
leaned-forward riding pose cannot put it over the controls. The world scale is
`cockpit_units_per_meter` (default 100) multiplied by the character's eye height over 100 units,
so tall characters sit at a comparable height, and by the player's current size, so a lightning
strike or a mega mushroom resizes the view, the wheel and the grab reach together. The seat
follows the simulation's position and driving direction, never the animated chassis, so damage
spins and tricks do not throw it around.
- `first_person_seat = "custom"` places the head at `first_person_head_up_meters` and its two
companions in the kart's own frame, at `first_person_units_per_meter`.
Both are a matter of taste rather than properties of the game, so the F10 bar exposes them.
The kart is selected through the game's local-screen-to-racer mapping, including online races
where your racer is not slot zero. First person requires a locally controlled racer; spectating
@@ -280,9 +308,11 @@ All three are the same construction from a forward and an up axis, differing onl
they take: pairing a forward with world up is what removes roll. The headset always adds free look
on top of whichever is chosen, and only the translation onto the head is common to all three.
The head's place in the kart is `first_person_head_up_meters` and its two companions, measured in
the kart's own frame; the F10 sliders exist because the comfortable value is a matter of taste and
is best judged from inside the headset.
In the cockpit, `"yaw"` takes the kart's own driving direction rather than the chase camera's
lagging heading, from the level seat frame. With the custom seat, the head's place in the kart is
`first_person_head_up_meters` and its two companions, measured in the kart's own frame; the F10
sliders exist because the comfortable value is a matter of taste and is best judged from inside the
headset.
The mode engages only in a single-screen race, the same content that already qualifies for
immersive stereo. Menus, split-screen, and the virtual-screen fallback are unaffected, and so is
@@ -307,6 +337,65 @@ wide head turn in first person can reveal the edge of what the game decided to d
rest of the race instrumentation, the object offsets this reads are specific to the project's
supported PAL `RMCP01` translation.
## Steering wheel and hand steering
Ported from [heurazy's mario-kart-wii-VR-port](https://github.com/heurazy/mario-kart-wii-VR-port)
(GPL-3.0-or-later). It applies to the cockpit seat.
**The wheel turns.** With `steering_wheel = true` (the default) the kart's steering wheel or the
bike's handlebar turns with your steering: the left stick's deflection at the full-lock angle
(`wheel_kart_degrees` 90, `wheel_bike_degrees` 45), eased so a flicked stick does not snap it round,
or the hands' own angle while they hold it. `native_steering_wheel = true` turns the vehicle's own
model. Karts bake the wheel into the body, so at the race draw boundary the runtime decodes the
body's MDL0 position arrays, turns only the disc around the authored hand grips on a copy, and hands
the copy to the GX thread; Aurora substitutes it into the draws that bind that array with the
player's own model-view matrix (`aurora_set_native_wheel_vertices`), checking each changed vertex's
matrix slot, so an opponent sharing the asset and other joints of the same draw are untouched. The
guest's own vertices are never written, and the copies are dropped after the frame's draws. Bikes
turn their handle part in the game already; its copy is only re-seated on the level cockpit frame so
the bars stay with your hands while the bike banks. If no draw takes the copy for 30 frames the log
says so and the vehicle falls back to a separate VR wheel, which is also what
`native_steering_wheel = false` draws.
The copy is matched against the race camera's view (`RaceCamera::GetViewMtx` with no dolly offset),
because the scene camera is only set once the draws run. The log reports, once a second, how far
that view is from the scene camera at the seal (`[mkw-vr] cockpit: race camera view vs scene view`)
and how many draws took the copy; the F10 bar shows the same under the steering-wheel settings.
**Hand steering.** `hand_steering = true` (off by default; also in WheelWizard's OpenXR VR settings)
lets you take hold of the wheel or handlebar with the tracked controllers. Squeeze a grip near it:
past 55 % squeeze, within `wheel_grab_distance` metres of its plane (default 0.35) and near the rim,
or near a bar end, scaled by `wheel_grab_assist`. Once taken, only letting go of the grip releases
it. One hand steers by its angle around the hub; two hands steer by the line between them, so leaning
or moving both arms together does not steer, and a hand joining, leaving or crossing the hub keeps
the steering where it was. Turning past full lock is kept, so retracing the gesture returns to the
same centre, while the game's steering saturates at full lock. `wheel_response` scales how quickly
the wheel follows, `wheel_tracking_grace` (seconds) how long a hand that loses tracking keeps hold,
and `wheel_haptics` gives a short pulse on grab and release.
While the wheel is held it replaces the left stick's X axis, in both the Wii Remote and the gamepad
presentation, and the game keeps its own steering curve. The stick's Y axis still aims items, and a
holding grip no longer reaches the game (it would press C on the Nunchuk or a shoulder on the
gamepad); the triggers, A and the right stick are unchanged. Releasing both grips gives steering back
to the stick. The settings panel withholds the wheel like any other input.
**Hands and the separate wheel.** Hands are drawn while hand steering is on: the runtime's own hand
mesh where it offers one (`XR_EXT_hand_tracking` and `XR_FB_hand_tracking_mesh`, requested only when
hand steering is on at launch), otherwise procedural gloves that curl with the squeeze. They and the
separate VR wheel or handlebar travel with the stereo packet in metres in the seated frame, and each
eye draws them inside the scene's pass just before the first 2D-layer draw, depth-tested with the
world's own depth mapping, so the kart and the track hide them and the HUD cannot
(`aurora-main/lib/gfx/cockpit.hpp`). The anchor also carries the frame's exact world scale
(`aurora_set_stereo_scene_anchor_scaled`), and Aurora rescales each eye's head translation to it, so
a scale change between the XR packet and the frame cannot misplace the hands.
The guest offsets involved (driver, movement, damage, grip frames, bike handle, driver bones and
their world matrices) are PAL `RMCP01` constants listed with the leaf getter or constructor that
proves each in `runtime/src/vr/mkw_vr_first_person.cpp`. `mkw_steering_wheel_tests`,
`mkw_vr_cockpit_tests` and `mkw_vr_hand_steering_tests` cover the grab model, the seat and wheel
geometry and the hand-off to the game; `gx_fifo_tests` covers the per-draw substitution and the
overlay geometry, and `cockpit_gpu_smoke` its depth test on a real GPU.
## Presentation policy
The runtime deliberately fails safe instead of guessing which Mario Kart camera is active:
@@ -614,6 +703,9 @@ ends, including mid-frame flushes, so live setting changes cannot invalidate pen
Lifecycle events and performance (about 43 game FPS) are still open. Apple visionOS packaging
is not implemented.
- Scene-specific comfort options, culling fixes and replay/spectator classification are future work.
- The cockpit seat, the turning wheel and hand steering have not yet been validated in a headset on
this build: the native wheel's match against the race camera's view, bikes and Quacker, and the
Quest. Hand steering needs analog grips (Touch); the simple controller profile cannot grab.
- The headset settings panel is drawn into the eye images rather than submitted as its own quad
layer, so its text is resampled once more than a compositor layer's would be. It has no laser
beam, only the cursor on the panel itself, and text fields cannot be typed into without a keyboard.
+5 -1
View File
@@ -54,7 +54,9 @@ Windows builds can render through an OpenXR runtime on D3D12, or on Vulkan with
build, without CPU readback. Menus and
unsupported scenes appear as a head-locked virtual screen; a validated single-camera race switches
to immersive stereo rendering. VR is opt-in and falls back to the normal desktop renderer if the
runtime or headset is unavailable. See [`OPENXR.md`](OPENXR.md) for setup, configuration, and the
runtime or headset is unavailable. In first person you sit in the cockpit, where the steering wheel
or handlebar turns with your steering, and optional hand steering by heurazy lets you grab it with
the tracked controllers and turn it. See [`OPENXR.md`](OPENXR.md) for setup, configuration, and the
current limitations.
**Music ducking.**
@@ -234,6 +236,8 @@ All translated output is verified against real hardware behavior and most import
aurora's Direct3D, Vulkan and OpenGL backends.
- **[OpenXR](https://www.khronos.org/openxr/)** - the Khronos cross-platform API used by the
experimental VR renderer.
- **heurazy** - the VR cockpit's turning steering wheel and hand steering, ported from
**[mario-kart-wii-VR-port](https://github.com/heurazy/mario-kart-wii-VR-port)** (GPL-3.0).
- **[Dolphin Emulator](https://github.com/dolphin-emu/dolphin)** - an invaluable reference for Wii
hardware behavior during development, plus the source of the free DSP coefficient ROM and the
unmodified default WiiConnect24 bootstrap tree bundled with the runtime.
+21
View File
@@ -71,6 +71,21 @@ The runtime's Riivolution patch handling is a port of Dolphin's
(both marked `SPDX-License-Identifier: GPL-2.0-or-later`).
Source: <https://github.com/dolphin-emu/dolphin>
### heurazy's mario-kart-wii-VR-port - GPL-3.0-or-later
- Source: <https://github.com/heurazy/mario-kart-wii-VR-port>
- Author: heurazy
- License: GNU General Public License v3.0 or later, the same license as WiiCompiled.
The VR cockpit's steering wheel and hand steering are ported from this project: the grab-and-turn
model (`runtime/include/vr/steering_wheel.h`), the native wheel vertex rotation
(`runtime/include/vr/native_wheel_mesh.h`), the level seat (`runtime/include/vr/cockpit_stabilizer.h`),
the runtime hand-mesh loader (`runtime/include/vr/openxr_hand_mesh.h`), the per-draw substitution
(`aurora-main/include/aurora/native_wheel_match.hpp`, `aurora-main/lib/gx/native_wheel.hpp`), the
cockpit overlay renderer (`aurora-main/lib/gfx/cockpit.hpp`), their tests, and the seat, eye and
wheel geometry and guest reads in `runtime/src/vr/mkw_vr_first_person.cpp` and
`runtime/include/vr/mkw_vr_first_person.h`. The files carry that attribution in their headers.
### pugixml - MIT
Copyright (c) 2006-2025 Arseny Kapoulkine.
@@ -241,6 +256,12 @@ Not code, but the documentation this project depends on:
- [Retro Rewind](https://wiki.tockdom.com/wiki/Retro_Rewind) by ZPL - the mod distribution this
project can build as a static profile. No Retro Rewind content is redistributed here; users
supply their own copy.
- The references heurazy's mario-kart-wii-VR-port credits for the cockpit, none of whose source is
compiled into this repository:
[AnimalCrossing-VR-MR-Standalone](https://github.com/heurazy/AnimalCrossing-VR-MR-Standalone)
(OpenXR hand meshes), [Cyberpunk VR port](https://github.com/dariulone/cyberpunk-vr-port)
(squeeze-to-grab steering) and [Pulsar](https://github.com/MelgMKW/Pulsar) (Mario Kart Wii class
layouts).
---
+124 -3
View File
@@ -3,6 +3,7 @@
#include "aurora_events.h"
#include "controller_button_names.h"
#include "controller_mapping_wizard.h"
#include "gx_native_wheel.h"
#include "input_bindings.h"
#include "game_graphics_options.h"
#include "log_export.h"
@@ -139,6 +140,14 @@ bool g_vrSkipCopyClears = RuntimeConfigFile::VrSkipCopyClears(true);
bool g_vrHudVirtualScreen = RuntimeConfigFile::VrHudVirtualScreen(true);
bool g_vrFirstPerson = RuntimeConfigFile::VrFirstPerson(false);
float g_vrFirstPersonUnitsPerMeter = RuntimeConfigFile::VrFirstPersonUnitsPerMeter();
// 0 = cockpit, 1 = custom, matching kVrFirstPersonSeatNames.
constexpr std::array<const char*, 2> kVrFirstPersonSeatNames{"cockpit", "custom"};
int g_vrFirstPersonSeat = RuntimeConfigFile::VrFirstPersonSeat() == "custom" ? 1 : 0;
float g_vrCockpitUnitsPerMeter = RuntimeConfigFile::VrCockpitUnitsPerMeter();
bool g_vrSteeringWheel = RuntimeConfigFile::VrSteeringWheel();
bool g_vrNativeSteeringWheel = RuntimeConfigFile::VrNativeSteeringWheel();
bool g_vrHandSteering = RuntimeConfigFile::VrHandSteering();
mkw::vr::WheelTuning g_vrWheelTuning = RuntimeConfigFile::VrWheelTuning();
float g_vrFirstPersonHeadUp = RuntimeConfigFile::VrFirstPersonHeadUpMeters();
float g_vrFirstPersonHeadForward = RuntimeConfigFile::VrFirstPersonHeadForwardMeters();
float g_vrFirstPersonHeadRight = RuntimeConfigFile::VrFirstPersonHeadRightMeters();
@@ -1113,6 +1122,82 @@ void ApplyVrHudVirtualScreen() {
RuntimeConfigFile::VrHudDistanceMeters(2.0f) * unitsPerMeter);
}
// The cockpit's steering wheel and hand steering, under the first-person camera.
void DrawVrSteeringWheelSettings() {
ImGui::Separator();
ImGui::Text("Steering wheel");
ImGui::BeginDisabled(g_vrFirstPersonSeat != 0);
if (ImGui::Checkbox("Turn the steering wheel", &g_vrSteeringWheel)) {
RuntimeConfigFile::SetVrSteeringWheel(g_vrSteeringWheel);
mkw::vr::MkwVRFirstPersonApplyConfiguredSettings();
}
if (ImGui::IsItemHovered()) {
ImGui::SetTooltip("In the cockpit, the kart's steering wheel or the bike's handlebar turns "
"with your steering.");
}
ImGui::BeginDisabled(!g_vrSteeringWheel);
if (ImGui::Checkbox("Use the vehicle's own wheel", &g_vrNativeSteeringWheel)) {
RuntimeConfigFile::SetVrNativeSteeringWheel(g_vrNativeSteeringWheel);
mkw::vr::MkwVRFirstPersonApplyConfiguredSettings();
}
if (ImGui::IsItemHovered()) {
ImGui::SetTooltip("Turns the wheel or handlebar of the vehicle's own model. Off draws a "
"separate VR wheel instead, which is also what appears when a vehicle's "
"own wheel cannot be animated.");
}
ImGui::EndDisabled();
if (ImGui::Checkbox("Hand steering (by heurazy)", &g_vrHandSteering)) {
RuntimeConfigFile::SetVrHandSteering(g_vrHandSteering);
}
if (ImGui::IsItemHovered()) {
ImGui::SetTooltip("Squeeze a grip near the wheel or handlebar to take hold of it, and turn "
"it to steer, with one hand or both. Releasing both grips gives steering "
"back to the stick, which still aims items. The runtime's hand mesh is "
"used when hand steering was on at launch.");
}
if (g_vrHandSteering && ImGui::TreeNode("Hand steering tuning")) {
bool changed = false;
changed |= ImGui::SliderFloat("Kart full lock (degrees)", &g_vrWheelTuning.kartDegrees,
RuntimeConfigFile::kVrWheelDegreesMin,
RuntimeConfigFile::kVrWheelDegreesMax, "%.0f");
changed |= ImGui::SliderFloat("Bike full lock (degrees)", &g_vrWheelTuning.bikeDegrees,
RuntimeConfigFile::kVrWheelDegreesMin,
RuntimeConfigFile::kVrWheelDegreesMax, "%.0f");
changed |= ImGui::SliderFloat("Grab reach (m)", &g_vrWheelTuning.grabDistance,
RuntimeConfigFile::kVrWheelGrabDistanceMin,
RuntimeConfigFile::kVrWheelGrabDistanceMax, "%.2f");
changed |= ImGui::SliderFloat("Grab assist", &g_vrWheelTuning.grabAssist,
RuntimeConfigFile::kVrWheelGrabAssistMin,
RuntimeConfigFile::kVrWheelGrabAssistMax, "%.2f");
changed |= ImGui::SliderFloat("Response", &g_vrWheelTuning.response,
RuntimeConfigFile::kVrWheelResponseMin,
RuntimeConfigFile::kVrWheelResponseMax, "%.2f");
changed |= ImGui::SliderFloat("Tracking-loss grace (s)", &g_vrWheelTuning.trackingGrace,
RuntimeConfigFile::kVrWheelTrackingGraceMin,
RuntimeConfigFile::kVrWheelTrackingGraceMax, "%.2f");
changed |= ImGui::Checkbox("Grab and release pulse", &g_vrWheelTuning.haptics);
if (ImGui::Button("Reset hand steering tuning")) {
g_vrWheelTuning = {};
changed = true;
}
if (changed) {
RuntimeConfigFile::SetVrWheelTuning(g_vrWheelTuning);
}
ImGui::TreePop();
}
ImGui::EndDisabled();
// What the cockpit found, for a report when the wheel does not behave.
const auto anchor = mkw::vr::MkwVRFirstPersonGetAnchor();
if (anchor.valid && anchor.cockpit) {
ImGui::TextDisabled("Cockpit: %s, %s, %.0f units/m, animated draws %u",
anchor.bike ? "handlebar" : "wheel",
!anchor.native_wheel.valid ? "grips not found"
: anchor.native_mesh_prepared ? "vehicle's own"
: "VR wheel",
anchor.units_per_meter, GxNativeWheel::LastDrawCount());
}
}
void DrawGraphicsSettings() {
g_displayMode = static_cast<int>(aurora_get_display_mode());
struct EffectFlag {
@@ -1391,11 +1476,37 @@ void DrawVrSettings() {
ImGui::SetTooltip(
"Moves the camera to the Player 1 driver's head and keeps the horizon level, "
"instead of riding behind the kart. Applies during a single-screen race; menus "
"and split-screen are unaffected. The world scale below replaces "
"world_units_per_meter while it is engaged.");
"and split-screen are unaffected.");
}
constexpr std::array<const char*, 2> kSeatLabels{"Cockpit", "Custom"};
if (ImGui::Combo("Seat", &g_vrFirstPersonSeat, kSeatLabels.data(), static_cast<int>(kSeatLabels.size()))) {
RuntimeConfigFile::SetVrFirstPersonSeat(kVrFirstPersonSeatNames[static_cast<size_t>(g_vrFirstPersonSeat)]);
mkw::vr::MkwVRFirstPersonApplyConfiguredSettings();
ApplyVrHudVirtualScreen();
}
if (ImGui::IsItemHovered()) {
ImGui::SetTooltip(
"Cockpit sits you at the driver's own eyes, behind the steering wheel, at a "
"life-size scale that allows for the character's height, so the wheel is within "
"reach. Custom places the head by the world scale and offsets below instead.");
}
if (g_vrFirstPersonSeat == 0) {
if (ImGui::SliderFloat("Cockpit scale (units per metre)", &g_vrCockpitUnitsPerMeter,
RuntimeConfigFile::kVrCockpitUnitsPerMeterMin,
RuntimeConfigFile::kVrCockpitUnitsPerMeterMax, "%.0f")) {
RuntimeConfigFile::SetVrCockpitUnitsPerMeter(g_vrCockpitUnitsPerMeter);
mkw::vr::MkwVRFirstPersonApplyConfiguredSettings();
ApplyVrHudVirtualScreen();
}
if (ImGui::IsItemHovered()) {
ImGui::SetTooltip(
"100 reads life-size for an average-height driver; taller characters raise it "
"further on their own. Raising it shrinks the world around you.");
}
}
// These are the tuning loop for the anchor: the right head height is a
// per-taste value that can only really be judged from inside the headset.
ImGui::BeginDisabled(g_vrFirstPersonSeat == 0);
if (ImGui::SliderFloat("World units per metre (first person)", &g_vrFirstPersonUnitsPerMeter,
1.0f, 200.0f, "%.1f")) {
RuntimeConfigFile::SetVrFirstPersonUnitsPerMeter(g_vrFirstPersonUnitsPerMeter);
@@ -1422,8 +1533,9 @@ void DrawVrSettings() {
mkw::vr::MkwVRFirstPersonApplyConfiguredSettings();
}
ImGui::PushTextWrapPos(ImGui::GetCursorPosX() + Scaled(380.0f));
ImGui::TextDisabled("Where the head sits in the kart's own frame.");
ImGui::TextDisabled("Custom seat: where the head sits in the kart's own frame.");
ImGui::PopTextWrapPos();
ImGui::EndDisabled();
constexpr std::array<const char*, 3> kRotationLabels{"Yaw only", "Yaw + Pitch", "Full rotation"};
if (ImGui::Combo("View rotation", &g_vrFirstPersonRotation, kRotationLabels.data(),
static_cast<int>(kRotationLabels.size()))) {
@@ -1466,8 +1578,17 @@ void DrawVrSettings() {
if (ImGui::IsItemHovered()) {
ImGui::SetTooltip("Removes the vehicle as well, leaving nothing of your own kart.");
}
DrawVrSteeringWheelSettings();
ImGui::Separator();
if (ImGui::Button("Reset first-person defaults")) {
g_vrFirstPersonSeat = 0;
g_vrCockpitUnitsPerMeter = RuntimeConfigFile::kVrCockpitUnitsPerMeterDefault;
g_vrSteeringWheel = RuntimeConfigFile::kVrSteeringWheelDefault;
g_vrNativeSteeringWheel = RuntimeConfigFile::kVrNativeSteeringWheelDefault;
RuntimeConfigFile::SetVrFirstPersonSeat(RuntimeConfigFile::kVrFirstPersonSeatDefault);
RuntimeConfigFile::SetVrCockpitUnitsPerMeter(g_vrCockpitUnitsPerMeter);
RuntimeConfigFile::SetVrSteeringWheel(g_vrSteeringWheel);
RuntimeConfigFile::SetVrNativeSteeringWheel(g_vrNativeSteeringWheel);
g_vrFirstPersonUnitsPerMeter = RuntimeConfigFile::kVrFirstPersonUnitsPerMeterDefault;
g_vrFirstPersonHeadUp = RuntimeConfigFile::kVrFirstPersonHeadUpDefault;
g_vrFirstPersonHeadForward = RuntimeConfigFile::kVrFirstPersonHeadForwardDefault;