{
  "schemaVersion": 1,
  "id": "domino-spiral",
  "version": "1.0.0",
  "status": "published",
  "kind": "object",
  "title": "Domino Spiral",
  "summary": "Hundreds of coloured dominoes in an expanding spiral topple in a chain reaction out along the spiral, then stand back up. Loops perfectly.",
  "description": "A few hundred dominoes stand on a studio floor in a spiral that spreads from the centre. One tips the next and a wave of falling runs all the way out along the spiral, each domino leaning on its neighbour; then the wave runs back and stands every domino up again. Choose the number of dominoes, the colours (rainbow, sunset, ocean or mono), the spacing, how many times the wave runs out and back per loop, the backdrop colour and whether the camera sways.",
  "role": "Object (3D, three.js): the most satisfying chain reaction there is, as a calm looping scene.",
  "collections": [
    "satisfying",
    "bouncing-falling",
    "hypnotic-loops"
  ],
  "tags": [
    "dominoes",
    "domino spiral",
    "chain reaction",
    "toppling",
    "satisfying",
    "spiral",
    "game",
    "studio",
    "loop",
    "3d"
  ],
  "synonyms": [
    "domino toppling",
    "domino chain",
    "falling dominoes",
    "domino effect",
    "domino run",
    "dominos"
  ],
  "useCases": [
    "A satisfying loop or a cause-and-effect explainer",
    "A game or toy brand scene",
    "A hypnotic backdrop with a travelling wave"
  ],
  "featured": null,
  "publishedAt": "2026-10-06",
  "implementation": {
    "target": "three",
    "runtime": "browser",
    "language": "javascript",
    "module": "esm",
    "entry": "src/domino-spiral.js",
    "exports": [
      {
        "name": "createDominoSpiral",
        "signature": "createDominoSpiral({ count?, palette?, gap?, turns? }) => { group, setProgress(progress), dispose() }",
        "description": "The dominoes as one instanced mesh in a spiral about 14 across, resting on y = 0; needs an environment map."
      },
      {
        "name": "PALETTES",
        "signature": "PALETTES: { rainbow, sunset, ocean, mono }",
        "description": "Colour schemes along the spiral."
      }
    ],
    "reusable": [
      "src/domino-spiral.js"
    ],
    "demo": "demo.js",
    "harness": "index.html"
  },
  "dependencies": [
    {
      "id": "three",
      "version": "0.185.1",
      "reason": "Renderer, geometry and shader 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."
    }
  ],
  "params": [
    {
      "key": "count",
      "label": "Dominoes",
      "type": "integer",
      "min": 120,
      "max": 480,
      "step": 10,
      "default": 320
    },
    {
      "key": "palette",
      "label": "Colours",
      "type": "select",
      "default": "rainbow",
      "options": [
        {
          "value": "rainbow",
          "label": "Rainbow"
        },
        {
          "value": "sunset",
          "label": "Sunset"
        },
        {
          "value": "ocean",
          "label": "Ocean"
        },
        {
          "value": "mono",
          "label": "Mono"
        }
      ]
    },
    {
      "key": "gap",
      "label": "Spacing",
      "type": "number",
      "min": 0.7,
      "max": 1.4,
      "step": 0.05,
      "default": 1
    },
    {
      "key": "waves",
      "label": "Waves per loop",
      "type": "integer",
      "min": 1,
      "max": 3,
      "step": 1,
      "default": 1
    },
    {
      "key": "background",
      "label": "Backdrop",
      "type": "color",
      "default": "#202633"
    },
    {
      "key": "orbit",
      "label": "Camera sway",
      "type": "boolean",
      "default": true
    }
  ],
  "presets": [
    {
      "id": "default",
      "label": "Rainbow, one wave",
      "params": {}
    },
    {
      "id": "sunset",
      "label": "Sunset, dense",
      "params": {
        "palette": "sunset",
        "count": 420,
        "gap": 0.8,
        "background": "#2a1a22"
      }
    },
    {
      "id": "ocean",
      "label": "Ocean, two waves",
      "params": {
        "palette": "ocean",
        "waves": 2,
        "background": "#102030"
      }
    },
    {
      "id": "mono",
      "label": "White, sparse",
      "params": {
        "palette": "mono",
        "count": 200,
        "gap": 1.3,
        "background": "#2a2f3a"
      }
    }
  ],
  "output": {
    "width": 1080,
    "height": 1080,
    "fps": 30,
    "durationSeconds": 16,
    "posterSeconds": 5,
    "alpha": false,
    "motion": "procedural",
    "loop": {
      "seamless": true,
      "cycleSeconds": 16,
      "method": "The wave of falling runs out along the spiral and a wave of standing up runs back, each domino's tilt a function of when the wave reaches it, and the camera sway is a sine of the loop, so the last frame meets the first."
    },
    "seed": null
  },
  "composition": {
    "inputs": "Time within the loop; the count, colours, spacing, waves per loop, backdrop and camera sway.",
    "outputs": "A full frame rendered in 3D with a studio environment.",
    "coordinates": "The spiral is centred on the origin on y = 0, starting about 1.2 from the centre and spreading outward; the camera looks down at about 54°.",
    "lighting": "A warm key light with a shadow map, a shadow-catching floor and the studio environment.",
    "timing": "setProgress(progress) sets every domino's tilt from the wave position; frames render in any order.",
    "compatibleWith": [
      "chrome-material",
      "orbit-camera",
      "kinetic-title",
      "number-reveal"
    ],
    "notes": [
      "Dominoes are one instanced mesh with a pip texture multiplied by the instance colour."
    ]
  },
  "reuse": [
    "Satisfying loop: Rainbow, one wave.",
    "Warm mood: Sunset, dense.",
    "Calm: Ocean, two waves."
  ],
  "integration": {
    "newProject": "Create a WebGLRenderer with a studio environment and a shadow-casting light, add createDominoSpiral().group over a floor and call dominoes.setProgress(progress) each frame.",
    "existingProject": "Copy src/domino-spiral.js; add the group to your scene with an environment map."
  },
  "performance": {
    "notes": "One instanced draw call of up to 480 boxes with a shadow map; under a millisecond a frame on an integrated Intel GPU.",
    "limits": "Software WebGL renders in about a second a frame."
  },
  "limitations": [
    "Nothing is simulated: each domino leans on the next in a fixed pose and neighbours may intersect slightly.",
    "Pips are the same on every domino."
  ],
  "license": {
    "spdx": "MIT",
    "notice": "Copyright (c) 2026 AI Pixel Wizard. Released under the MIT License. See LICENSE in this folder.",
    "thirdParty": []
  },
  "provenance": "Adapted from the owner's threejs-sketches/objects-scenes/domino-spiral (MIT) and rebuilt for AI Pixel Wizard in October 2026 as an original studio object: dominoes at equal arc-length along an Archimedean spiral with a closed-form topple-and-restore wave on an exact loop.",
  "changelog": [
    {
      "version": "1.0.0",
      "date": "2026-10-05",
      "notes": "Initial release."
    }
  ]
}
