Skip to content

Add OpenXR client integration with XR locomotion and controller support #27

Draft
shipilovden wants to merge 16 commits intoglaretechnologies:masterfrom
shipilovden:xr/upstream-openxr-clean
Draft

Add OpenXR client integration with XR locomotion and controller support #27
shipilovden wants to merge 16 commits intoglaretechnologies:masterfrom
shipilovden:xr/upstream-openxr-clean

Conversation

@shipilovden
Copy link
Copy Markdown

@shipilovden shipilovden commented Mar 27, 2026

Overview

This PR extracts the XR-only work from the larger downstream Metasiberia branch and rebases it onto current master as a focused upstream contribution.

The result is an initial native desktop OpenXR integration for gui_client, plus the follow-up runtime and gameplay fixes that were required to make the XR path practically usable:

  • OpenXR runtime detection and gated build integration
  • OpenXR instance / session / swapchain lifecycle management
  • XR startup mode selection in the desktop options UI
  • stereo per-eye rendering, mirror view, and direct eye render path support
  • XR recenter support from the desktop client
  • avatar grounding and XR eye-height behavior fixes
  • first-person hiding of the local avatar in XR
  • teleport locomotion
  • controller-based smooth locomotion bindings
  • controller proxy rendering and controller render-model loading
  • Vive Focus 3 interaction profile support
  • Meta Quest interaction profile support
  • restored final imaging / portal rendering when XR is active

This PR intentionally does not include Metasiberia-specific product work, release-prep changes, website changes, docs, notes, or unrelated branch content. The scope here is limited to XR-relevant client/runtime/build changes only.

Why This PR Exists

The XR work was originally developed inside a much broader downstream branch that also contained unrelated product and release activity. That made the OpenXR work difficult to review upstream because reviewers would have had to sift through a large amount of unrelated code and content.

This PR separates the XR implementation into an upstream-reviewable branch with a clean base on master, so the OpenXR work can be evaluated on its own technical merits.

High-Level Scope

At a high level, this PR does four things:

  1. Adds conditional OpenXR build plumbing for native client builds.
  2. Introduces the runtime/session layer required to talk to an OpenXR runtime.
  3. Wires XR into the existing desktop client, render loop, and options UI.
  4. Includes the follow-up usability fixes that were developed on top of the initial XR path: avatar visibility, grounding, locomotion, controller visuals, device-specific interaction profiles, and rendering-path fixes.

Extracted Commit Series

This PR is composed from the XR-focused work that previously lived in the downstream branch. The functional commit series included in the extracted branch is:

  • ac0ac111 Add initial OpenXR runtime integration
  • 7eb32d3a Refine XR avatar grounding and recenter
  • c85bf784 Hide local avatar mesh in XR first person
  • de88bc93 Add XR teleport locomotion
  • 4a127d68 Add XR controller smooth locomotion bindings
  • f682cd36 Show XR controller proxies and fix forward axis
  • 21d3538f Reduce XR controller proxy flicker
  • 834eba64 Load Vive Focus 3 XR controller render models
  • d3c37d61 Load XR controller render models at startup
  • e4e6c34b Stabilise XR controller visuals and reduce SteamVR eye size
  • 5e5deeac Use direct XR eye render path
  • 3e33b7e2 Restore XR final imaging and portal rendering
  • 2b05e6ff Add Meta Quest OpenXR controller profiles
  • ecd85bbf Fix XR local avatar visibility regression

The final two cleanup commits in the extracted branch are whitespace-only cleanup needed after reconstructing the branch history on top of current master:

  • 144c89fe Clean XR patch whitespace
  • 87862457 Fix XR whitespace nits

Detailed Functional Breakdown

1. Build and feature gating

  • Adds conditional OpenXR-related build wiring at the top-level and gui_client CMake layers.
  • Introduces XR_SUPPORT-gated compilation so the client can build with or without OpenXR support depending on environment/toolchain availability.
  • Wires the OpenXR SDK / loader dependency into the native client build rather than treating XR as an external patch layer.

