Skip to content

feat(pancake): first-person WASD + mouse-look camera mode #242

Description

@bradleypmartin

First post-v1.0 sketch. Filed during the #238 cluster-cutout review session on 2026-05-17 as an aside; capturing here so the idea doesn't drift.

Motivation

The pancake experience today uses OrbitControls — drag-to-orbit around SURFACE_CENTER, scroll to zoom, soft min/max distance clamps to keep the user inside the cluster envelope. It works, but a first-person scheme (WASD translation + PointerLockControls mouse-look) would be worth offering as a mode: it more closely matches the "step into the museum exhibit and look around" framing the v1.0 staged-exhibit vocabulary (#221) is reaching for, and center-reticle aim + click is conceptually identical to VR controller-aim picking — so a first-person pancake unifies the cross-mode interaction model in a way OrbitControls structurally can't.

Why this is architecturally cheap

The v0.9 pancake work already put the right seams in place:

Estimated knee-jerk scope: a weekend of code plus iteration on the feel. PointerLockControls + WASD translation in the camera's local XZ plane + a FirstPersonPointer (screen-center ray, not cursor-screen ray) + Esc-to-release-lock handling + soft bounding-sphere clamp around the cluster envelope.

Open design questions (defer to plan-doc phase)

  • Default vs toggle. Whether FPS becomes the pancake default, the OrbitControls default stays put with FPS opt-in (?mode=fps), or both modes coexist with a runtime UI toggle. Audience-fit (APPM 2350 cohort) is the load-bearing input here and not pre-decided — could go either way.
  • Cluster envelope shape under WASD. OrbitControls' radial min/max-distance clamp doesn't translate to free movement; either soft bounding-sphere around SURFACE_CENTER, floor-extent clamp (now that StageFloor.outerHalfExtent is per-scene per feat(staging): apply StageFloor to tangent-planes / gradient-levels / saddle-extrema (cutout UX decision) #238), or something else entirely. Worth re-eyeballing once E1.2 railing (feat(staging): illusory railing around floor periphery #223) and E1.3 environment surround (feat(staging): environment surround — skybox + baked lighting + distant detail #224) define the visual "room boundary."
  • WASD relative to what. Camera-local horizontal motion (W = forward in camera-XZ-projected direction) is the standard FPS idiom; world-relative motion is the alternative if pedagogy benefits from "W always means +X math-frame" or similar. Lean: standard FPS.
  • Whether to support running / jump / crouch. Probably not — museum-walk pacing matches the math-exhibit framing. Documented out-of-scope until smoke proves otherwise.
  • Interaction with railing once it lands. Should the player be able to walk through the illusory railing (since it's illusory), or does the railing become a soft soft-wall clamp? Design call at the plan-doc phase.

Out of scope (initial)

  • Collision detection beyond a soft cluster-envelope clamp.
  • Stamina / sprint / jump / crouch.
  • Head bob, footstep audio, or anything that adds "game feel" beyond a museum-walk pace.
  • Mobile pancake-FPS — MobilePointer is touch-based; FPS-on-mobile is a separate UX problem (virtual joystick + tap-to-look). Out of scope for the initial pass; revisit if mobile usage warrants.
  • Replacing OrbitControls. Even if FPS becomes the default, OrbitControls stays as a mode — it's the strictly-better interaction for "I want to inspect this surface from outside" workflows.

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions