# Newton's Cradle — `newtons-cradle@1.0.0`

Polished balls on a walnut base: one swings in, one swings out, click after click. Loops perfectly.

The classic executive toy on a glossy black table in a dark studio: a row of polished balls hung on V-shaped strings from two chrome rails, on a bevelled walnut base with brass feet. The end ball swings up and strikes the row, the far ball takes the motion and swings out, falls back and strikes again, the middle balls standing still, and so on. The balls mirror the studio and are mirrored in the table. Choose the finish of the balls (chrome, gold, black chrome or copper), the number of balls, whether one or two are lifted, how wide the swing is, how many clicks per loop, and the wood of the base.

- Kind: object; status: published; digest sha256:3b445b06dc672622f2a4c5ac3ef8dc4575858af6ea5132262b8d9f7a9108f366
- Role: Hero object (Three.js 3D): a satisfying, hypnotic desk toy for loops, intros and metaphors of cause and effect.
- Implementation: three; entry `src/newtons-cradle.js`
- Files: https://aipixelwizard.com/registry/newtons-cradle/1.0.0/<path> (`LICENSE`, `asset.json`, `demo.js`, `index.html`, `src/newtons-cradle.js`)
- Manifest JSON: https://aipixelwizard.com/api/v1/visuals/newtons-cradle/versions/1.0.0
- Runnable demo: https://aipixelwizard.com/registry/newtons-cradle/1.0.0/index.html (open over http; it imports sibling packages by relative path)
- Dependencies (exact): `three@0.185.1` (source) — Renderer, geometry and physical metals.; `chrome-material@1.1.0` (demo) — Studio environment light and backdrop.; `apw-runtime@1.0.0` (demo) — Demo harness.

## Exports
- `createNewtonsCradle({ balls?, lift?, finish?, base?, amplitude?, seed?, anisotropy? }) => { group, height, count, update(time, loopSeconds, { cycles? }), dispose() }` — The cradle as a THREE.Group (1 unit = 10 cm, base on y = 0). update(time, loopSeconds) swings the balls; cycles is the number of whole cycles per loop.
- `cradleSwing(u) => { left, right }` — The swing of the end balls at a position u in the cycle, in units of the amplitude (−1 … 1).
- `FINISHES: { chrome, gold, black, copper }` — Finishes for the balls.
- `BASES: { walnut, maple, ebony }` — Finishes for the base.

## Parameters
- `finish` (select one of chrome | gold | black | copper, default "chrome") — Balls
- `balls` (integer 3–7, default 5) — Number of balls
- `lift` (integer 1–2, default 1) — Balls lifted
- `swing` (number 20–48, default 36) — Swing (degrees)
- `cycles` (integer 1–6, default 4) — Clicks per loop: Whole cycles of the swing in each loop.
- `base` (select one of walnut | maple | ebony, default "walnut") — Base
- `background` (color, default "#13151b") — Studio
- `seed` (integer 1–999, default 3) — Seed: Changes the wood grain.

## Composition
- Inputs: Time within the loop; the balls' finish and number, how many are lifted, the swing and the cycles per loop.
- Outputs: A THREE.Group: base, feet, rails, posts, strings and balls, standing on y = 0.
- Coordinates: 1 unit = 10 cm. The balls have a radius of 0.5 and touch at rest; the rails stand 6.75 above the base; strings run from rails 1.9 apart to the top of each ball.
- Lighting: Physical metals: needs scene.environment for the balls to mirror the room; a shadow-casting key light draws the strings' and balls' shadows on the base.
- Timing: update(time, loopSeconds, { cycles }) is a pure function of time; frames render in any order.
- Works with: chrome-material, orbit-camera, kinetic-title
- Each ball hangs from two strings, so it swings only in the plane of the row; the strings are taut at every angle.
- The demo's reflection is a second, upside-down cradle seen through a translucent table.

## Output and loop
- 1080×1080, 30 fps, 9.6 s, procedural
- Seamless loop: yes — The swing repeats a whole number of cycles per loop, and a cycle starts and ends with the near end ball at the top of its swing, so the last frame meets the first.
- Verified 2026-10-06 in Chrome 154.0.8037.97 headless on Linux 7.0.0-38-generic (x64), Node 22.14.0 (WebGL 2 via SwiftShader (software)); deterministic: yes; loop check: Frame 0 vs end state (progress 1): mean |Δ| 0.0000, max |Δ| 0 of 255.

## Use it
New project: Set scene.environment (createStudioEnvironment from Chrome Material works), add createNewtonsCradle().group and a shadow-casting light, and call update(time, loopSeconds, { cycles }) each frame.

Existing project: Copy src/newtons-cradle.js. Add the group to your scene, scale it, and call update(seconds, loopSeconds) every frame.

Reuse ideas:
- Satisfying loop: Chrome on walnut, camera drift on.
- Cause and effect: Gold on black with two lifted, behind a title about chain reactions.
- Desk scene: add the group to your own table and call update with your timeline.

## Limitations
- The swing is an idealised cycle (a cosine in the swinging ball, the middle balls perfectly still): no slow loss of energy, no jitter of the middle balls.
- Balls do not rotate: they are smooth, untextured spheres.

## License
MIT. Copyright (c) 2026 AI Pixel Wizard. Released under the MIT License. See LICENSE in this folder.
- three.js 0.185.1: MIT (https://github.com/mrdoob/three.js)

Provenance: Adapted from the owner's threejs-sketches/webgpu-newton-cradle (mechanical-kinetic, MIT), rebuilt for AI Pixel Wizard in October 2026: V-strung polished balls on a chrome frame and walnut base, a four-quarter swing that loops exactly, a mirrored table, studio light and shadows, and the frame/time contract.

