The Quest offers XR_FB_hand_tracking_mesh without the app declaring hand
tracking, so a Quest 3 draws the runtime's own hand mesh rather than the
procedural gloves, and its fingers bent backwards on grip: the mesh's
joints point -Z towards the fingertip and +Y out of the back of the hand,
so flexion is negative about the joint's own X, on both hands. Fix and
test by the repository owner; OPENXR.md said the Quest always drew the
gloves, which was wrong.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
On a Quest 3 the gloves' fingers pointed up out of the fist and bent out
of the back of the hand as the grip closed: they were built along the
grip's -Z, which runs up the tube the curled fingers form towards the
thumb, and curled towards -Y, which is backwards on the right hand.
The fingers now run along Y, forwards out of the palm (+Y on the right
hand, -Y on the left, the frame being right-handed), and close towards
+X, the palm's outward normal, with the thumb on the -Z side of both
hands. A test pins the reach, the closing direction and that nothing
bends out of the back of the hand.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
A stereo packet can now carry an AuroraCockpit: tracked hands and, when the
vehicle's own wheel cannot be animated, a synthetic steering wheel or
handlebar, all in metres in the seated frame. Each eye draws it inside the
scene's pass just before the first virtual-screen draw, depth-tested with
the world's own depth mapping (captured from a full-view world draw), so
the kart and track occlude the hands and the 2D layer cannot hide them.
Hands use a runtime-provided hand mesh when one is supplied and a
procedural glove otherwise.
aurora_set_stereo_scene_anchor_scaled lets the sealed frame own its world
scale: each eye's head translation is rescaled from the packet's scale to
the frame's. A non-finite cockpit is dropped with one warning; the frame
still renders.
Ported from heurazy's mario-kart-wii-VR-port (GPL-3.0-or-later).
The VR first-person camera will animate the local vehicle's steering wheel
by handing Aurora a rotated copy of one of the vehicle's position arrays.
A draw picks up the copy only when it binds that exact array with the local
vehicle's position matrix (per-position ownership for indexed-matrix
draws), so opponents sharing the asset keep the original vertices. The copy
takes the same padded upload path as the original and never touches the
shared array cache.
Ported from heurazy's mario-kart-wii-VR-port (GPL-3.0-or-later).
Brings in patchzyy/Wiicompiled main: os_sleep parked-thread fix (#195),
HTTPS Retro WFC payload (#198), macOS build guide (#177), and the
reverse-Z depth fix (#134).
Conflicts were in aurora-main/lib/gfx/common.cpp and lib/gx/shader.cpp,
both from #134, which lands squarely on the VR stereo replay path.
#134 makes UseReversedZ genuinely reversed: the near/far correction now
applies exactly once, inside effective_projection(), instead of being
applied there AND per-vertex in the shader (the double application had
been cancelling out, so "reversed" Z silently behaved like forward Z).
Three pieces of the VR path were built against that old behaviour and
would have broken silently, so they are adapted here:
- shader.cpp exact-screen-depth parked the virtual screen at -0.5*w
specifically so the shader's following negation would land it at
+0.5*w. With that negation gone it now writes +0.5*w directly; keeping
the minus sign would park the screen at NDC -0.5, outside the clip
volume, discarding every 2D/HUD draw.
- stereo_replay.hpp backend_ndc_depth_row re-applied the correction to
the projection it was handed. That projection is effective_projection()
output, which now already carries it, so the function is a pass-through
of the Z row and no longer depends on the reversed-Z setting; the dead
bool parameter is dropped. Re-applying it would invert the virtual
screen's depth ordering, so 2D layers meant to sit on top would lose
the depth test to the ones behind them.
- shader_info.cpp stages the host depth window for that exact-depth path.
It now uses the same reversed-Z remap as upstream's new SetViewport
code, since frag_depth is written directly and has to reproduce the
window the fixed viewport transform would have applied. Restricted
depth windows (how the game forces an element in front of everything)
are exactly the 2D draws the virtual screen carries.
The SetViewport resolution keeps upstream's remap but retains the
ordering/clamp guard our version had: for any ordered guest range the
result is identical to upstream, and it avoids handing WebGPU
minDepth > maxDepth for the swapped pair MKW is known to emit. The VR eye
replay reuses these recorded values, so the guard covers that path too.
Test updates:
- stereo_replay_test now asserts the composed Z row against the staged
projection's own Z row rather than against the helper's output, so it
actually catches a re-introduced double correction (verified: it fails
when the old negation is put back; the previous self-consistent form
passed).
- gx_fifo_test's clearDepthValue expectation followed #134's deliberate
clear_depth_value() inversion, expressed through UseReversedZ rather
than hardcoded. Upstream changed the behaviour without updating this
test, so it fails on upstream/main as-is.
Verified: aurora suite 247 passed with the same 2 failures that already
fail on the pre-merge branch (IndexedPaletteHistoryKeepsAbsoluteVertexSlots,
PacksOneUniformWhenBothHalvesNeedInitialValue - both pre-existing, unrelated
to depth); shader.cpp and common.cpp compile clean; translator suite 577
passed. Not yet validated on-device in VR.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>