{"id":"ball-clock","version":"1.0.1","title":"Ball Clock","summary":"Steel balls roll down twin rails, round the bend and up again. Loops perfectly.","kind":"object","target":"three","collections":["satisfying","hypnotic-loops","product-reveals"],"tags":["ball clock","rolling balls","rails","kinetic","mechanical","clock","satisfying","marble run","loop","3d"],"loopable":true,"motion":"procedural","durationSeconds":16,"status":"published","media":{"poster":"https://aipixelwizard.com/media/ball-clock/1.0.1/poster.webp","preview":"https://aipixelwizard.com/media/ball-clock/1.0.1/preview.mp4","sample":"https://aipixelwizard.com/media/ball-clock/1.0.1/sample.mp4","sampleBytes":1343327,"sampleNote":"Pre-rendered with the default settings. Customised settings must be exported locally (npm run render)."},"urls":{"page":"https://aipixelwizard.com/visuals/ball-clock","manifest":"https://aipixelwizard.com/api/v1/visuals/ball-clock/versions/1.0.1","agentMd":"https://aipixelwizard.com/registry/ball-clock/1.0.1/agent.md","files":"https://aipixelwizard.com/registry/ball-clock/1.0.1/","demo":"https://aipixelwizard.com/registry/ball-clock/1.0.1/index.html"},"description":"A kinetic desk toy on a wooden board: steel balls roll one after another down a zig-zag of twin brass rails, gathering speed as they fall, drop round the bottom bend and are carried up the side to start again. The balls are spaced evenly round the closed track, so there is always a ball in every part of it. Choose the number of balls, the finish (steel, brass, copper, black), the board (walnut, oak, slate, white), how many laps a loop holds, the backdrop and whether the camera drifts.","role":"Object (3D, three.js): a hypnotic mechanical hero object for time, flow and rhythm content.","useCases":["A satisfying backdrop for time, flow and rhythm content","A desk-toy product-style loop","A title scene about cycles and continuity"],"synonyms":["rolling ball clock","ball run","marble track","kinetic sculpture","ball machine","ball track"],"digest":"cba86a29fc1035ad32d7de35f96b1c9907404c868f32e7a4d9f70b7c57c3e05b","implementation":{"target":"three","runtime":"browser","language":"javascript","module":"esm","entry":"src/ball-clock.js","exports":[{"name":"createBallClock","signature":"createBallClock({ balls?, metal?, board?, laps? }) => { group, setProgress(progress), dispose() }","description":"The board, rails and instanced balls as a group (8 wide, 9 tall, facing +z); add it with an environment map and a light."},{"name":"METALS","signature":"METALS: { steel, brass, copper, black }","description":"Ball finishes."}],"reusable":["src/ball-clock.js"],"demo":"demo.js","harness":"index.html"},"dependencies":[{"id":"three","version":"0.185.1","scope":"source","reason":"Renderer, geometry and physical materials."},{"id":"chrome-material","version":"1.1.0","scope":"demo","reason":"Studio environment light, backdrop and contact shadow."},{"id":"apw-runtime","version":"1.0.0","scope":"demo","reason":"Demo harness."}],"uses":[],"usedBy":[],"params":[{"key":"balls","label":"Balls","type":"integer","min":8,"max":24,"step":1,"default":14},{"key":"metal","label":"Balls","type":"select","default":"steel","options":[{"value":"steel","label":"Steel"},{"value":"brass","label":"Brass"},{"value":"copper","label":"Copper"},{"value":"black","label":"Black"}]},{"key":"board","label":"Board","type":"select","default":"walnut","options":[{"value":"walnut","label":"Walnut"},{"value":"oak","label":"Oak"},{"value":"slate","label":"Slate"},{"value":"white","label":"White"}]},{"key":"laps","label":"Laps","help":"Whole laps of the track each ball makes per loop.","type":"integer","min":1,"max":3,"step":1,"default":1},{"key":"background","label":"Backdrop","type":"color","default":"#1b2a3a"},{"key":"orbit","label":"Camera drift","type":"boolean","default":true}],"presets":[{"id":"default","label":"Steel balls, walnut","params":{}},{"id":"brass","label":"Brass balls, slate","params":{"metal":"brass","board":"slate","balls":18,"background":"#201a14"}},{"id":"copper","label":"Copper, white board","params":{"metal":"copper","board":"white","background":"#2a3a46"}},{"id":"fast","label":"Fast, three laps","params":{"laps":3,"balls":10,"metal":"black","board":"oak"}}],"output":{"width":1080,"height":1080,"fps":30,"durationSeconds":16,"posterSeconds":4,"alpha":false,"motion":"procedural","loop":{"seamless":true,"cycleSeconds":16,"method":"The balls are spaced evenly round a closed track and each makes a whole number of laps per loop, with a speed that depends only on its height, so the pattern returns exactly; the camera drift is a sine of the loop."},"seed":null},"composition":{"inputs":"Time within the loop; the balls, finish, board, laps, backdrop and camera drift.","outputs":"A full frame rendered in 3D with soft shadows and a studio environment.","coordinates":"The board is 9.4 × 10.4 in the xy plane facing +z, the track a closed spline inside it, .","lighting":"A key light with a shadow map and the studio environment on the polished balls and brass rails.","timing":"setProgress(progress) places every ball by table lookup; frames render in any order.","compatibleWith":["chrome-material","orbit-camera","kinetic-title","number-reveal"],"notes":["A ball's place is a table lookup on the track's cumulative travel time, where the speed grows as the ball falls (1.3 → 3.0) and is constant on the way up, so no simulation state is kept.","The balls roll: each turns by the arc length it has travelled."]},"reuse":["Time or flow title: Steel balls, walnut.","Luxury desk-toy loop: Brass balls, slate.","Cheerful product loop: Copper, white board."],"integration":{"newProject":"Create a WebGLRenderer with shadows and a studio environment (see chrome-material), add createBallClock().group and call clock.setProgress(progress) each frame.","existingProject":"Copy src/ball-clock.js; add clock.group to your scene with an environment map and a shadow-casting light."},"performance":{"notes":"About 14 instanced balls, two tube rails and a couple of boxes, one shadow map. A few milliseconds a frame on an integrated Intel GPU.","limits":"Software WebGL renders in about a second a frame."},"limitations":["The balls follow a prescribed speed, not a physical simulation: they never bunch up or collide.","There is no dial: the balls count nothing, they only circulate."],"license":{"spdx":"MIT","notice":"Copyright (c) 2026 AI Pixel Wizard. Released under the MIT License. See LICENSE in this folder.","thirdParty":[]},"rights":{"approvedForPublicRelease":true},"provenance":"Adapted from the owner's threejs-sketches/mechanical-kinetic/ball-clock (MIT) and rebuilt for AI Pixel Wizard in October 2026 as an original object: evenly spaced balls on a closed twin-rail track with a fall-speed table, rolling rotation and an exact loop.","changelog":[{"version":"1.0.1","date":"2026-10-08","notes":"Instanced meshes are no longer culled using their first-frame bounds, so nothing can vanish when parts move far from where the first frame left them. No visual change."},{"version":"1.0.0","date":"2026-10-05","notes":"Initial release."}],"verification":{"testedOn":"2026-10-08","inputs":{"ball-clock@1.0.1":"cba86a29fc1035ad32d7de35f96b1c9907404c868f32e7a4d9f70b7c57c3e05b","three@0.185.1":"664ca387e5fab46ff2daaa6895e1d015426850891af5ea5082cbbcc3985b068c","chrome-material@1.1.0":"ecb41776bfc1ee88997604f916a5ffe833f971d7edcc97c855697a5792d6f1dd","apw-runtime@1.0.0":"5be859cdac74823ba0bcc32c6daf06688a871104d24db5d4ceaffffd84d7c40d"},"environment":"Chrome 154.0.8037.97 headless on Linux 7.0.0-38-generic (x64), Node 22.14.0","renderer":"WebGL 2 via SwiftShader (software)","width":1080,"height":1080,"fps":30,"frames":480,"renderSeconds":1329.1,"loopCheck":{"checked":true,"seamless":true,"maxDifference":0,"note":"Frame 0 vs end state (progress 1): mean |Δ| 0.0000, max |Δ| 0 of 255."},"determinism":{"checked":true,"identical":true},"errors":[],"media":{"poster":"/media/ball-clock/1.0.1/poster.webp","preview":"/media/ball-clock/1.0.1/preview.mp4","sample":"/media/ball-clock/1.0.1/sample.mp4","sampleBytes":1343327}},"files":[{"path":"LICENSE","size":1072,"sha256":"8a5f3a96f07e11522ec4bdd0a583356f99bad1245920f9709cee09b995a45153","contentType":"text/plain; charset=utf-8","url":"https://aipixelwizard.com/registry/ball-clock/1.0.1/LICENSE"},{"path":"asset.json","size":8051,"sha256":"5666bc6c75e1602e418cc623ed4e0fb58567c586ba12baad88e20cc683b92821","contentType":"application/json; charset=utf-8","url":"https://aipixelwizard.com/registry/ball-clock/1.0.1/asset.json"},{"path":"demo.js","size":2851,"sha256":"dcb6c32be5555370d55a24dc69248d30124df1072ae979682fa491f42e06c608","contentType":"text/javascript; charset=utf-8","url":"https://aipixelwizard.com/registry/ball-clock/1.0.1/demo.js"},{"path":"index.html","size":524,"sha256":"39fd8ff787d86324500cb2e47f6c97793c7186b138718a0b25f6a687bddcf474","contentType":"text/html; charset=utf-8","url":"https://aipixelwizard.com/registry/ball-clock/1.0.1/index.html"},{"path":"src/ball-clock.js","size":5481,"sha256":"39fbd3f1f80fe1f931b048f3df4ae2661081527644f9b27363321c10f6aa14f4","contentType":"text/javascript; charset=utf-8","url":"https://aipixelwizard.com/registry/ball-clock/1.0.1/src/ball-clock.js"}],"warnings":[]}