2. OpenXR runtime and session lifecycle

  • Introduces a dedicated XR runtime/session layer rather than scattering raw OpenXR calls through the UI code.
  • Adds runtime probing / availability helpers so the desktop client can reason about whether OpenXR support is available before attempting to start XR.
  • Adds the core session plumbing required to create and maintain an XR session:
    • instance creation
    • system selection
    • session creation
    • reference space setup
    • swapchain setup
    • frame begin / frame end handling
    • per-eye view/projection preparation
    • runtime state tracking

3. Desktop client integration

  • Wires XR support into the existing GUIClient lifecycle instead of implementing XR as a separate standalone executable path.
  • Adds option/state flow so the user can control XR startup behavior from the normal desktop client settings.
  • Connects the XR session to the existing render loop, mirror view path, and main window actions.
  • Adds desktop recenter support so the user can re-align XR without restarting the client.

4. Rendering path work

  • Adds the initial stereo per-eye render plumbing needed for XR rendering.
  • Adds a desktop mirror view path so XR output can still be observed on the normal window.
  • Switches XR toward a direct eye render path to reduce rendering indirection.
  • Restores final imaging / portal rendering when XR is active so the XR path is not missing key late-stage visuals already present in the non-XR renderer.

5. Avatar behavior in XR

  • Adds avatar grounding helpers required to make XR pose / eye-height behavior more coherent with the world.
  • Refines recenter and grounding interactions so the avatar pose better follows the XR user’s effective standing position.
  • Hides the local avatar in first-person XR to avoid showing the user their own mesh incorrectly.
  • Includes a follow-up regression fix so local avatar visibility stays correct in XR after the earlier visibility work.

6. XR movement and interaction

  • Adds teleport locomotion support for XR.
  • Adds controller-based smooth locomotion bindings on top of the teleport path.
  • Routes XR controller state through the runtime layer so locomotion decisions can be made from OpenXR action data instead of desktop-style input assumptions.

7. Controller visuals and device-specific support

  • Adds controller proxy rendering so XR controllers have visible in-world representations.
  • Fixes controller-forward-axis handling so controller visuals and behavior are aligned more correctly.
  • Reduces controller proxy flicker.
  • Loads controller render models earlier / more reliably.
  • Adds Vive Focus 3 controller profile support.
  • Adds Meta Quest controller profile support.
  • Includes SteamVR-specific visual tuning that reduces overly large eye presentation artifacts observed during XR use.

Review Guidance

The files with the largest diffs are central client files such as GUIClient.cpp, GUIClient.h, and MainWindow.cpp. Those files already sit at major orchestration points in the native client, so the XR feature naturally had to be connected there.

Also, because this PR was reconstructed from downstream XR commits that originally lived inside a larger branch, some of the diff volume is inflated by extraction cleanup and whitespace normalization. Even where the textual diff is large, the intended semantic scope remains XR-only.

Reviewers may find it easiest to review this PR in the following order:

  1. gui_client/XRSupport.*
  2. gui_client/XRSession.*
  3. gui_client/CMakeLists.txt and top-level CMakeLists.txt
  4. MainOptionsDialog.* / .ui
  5. GUIClient.*
  6. GlWidget.*
  7. MainWindow.cpp
  8. avatar and controller follow-up files

File-by-File Breakdown

