fix(oxr): 2D/mono locate must build the Kooima FOV from the CENTRE eye - #1148
Open
dfattal wants to merge 1 commit into
Open
fix(oxr): 2D/mono locate must build the Kooima FOV from the CENTRE eye#1148dfattal wants to merge 1 commit into
dfattal wants to merge 1 commit into
Conversation
In a single-view (2D) rendering mode xrLocateViews already sets XrView.pose to the centroid of the DP's eyes, but the FOV is taken verbatim from fovs[0] — the Kooima frustum built from adj_eyes[0], i.e. the LEFT eye's off-axis frustum. A centred pose paired with an off-axis frustum shifts the rendered image laterally: on a 235 mm panel at a 65 mm nominal IPD the frustum skew is 3.53 deg against a 13.17 deg half-FOV, i.e. tan(3.53)/ tan(13.17) = 27 % of the half width -> ~14 % of the canvas, to the left. The service path has collapsed the mono render input to the centre eye since #521/#575 (ipc_server_handler.c), so this only ever bit in-process sessions. It surfaced when displayxr-demo-modelviewer moved in-process on Android (its PR #97): the same app was correct over IPC and shifted left in-process, with the runtime unchanged. Generalise the existing legacy_app_tile_scaling-only centre override to every app whose ACTIVE mode has view_count == 1. DP-agnostic: a DP that already reports one centred eye in 2D (the Windows Leia SR path) makes the centroid that same eye, so this is a no-op there — which is why Windows never showed the bug. No change for view_count > 1, and the XR_DXR_view_rig raw channel is captured before this point, so the app's face-dot HUD still sees the DP's verbatim per-eye set. Measured on NP02J (nubia pad, in-process, iface=leia-cnsdk, runtime v1.21.1-785-g9c83df864, modelviewer probe debug.dxr.mv.viewprobe=1): 3D (LeiaSR, 2 views) view[0] pose=(-0.2365,0,3.6392) fov L=-9.648 R=16.699 hcen=+3.526 view[1] pose=(+0.2365,0,3.6392) fov L=-16.699 R=9.648 hcen=-3.526 2D (mono, 1 view) — BEFORE view[0] pose=( 0.0000,0,3.6392) fov L=-9.648 R=16.699 hcen=+3.526 ^ the LEFT eye's frustum on a centred pose Fixes DisplayXR/displayxr-demo-modelviewer#100 (runtime side)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
In a single-view (2D) rendering mode,
xrLocateViewssetsXrView.poseto the centroid of the DP's eyes (oxr_session.c:2724for the override path,:2746for the tracked path) but the FOV is taken verbatim fromfovs[0](:2797→:2803) — the Kooima frustum built fromadj_eyes[0], i.e. the left eye's off-axis frustum. A centred pose paired with an off-axis frustum shifts the rendered image laterally.The service path has collapsed the mono render input to a centred eye since #521/#575 (
ipc_server_handler.c:690-711and theactive_view_count == 1branch at:1507). The in-process path only did it for legacy apps (legacy_app_tile_scaling-gated block atoxr_session.c:2001-2022), so extension apps running in-process never got it.That is why this surfaced on Android now:
displayxr-demo-modelviewermoved in-process in its PR #97, and the same app that was correct over IPC started shifting left in-process — with the runtime unchanged. Windows never showed it because the Leia SR DP already reports a single centred eye in 2D, so the centroid is a no-op there.Evidence (NP02J, in-process,
iface=leia-cnsdk, runtimev1.21.1-785-g9c83df864)Numbers from a kill-switched probe in the demo (
setprop debug.dxr.mv.viewprobe 1);hcen=(angleLeft+angleRight)/2in degrees, i.e. the frustum's horizontal skew (0 = centred).rawEyes = 2andtracking = 0(nominal ±32.5 mm at z = 0.5 m) in both modes.Pose centroided ✔, FOV not ✘. Predicted shift:
tan(3.5256°)/tan(13.1735°) = 0.277of the half width → 13.8 % of the canvas to the left (~354 px of 2560). The on-device capture matches (model centre ≈ 0.53 of width in 3D, ≈ 0.33 in 2D).Fix
Generalise the legacy-only centre override to every app whose active mode has
view_count == 1, collapsingadj_eyes[]to their centroid before the Kooima compute, so pose and FOV are derived from the same eye.active_view_count > 1(per-eye off-axis frusta are the point of a 3D mode).XR_DXR_view_rigraw channel is captured before this point, sorawEyes[]still reports the DP's verbatim per-eye set (app face-dot HUDs unaffected).legacy_app_tile_scalingblock — legacy 2D apps reach the same centroid through the new gate, so their behaviour is unchanged.Testing
cmake -G Ninja -DBUILD_TESTING=ON+ninja) green;ctest23/23 pass../scripts/build-android.sh build debug) — not installed on any device.NOT tested: no on-device verification of the fixed runtime. The pad's runtime APK was deliberately left untouched (
v1.21.1-785-g9c83df864); the before-numbers above come from that stock runtime. Device verification of the after state needs a coordinated runtime swap on NP02J. Windows/macOS/Linux regression of 2D mode (expected no-op) also unverified on hardware.Fixes DisplayXR/displayxr-demo-modelviewer#100 (runtime side)