Skip to content

feat(studio): mouse-driven camera parallax (C3) - #21

Merged
ZuluYokohama merged 3 commits into
masterfrom
feat/camera-parallax
Jun 6, 2026
Merged

ZuluYokohama merged 3 commits into
masterfrom
feat/camera-parallax

Conversation

@ZuluYokohama

@ZuluYokohama ZuluYokohama commented Jun 6, 2026 •

Copy link
Copy Markdown
Collaborator

C3: Mouse → camera parallax (dependency-free)

Branch-target note: Fork has no dev branch; default is master. Internal fork PR → targets master.

Who is submitting this PR? (required)

Field Value
Your model + version Orchestration: Claude Opus 4.8 (claude-opus-4-8, 1M context). Implementation/review subagents: dispatched at the opus tier; the harness does not surface the exact minor version and cannot pin 4.7, so workers most likely ran on Opus 4.8. Disclosed honestly.
Harness + version Claude Code (CLI). Exact build/version not surfaced to the agent.
All plugins installed superpowers 5.1.0, plugin-dev, context7 (MCP). MCP servers: claude.ai Gmail / Google Calendar / Google Drive / Hugging Face.
Human partner who reviewed this diff b.jones@jtech.ai (ZuluYokohama)

What problem are you trying to solve?

The 3D scene was static — no response to the cursor. The R3F plan's Phase 2·Step 4 (mouse-coordinate → camera parallax for "buttery smooth AAA interaction") was the last unchecked task. The spec named framer-motion-3d, but it isn't installed and is largely unmaintained.

What does this PR change?

Adds dependency-free mouse→camera parallax: a pure parallax.ts (computeParallaxTarget scales the normalized pointer by an intensity; damp is frame-rate-independent exponential smoothing), applied in the existing MatrixScene useFrame to ease the camera toward the pointer and lookAt the dial. No new dependency — a 5-line useFrame rig replaces what framer-motion-3d would have added.

Is this change appropriate for the core library?

No. Fork-specific studio UI. Internal fork PR only.

What alternatives did you consider?

  • framer-motion-3d (named in the spec) — rejected: not installed, largely unmaintained, and a heavier dependency than the one-function damp needed. The dependency-free useFrame rig achieves the same parallax and is unit-testable.
  • Linear interpolation (lerp) by a fixed factor — rejected: frame-rate-dependent (faster at high fps). Exponential damp (1 - e^(-λ·dt)) is fps-independent — verified by a test asserting one dt step equals two dt/2 steps.
  • Translation-only parallax (no lookAt) — viable, but lookAt keeps the namesake dial framed/centered as the camera drifts, which reads better for a focal object.

Does this PR contain multiple unrelated changes?

No. One feature: camera parallax + its tested math.

Existing PRs

Environment tested

Harness Harness version Model Model version/ID
Claude Code (CLI) not surfaced to agent Claude Opus 4.8 orchestration; opus-tier subagents
  • npm test → 16 passed (4 parallax incl. fps-independence + negative-target no-overshoot, plus C1's 5 store + C2's 5 dial, + 2 added in review).
  • npm run build → Compiled successfully; npx tsc --noEmit → exit 0.
  • TDD: parallax-math test written first, observed RED (Failed to load url ../parallax) before implementation.
  • Note: live mouse parallax can't be observed headlessly on this host; the math is unit-tested and the camera wiring type-checks/builds. PARALLAX_INTENSITY is a named const (1.5) — trivially tunable lower if it reads too strong in-browser.

New harness support

N/A.

Evaluation

N/A for skill evals — UI feature. Functional: red→green TDD on the damp/parallax math; two independent reviews — spec compliance (swept lambda × dt to confirm no overshoot; verified C1+C2 byte-intact, no new deps) and code quality (confirmed the damp primitive matches three's MathUtils.damp; flagged magic numbers + a per-frame allocation + a missing fps-independence test, all since fixed — consts extracted, state.pointer passed directly, two invariants now tested).

Rigor

  • Skills change — N/A.
  • Tested adversarially — reviewers verified the damping math numerically (no overshoot incl. negative targets; fps-independence) from the code, not the report.
  • Did not modify behavior-shaping content.

Human review

  • A human has reviewed the COMPLETE proposed diff before submission.

Summary by CodeRabbit

Release Notes

  • New Features
    • Implemented interactive parallax camera system that dynamically responds to mouse and pointer movements, delivering enhanced visual depth perception and intuitive spatial awareness throughout interactions. The camera smoothly follows user input with frame-rate-independent motion smoothing, creating consistently fluid and responsive visual feedback across all frame rates and user interaction patterns with the scene.

…s-independence

- extract PARALLAX_INTENSITY/PARALLAX_LAMBDA/DIAL_Z (DIAL_Z shared with the dial group)
- pass state.pointer directly to drop a per-frame object alloc
- test no-overshoot toward a negative target and frame-rate independence
@coderabbitai

coderabbitai Bot commented Jun 6, 2026 •

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: be039a38-61a4-4019-85b2-53963ea441d7

📥 Commits

Reviewing files that changed from the base of the PR and between e1facfc and 9e9182c.

📒 Files selected for processing (3)
  • ui/studio/src/components/MatrixScene.tsx
  • ui/studio/src/lib/__tests__/parallax.test.ts
  • ui/studio/src/lib/parallax.ts

📝 Walkthrough

Walkthrough

A new parallax utility module provides Vec2, computeParallaxTarget, and frame-rate-independent damp functions. MatrixScene imports these, adds parallax tuning constants and a shared DIAL_Z depth constant, then applies pointer-driven camera parallax with exponential damping in its render loop.

Changes

Pointer-driven camera parallax

Layer / File(s) Summary
Parallax utility library and tests
ui/studio/src/lib/parallax.ts, ui/studio/src/lib/__tests__/parallax.test.ts
Vec2 interface, computeParallaxTarget (scales pointer by intensity), and damp (exponential smoothing) are defined and tested for correctness, convergence, non-overshoot behavior, and frame-rate independence.
MatrixScene camera parallax integration
ui/studio/src/components/MatrixScene.tsx
Parallax utilities are imported; tuning constants PARALLAX_INTENSITY and PARALLAX_LAMBDA, plus shared depth constant DIAL_Z, are defined. The render loop computes a damped camera offset target from pointer state and updates the camera's lookAt direction using DIAL_Z.

Possibly related PRs

  • ZuluYokohama/RotarySlider#20: Both PRs modify MatrixScene.tsx dial positioning—PR #20 introduces the dial group at z = -5, while this PR replaces that hardcoded value with the shared DIAL_Z constant.

Poem

🐰 Hop into the scene with pointer in paw,
Smooth damping makes cameras sway without flaw,
Constants aligned, and tests shining bright,
Parallax whispers—perspective just right! ✨

🎯 2 (Simple) | ⏱️ ~12 minutes

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely summarizes the main change: adding mouse-driven camera parallax to the studio UI, matching the primary feature in the changeset.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/camera-parallax

Comment @coderabbitai help to get the list of available commands and usage tips.

@ZuluYokohama
ZuluYokohama merged commit 67aa8d4 into master Jun 6, 2026
1 of 2 checks passed
@ZuluYokohama
ZuluYokohama deleted the feat/camera-parallax branch June 6, 2026 14:02
ZuluYokohama added a commit that referenced this pull request Jun 6, 2026
Check Phase 1.3/2.3/2.4 (C1 #18 / C2 #20 / C3 #21), correct the canvas/ path drift, uncheck Phase 4.1-4.3 (DOM components, not the 3D meshes described), record the C4 (#17) prerequisite. CodeRabbit: approved.
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.

2 participants