threejs-camera-direction skill (Threejs-Awesome-Graphics-Agent-Skills)
- Install
- SKILL.md (verbatim)
- Build order
- Non-negotiable rules
- Routing boundary
- Other files in this skill
- references/camera-rig-and-cinematic-systems.md (verbatim)
- Contents
- Camera contract
- Ship-scaled chase mount
- Thrust-lag spring
- Side and orbit camera
- Explicit camera handoffs
- Cinematic shot ownership
- Pointer-look and movement constraints
- Floating origin and background handling
- Projection and lifecycle ownership
- Failure modes and diagnostics
What it does. Direct advanced Three.js camera systems. Use for scale-aware chase rigs, thrust lag, side/orbit cameras, body-relative up vectors, quaternion handoffs, authored cinematic framing, floating origins, pointer-look controls, camera collision constraints, projection ownership, and lifecycle restoration. Part of scottstts/Threejs-Awesome-Graphics-Agent-Skills (scottstts/Threejs-Awesome-Graphics-Agent-Skills).
| Upstream | scottstts/Threejs-Awesome-Graphics-Agent-Skills |
| Skill file | skills/threejs-camera-direction/SKILL.md |
| License | MIT |
| Author | Scott Sun (scottstts) |
| Fetched | 2026-09-10 |
Install
npx skills add scottstts/Threejs-Awesome-Graphics-Agent-Skills --skill threejs-camera-direction, or copy the skill folder into~/.claude/skills/threejs-camera-direction/.- Raw file:
curl -sL https://raw.githubusercontent.com/scottstts/Threejs-Awesome-Graphics-Agent-Skills/HEAD/skills/threejs-camera-direction/SKILL.md
SKILL.md (verbatim)
name: threejs-camera-direction
description: Direct advanced Three.js camera systems. Use for scale-aware chase rigs, thrust lag, side/orbit cameras, body-relative up vectors, quaternion handoffs, authored cinematic framing, floating origins, pointer-look controls, camera collision constraints, projection ownership, and lifecycle restoration.
Camera Direction
Treat the camera as an authored visual system, not a passive viewport. Compose the subject, establish scale, choose a stable up frame, and make every mode handoff explicit.
Build order
- Define the design frame: subject size, screen occupancy, lens, near/far, motion, and horizon/up convention.
- Build camera targets in semantic frames: ship, body surface, docking axis, or scene-authored shot.
- Derive position and orientation independently, then combine them once.
- Add input orbit/look only inside declared yaw/pitch and spatial constraints.
- Add frame-rate-independent follow or a bounded spring where the reference uses inertia.
- Snapshot and restore camera projection/state when a scene owns it.
- Test mode transitions, cuts, pointer-lock reacquisition, resize, and large coordinates.
Read references/camera-rig-and-cinematic-systems.md for exact chase/side/orbit rigs, projection values, transition rules, floating-origin shot, pointer controls, and implementation limits.
Non-negotiable rules
- Use subject dimensions to derive offsets; do not tune one fixed distance for differently scaled assets.
- For planetary motion, derive up from the dominant body rather than global Y.
- Interpolate position with
lerpand orientation withslerp. - During an explicit handoff, use one interpolation stage. Do not stack a transition blend and a second follow smoother over the same interval.
- Re-sync yaw/pitch from the camera when pointer lock is acquired.
- Update the projection matrix whenever FOV, near, far, or aspect changes.
- Keep stars or infinite backgrounds camera-relative when large translation would create false parallax or precision loss.
- Restore camera and input ownership on scene disposal.
Routing boundary
Use $threejs-procedural-animation for object motion timelines, springs,
docking, staging, and debris. This skill owns how the scene is viewed and how
camera modes hand off.
Other files in this skill
references/camera-rig-and-cinematic-systems.md (verbatim)
Camera rig and cinematic systems
Use this reference for scale-aware chase, side, orbit, authored-shot, pointer-look, floating-origin, projection, and lifecycle camera systems. It defines two systems: a planetary flight rig (chase, side, and orbit cameras around large bodies) and an authored cinematic shot system.
Contents
- Camera contract
- Ship-scaled chase mount
- Thrust-lag spring
- Side and orbit camera
- Explicit camera handoffs
- Cinematic shot ownership
- Pointer-look and movement constraints
- Floating origin and background handling
- Projection and lifecycle ownership
- Failure modes and diagnostics
Camera contract
Record before implementation:
type CameraDirectionContract = {
subject: THREE.Object3D
subjectScale: number
projection: { fov: number; near: number; far: number }
positionMode: "authored" | "mount" | "body-relative" | "floating-origin"
upMode: "world" | "subject" | "dominant-body"
inputMode: "locked" | "pointer-look" | "orbit-offset"
handoffOwner: string
spatialConstraints: string[]
}
Do not combine modes until each can produce a valid position and quaternion independently.
Ship-scaled chase mount
CameraRigSystem derives the chase mount from ship length:
height = shipLength * 0.5
back = shipLength * 1.3
mount position = (0, height, -back)
look target:
up = shipLength * 0.0001
forward = shipLength * 0.35
It constructs a basis:
forward = normalize(target - mount)
right = normalize(cross(worldUp, forward))
up = normalize(cross(forward, right))
quaternion = quaternion(makeBasis(right, up, forward))
quaternion *= rotation(worldUp, π)
The final π correction is model-convention specific. Verify the camera’s
local forward convention before retaining it.
The mount is parented to ShipRoot, so its world position/quaternion follows
the ship without recomputing the authored chase pose.
Thrust-lag spring
The chase rig adds camera distance behind the ship only while manual thrust is active. Throttle and boost own separate scalar spring states:
throttle max = 3.8
boost max = 5.8
combined max = 8.2
drive acceleration:
throttle 12
boost 22.8
held stiffness:
throttle 6
boost 7.5
return stiffness = 34
held damping ratio = 1.04
return damping ratio = 1.30
Per component:
damping = 2 * dampingRatio * sqrt(stiffness)
acceleration =
activeDrive
- stiffness * distance
- damping * velocity
velocity += acceleration * dt
distance += velocity * dt
distance = clamp(distance, 0, maxDistance)
If clamping blocks velocity in the same direction, zero it. Apply total lag along negative ship forward after reading the chase mount’s world pose.
This gives acceleration weight without adding camera rotation lag.
Side and orbit camera
Scale-aware offsets after the ship model loads:
side = (
shipLength * 3.2,
shipLength * 1.0,
-shipLength * 1.35
)
orbit = (
shipLength * 4.85,
shipLength * 1.35,
-shipLength * 2.15
)
The camera uses the dominant-body radial vector as up:
bodyUp = normalize(shipPosition - bodyPosition)
For orbit lock, forward comes from relative velocity; otherwise it comes from ship orientation. Project forward onto the body tangent plane:
tangent = forward - bodyUp * dot(forward, bodyUp)
Frame-rate-independent smoothing:
side forward response = 1 - exp(-6.5 * dt)
offset response = 1 - exp(-3.6 * dt)
mode blend lambda = 3.2
Rebuild an orthonormal frame:
right = normalize(cross(bodyUp, tangent))
tangent = normalize(cross(right, bodyUp))
offset =
right * offset.x
+ bodyUp * offset.y
+ tangent * offset.z
Yaw rotates the offset around bodyUp. Pitch rotates around
cross(bodyUp, offset). Pointer input scales:
yaw -= mouseDeltaX * 0.0022
pitch -= mouseDeltaY * 0.0018
Pitch bounds vary by flight mode. The implementation also enforces camera height above the ship:
landed minimum = shipLength * 0.42
other side-camera minimum = shipLength * 0.20
If tangent becomes nearly parallel to up (abs(dot) > 0.985), rebuild it from
cross(bodyUp, worldUp) and then X as a final fallback.
Look target:
target = bodyUp * shipLength * 0.12
quaternion = lookAt(cameraPosition, target, bodyUp)
This camera is positioned in ship-root-local coordinates. Preserve that coordinate ownership when adapting the rig.
Explicit camera handoffs
The rig captures position and quaternion at transition start. Launch handoff
begins at progress 0.68; orbit-exit duration varies from 1.1 to 2.6
seconds based on the current side-camera blend.
Ease:
eased = 1 - (1 - t)^1.8
position = lerp(startPosition, chasePosition, eased)
orientation = slerp(startQuaternion, chaseQuaternion, eased)
Critical transition invariant:
explicit transition active
-> write camera directly from one lerp/slerp
-> return from camera update
Do not apply the normal follow smoother after this interpolation. Stacked smoothing causes a mid-transition half-halt.
Outside explicit transitions, the final chase/side pose is followed with:
lambda 9.5 while side blend is active/transitioning
lambda 18 when pure chase
At effectively zero blend, copy the chase pose exactly to prevent a permanent subpixel tail.
Cinematic shot ownership
Each cinematic scene owns its shot and projection values, for example:
gas-giant approach:
FOV 40
near 12
far 360000
spin docking:
FOV 46
near 35
far 90000
Scenes save prior FOV/near/far, update the projection, and restore all three on dispose.
The spin-docking shot uses authored world anchors:
camera position = (6878.606, 4914.173, 6141.678)
look target = (6301.714, 4779.175, 5336.091)
Ships are then staged in the camera frame:
forward = normalize(lookTarget - cameraPosition)
right = normalize(cross(forward, worldUp))
up = normalize(cross(right, forward))
staging center = cameraPosition + forward * 340
Subject offsets are expressed in this shot basis. This is more robust than tuning independent world coordinates after the camera is framed.
The launch shot instead hard-anchors to a rocket-relative orbit target every frame. It intentionally avoids follow lag against a rapidly accelerating subject.
Pointer-look and movement constraints
PointerLookControls uses Euler order YXZ, clamps pitch to
±(π/2 - 0.01), and re-syncs yaw/pitch from the current camera quaternion
whenever pointer lock is acquired.
Movement:
forward = camera world direction
right = normalize(cross(forward, worldUp))
distance = movementSpeed * dt
Default speed is 9, sensitivity 0.0023.
Keys are cleared on:
- pointer-lock exit;
- window blur;
- any update while unlocked.
Scene-specific constraints then run after controls:
- An interior room scene clamps X/Y/Z with floor, ceiling, and wall clearance.
- A terrain-walk scene clamps camera Y above sampled terrain plus
0.2. - cinematic scenes block movement keys while retaining their authored camera.
Input control and spatial constraint are separate layers.
Floating origin and background handling
The gas-giant approach scene first computes a virtual camera pose, stores its orientation basis, then:
camera position = origin
planet group position = -virtualCameraPosition
atmosphere center uniform = planet group position
stars position = camera position
The ship flyby is animated in the stored camera basis. This preserves the authored composition while avoiding enormous camera coordinates.
Stars are tethered to the camera in multiple scenes to remove deep-space parallax and prevent them from crossing the far envelope.
Projection and lifecycle ownership
The flight rig’s global camera uses:
FOV 38
near 0.2
far 3.0e7
It prewarms pipelines by temporarily aiming at representative bodies, then
restores both position and quaternion in finally.
The cinematic scene manager:
dispose active scene
clear scene-root children
create next scene
await init
Every scene that changes projection or background restores it on disposal. This ownership prevents one shot’s lens from leaking into another.
Failure modes and diagnostics
Observed boundaries:
- The thrust-lag scalar spring is semi-implicit Euler; clamp
dtduring long frame stalls. - The chase mount’s final 180-degree correction depends on model conventions.
- Side-camera local/world ownership is easy to break when adapting the ship hierarchy.
- Authored cinematic world coordinates are scene-specific; preserve the camera-frame staging method, not literal positions.
- Hard camera anchoring is correct for launch composition but unsuitable when inertial camera feel is the goal.
- Global-Y pointer movement is not valid for walking on a spherical planet.
Expose:
camera mode and owner
design-frame guides and subject screen bounds
camera local basis
body-up/tangent/right vectors
chase mount and thrust-lag distance/velocity
side/orbit target pose and blend
handoff start, target, t, and easing
FOV/near/far and depth precision
constraint contacts
floating-origin offset
camera-relative background state
Back to scottstts/Threejs-Awesome-Graphics-Agent-Skills or Agent skills.