Commit Graph
18 Commits
Author SHA1 Message Date
Madison 0b636ed5b6 Show the body in vehicles, its hands on the controls (headset-unverified)
In a seat seen from it (vr.vehicle_view "first_person"), vr.body now draws
the player's body as the game seats it, with only the head and neck taken
away: its own animation has the hands on the Warthog's wheel (turning with
the steering), on the turret's handles, on the Banshee's controls. The
view rides at its head, so its shoulders sat inside the near plane, cut
into flat shards across the view: the chest and all on it go back 12 cm
and down 4 cm (along the way the body faces, from its shoulders, so a
gunner's follows the turret), each arm reaches from its moved shoulder to
where the animation had its hand, elbow bent as before, and the hands are
put back as animated.

Dumps on the device, driver and gunner of a Warthog (b30) and a Banshee's
pilot (b40), looking down: the arms reach the wheel, handles and controls,
the chest and legs below, the shoulder shards gone but for a small flap at
the view's lower corner.
2026-10-04 00:06:47 +09:00
Madison 6eaf8e92e5 Mask each eye's hidden area, and time the GPU's frame from timestamps
At 1.5x the GPU needed 11.5 ms a frame (timestamps, vr.timing_gpu_stamps),
over 90 Hz's 11.1, almost all of it the eyes' pixels. The runtime's
visibility mask (XR_KHR_visibility_mask, 15.6% of each eye's image on the
Frame) is now drawn first in each eye's pass at the near plane, black, so
the scene is not shaded there (vr.visibility_mask, on). Two things it took:
the device binds its target and viewport lazily, so the mask binds the
eye's first (halo_vr_bind_current_target); and its depth goes through the
position, not gl_FragDepth, which turned Adreno's early depth culling off
for the rest of the pass (it saved 0.3 ms that way, 1.5 ms this way).

On the device in a30 at 1.5x: the GPU's frame from 11.5 to 10.0 ms (the
eyes 4.4/5.1 to 3.6/4.1), 85.5 fps with 45 misses in 10 s to 89.4 with 2
to 5. Cutscenes (the 3D screen, not masked) hold 78 to 89.

Also: vr.timing_gpu_passes (each pass waited for; Zink's glFinish costs
too much for it to mean much), glQueryCounterEXT and
glGetQueryObjectui64vEXT for the guest, the mask's share logged.
2026-10-03 21:49:13 +09:00
Madison a93462a29e Offer the body as legs or torso, chosen in the VR settings (headset-unverified)
vr.body is now "off", "legs" (the hips down: all above the spine scaled
away, set 5 cm behind the eyes) or "torso" (the chest down, 10 cm behind
and 15 cm below, as before), and BODY on the VR settings' second page sets
it, taking effect at once. Looking down, the legs alone have nothing near
the eyes (no shards, no collar), though from above the hips' top hides
much of the legs; the torso shows the chest armour and a dark collar.
Dumps only: which reads better worn is for the player.
2026-10-03 20:33:01 +09:00
Madison abad4d7352 Draw the player's own legs and torso in VR, behind vr.body (headset-unverified)
Halo draws no body of the player's own in first person. With vr.body
"legs" (off by default) the eyes' passes draw the player's unit, on foot
and outside cutscenes, from a copy of its bones' matrices: the head, neck
and upper arms (and all under them) scaled away, the body turned to the
head's yaw (as the first-person shoulders now are) and moved under the
head, 12 cm behind the eyes. What the unit carries (its third-person
weapon) is not drawn with it, nor is its shadow. The body's bone names are
logged once, with which are hidden. The head-yaw direction is now shared
with the shoulders (vr_head_yaw_forward). Built only; not yet run.
2026-10-03 20:04:06 +09:00
Madison 3cfa297bde Put both eyes and the quad in one swapchain, acquired once a frame
SteamVR's GL binding makes its own context current for every swapchain
acquire, wait and release (and the game's again after), each a flush,
fences and trace markers in Zink: on the device they were a fifth of the
game thread's cycles. The eyes and the quad (HUD or flat screen) are now
parts of one atlas swapchain, acquired by whichever part comes first and
released as the frame ends; the layers take their parts' rectangles
(halo_xr_info.x, .y). Every layer shown is still drawn the frame it is
shown, as a new image of the atlas is each frame's.

On the device at 90 Hz and 1.0x: a30 play from 10.3 to 7.8-9.9 ms of CPU
a frame, 84-90 to 87-90 fps; a10's opening cutscene at 89-90 fps. Dumps of
a stereo frame (eyes, HUD) and a cutscene frame (the 3D screen's eyes)
show each part where it belongs.
2026-10-03 13:46:09 +09:00
Madison e3a9ce6248 Document sfvr, the turn settings, the settings pages and the perf line (headset-unverified) 2026-10-02 18:17:14 +09:00
Madison 6c031d3024 Document the system layer, quit, settings version and the 72 Hz fallback (headset-unverified)
docs/VR_ARCHITECTURE.md: the View system layer (short press, 1 s, 3 s) and
what a recentre does, the Touch and Index fallbacks, QUIT TO STEAM, the
settings file's version, migration and ranges, the display rate request and
its automatic fall back to 72 Hz (which the doc did not mention), the nine
host imports, and status rows for each of these marked not yet run on the
device, with the standard's items still to do.
2026-10-02 18:07:10 +09:00
Madison 7bbb9ccdc1 Add vr.hud_mode: far, near and leash HUD panels (headset-unverified)
far keeps the HUD as it was (15 m, 10 m wide, head-locked, drawn from the
head). near brings it to 1.5 m, 1.1 m wide (40 degrees), in LOCAL space at
the head's place turned by its yaw and pitch but not its roll. leash holds
that panel level in the room, following the head's position, and eases it
(about 0.3 s) to the head's yaw only once the head is 25 degrees off it;
a recentre or a return from a flat screen puts it ahead again.

vr.hud_distance and vr.hud_width now default to 0, the mode's own, and
override it when above 0. The HUD pass is drawn from the head's place
turned as the panel is (vr_hud_view), with bounds from the same distance
and width in every mode, and the menus' pointer meets the panel where it
is. Documented in docs/VR_ARCHITECTURE.md.
2026-10-02 18:02:18 +09:00
MadisonandClaude Opus 5.5 cff675537d VR settings in the pause menu (untested on device)
When a level's tags load, the VR build adds widget tags cloned from the
solo pause menu's (same font, colours, buttons and boxes): a fifth item,
VR SETTINGS, in the pause list (its button hints move under the mission
objectives to make room), and a screen of nine settings in two columns -
controls, aim, gun hand, turning, room-scale, scope, vehicle view,
steering and cutscenes. A or right steps a setting on, left back, B
returns to the pause menu; the laser pointer clicks them too.

Changes are written into config.toml (config_write_real/_string join
config_write_boolean) and the VR layer takes them up at once
(vr_reload_settings). cache_file_add_tag adds tags made in memory after
a map's own; the buttons' text and changes come through a new game data
input function and two event handler functions.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 17:03:30 +09:00
MadisonandClaude Opus 5.5 b5c6ae2a9b Walk the player by walking the room (untested on device)
vr.roomscale (off by default, after the PC mod HaloCEVR's) moves the
player's collision pill each tick by how far the head walked from where
they stand, through collision_move_pill so walls stop or slide it as
walking does. The eyes lean from that standing place blended between its
last two ticks, as the game's camera is, so walking adds no latency and
no judder at the 30 Hz ticks. Vehicles, cutscenes, scripted holds,
death and network games pause it; a jump of over 0.5 m in a tick is
taken up without moving. vr.diag_walk_speed walks the synthetic head for
unattended checks.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 16:48:28 +09:00
MadisonandClaude Opus 5.5 e45cf2a637 Point at the menus with the weapon hand (untested on device)
The hand's aim drives the menus' mouse pointer (halo_ui_pointer_update),
on the flat screen or, for the pause menu in stereo, the HUD's panel.
The trigger clicks, the right B goes back, and a dot on the reticle's
layer marks the spot. After the PC mod HaloCEVR's menu pointer.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 16:35:31 +09:00
MadisonandClaude Opus 5.5 b3fd4c345f Float the HUD far off, drawn from the head (untested on device)
The HUD panel defaults to 15 m away and 10 m wide (about 37 degrees, as
the PC mod HaloCEVR's), so the eyes need not refocus between it and the
world. Its pass is drawn from the head's camera with frustum bounds
matching the panel, so nav points and friends' names sit over what they
mark rather than following the hand's aim. The motion sensor turns with
the head too.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 16:33:32 +09:00
MadisonandClaude Opus 5.5 b70ff4cfca Show a zoom in a scope held at the gun (untested on device)
While a hand-aimed weapon is zoomed, a pass between the eyes and the HUD
renders the view along the gun into a corner of the back buffer, sized
to the scope's 768x768 image. It goes through a sight mask (round, or
the sniper rifle's wide one) onto a layer held at the gun, at the PC
mod HaloCEVR's per-weapon offsets. The eyes never zoom: the first-person
gun stays in the hand and the HUD layer drops the zoom mask.

vr.scope and vr.scope_size are the settings; vr.diag_zoom_seconds zooms
unattended for dumps (vr-scope.bmp). The docs now cover the VR controls,
gestures, weapon feel and scope, and credit LivingFray's HaloCEVR for
their designs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 16:31:34 +09:00
MadisonandClaude Opus 5.5 7c0adfc6d0 Vehicles in first person, steered by the stick (untested on device)
vr.vehicle_view "first_person" (the default) has the director treat every
seat as first person, which hides the player's body, and puts the eyes at
the player's head in the seat (a seat's camera marker is where the chase
camera sits). The view turns with the vehicle's yaw only, the horizon
kept level; a passenger seat facing aside keeps its turn from the
vehicle. The player's own gun is put away in driver and gunner seats.

vr.vehicle_steering "stick" (the default) leaves a driver's facing to the
game, so the right stick steers (and pitches the Banshee) as on a flat
screen while the head only looks; "head" and "hand" steer where you look
or point. Gunners aim with the head relative to the vehicle, so a turret
follows the head without turning the view.

vr.diag_drive_seconds seats the player as the nearest vehicle's driver,
for unattended checks (after cheat_all_vehicles). The headset went
offline before the first vehicle test ran; the build is warning-clean.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 13:25:19 +09:00
MadisonandClaude Opus 5.5 972e17d78b Launch from the Steam library; the refresh rate follows the headset
The build is registered on the Frame as a Lepton devkit title, HaloCEVR,
which deploy.sh keeps up to date, so the game starts from the Steam
library without the Mac. SteamVR offers an app only the rate its display
setting is on, so vr.refresh_rate takes the highest offered at or below
it; the docs say where to set 90 Hz.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 11:49:08 +09:00
MadisonandClaude Opus 5.5 deeba33887 Bring the VR status and measuring notes up to date
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 11:41:03 +09:00
MadisonandClaude Opus 5.5 ff7365b5d5 Package the OpenXR loader with the VR build only
It is staged in build/android/jniLibs-vr, which only the vr flavour
packages, instead of beside the flat build's libraries.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 09:35:43 +09:00
MadisonandClaude Opus 5.5 c928948b05 Document the VR build's architecture and status
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 09:29:29 +09:00