File Why it changed Detailed notes
CMakeLists.txt Top-level build integration Adds the top-level wiring needed for conditional XR-enabled native builds and propagates the relevant build-time configuration into the client build.
gui_client/CMakeLists.txt Client-side OpenXR build plumbing Adds the OpenXR-specific source files, conditional compilation, SDK/library discovery, and linking logic needed for gui_client to build with XR_SUPPORT. This is the main CMake entry point for turning the XR code on.
gui_client/XRSupport.h Runtime support declarations Declares the lightweight support layer used to check whether OpenXR support/runtime availability should be exposed to the rest of the client.
gui_client/XRSupport.cpp Runtime support implementation Implements the small helper/runtime probing layer used by the desktop client before attempting XR startup.
gui_client/XRSession.h Core XR session API Introduces the main XR session class/interface that owns OpenXR state and exposes the functionality needed by the client/render loop.
gui_client/XRSession.cpp Core XR session implementation Implements the OpenXR instance/session lifecycle, reference spaces, frame timing, swapchain handling, per-eye state preparation, action/input integration, controller pose/render-model handling, locomotion support hooks, rendering-path support, and related runtime behavior. This is the core of the feature.
gui_client/GUIClient.h Client orchestration interface Adds XR-related state, ownership, and integration points to the main native client so XR can participate in the normal client lifecycle.
gui_client/GUIClient.cpp Main client integration Wires XR startup, runtime/session management, render-loop integration, mirror rendering, per-frame XR updates, controller/runtime coordination, and local-avatar XR behavior into the main desktop client. This file carries much of the orchestration glue between the new XR layer and existing client systems.
gui_client/GlWidget.h Render widget XR entry points Adds the XR-related declarations needed at the GL widget layer for mirror/stereo rendering integration.
gui_client/GlWidget.cpp Render widget XR integration Connects the existing GL widget/render path to XR-specific rendering behavior, including the desktop mirror path and XR-aware rendering entry points.
gui_client/MainWindow.cpp Main window XR actions Wires XR-related actions from the desktop shell, including recenter-related behavior and propagation of XR state through existing UI/application control flow.
gui_client/MainOptionsDialog.h XR UI declarations Adds the dialog-side declarations required for the XR startup option(s).
gui_client/MainOptionsDialog.cpp XR UI logic Reads/writes the XR startup setting and integrates it with the existing options dialog logic so XR behavior can be configured from the standard client settings flow.
gui_client/MainOptionsDialog.ui XR startup controls Adds the actual UI widgets/controls for choosing XR launch behavior from the desktop options dialog.
gui_client/AvatarGraphics.h XR avatar rendering hooks Adds declarations needed for XR-specific avatar rendering/visibility behavior.
gui_client/AvatarGraphics.cpp XR avatar visibility behavior Implements XR-related avatar rendering behavior, including first-person hiding of the local avatar and related visibility adjustments needed for XR.
gui_client/AvatarGroundingUtils.h Avatar grounding helpers Introduces helper logic used by the XR grounding/recenter work so avatar/world alignment and effective eye-height behavior can be handled more consistently.
gui_client/AvatarSettingsDialog.cpp XR-facing avatar settings interactions Adjusts avatar settings handling where needed to cooperate with the grounding/recenter work that supports XR avatar pose behavior.
gui_client/SDLClient.cpp Native frontend parity Adds the small XR-related client-side adjustments needed on the SDL-native path so XR-specific behavior is not hardcoded only into the Qt frontend integration.

What Is Explicitly Out of Scope

This PR does not include:

  • Metasiberia-specific website/admin/content changes
  • release notes
  • downstream-only scripts
  • branch-local analysis notes
  • non-XR product behavior changes
  • unrelated release-preparation changes

Those were intentionally left out so the upstream review surface remains focused on the OpenXR client/runtime work.

Validation Performed

I validated the extracted branch as follows:

  • rebuilt the branch history onto current master so the PR contains only XR-relevant files
  • verified the final diff against origin/master is limited to the XR/build/client files listed above
  • checked the extracted branch with git diff --check origin/master...HEAD

I did not run a full project build or end-to-end runtime XR session test in this environment, so this PR should be considered code- and scope-cleaned, but not fully runtime-validated here.

@Ono-Sendai
Copy link
Copy Markdown
Contributor

I'm going to get hold of a VR device then try this branch out.

However we want to move a lot of this code from Substrata to glare-core.

There should also be as few additions to GUIClient as possible, because it's already gigantic!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants