{
  "schemaVersion": 1,
  "id": "bookshelf-cascade",
  "version": "1.0.1",
  "status": "published",
  "kind": "object",
  "title": "Bookshelf Cascade",
  "summary": "Rows of cloth-bound books lean against one another in a slow domino wave along a bookcase. Loops perfectly.",
  "description": "A bookcase with shelves of cloth-bound books of every thickness and height, gold bands on their spines, and a slow wave of leaning running through them like a row of dominoes: one book tips against the next, which tips against the next, a ripple that runs along each shelf (the shelves running in opposite directions) before every book settles upright again. Choose the number of shelves and books, the cloth colours (library, pastel, mono or jewel), how far the books lean, the seed, the backdrop and whether the camera drifts.",
  "role": "Object (3D, three.js): a calm, satisfying domino-style object for reading, learning and knowledge content.",
  "collections": [
    "satisfying",
    "hypnotic-loops",
    "product-reveals"
  ],
  "tags": [
    "books",
    "bookshelf",
    "library",
    "domino",
    "wave",
    "cascade",
    "reading",
    "satisfying",
    "loop",
    "3d"
  ],
  "synonyms": [
    "book wave",
    "book domino",
    "bookcase",
    "library shelves",
    "falling books",
    "leaning books"
  ],
  "useCases": [
    "A library, education or reading-app title scene",
    "A domino-effect or chain-reaction metaphor",
    "A cosy study backdrop"
  ],
  "featured": null,
  "publishedAt": "2026-10-08",
  "implementation": {
    "target": "three",
    "runtime": "browser",
    "language": "javascript",
    "module": "esm",
    "entry": "src/bookshelf-cascade.js",
    "exports": [
      {
        "name": "createBookshelf",
        "signature": "createBookshelf({ shelves?, books?, palette?, lean?, seed? }) => { group, setProgress(progress), dispose() }",
        "description": "The case and its books (one instanced mesh) as a group, 12 wide, standing on y = 0; add it with an environment map and a shadow-casting light."
      },
      {
        "name": "PALETTES",
        "signature": "PALETTES: { library, pastel, mono, jewel }",
        "description": "Book cloth colours."
      }
    ],
    "reusable": [
      "src/bookshelf-cascade.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": "shelves",
      "label": "Shelves",
      "type": "integer",
      "min": 2,
      "max": 4,
      "step": 1,
      "default": 3
    },
    {
      "key": "books",
      "label": "Books per shelf",
      "type": "integer",
      "min": 8,
      "max": 24,
      "step": 1,
      "default": 16
    },
    {
      "key": "palette",
      "label": "Cloth",
      "type": "select",
      "default": "library",
      "options": [
        {
          "value": "library",
          "label": "Library"
        },
        {
          "value": "pastel",
          "label": "Pastel"
        },
        {
          "value": "mono",
          "label": "Black and white"
        },
        {
          "value": "jewel",
          "label": "Jewel"
        }
      ]
    },
    {
      "key": "lean",
      "label": "Lean",
      "type": "number",
      "min": 0.4,
      "max": 1.6,
      "step": 0.05,
      "default": 1
    },
    {
      "key": "seed",
      "label": "Seed",
      "type": "integer",
      "min": 1,
      "max": 999,
      "step": 1,
      "default": 4
    },
    {
      "key": "background",
      "label": "Backdrop",
      "type": "color",
      "default": "#2a1f18"
    },
    {
      "key": "orbit",
      "label": "Camera drift",
      "type": "boolean",
      "default": true
    }
  ],
  "presets": [
    {
      "id": "default",
      "label": "Library, three shelves",
      "params": {}
    },
    {
      "id": "pastel",
      "label": "Pastel, cheerful",
      "params": {
        "palette": "pastel",
        "seed": 9,
        "background": "#3a3040"
      }
    },
    {
      "id": "mono",
      "label": "Black and white",
      "params": {
        "palette": "mono",
        "lean": 1.3,
        "background": "#1c1c20"
      }
    },
    {
      "id": "jewel",
      "label": "Jewel tones, four shelves",
      "params": {
        "palette": "jewel",
        "shelves": 4,
        "books": 20,
        "seed": 14,
        "background": "#1a1e2a"
      }
    }
  ],
  "output": {
    "width": 1080,
    "height": 1080,
    "fps": 30,
    "durationSeconds": 16,
    "posterSeconds": 3,
    "alpha": false,
    "motion": "procedural",
    "loop": {
      "seamless": true,
      "cycleSeconds": 16,
      "method": "A smooth window of lean passes along each shelf once per loop; every book's tilt is a function of its position and the loop's phase only, so the last frame meets the first."
    },
    "seed": {
      "param": "seed",
      "behavior": "Seed picks every book's thickness, height, depth, colour and lean: same seed, same shelf."
    }
  },
  "composition": {
    "inputs": "Time within the loop; the shelves, books, cloth colours, lean, seed, backdrop and camera drift.",
    "outputs": "A full frame rendered in 3D with soft shadows and a studio environment.",
    "coordinates": "The case is 12 wide, each shelf 3.4 tall, standing on y = 0 with its back at z = -0.8; books tilt in the xy plane about their bottom corners.",
    "lighting": "A warm key light with a shadow map and the studio environment.",
    "timing": "setProgress(progress) sets every book; frames render in any order.",
    "compatibleWith": [
      "chrome-material",
      "orbit-camera",
      "kinetic-title",
      "number-reveal"
    ],
    "notes": [
      "Each book is a scaled box in one instanced mesh, coloured per instance and given gold bands by a shared spine map; its lean is a smoothstep window (up to 0.5 rad times the lean setting) that passes along its shelf in the shelf's direction."
    ]
  },
  "reuse": [
    "Library or reading-app title: Library, three shelves.",
    "Cheerful education loop: Pastel, cheerful.",
    "Chain-reaction metaphor: Black and white."
  ],
  "integration": {
    "newProject": "Create a WebGLRenderer with shadows and a studio environment (see chrome-material), add createBookshelf().group and call shelves.setProgress(progress) each frame.",
    "existingProject": "Copy src/bookshelf-cascade.js; add shelves.group to your scene with an environment map and a shadow-casting light."
  },
  "performance": {
    "notes": "One instanced mesh of up to 96 books and a few 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 books lean in a prescribed wave without collision: a leaning book may pass through its neighbour a little.",
    "Books are plain boxes with a shared spine pattern, with no readable titles."
  ],
  "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/bookshelf-cascade (MIT) and rebuilt for AI Pixel Wizard in October 2026 as an original object: seeded books on an instanced shelf, a closed-form domino lean wave in opposite directions per shelf 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."
    }
  ]
}
