Trackpad indicator: hug the real (tilted) pad surface (#93)#98
Merged
Conversation
The Steam Controller touch dot rode a single flat plane — the pad's
axis-aligned bounding-box top plus a fixed Y lift — while the actual pad
surface is canted. The cant is baked into the mesh geometry (the GLB node
transform is identity), so the AABB top does not match the real surface:
measured against the shipped model, the `touchpad` pad tilts ~10.6° about X
and ~3.3° about Z, and the flat placement floats the dot up to ~3.2 mm off
the surface at the pad edge — exactly the reported "viewed from the side, the
circle hovers above the pad in a plane at a different angle."
Fix: raycast straight down (in the pad mesh's own frame, using its live world
matrix) onto the pad mesh to find the true surface point for the finger's
fractional position, then move the dot from its calibrated rest (pad-center)
position by that surface-space delta. This preserves the baked rest clearance
and makes the dot ride parallel to the real surface. It stays correct as gyro
rotates the whole model (the returned local point is rotation-invariant) and
falls back to the previous flat placement if a ray ever misses. Generalizes
the DualSense `_touchToLocal` raycast to the per-pad Steam Controller path, as
the prior TODO intended.
Sensitivity ("need to press for the circle to appear"): investigated and left
as-is. The dot already shows on any firmware-reported contact (area > 0), which
a real capture confirms is the most sensitive signal available — the touch bits
in the report track area>0 exactly (no lighter-touch capacitive bit) and the
signal doesn't flicker. A feather touch that never registers contact area is a
firmware/hardware floor the overlay can't lower; documented in a code comment.
Closes #93
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HwZjBdVgWqxqCoKkXsZnr4
🔎 PR #98 preview — torn downThis PR is closed; its web preview and desktop prerelease have been removed. |
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.
Summary
Closes #93. Two facets in the report; one is a real, fixed 3D bug, the other is a firmware limit I investigated and documented.
Alignment (fixed) — "the circle hovers above the pad in a plane at a different angle"
The Steam Controller touch dot rode a single flat plane: the pad mesh's axis-aligned bounding-box top plus a fixed Y lift. But the real pad surface is canted, and that tilt is baked into the mesh geometry (the GLB node transform is identity) — so the AABB top does not match the surface.
Measured against the shipped
steam-controller-split.glb:touchpadpad tilts ~10.6° about X and ~3.3° about ZFix: raycast straight down in the pad mesh's own frame (using its live world matrix) onto the pad mesh to get the true surface point for the finger position, then move the dot from its calibrated rest (pad-center) position by that surface-space delta. This preserves the baked rest clearance and makes the dot ride parallel to the real surface. It stays correct as gyro rotates the whole model (the returned local point is rotation-invariant), and falls back to the old flat placement if a ray ever misses. This generalizes the DualSense
_touchToLocalraycast to the per-pad SC path — what the priorTODO(trackpad contour)intended.Sensitivity (investigated, firmware-limited) — "need to press for the circle to appear"
The dot already appears on any firmware-reported contact (
area > 0). Verified against a real Puck capture:area > 0is the most sensitive available signal — the report's touch bits (byte 4 bit 1 left / byte 3 bits 5–6 right) trackarea > 0exactly (P ≈ 0when area is zero); there is no lighter-touch capacitive bit.A feather touch that never registers contact area is a firmware/hardware floor the overlay can't lower. Left the detection as-is and documented it in a code comment rather than adding a fake knob.
Verification (against real model + capture)
touchpadmesh from the GLB and raycast it: surface height varies 0.0107→0.0182 across the pad (tilt confirmed); old code pinned every dot to a constant y.node --checkpasses;packages/visualizertrackpad-math tests pass (5/5).Changes
packages/visualizer/src/controller-overlay.js— new_trackpadSurfaceLocal()raycast helper; per-pad surface-delta placement in_updateTrackpads; pad setup storesbbMaxY/thickness/centerSurface; replaced theTODO(trackpad contour); sensitivity note.🤖 Generated with Claude Code