{
  "schema": "leumas.docs.page/1",
  "id": "pkg:@leumas/body-viewer",
  "slug": "packages/body-viewer",
  "kind": "capabilities",
  "bucket": "package",
  "title": "@leumas/body-viewer",
  "name": "@leumas/body-viewer",
  "eyebrow": null,
  "chip": null,
  "summary": "The generic 3D body viewer — a React/r3f surface that renders ANY species' model manifest, with the layer system, the selection model, isolate/ghost/clip, camera presets and the closed visual-command...",
  "keywords": [
    "body-viewer",
    "ghost",
    "clip",
    "viewer",
    "presets",
    "leumas body viewer",
    "executor",
    "species"
  ],
  "audience": "both",
  "funnel": {
    "product": null,
    "cta": null
  },
  "body": "# @leumas/body-viewer\n\nThe generic 3D body surface. It takes a loaded body and a model manifest and draws whatever they\ndescribe — grep it for `human`, `heart`, `skeletal` or `bone` and you find none of them.\n\n```jsx\nconst Viewer = lazy(() => import('@leumas/body-viewer'));   // three + fiber + drei: ALWAYS lazy\n\nconst store = createViewerStore({ species: 'human', variant: 'adult-female' });\n<BodyViewer body={body} manifest={body.manifests[body.variant.modelManifest]} store={store} />\n<LayerPanel body={body} store={store} />\n```\n\n## The two rules\n\n**1. A `THREE.Mesh` is never application truth.** Selection, visibility, opacity and isolation are\nsets of canonical structure ids. The scene is a function of them. That is what makes the tree, the\ngraph, the 3D and an agent's command interchangeable — all four read and write the same ids — and it\nis why a variant switch cannot leave a highlight pointing at geometry that is no longer the structure\nit names.\n\n**2. The command list is closed.** `applyCommand` is a trust boundary: the command is generated by a\nmodel, relayed through a tool result, and executed in a browser. Anything outside `VISUAL_ACTIONS` is\nrefused **by name**, no command in this package reads or writes anything but view state, and an id\nthat does not exist in the body is **reported** rather than silently dropped.\n\n## Import it lazily\n\n`three`, `@react-three/fiber` and `@react-three/drei` are peers, and both Leumas products' eager JS is\nbudgeted at ~300 KB. `./store` and `./commands` are three-free subpaths, so a panel that only reads\nthe selection — or an agent bridge that only applies a command — never touches WebGL.\n\n## What is in it\n\n| | |\n|---|---|\n| `store.js` | the canonical viewer state, as an external store (`useSyncExternalStore`) |\n| `commands.js` | the closed visual-action executor + lesson-step → command mapping |\n| `BodyViewer.jsx` | the r3f scene, selection, hover, clipping, the camera-nonce driver |\n| `LayerPanel.jsx` | layers, colour mode, peel, ghost, cross-section, camera presets |\n| `palette.js` | six colour schemes, keyed by slug so an unknown species is still legible |\n| `geometry.js` | placements → drawable instances, the primitive vocabulary, the shared geometry cache, explode offsets |\n| `batches.js` | **pure** — grouping into InstancedMeshes, slot assignment, the confidence fade. No `three`, no React |\n| `InstancedBody.jsx` | the InstancedMeshes, the per-frame pick loop, the colour/alpha/matrix writes |\n\n## It draws the WHOLE body, in about sixty draw calls\n\nOne React component and one `THREE.Mesh` per structure is fine for the ~100 a body plan places by\nhand and ruinous for the ~6,500 a species slice contains. Every distinct shape is now two\nInstancedMeshes — opaque and transparent — and an instance moves between them with a zero-scale\nmatrix rather than a scene-graph rebuild.\n\nThe slot-to-structure mapping lives in `batches.js`, away from the renderer, because getting it wrong\nby one renders a complete, plausible body at sixty frames a second in which clicking the liver selects\nthe spleen. `test/instancing.test.js` shuffles the input and asserts every slot still resolves.\n\n**Only an `authored` placement gets a rich primitive.** A derived one gets a generic proxy sized from\nits category, because we know roughly where it is and nothing at all about its shape — and a\nconvincingly-shaped organ nobody has evidence for is the exact failure the schematic approach exists\nto refuse. It is also the performance answer: the cache holds ~100 rich buffers plus a couple of dozen\nproxies rather than 6,500 distinct meshes.\n\n## Three traps it already handles\n\n- **`visibleSystems: null` means ALL, not none.** The first \"hide one layer\" click resolves it against\n  the full system list; treating null as empty turns one click into a blank viewer.\n- **The camera moves on a NONCE, not on a value.** Reacting to `view` or `focusIds` directly means\n  every unrelated re-render re-applies the last camera intent, and the user's orbit snaps back to the\n  front whenever anything else updates.\n- **Shared geometry must not be disposed by a component teardown.** Same rule as `@leumas/body-3d`:\n  `disposeShapeCache()` is process-wide and is the only sanctioned way to free it.\n\nPlus three more that arrived with instancing, all guarded by `check:body`:\n\n- **Never `vertexColors` on an instanced material.** `setColorAt` already defines\n  `USE_INSTANCING_COLOR`; adding `USE_COLOR` makes the shader multiply by a per-vertex attribute the\n  geometry lacks and every instance renders black — with a correct palette and a correct buffer.\n- **Null `boundingSphere` after every matrix write.** three computes an InstancedMesh's sphere lazily\n  on the first raycast and never again, so a stale one culls the whole mesh and picking silently stops\n  working for everything.\n- **Inject per-instance alpha AFTER `#include <clipping_planes_fragment>`.** The cross-section discards\n  there; patching earlier multiplies alpha into pixels about to be thrown away.\n\n## Prove it\n\n```sh\npnpm --filter @leumas/body-viewer test   # 13 tests, no browser, no WebGL\n```\n\nThe store and the executor are plain JavaScript, and every viewer failure a user actually notices\nlives in one of them.\n",
  "source": {
    "path": "shared/packages/body-viewer/README.md",
    "blobSha": "",
    "commit": "",
    "committedAt": "",
    "provenance": "no-git",
    "bytes": 5505,
    "hash": "61106a718f619acf56329f3361d3188460720472"
  },
  "urls": {
    "html": "/p/packages/body-viewer",
    "json": "/docs/packages/body-viewer.json",
    "md": "/docs/packages/body-viewer.md"
  },
  "links": {
    "composes": [
      "pkg:@leumas/body"
    ],
    "usedBy": [
      "pkg:@leumas/studio"
    ],
    "product": [
      "pkg:@leumas/studio"
    ],
    "howTo": [],
    "skills": [
      "skill:leumas-body"
    ]
  },
  "exports": {
    "total": 72,
    "component": 22,
    "hook": 4,
    "helper": 46,
    "names": [
      {
        "n": "BodyViewer",
        "k": "component"
      },
      {
        "n": "BundleLoader",
        "k": "component"
      },
      {
        "n": "CATEGORY_COLORS",
        "k": "component"
      },
      {
        "n": "COLOR_MODES",
        "k": "component"
      },
      {
        "n": "COLOR_MODES",
        "k": "component"
      },
      {
        "n": "DEFAULT_HIDDEN_SLUGS",
        "k": "component"
      },
      {
        "n": "DEFAULT_HIDDEN_SLUGS",
        "k": "component"
      },
      {
        "n": "DETAIL_LEVELS",
        "k": "component"
      },
      {
        "n": "DETAIL_LEVELS",
        "k": "component"
      },
      {
        "n": "EMPTY_SET",
        "k": "component"
      },
      {
        "n": "InstancedBody",
        "k": "component"
      },
      {
        "n": "LayerPanel",
        "k": "component"
      },
      {
        "n": "LayerPanel",
        "k": "component"
      },
      {
        "n": "MATERIAL_IDS",
        "k": "component"
      },
      {
        "n": "MOUNT_CHUNK",
        "k": "component"
      },
      {
        "n": "MOUNT_FIRST_CHUNK",
        "k": "component"
      },
      {
        "n": "REALISTIC_COLORS",
        "k": "component"
      },
      {
        "n": "REVEAL_MODES",
        "k": "component"
      },
      {
        "n": "REVEAL_MODES",
        "k": "component"
      },
      {
        "n": "SYSTEM_COLORS",
        "k": "component"
      },
      {
        "n": "VIEWS",
        "k": "component"
      },
      {
        "n": "VIEWS",
        "k": "component"
      },
      {
        "n": "useViewerSelector",
        "k": "hook"
      },
      {
        "n": "useViewerSelector",
        "k": "hook"
      },
      {
        "n": "useViewerState",
        "k": "hook"
      },
      {
        "n": "useViewerState",
        "k": "hook"
      },
      {
        "n": "applyCommand",
        "k": "helper"
      },
      {
        "n": "applyCommand",
        "k": "helper"
      },
      {
        "n": "applyCommands",
        "k": "helper"
      },
      {
        "n": "applyCommands",
        "k": "helper"
      },
      {
        "n": "bundleGeometry",
        "k": "helper"
      },
      {
        "n": "bundleGeometry",
        "k": "helper"
      },
      {
        "n": "bundleReport",
        "k": "helper"
      },
      {
        "n": "bundleReport",
        "k": "helper"
      },
      {
        "n": "bundleRevision",
        "k": "helper"
      },
      {
        "n": "bundleRevision",
        "k": "helper"
      },
      {
        "n": "bundlesIn",
        "k": "helper"
      },
      {
        "n": "bundlesIn",
        "k": "helper"
      },
      {
        "n": "colorFor",
        "k": "helper"
      },
      {
        "n": "commandsForStep",
        "k": "helper"
      },
      {
        "n": "commandsForStep",
        "k": "helper"
      },
      {
        "n": "confidenceFade",
        "k": "helper"
      },
      {
        "n": "createViewerStore",
        "k": "helper"
      },
      {
        "n": "createViewerStore",
        "k": "helper"
      },
      {
        "n": "disposeBundles",
        "k": "helper"
      },
      {
        "n": "disposeBundles",
        "k": "helper"
      },
      {
        "n": "disposeShapeCache",
        "k": "helper"
      },
      {
        "n": "explodedPosition",
        "k": "helper"
      },
      {
        "n": "failBundle",
        "k": "helper"
      },
      {
        "n": "failBundle",
        "k": "helper"
      },
      {
        "n": "geometriesFrom",
        "k": "helper"
      },
      {
        "n": "geometriesFrom",
        "k": "helper"
      },
      {
        "n": "hasBundleMesh",
        "k": "helper"
      },
      {
        "n": "hasBundleMesh",
        "k": "helper"
      },
      {
        "n": "instancesFor",
        "k": "helper"
      },
      {
        "n": "isVisible",
        "k": "helper"
      },
      {
        "n": "isVisible",
        "k": "helper"
      },
      {
        "n": "materialFor",
        "k": "helper"
      },
      {
        "n": "materialProps",
        "k": "helper"
      },
      {
        "n": "mountOrder",
        "k": "helper"
      },
      {
        "n": "opacityFor",
        "k": "helper"
      },
      {
        "n": "opacityFor",
        "k": "helper"
      },
      {
        "n": "planBatches",
        "k": "helper"
      },
      {
        "n": "quantizeRadius",
        "k": "helper"
      },
      {
        "n": "registerBundle",
        "k": "helper"
      },
      {
        "n": "registerBundle",
        "k": "helper"
      },
      {
        "n": "resolveInstance",
        "k": "helper"
      },
      {
        "n": "shapeExtent",
        "k": "helper"
      },
      {
        "n": "shapeGeometry",
        "k": "helper"
      },
      {
        "n": "shapeKey",
        "k": "helper"
      },
      {
        "n": "simplify",
        "k": "helper"
      },
      {
        "n": "systemColor",
        "k": "helper"
      }
    ]
  }
}
