# Constructing scenes by hand and by instructions

Open **Builder** (`/builder.html`) or **Scene Factory** (`/factory.html`) in Tracker
Desk. These are working authoring prototypes, using the same original masonry and
material generators as the existing worlds. The **Arcade** entry (`/arcade.html`)
opens the library's exact interactive arcade specimen.

## Build visually

Builder starts with a small generated passage. Add an arcade, column, wall, floor
or plinth. Select a part by clicking its geometry in Edit / Orbit or by choosing it
from the scene list. Drag the coloured axis handles to move it, snapped to .25 units.

The inspector exposes X/Y/Z placement, rotation, material and the relevant shape
parameters: arch bays, radius and spring height; column height; or width, height
and depth for boxes. Sliders apply on release; adjacent buttons make precise changes.
X/Z are ground coordinates. Y is the base height for walls, plinths and columns,
but the centre height for a floor slab. Rotations are degrees around Y.

Duplicate, remove, undo and redo operate on the scene document. The last 30 edits
are retained in the current page session. Save local draft stores one document in
this browser. Open local draft restores it. Export scene downloads a versioned
JSON file; import validates such a file before replacing current work. Export is
the durable handoff: browser storage can be cleared and does not synchronize devices.

Edit / Orbit provides visual selection and axis handles. Walk uses the shared
W/S forward/backward, A/D turning, Shift boost and Escape release controller.
Reset view frames the current assembly. These authoring views have no collision,
stairs or terrain following; walking through a part does not validate a route.

## Generate a scene family

Scene Factory offers three initial layouts: courtyard, gallery hall and passage.
Choose bays, spring height, spacing, material and a seed, then generate. A seed
changes bounded accent placement and proportions reproducibly. The same recipe
produces the same scene document. Layout rules are deliberately small and readable.

The alternative instruction input accepts this exact local grammar:

```text
layout: courtyard
bays: 3
height: 3.1
spacing: 3.8
material: stone
seed: 42
```

Supported layouts: `courtyard`, `gallery`, `passage`. Bays: integer 1–5. Height:
2–5. Spacing: 3.5–5. Material: `stone`, `terracotta`, `fabric`, `bronze`, `linen`, `darkstone`, `water` or `lamp`. Seed:
integer 0–2147483647. Blank lines and lines starting with `#` are ignored. Duplicate
keys, unknown keys, invalid values and arbitrary commands are rejected. Missing
keys use explicit defaults. This is structured generation, not a connected language
model or unrestricted natural-language interpreter.

**Open in Builder** transfers the generated document through local browser storage,
then opens it for visual editing. It does not overwrite an existing saved draft.
Transfer requires the same origin; exporting/importing is the cross-origin handoff.
Factory's preview is read-only; use Builder to move or reshape individual parts.

## Agent interfaces

Agents can generate data without initializing a browser or GPU:

```sh
cd ~/FMVisual
node src/construction/cli.mjs --layout gallery --bays 4 --seed 42 \
  --out artifacts/generated-gallery.json
# Or use --instructions path/to/recipe.txt --out path/to/new-scene.json
# Omitting --out prints the scene JSON. Existing files are never overwritten.
```

The pure generator and schema are also importable:

```js
import { generateAssembly } from './src/construction/generation.js';
import { makeBlock, validateAssembly } from './src/construction/schema.js';

const scene = generateAssembly({layout:'courtyard', bays:3, seed:42});
const wall = makeBlock('wall', 'shelter-wall', [0, 0, -6]);
wall.params.width = 8;
scene.blocks.push(wall);
const validated = validateAssembly(scene);
```

A capable agent can author a different layout generator by composing these blocks
and returning the same schema. Existing presets are examples, not the extent of the
format. Changing a generator does not require recreating a second editor or renderer.
Source, parameter constraints, ownership and instruction parsing are separate modules.

In a ready Builder browser page:

