# The memory market — v2

An owned Blender-authored timber stall in a sunlit, limewashed courtyard.
The canopy is sage and unbleached canvas; the stall has a slatted green front,
weathered timber, empty crates and a spare handcart. Scenery contains no produce,
produce names, labels or other catalog answers. The existing 121 produce models
retain their separate sources and immutable versions.

## Construction

`src/lib/produce-market-layout.json` owns the counter, canopy, colliders,
collection footprint, camera and light positions. One unit is 0.15 m. The
counter stands 0.90 m high and measures 3.21 × 1.50 m. The 3.75 m canopy has
90 mm timber posts and sits 2.78–3.14 m above the courtyard. It is an original
stall, not a replica of a particular shop.

The reference for the timber frame and human scale is
[Marktverwaltung Rainer Perske's market stand](https://www.mv-perske.de/marktstaende.html),
whose published dimensions are 3.00 × 2.50 × approximately 2.40 m. The reference
for stripe width and the relationship between canopies and closed shopfronts is
[Adem Erkoç's empty market photograph](https://www.pexels.com/photo/abandoned-market-stalls-with-striped-awnings-31599622/),
available under the [Pexels licence](https://www.pexels.com/license/).
Reference photographs are not shipped or used as textures.

The canopy and its scalloped valance settle together in Blender's cloth solver;
the roof perimeter is pinned while the valance's lower hem hangs freely. Roof
sag is 73 mm and the deepest scallop hangs 295 mm below the front seam.
The counter's rendered surface matches its collision plane. Empty crates remain
outside the collection footprint. The closer, higher desktop camera gives the
counter 60% of the frame width, up from 45%, and almost twice the projected
surface depth. On portrait screens the whole counter still fits, with 82% more
projected surface depth. Narrower aspects widen the field of view to keep both
counter edges reachable. Both cameras are measured against the counter before
rendering. Cycles bakes direct sunlight,
sky and bounce into one 2048-pixel atlas at 128 samples, denoised offline.
The background displays the baked light; the counter remains physically lit
so newly accepted produce casts shadows. Contact shadows also work in Light.

A small primitive stall is playable immediately and remains when the room or
lightmap fails. Geometry mounts only with its matching bake; arrivals after
teardown are released. The no-WebGL collection uses the versioned still.

## Sources and licence

Geometry, cloth, palette, lighting and composition are authored for Can You Name.
The sole external texture is [Wood Table 001](https://polyhaven.com/a/wood_table_001)
by **Dimitrios Savva and Rico Cilliers**, from Poly Haven under
[CC0](https://polyhaven.com/license). The diffuse scan is desaturated, lightened
and tinted offline into weathered timber; no normal map is used.

The pinned source is `wood_table_001_diff_1k.jpg`, SHA-256
`460dd08d240f4a1f02982415048c3c5c200f385db212da18dc7e2df68bf4d0be`.
Its download and integrity record are shared with
`scripts/artwork/books-reading-room-sources.json`. There is no request-time
source provider and no additional purchased asset.

## Rebuild and delivery

Prerequisites: Windows Blender 5.2.1 with Cycles/OptiX, the sibling `blender-kit`,
the pinned source under ignored `tmp/books-reading-room/sources`, and the
existing offline glTF tools under `tmp/books-reading-room/tools`.

```sh
blender --background --factory-startup --python-exit-code 1 \
  --python scripts/artwork/build-produce-market-stall.py
node scripts/artwork/pack-produce-market-stall.mjs
```

Use `-- --proof` for composition only. Look decisions are in
`scripts/artwork/styles/produce-market-stall.toml`. The authoring script creates
a separate scene and never opens or clears a live Blender file. Source `.blend`,
proof PNGs, construction measurements and validator reports are reproducible
scratch output under ignored `tmp/produce-market-stall`.

The packer quantizes positions/UVs to 16 bits, uses meshopt, checks all nine
lightmap batches through Three.js's own decoder and validates the decoded glTF
with Khronos Validator. The current bundle ships under `v2/`; `v1/` stays
published unchanged. Future versions must use a new directory. Asset hashes:

| Asset | Bytes | SHA-256 |
| --- | ---: | --- |
| `v2/room.glb` | 1,128,852 | `da07886ae062a009b1d3e79aab885c66813e104ebc07aa0fc291117a263f1688` |
| `v2/lightmap.webp` | 307,604 | `e70285697c09e99f0294156023f8191d4a5e879329bc151be3ae92a53e542fe0` |
| `v2/preview.webp` | 48,992 | `22a272a51dc93e2b2ca36f759d96411bd2ef3eb782fdfeb22dc09fa2cc127f9a` |
| `v1/room.glb` | 1,118,224 | `0de00b0cbd2143446a60ab8074ed34b328d093f5b816a144755e25ede98bf606` |
| `v1/lightmap.webp` | 304,540 | `77acdda6aa4601b225608f9ecb2e1359f405bdc4b779ac9370dbddc09e54a8d1` |
| `v1/preview.webp` | 38,766 | `ea8b1fcdfaff37a833e2ba05635d2b9bdda5371dfd1750d6299f11351f019d55` |

Current room: 71,752 triangles, nine material batches, zero validator errors/warnings.
The atlas clips no sampled light; material UV quantization moves a texel by at
most 0.08 pixels. The room and bake stay below the 3,500 KiB delivery budget.
