# Add 3D models to an Environment

Your Environment starts procedural — boxes, shapes, and light. When you want a
real tree, chair, or lamppost, download one and run one command. You do not
need to be a 3D artist, and you do not need to learn a modelling tool.

## 1. Get a model

All five of these are free and usable in a published Environment. Check the
licence on the page you download from; it is stated on every one of them.

- [Quaternius](https://quaternius.com) — big stylised low-poly sets: nature,
  furniture, buildings. The easiest starting point.
- [Poly Haven](https://polyhaven.com/models) — photoreal models, all CC0.
- [Kenney](https://kenney.nl/assets) — tiny, cheerful, game-ready kits.
- [ambientCG](https://ambientcg.com) — mostly materials, some models, all CC0.
- [Sketchfab](https://sketchfab.com/search?features=downloadable&licenses=cc0)
  — enormous, but filter to CC0 or you cannot ship what you find.

## 2. What to look for

- **Low-poly.** Tens of thousands of triangles, not millions.
- **Few materials.** One or two beats forty; forty means forty draw calls.
- **`.glb` format.** Choose it in the download options if offered. `.gltf`
  works too. FBX and OBJ do not.
- **Y-up, pivot at the base.** A tree's origin should sit where it meets the
  ground, not in the middle of its canopy.

## 3. Put it in your project

Make a folder per set, inside `assets/models/`. The folder name becomes the
pack name, so pick something you will recognise later:

```text
assets/models/
  grove/
    Poplar_1.glb
    Poplar_2.glb
    Flower_Gazania.glb
```

Nothing in this folder is ever changed or deleted by anything below. It is your
copy of what you downloaded.

## 4. Build the pack

```bash
npm run assets:pack
```

That is the whole command — no arguments. It writes
`public/models/PACK-grove.glb`, one file per folder, and it only rebuilds packs
whose source files changed.

## 5. Read what it prints

```text
  grove -> public/models/PACK-grove.glb

  variant                    primitives  triangles   bbox (m)
  Flower_Gazania                     12      1,204   0.30 x 0.40 x 0.30
  Poplar_1                            2      4,812   1.40 x 8.20 x 1.40
```

Two columns matter to you:

- **variant** — the name to ask for in code. It is the file name, so
  `Poplar_1.glb` is the variant `Poplar_1`.
- **bbox (m)** — how big the model actually is, in metres. A poplar should be
  several metres tall. If it says `0.02`, the model was exported in
  centimetres and you will need to scale it up by 100. If it says `820`, scale
  it down. Check this before you write any code; a wrongly scaled model renders
  perfectly and is invisible.

## 6. Hand it to your agent

Tell your coding agent the pack path and the variant names, and let it write
the scene:

```text
Place five Poplar_1 and about forty Flower_Gazania from
/models/PACK-grove.glb around the clearing.
```

The rules it must follow — how to load a pack, when to clone and when to
instance — are written down for it in the
[Environment 3D models recipe](/docs/recipes/environment-3d-models). Point it
there if it asks.

## When it does not work

| What you see                                           | Why                                                            | Fix                                                                               |
| ------------------------------------------------------ | -------------------------------------------------------------- | --------------------------------------------------------------------------------- |
| `no .glb or .gltf files — skipped`                     | The folder has `.fbx`, `.obj`, or a `.zip` you did not extract | Re-download and choose glTF/GLB, or convert in [Blender](https://www.blender.org) |
| The pack is far larger than the others                 | One model carries 4K textures                                  | Re-run with `npm run assets:pack -- --max-texture 512` and compare                |
| The model is invisible in the world                    | The bounding box in step 5 is tiny or enormous                 | Scale it in your scene code by the factor the table implies                       |
| The model is lying on its back                         | It was authored Z-up                                           | Rotate it `-90°` on X in your scene code                                          |
| A black screen for twenty seconds, then a load error   | The texture decoders are missing                               | Stop the dev server and start it again; `predev` installs them                    |
| A model appears in one place but vanishes from another | The same object was mounted twice                              | Your agent skipped the clone rule — send it the recipe above                      |
