log mode it
prints the tracking and input calls the app makes, with timings. In
record mode it writes every frame’s head pose, eye
views, controller poses and action states to a small binary file. In
replay mode it feeds those poses back into the app and
rewrites the poses the app submits for display. The same motion runs
again with no headset moving. That gives a VR developer a repeatable
repro for a tracking bug, and a CI job a fixed input to render against.
It watches what a VR app asks the runtime for, the way
Pointer Lab watches what a game reads and
writes.
Run poseplay info on a recording and you get this summary.
This is real output, over a 120-frame recording the layer wrote in
record mode. The layer was driven by its own test harness,
not by a headset.
poseplay 1.0.1
file sample.oxrr
format version 1
frames 120
duration 1322.2 ms (90.0 fps)
view sets 120
space locates 120 single, 0 grouped
inputs 0 pose, 120 boolean, 120 float, 0 vector2f
head position x [-0.0300, 0.0300] y [1.5500, 1.6500] z [-0.0200, 0.0200] (120 frames)
Each frame is one xrWaitFrame. The harness made one
xrLocateViews, one xrLocateSpace, one boolean and
one float action-state call per frame, so each of those counts is 120. It
never asked for a pose or vector2f action state, so those read 0.
xrWaitFrame. Poses and inputs are stored under the frame index the layer assigns, and replayed in the order they were recorded. Nothing is keyed on an XrSpace or XrAction handle, because those do not survive into a new run.xrWaitFrame, xrLocateViews, xrLocateSpace, xrLocateSpaces, xrSyncActions, the four xrGetActionState* calls, and xrEndFrame. Anything else passes straight through.xrEndFrame rewrites the projection-layer view poses as well, so an app that caches its poses still renders from the recorded path. Frame timing stays whatever the runtime returns.x y z yawDegrees offset plays the recorded path from a new place or facing.--json for scripts.poseplay recording toolHKEY_CURRENT_USER.oxrr file, format version 1, keyed by frame indexopenxr-pose-layer-v1.0.1.zip: openxr_pose_layer.dll, its manifest, poseplay.exe, install.ps1 and uninstall.ps1xrLocateSpaces groups (OpenXR 1.1)xrEndFrameposeplay info, dump and trimuninstall.ps1 to remove it
Intended use. openxr-pose-layer is for testing and
studying OpenXR apps you own or are authorized to analyze: your own apps,
sample apps such as hello_xr, and development builds. Feeding
recorded input into an online or competitive game may trip anti-cheat
software and get the account banned, and modifying software
you do not have permission to modify may be illegal where you live. This
is a development and research tool.
What has been tested. The 40 unit tests drive the real
layer code through an in-process fake next layer, with no OpenXR runtime
and no headset. They run in CI. The output above came from that
harness, not from a headset. End-to-end replay against
hello_xr on a null runtime is a manual check, outside CI.
Replay replaces tracking. On real hardware, replay
overrides tracking, so the scene world-locks to the recorded path and
stops following your head. That is expected. To run with no headset, put
a null runtime under the layer: Monado’s simulated driver or the
SteamVR null driver. In record mode the file is written only
when the app shuts down OpenXR. If the app crashes or is killed, nothing
is saved.
The binaries are unsigned. Antivirus software may flag a
new unsigned DLL that loads into other processes.
Build
it from source if you would rather not take a binary on trust.
install.ps1 writes only under HKEY_CURRENT_USER
and needs no administrator rights. uninstall.ps1 undoes it.