Fix XrNavigation NaN rig corruption on gamepads without thumbstick axes#8850
Merged
Conversation
XrNavigation reads thumbstick input from gamepad.axes[2]/[3] (the WebXR xr-standard mapping). Apple Vision Pro hand-tracking input sources expose a gamepad with an empty axes array, so those reads return undefined and -undefined is NaN. The smooth-turn guard 'Math.abs(turn) <= threshold' does not catch NaN (NaN comparisons are always false), so the NaN flowed into rotateLocal and corrupted the camera rig transform to NaN permanently. Splats still submitted but projected to NaN, leaving the scene blank in VR on AVP while head tracking worked. Controller headsets (Quest) report real axes and were unaffected. Skip input sources whose gamepad does not expose thumbstick axes (axes.length < 4) in handleSmoothLocomotion and handleSnapVertical.
6a33e1d to
3015d48
Compare
mvaligursky
added a commit
that referenced
this pull request
Jun 5, 2026
…es (#8850) XrNavigation reads thumbstick input from gamepad.axes[2]/[3] (the WebXR xr-standard mapping). Apple Vision Pro hand-tracking input sources expose a gamepad with an empty axes array, so those reads return undefined and -undefined is NaN. The smooth-turn guard 'Math.abs(turn) <= threshold' does not catch NaN (NaN comparisons are always false), so the NaN flowed into rotateLocal and corrupted the camera rig transform to NaN permanently. Splats still submitted but projected to NaN, leaving the scene blank in VR on AVP while head tracking worked. Controller headsets (Quest) report real axes and were unaffected. Skip input sources whose gamepad does not expose thumbstick axes (axes.length < 4) in handleSmoothLocomotion and handleSnapVertical. Co-authored-by: Martin Valigursky <mvaligursky@snapchat.com>
ilimtvtr-alt
approved these changes
Jun 5, 2026
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.
Entering VR on Apple Vision Pro left the scene blank (only the camera clear color visible) while head tracking worked. The camera rig transform was being corrupted to NaN on the second XR frame.
Cause:
XrNavigation reads thumbstick input from
gamepad.axes[2]/[3](the WebXR xr-standard mapping). AVP hand-tracking input sources expose a gamepad with an empty axes array, so those reads returnundefinedand-undefinedisNaN.The visible corruption was specific to
turnMode: 'smooth'— its guardMath.abs(turn) <= thresholddoes not catch NaN (NaN comparisons are always false), so the NaN flowed intorotateLocaland corrupted the rig — and its child camera — to NaN permanently. Splats still submitted but projected to NaN, so nothing rasterized.This was not a problem in the general case: the snap-turn path (
Math.abs(rotate) > threshold) and smooth locomotion (length() > threshold) gate on conditions that are correctly false for NaN, so they were already inert with absent axes — they just never moved. Only the smooth-turn polarity let NaN through. Controller-based headsets (Quest) report realaxes[2] = 0and were unaffected regardless of turn mode.Changes:
axes.length < 4) inhandleSmoothLocomotion(covers locomotion and both turn modes) andhandleSnapVertical.On hand-tracking-only devices, thumbstick locomotion/turning is now cleanly inert (there is no thumbstick to drive it) rather than corrupting the rig. Devices with conformant xr-standard gamepads report 4 axes and are unchanged.