```js
window.fmvisualBuilder.getDocument();       // Returns a copy
window.fmvisualBuilder.load(scene);         // Validate, build, then replace
window.fmvisualBuilder.select('shelter-wall');
window.fmvisualBuilder.snapshot();          // Scene, selection, camera, metrics
window.fmvisualBuilder.projectPoint([0,1,0]); // Screen point for visual interaction
```

In a ready Factory page:

```js
window.fmvisualFactory.generate({layout:'passage', bays:4, seed:9});
window.fmvisualFactory.runInstructions('layout: gallery\nbays: 2\nseed: 5');
window.fmvisualFactory.snapshot();
```

These interfaces are local page/module APIs, not unauthenticated remote endpoints.
No AI model, cloud account or GPU worker is connected by these pages. Arbitrary
instruction text is never evaluated as JavaScript or shell commands.

## Shared document and resource contract

A version 1 document contains `title` and `blocks`. Every block has a unique stable
`id`, a known `kind`, `position: [x,y,z]`, `rotation`, `material` and validated
kind-specific `params`. Validation produces a fresh normalized object rather than
retaining caller-owned mutable references. Unknown block parameters are rejected.

`buildAssembly(document)` returns a fresh `group`, normalized `document`, actual
geometry `metrics` and idempotent `dispose()`. Materials and textures are shared
within one assembly, then released once when its last owner retires. Static mesh
parts are batched per material key within each block so blocks remain independently
selectable. This is not cross-scene instancing or a GPU meshlet renderer.

Construction viewer owns its renderer, shared movement controller, orbit and
transform controls, grid, lights, resizing and frame loop. Replacing a scene builds
the candidate before retiring the old assembly. Invalid imports or generation
requests preserve the current document. A successful edit rebuilds static geometry;
this favours simple ownership over efficient high-frequency editing of huge scenes.
That rebuild can transiently retain both assemblies and is part of the peak budget.

## Budgets and present limitations

The authoring guard is 64 blocks and 500,000 triangles, with finite dimensions and
placements. It is an allocation guard, not a guarantee of acceptable performance.
The UI reports actual triangles, material batches and CPU geometry attribute bytes;
those are not total draw passes, complete VRAM or GPU timestamps. Measure frame
delivery and retained resources on the target device before extending the limits.

Both new pages deliberately use a WebGL direct-light authoring preview, supporting
views without WebGPU. They do not commission voxel GI or give an exported assembly
the sanctuary's walking containment. Lighting bounds, voxel spacing, shadows,
material quality, navigation and streaming must be qualified before promoting a
prototype into the presentable-world catalog.

The GPU workshop remains a separate planned production workflow. Available remote
GPUs could produce or qualify assets in parallel, but no paid or external jobs are
launched here. This Factory optimizes reuse of generation concepts and assembly
materials; development-time gains and runtime performance improvements still need
measurement on actual extensions.

## Verification

`make check` covers schema rejection, deterministic recipes, all layouts, shared
material disposal and the agent CLI, then builds the authoring routes.
`npm run test:construction` uses the production bundle with WebGPU absent and checks
real geometry selection, pointer dragging of a translation handle, parameters,
undo/redo, save/import/export, agent APIs, invalid-document preservation, instructions,
Factory-to-Builder transfer, shared walking input, mobile layout and the direct Arcade
entry. Evidence is generated under ignored `artifacts/`.

## Architectural series and shared project shelf

The [five original studies](ARCHITECTURAL-SERIES.md) extend Factory with `woven`,
`amber`, `procession`, `exchange` and `sanctum` recipes and use the same editable
schema. Material choices also include linen, dark stone, water and lamp surfaces.
Builder now has a name field, an undoable New blank scene action and Save to project
library. Factory and Studies can save there too. The project shelf is stored under
`data/assemblies/` and is shared across local app origins; the older single local
draft remains browser/origin-specific. See the series guide for persistence limits.

Current whole-world target: **one million purposeful triangles**, qualified with materials, light, route and complete-render evidence. See [World geometry profile](WORLD-GEOMETRY-PROFILE.md). The existing 500,000-triangle single-assembly software guard is separate and unchanged.
