Files
OpenVR-AdvancedSettings-frame/docs/steamframe/OVRAS-FEATURES.md
T
Matthias JanetschekandClaude Opus 5.5 7c5a9a7a1e Handover documentation for continuing on another computer
- docs/steamframe/README.md: entry point with status, branches/remotes, setup,
  commands, Steam Frame facts, open points.
- CLAUDE.md: working rules and code conventions (fork-only).
- docs/steamframe/OVRAS-FEATURES.md: OVRAS's features, how they are
  implemented, issues found while reading.
- PROGRESS.md: status and wrap-up.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 14:57:20 +02:00

198 lines
9.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# OVRAS: features and how they are implemented
Analysis of 2026-10-07, based on upstream `master` (`31df8b4`, 5.8.17). Line numbers refer to
that state. `qt6` has the same features, so the numbers are close. Paths are relative to
`src/`. Which of these features SteamVR now offers itself is in
[REQUIREMENTS.md](REQUIREMENTS.md), "Feature classification".
## Architecture
- **Dashboard overlay:**
- `VR_Init(VRApplication_Overlay)`, app key `steam.overlay.1009850`.
- QML UI (1200×800) rendered off-screen via `QQuickRenderControl`.
- The texture goes to `SetOverlayTexture`. On `steamframe` the render backends in `render/`
do this; before, it was an OpenGL FBO, and on `qt6` QRhi.
- **Input:** SteamVR mouse/scroll events are turned into Qt events (`overlaycontroller.cpp`,
`mainEventLoop()`).
- **Main loop (`OnTimeoutPumpEvents` → `mainEventLoop()`):**
- Timer; "vsync" mode once per compositor frame (`GetTimeSinceLastVsync`).
- Per tick:
1. input actions
2. VR events
3. poses
4. `eventLoopTick` of the tab controllers (always)
5. `dashboardLoopTick` (only while the dashboard is visible)
- **SteamVR Input:** `package_files/action_manifest.json`, 5 action sets:
- `motion`: space drag/turn, gravity, snap/smooth turn, height toggle, offsets, auto-turn
- `music`: media keys
- `misc`: axis locks, chaperone toggle, keyboard shortcuts
- `system`: push-to-talk, exclusive input, haptic clicks
- `haptic`: vibration, proximity sensor
Default bindings exist for Vive, Index, WMR, HP, Touch, generic HMD and Frame controllers.
- **Persistence:**
- App settings in a `QSettings` INI file (`settings/`). Profiles are stored as arrays
(`ISettingsObject`).
- SteamVR's own settings go directly through `vr::VRSettings()` (`openvr/ovr_settings_wrapper`).
- **Platform:**
- Windows: WASAPI / `IPolicyConfig`, `SendInput`.
- Linux: PulseAudio, X11 XTest, D-Bus MPRIS.
- Elsewhere: dummies.
## Features
### Playspace movement (`tabcontrollers/MoveCenterTabController.cpp`)
Almost everything shifts or rotates the **working standing zero pose** through
`IVRChaperoneSetup` and shows it live with `ShowWorkingSetPreview()`. Nothing is committed
per frame. This mechanism does **not work on the Frame** (inside-out tracking).
- **Core, `updateSpace()` (:2497–2721):**
- Offsets X/Y/Z and the rotation (centidegrees) are multiplied with the stored basis.
- The result goes to `SetWorkingStandingZeroPoseToRawTrackingPose`, in seated mode
additionally to the seated pose.
- Safety limit: about 40 km.
- **Space drag:**
- The controller's position delta, multiplied by `dragMult`, is added to the offsets.
- Axis locks; the speed is kept for fling.
- Comfort mode skips frames.
- **Space turn:** the change of the yaw angle via quaternions
(`q·conj(q_last)`, `quaternion/quaternion.h`). Rotation pivots on the HMD by default.
- **Snap/smooth turn:** fixed angle per press resp. per tick, so smooth turn depends on the
frame rate.
- **Gravity/momentum:** Euler integration with friction, terminal velocity 50 m/s, landing on
the floor, reversible.
- **Height toggle:** Y offset plus a new gravity floor.
- **Offset profiles, apply/reset:**
- "Apply" commits with `CommitWorkingCopy(Live)` (limit 990 m).
- `zeroOffsets()` / `updateChaperoneResetData()` also commit at start-up. On the Frame
this shifts the play area, hence R7.
### Rotation (`tabcontrollers/RotationTabController.cpp`, via `setRotation`)
- **Auto-turn:**
- Rotates the space when the user gets near a wall, either as a snap or smoothly.
- Direction: from the corner shared with the last wall, otherwise cord untangling (HMD
total rotation count).
- **Vestibular motion:** rotation as if walking on a circle of radius r
(`2·asin(d/2r)`).
- **View ratchetting:** amplifies head turns away from the wall.
### Fix floor / recenter (`tabcontrollers/FixFloorTabController.cpp`)
- **Fix floor:**
- Measures the lower controller over 25 frames.
- Subtracts the controller thickness per model and orientation (Vive / Knuckles).
- Commits the result as a Y offset; undo is possible.
- **Recenter:** `VRChaperone()->ResetZeroPose(...)`.
### Chaperone (`tabcontrollers/ChaperoneTabController.cpp`)
- **Settings:**
- Visibility, color, fade distance, wall height, center marker, floor bounds and style.
- These are keys in `k_pch_CollisionBounds_Section`.
- "Disable" sets the fade distance to 0 and remembers the old value.
- **Own center marker overlay:** shows the rotation count (cord).
- **Dim when crouching:** below a height, the fade distance goes to 0 over 10 s.
- **Proximity warnings:**
- Distance of HMD and controllers to the walls (`utils/ChaperoneUtils.cpp`: projection onto
each wall segment).
- Reactions: switch to the beginner style, vibration (own thread,
`TriggerHapticVibrationAction`), alarm sound with distance-dependent volume, open the
dashboard.
- **Chaperone profiles:**
- Save the geometry (`GetLiveCollisionBoundsInfo`, zero pose, size) and the settings.
- Apply them with `SetWorking…` + `CommitWorkingCopy`.
- Autosave profile.
### Video (`tabcontrollers/VideoTabController.cpp`)
- **Brightness:** a black overlay right in front of the HMD. Its alpha `(1−x)^(1/3)`
compensates for perception.
- **Color tint:**
- either a colored overlay (`SetOverlayColor`)
- or SteamVR's `HmdDisplayColorGainR/G/B`
- **SteamVR keys:** supersampling (incl. manual override), motion smoothing, supersample
filtering.
- **Video profiles.**
### Audio (`tabcontrollers/AudioTabController.cpp`, `audiomanager/`)
- **Interface:** `AudioManager` with a Windows, a PulseAudio and a dummy implementation.
- **Windows:**
- WASAPI/MMDevice, `IAudioEndpointVolume`.
- The default device is set via the undocumented `IPolicyConfig`.
- External changes come in via `IMMNotificationClient`.
- **Linux:**
- PulseAudio: `pa_context_set_default_sink/source`; existing source outputs are moved to
the new source.
- The original state is restored at exit.
- **No mirror device.**
- **Mirror device and device override:** these are SteamVR keys (`k_pch_audio_*`), not
OVRAS's own routing.
- **Push-to-talk / -mute:** SteamVR Input action → mic mute + notification overlay on the
HMD.
- **Mute the mic when the HMD is taken off:** proximity sensor action.
- **Audio profiles.**
### SteamVR tab (`tabcontrollers/SteamVRTabController.cpp`)
- **Toggles:** each is a SteamVR setting.
- performance graph, multiple drivers, do not disturb, no-HMD mode
- camera options
- system button to all apps, don't fade to grid, controller power auto-launch
- **Restart SteamVR:** Windows only, via `.bat`.
- **Per-game controller bindings:**
- Use SteamVR's web server `localhost:27062`, with a spoofed `Referer`.
- Saved as JSON and applied when the scene app changes.
- **Receiver/tracker pairing:** WebSocket to the lighthouse web interface (`start_pairing`).
- **`openvr/lh_console_util.cpp`** (`lighthouse_console`) is compiled but **not used**.
- There is no base-station power management.
### Utilities (`tabcontrollers/UtilitiesTabController.cpp`, `keyboard_input/`, `media_keys/`, `alarm_clock/`)
- **Keyboard:**
- Buttons (Enter, Alt-Tab, Ctrl-C/V, …) and 3 freely defined shortcuts.
- A parser for the syntax `^`=Ctrl, `*`=Alt, `>`=Shift, `#`=Super.
- Sent via Windows `SendInput` or X11 XTest. On the Frame (gamescope) the X11 path probably
doesn't reach games.
- **Media keys:**
- Windows: `VK_MEDIA_*`.
- Linux: D-Bus to every `org.mpris.MediaPlayer2.*`.
- **Tracker battery:** icon overlay on each tracker (`Prop_DeviceBatteryPercentage_Float`),
only while the dashboard is visible.
- **Alarm clock:** HMD overlay at a set time, shown for 3 s.
### Statistics (`tabcontrollers/StatisticsTabController.cpp`)
- **Frame counters:** `VRCompositor()->GetCumulativeStats()` gives presented, dropped,
reprojected and timed-out frames. "Reset" only stores an offset.
- **Distance traveled:** horizontal HMD movement, every 11th tick, steps ≥ 1 cm.
- **Rotation count, maximum controller speed.**
### Settings tab (`tabcontrollers/SettingsTabController.cpp`)
Autostart (`SetApplicationAutoLaunch`), native chaperone import, block Oculus SDK, desktop
mode, tick rate (vsync / custom tick rate).
## Issues found while reading (not verified)
| Place (master) | Issue |
|---|---|
| `MoveCenterTabController.cpp:1198` | `updateChaperoneResetData()` allocates `new vr::HmdQuad_t[]` on every call and never frees the old array (memory leak) |
| `MoveCenterTabController.cpp:2512` | `if ( m_chaperoneHasCommit ) { m_chaperoneHasCommit = true; … }` looks like a slip |
| `MoveCenterTabController.cpp:1332` | `leftHandSpaceDrag`: the final `else` overwrites the swap/override choice |
| `MoveCenterTabController` | Rotation is wrapped inconsistently (snap/smooth/auto-turn 0–36000 vs. ±18000 elsewhere) |
| `VideoTabController.cpp:114` | Sets the sort order of the brightness overlay instead of the color overlay |
| `ChaperoneTabController.cpp:903` | Floor bounds are read as Bool but written as Int32 |
| `MoveCenterTabController::zeroOffsets` | If `GetCalibrationState() == 200`, init never completes and the commit repeats every tick (with commits enabled) |
| `utils/FrameRateUtils.cpp`, `openvr/lh_console_util.cpp` | Compiled but unused |
Found on the `qt6` branch and fixed on `steamframe` (see PROGRESS.md):
- the build fails on Linux
- QRhi Vulkan path: wrong `m_nFormat` (Qt enum instead of `VkFormat`); no layout transition,
no SteamVR extensions, no choice of the HMD's GPU
- mouse y not flipped on Linux
- no `VR_Shutdown`
- hard-coded version 5.7.4