# Build a 3D scene

Write a scene file, check that no body goes through a prop, and draw a still from its camera on your computer.

A 3D scene is one file that holds people, props, cameras and a timeline. Your agent writes it, and MiniCut checks it and draws it on your computer. Distances are in metres, the floor is at 0 and turns are in degrees.

Before you start, sign in and make a project. See [Quickstart](/docs/cli/quickstart). Every command here needs a signed-in computer. Run them in the project folder, `~/.minicut/projects/rain-shop` here.

## Write the scene

1. Make the folder `episodes/ep01/scenes` in the project if it is not there. A scene for shot 1 is named `c01`, for shot 2 `c02`, and on.
2. Write an operations file in that folder, `c01.scene.ops.json`. It is data: a list of scene operations with their arguments, and no code.

```json c01.scene.ops.json
{
  "ops": [
    { "op": "setWorld", "args": [{ "aspect": "9:16" }] },
    { "op": "addCharacter", "args": [{ "name": "Lin", "body": "female", "position": [-0.8, 0, 0] }], "as": "lin" },
    { "op": "addCharacter", "args": [{ "name": "Chen", "body": "male", "position": [0.8, 0, 0], "facing": "$lin" }] },
    { "op": "addProp", "args": [{ "name": "Table", "shape": "table", "position": [0, 0, 0.9] }] },
    { "op": "addCamera", "args": ["front_medium", { "name": "Front" }], "as": "cam" },
    { "op": "setCamera", "args": ["$cam", { "position": [0, 1.6, 6], "lookAt": [0, 1.4, 0], "fov": 40 }] },
    { "op": "setDuration", "args": [4] }
  ]
}
```

`as` names the id that an operation makes, and `$lin` uses it in a later operation. An operation name that does not exist makes `build` print the names it takes.

3. Optional: if your agent writes code, run `minicut scene api`. It prints one import line for a Node.js script. The script ends with `await api.save("episodes/ep01/scenes/c01.scene.json")`, which checks the scene and writes it. MiniCut never runs the script. Your agent runs it with `node`.

## Build the scene file

1. Build the file:

```bash Terminal
minicut scene build episodes/ep01/scenes/c01.scene.ops.json
```

It prints `Wrote` with the path of `c01.scene.json`, the count of objects and cameras, the length, and each camera's id and name.

2. Read the camera id in the output. Every build makes new ids, so a camera id from an earlier build no longer fits.

`build` checks the scene before it writes. If a check fails, it prints each problem, says `Not written`, and leaves the old file as it was. A file that holds code is refused.

## Check the scene

1. Check that no body goes through a prop or the floor:

```bash Terminal
minicut scene check episodes/ep01/scenes/c01.scene.json
```

```text Output
OK ~/.minicut/projects/rain-shop/episodes/ep01/scenes/c01.scene.json: 3 object(s), 1 camera(s), 4 s. Cameras: cam_a6tl (Front). No body goes through a prop or the floor.
```

2. If it prints problems, change the operations file and build again. Each line names the body part, the prop, how deep and at which second, and how far to move. For example, `Lin's left thigh goes 9 cm into "Table" (p_kg3w), at 0 s`.
3. To go back to the file before the last build, run `minicut scene undo episodes/ep01/scenes/c01.scene.json`. The last 20 versions are kept.

## Draw a still

1. Draw the middle second of the scene:

```bash Terminal
minicut scene render episodes/ep01/scenes/c01.scene.json --still middle
```

The command prints `Drawing` with the camera and the second, then `Rendered` with the size in bytes, then the path. With no `--camera`, it uses the scene's own camera.

2. Open the picture. Without `--project` or `--id`, it is in the `cache/stills` folder of your MiniCut home folder, and the command prints its path. A copy in the `labeled` folder beside it has a name tag on every asset, for people to read.
3. Optional: to keep the still in your library as a location, add `--project rain-shop`.
4. Optional: for a smaller picture, add `--draft` for half of each side, or `--size WIDTH` with an even width.
5. Optional: to draw the middle second of every shot scene in an episode, run:

```bash Terminal
minicut scene render --project rain-shop --episode ep01 --still middle
```

It draws each `cNN.scene.json` in turn. The last line says how many it drew and how many it did not draw.

## Check it worked

The still is a `.png` that shows the scene from the camera. A scene that fails `minicut scene check` is not drawn. The command prints `Not rendered` and the problems. To draw a clip instead of a still, see [minicut scene render](/docs/cli/scene-and-music#minicut-scene-render).

## If a step fails

| Message | What to do |
|---|---|
| `ops[1].op: "NAME" is not a composer op.` | Use one of the operation names the message lists |
| `this text reads as code. An ops file holds names, numbers and text, never code.` | Write the value itself, not code that makes it |
| `scene build reads data only, never a script.` | Build a file named `NAME.scene.ops.json` |
| `Not written: N problem(s).` | Fix the problems printed above it, then build again |
| `No camera in c01.scene.json: add one to the scene.` | Add an `addCamera` operation, then build again |
| `--still is a second from 0 to 4 (the timeline).` | Give a second inside the scene's length |
| `Use --draft or --size <width>, not both.` | Pick one of the two |
| `The render page is not on this computer ...` | Run `minicut update`, then render again |
| `No headless browser (chrome-headless-shell) on this computer.` | Run `minicut setup`, then render again |

## Next

[Scene and music](/docs/cli/scene-and-music) [Write the music](/docs/cli/write-the-music) [Checks and loops](/docs/cli/checks-and-loops)
