Skip to content

Trackpad indicator: hug the real (tilted) pad surface (#93)#98

Merged
petegordon merged 1 commit into
mainfrom
fix/93-trackpad-dot-surface-align
Jul 2, 2026
Merged

Trackpad indicator: hug the real (tilted) pad surface (#93)#98
petegordon merged 1 commit into
mainfrom
fix/93-trackpad-dot-surface-align

Conversation

@petegordon

Copy link
Copy Markdown
Member

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:

  • the touchpad pad tilts ~10.6° about X and ~3.3° about Z
  • the old flat placement floats the dot up to ~3.2 mm off the surface at the pad edge — the "different angle / hovering above" the user saw from the side.

Fix: 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 _touchToLocal raycast to the per-pad SC path — what the prior TODO(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 > 0 is the most sensitive available signal — the report's touch bits (byte 4 bit 1 left / byte 3 bits 5–6 right) track area > 0 exactly (P ≈ 0 when area is zero); there is no lighter-touch capacitive bit.
  • the touch signal is a clean continuous run with no sub-18 ms dropouts, so hysteresis wouldn't help.

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)

  • Built the actual touchpad mesh 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.
  • Simulated the full fix path (including gyro yaw/pitch/roll on the parent): dot rides parallel to the surface with clearance error ~1e-18, rotation-invariant.
  • node --check passes; packages/visualizer trackpad-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 stores bbMaxY/thickness/centerSurface; replaced the TODO(trackpad contour); sensitivity note.

🤖 Generated with Claude Code

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
@github-actions

github-actions Bot commented Jul 2, 2026

Copy link
Copy Markdown

🔎 PR #98 preview — torn down

This PR is closed; its web preview and desktop prerelease have been removed.

@petegordon petegordon merged commit 2ec0352 into main Jul 2, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Trackpad dot touch indicator

1 participant