threejs-procedural-animation skill (Threejs-Awesome-Graphics-Agent-Skills)
- Install
- SKILL.md (verbatim)
- Build order
- Non-negotiable rules
- Routing boundary
- Other files in this skill
- references/procedural-motion-and-docking-systems.md (verbatim)
- Contents
- State contract
- Piecewise launch kinematics
- Planet-relative gravity turn
- Camera-independent shake and roll
- Stage detachment
- Spin-docking timeline
- Docking-frame decomposition
- Spring convergence and terminal lock
- Peeling and released debris
- Frame-rate-independent response and orientation patterns
- Failure modes and diagnostics
What it does. Build advanced procedural animation in Three.js. Use for launch kinematics, gravity turns, staging, spin docking, target-frame decomposition, spring-follow motion, rotating-frame alignment, peeling debris, analytic transform timelines, frame-rate-independent response, and quaternion control. 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-procedural-animation/SKILL.md |
| License | MIT |
| Author | Scott Sun (scottstts) |
| Fetched | 2026-09-10 |
Install
npx skills add scottstts/Threejs-Awesome-Graphics-Agent-Skills --skill threejs-procedural-animation, or copy the skill folder into~/.claude/skills/threejs-procedural-animation/.- Raw file:
curl -sL https://raw.githubusercontent.com/scottstts/Threejs-Awesome-Graphics-Agent-Skills/HEAD/skills/threejs-procedural-animation/SKILL.md
SKILL.md (verbatim)
name: threejs-procedural-animation
description: Build advanced procedural animation in Three.js. Use for launch kinematics, gravity turns, staging, spin docking, target-frame decomposition, spring-follow motion, rotating-frame alignment, peeling debris, analytic transform timelines, frame-rate-independent response, and quaternion control.
Procedural Animation
Animate semantic state, not unrelated transform curves. Define phases, coordinate frames, velocities, and ownership before writing per-frame updates.
Build order
- Define the timeline phases and event boundaries.
- Choose the frame for each motion: world, subject local, orbital radial, docking axis, or camera shot.
- Derive target position/orientation from that frame.
- Use analytic kinematics for authored travel and springs for responsive convergence.
- Preserve world transforms when detaching children from a hierarchy.
- Separate translation, alignment, spin, and secondary debris state.
- Clamp integration delta and reset every state variable on replay/disposal.
Read references/procedural-motion-and-docking-systems.md for the launch, staging, docking, debris, spring, quaternion, and frame-rate-independent response implementations.
Non-negotiable rules
- Use elapsed seconds and
deltaSeconds; do not make motion frame-count based. - Derive orientation from direction/frame, then apply roll or spin as a separate quaternion.
- Decompose docking error into axial and radial components.
- Switch from spring convergence to an exact terminal pose at the end of a sequence.
- When reparenting an animated object, capture world position, quaternion, and scale before removal.
- Use seeded randomness when motion must be reproducible.
- Keep visual shake in a bounded envelope and separate it from trajectory.
Routing boundary
Use $threejs-camera-direction for shot composition and camera handoffs.
Use $threejs-procedural-vfx when the deliverable is primarily plasma, sparks,
or effect pooling rather than object transform motion.
Other files in this skill
references/procedural-motion-and-docking-systems.md (verbatim)
Procedural motion and docking systems
Use this reference for phase-based launch, staging, docking, spring, rotating-frame, detachment, and debris motion with explicit coordinate frames and terminal states.
Contents
- State contract
- Piecewise launch kinematics
- Planet-relative gravity turn
- Camera-independent shake and roll
- Stage detachment
- Spin-docking timeline
- Docking-frame decomposition
- Spring convergence and terminal lock
- Peeling and released debris
- Frame-rate-independent response and orientation patterns
- Failure modes and diagnostics
State contract
Use explicit persistent state:
type ProceduralAnimationState = {
elapsedSeconds: number
phase: string
position: THREE.Vector3
velocity: THREE.Vector3
baseQuaternion: THREE.Quaternion
spinAngle: number
angularVelocity: THREE.Vector3
eventFlags: Record<string, boolean>
}
Keep scratch vectors/quaternions outside the state. Reset all persistent values when restarting the sequence.
Piecewise launch kinematics
The authored launch timeline uses:
ignition hold = 1.2 s
ascent = 24 s
slow phase = 5 s
acceleration phase = 11 s
deceleration phase = 8 s
slow distance fraction = 0.00035
coast linear = 1.2 s
terminal deceleration = 4 s
computeAscentKinematics() solves a normalized distance curve whose position
and speed remain continuous across all three ascent phases.
For slow phase:
speed = slowDistance / slowDuration
distance = speed * t
Solve acceleration so total normalized distance reaches one after the acceleration and deceleration phases:
remaining = 1 - slowDistance
accel =
(
remaining
- slowSpeed * (accelDuration + 0.5 * decelDuration)
)
/
(
0.5 * accelDuration * (accelDuration + decelDuration)
)
peakSpeed = slowSpeed + accel * accelDuration
decel = peakSpeed / decelDuration
Then integrate each phase analytically. Do not approximate this authored timeline by repeatedly lerping position toward an endpoint.
Planet-relative gravity turn
The launch maps normalized distance to:
altitude = ascentProgress * targetOrbitAltitude + coastDistance * coastRate
groundArcDistance =
ascentProgress^1.22 * maxGroundArcDistance * turnBlend
+ coastDistance * groundTrackRate
arcAngle = groundArcDistance / planetRadius
Motion constants:
target altitude = 420 km in scene scale
max ground arc = 2200 km
max crossrange = 26 km
Construct:
radial = normalize(0, cos(arcAngle), -sin(arcAngle))
tangent = normalize(0, -sin(arcAngle), -cos(arcAngle))
position = planetCenter + radial * (planetRadius + altitude)
position.x += crossrange
Orientation:
flightDirection = normalize(lerp(radial, tangent, gravityTurn * 0.9))
base = quaternionFromUnitVectors(rocketLocalUp, flightDirection)
roll = quaternionAround(flightDirection, rollAmount)
orientation = base * roll
This separates trajectory direction from authored roll/vibration.
Camera-independent shake and roll
Rocket roll:
shake envelope = 1 - smoothstep(0.05, 0.9, ascentProgress)
vibration =
(
sin(time * 52)
+ sin(time * 31 + 0.7)
)
* 0.0024
* envelope
roll =
sin(time * 2.5) * 0.008 * envelope
+ vibration
The camera has a separate early launch shake envelope and offset. Keep object vibration and camera shake separate so either can be disabled for diagnostics.
Stage detachment
Before reparenting stage one:
capture world position
capture world quaternion
capture world scale
remove from rocket
add to scene
restore captured world transform
The detached stage immediately receives readable separation:
along offset = -3.4 m
side offset = 4.2 m
earthward offset = 1.2 m
along speed = -5.2 m/s
side speed = 5.8 m/s
earthward speed = 4.2 m/s
It then integrates separate along, side, and earthward scalar velocities. A short kick phase blends into growing lag accelerations.
For the first 2 s, orientation slerps from the captured quaternion to a
random 10–30° tilt. Afterward, it integrates a bounded spin rate
0.06–0.15 rad/s.
The side direction is chosen relative to the camera so separation reads in the shot. That is a presentation-aware choice, not a physical rule.
Spin-docking timeline
Docking phases:
station spin = 3.15 rad/s
chaser spin-up = 6.5 s
approach starts = 4.0 s
approach duration = 14.5 s
dock settle = 3.0 s
post-dock spin-down = 3.0 s
dock axial clearance = 4.1
dock radial offset = 0.35
Every phase uses a named smoothstepRange(start, end, time). The sequence does
not hide all timing in one normalized zero-to-one value.
Station spin state:
currentSpinRate = lerp(3.15, 0, spinDownT)
spinAngle += currentSpinRate * dt
orientation = baseOrientation * rotation(localForward, spinAngle)
The docking frame is recomputed from the newly rotated station every frame.
Docking-frame decomposition
At approach start:
offset = chaserPosition - dockPort
parallel = dot(offset, dockAxis)
radialVector = offset - dockAxis * parallel
radialDistance = length(radialVector)
radialDirection = normalize(radialVector)
Target during approach:
parallelApproach =
lerp(startParallel, dockClearance, approachT)
parallel =
lerp(parallelApproach, dockClearance, dockT)
radialApproach =
lerp(startRadial, dockRadialOffset, approachT)
radial =
lerp(radialApproach, 0, dockT)
radial = lerp(radial, 0, spinDownT)
target =
dockPort
+ dockAxis * parallel
+ radialDirection * radial
This preserves a readable approach corridor while progressively removing lateral error.
Spring convergence and terminal lock
The chaser position follows the target through a vector spring:
acceleration =
(target - current) * stiffness
- velocity * damping
velocity += acceleration * dt
current += velocity * dt
Stiffness increases from 5.0 to 9.8; damping from 4.6 to 7.4 as docking
settles.
Orientation aligns local up to negative docking axis, then applies spin around the docking axis:
alignment = quaternionFromUnitVectors(localUp, -dockAxis)
spin = quaternionAround(dockAxis, chaserSpinAngle)
orientation = spin * alignment
Near completed docking, position receives a final lerp toward target. After
spin-down reaches 0.995, copy target exactly and zero velocity. A spring alone
can retain imperceptible but destabilizing residual motion.
Peeling and released debris
Debris shed from the spinning station hull has two states.
Attached peel:
peelT = smoothstep(peelStart, detachTime, sequenceTime)
peelDistance = maxDistance * peelT^2
position = shipTransform(localAnchor + outward * peelDistance)
orientation = shipOrientation * localBase * peelTwist
At release, velocity inherits rotating-frame tangential velocity:
angularVelocityOfShip =
dockAxis * currentSpinRate
tangentialVelocity =
cross(angularVelocityOfShip, worldOffsetFromShip)
velocity =
tangentialVelocity
+ outward * outwardSpeed
+ axis * axialSpeed
Released debris then integrates linear velocity and quaternion rotation from
its angular-velocity vector. Speed is capped at 95.
This rotating-frame inheritance is the defining mechanism. Random outward velocity alone would not match the spinning hull.
Frame-rate-independent response and orientation patterns
Use frame-rate-independent exponential response:
alpha = 1 - exp(-lambda * dt)
value = lerp(value, target, alpha)
Use it for camera blends, side-camera forward, effect intensities, color response, and control state.
Ship orientation control separates desired forward/up from angular physics. Quaternion targets are converted to angular error; damping acts on angular velocity. This keeps user control and rigid-body response distinct.
For bounded camera lag, use a second-order spring with critical-like damping ratios rather than exponential interpolation. Choose exponential response for perceptual parameter smoothing and a spring when velocity/inertia is part of the motion.
Failure modes and diagnostics
Observed boundaries:
- Stage-detachment randomness uses
Math.random; seed it for replay and regression. - Semi-implicit springs need a clamped
dt, especially after tab suspension. - The launch path is authored for one planet scale and shot duration.
- Camera-relative separation is intentionally cinematic rather than physical.
- Repeated quaternion multiplication should normalize periodically.
- Timeline phase constants are coupled; changing one duration requires recomputing later event boundaries.
Expose:
sequence time and current phase
analytic position/speed curve
radial, tangent, and flight-direction vectors
base orientation, roll, and final orientation
stage world transform before/after reparent
detached scalar offsets/velocities
dock port, axis, parallel error, and radial error
spring target, velocity, stiffness, and damping
spin rates and accumulated angles
debris inherited tangential/outward/axial velocity
terminal lock state
Back to scottstts/Threejs-Awesome-Graphics-Agent-Skills or Agent skills.