# Breton atom kit v2

30 named masters in `kit.glb`, 17 external materials, four independent paint slots. 17,100 triangles for the complete library; every requested cap passes. The standard window is the v1 ground-floor opening, used unchanged at unit scale on every full storey. The 0.85 × 1.10 m dormer window is authored separately.

The reference sheet guides the architecture and material family. The four houses in the viewer are assembly demonstrations, not a replacement for the original finished house or a new wall-generator product.

## Open and rebuild

Serve this directory with `python3 -m http.server 8000`, then open `http://localhost:8000/viewer/`. Select any master, the two-storey assembly, roof detail, or four material palettes. Drag to orbit; use Clay and Reverse view for inspection. All Three.js dependencies and textures are local.

`python3 prepare_materials.py` rebuilds the shelf from the included, copied `source_materials/` and `source_materials.json` (Python, Pillow, NumPy).

`blender -b --python-exit-code 1 --python build_kit.py` rebuilds the GLB, manifest, and Blender contact/detail renders. Tested with Blender 5.2. Add `-- --export-only` to skip renders, or `-- --preflight` for the small export/import/render test. The builder does not read or write the original v1 or house directories.

`python3 validate_delivery.py` checks the exported GLB and shelf. `browser_check.py` uses Playwright/Chromium against port 18776 and records runtime views and counters. `audit.json` is the strict independent GLB audit report.

## Coordinates and openings

Metres, +Y up, +Z outward from the façade, +X horizontal. Top-level masters have identity transforms. Place openings with the bottom-centre origin on the wall face at Z=0. Cut the wall opening; do not place a closed wall through the glazing or leaf. Frame returns reach Z=-0.38.

| Master | Clear opening, width × height | Usage |
|---|---:|---|
| window_std | 0.95 × 1.30 m | Every full storey, scale 1 |
| shutters_std | Matching open pair | Separate `Shutter_paint` slot |
| window_small | 0.50 × 0.70 m | Gable/attic only |
| window_shop | 2.00 × 1.90 m | Granite surround, timber frame and blank fascia |
| door_main | 1.00 × 2.10 m | Left-hinged child `door_leaf`, step |
| door_back | 0.90 × 2.10 m | Child `door_back_leaf`, modest step |
| door_double | 1.60 × 2.40 m | Segmental arch; spring height 2.16 m; two child leaves |
| dormer | 0.85 × 1.10 m | Its own window; never a scaled standard window |

Rotate door children about local Y; retain their exported hinge translations. Surround bounds are larger than the clear opening. Exact bounds, caps, triangle counts and attachment origins are in `kit.json`. Quoins must stay clear of the open shutter envelope.

## Slate and rainwater assembly

The four 0.345 × 0.420 m slates have different chamfered/chipped outlines, 10–13 mm material thickness, and 2.5 mm bow. Each is 38 triangles. The four-slate strips are 152 triangles and span a nominal 1.38 m. The bow adds to the overall bounding-box height; it is not additional solid thickness. Ridge tiles include mortar bedding beneath their edges.

For pitch P in 42–47°, place course origins on the roof plane at 0.21 m gauge, offset all origins 0.018 m along the roof normal, and rotate slate X by P − atan(0.07). This small cant seats overlapping courses without accumulating a height error. Stagger successive rows by 0.1725 m. Cut terminal half slates at verges; do not leave whole tiles projecting on alternate rows. The viewer contains a working triangle clipper. Scale the underlay to the roof, not the individual slates. Cut roof openings and use appropriate flashing when installing dormers/chimneys.

The gutter datum is its rear rim, not the roof plane. Place the rim 60 mm below the actual slate tail and the rear edge 35 mm inward from the tail's outward Z coordinate. The exported geometry gives 54 mm minimum vertical separation including the rolled bead in the 44° test assembly. Visible brackets repeat every 0.5 m; fit end caps at terminal X planes.

`gutter_outlet` is a hollow funnel/neck. Cut a radius-0.043 m drain opening through the gutter bowl at the outlet; placing it under an intact bowl is not a valid assembly. The viewer performs this cut on a cloned gutter mesh. Its throat ends at Y=-0.19 relative to the rim. Downpipe centre Z=0.086 relative to the shared datum. The shoe inlet is Y=0.26. Trim pipe lengths between these two datums. At corners or stepped façades, an assembler must author the required elbows and flashings.

Linear fascia/verge/gutter/pipe terminal pieces may be trimmed along their length. Keep the profile dimensions fixed. The viewer's modest terminal length scaling is only an assembly demonstration; production trimming should preserve metric UVs.

## Material binding and coherence

The GLB deliberately embeds no textures. Bind materials by exact name from `materials.json`. BaseColor uses sRGB; Normal and ORM use linear sampling. ORM = occlusion / roughness / metallic. Normal maps use OpenGL +Y. The original eight material names remain available, along with the rebuilt optional moss base.

`Granite_lime_moss`, `Granite_ochre`, `Granite_pink`, and `Lime_render_white` share the **identical registered 16-bit Height**, 2.25 m repeat, displacement scale 0.105 m and bias 0.006 m. Apply outward displacement = 0.006 + Height × 0.105. The white material is a lime wash over the same rubble relief. `Green_grey_slate` is a restrained companion to `Blue_grey_slate`.

`Granite_lime_moss_base` covers only the bottom 0.9 m. U repeats every 2.25 m; V spans exactly 0.9 m and clamps. Damp darkening and relief-following lichen fade upward; no vertical streak-noise term is used. All four map edges match exactly in X. In source/Blender UV convention use U=x/2.25, V=y/0.9. In manually generated Three.js geometry with `flipY=false`, use **V=1−y/0.9**; ordinary wall UV uses V=1−y/2.25. GLTFLoader meshes already contain the exporter’s V conversion: do not flip those again.

For coloured walls the viewer applies the selected-wall/grey-wall colour ratio to the base, sampled at the corresponding physical height. This preserves the damp fade without a grey plinth or colour seam. See `baseFor()` in `viewer/main.js`; the base texture itself remains the requested grey material. Do not repeat it vertically up the façade.

`paint_slots`: `Window_frame_paint`, `Door_paint`, `Shutter_paint`, `Sign_paint`. These are separate neutral, lightly worn timber maps, intended for multiplicative linear-space tinting. The shelf includes four coherent palette presets. Use one main wall/roof pair per street, keep frames lighter than doors/shutters, and restrict neighbouring accents to one adjacent palette. Shared dressed stone, opening sizes, slate gauge and zinc profiles maintain the village family.

Sources: copied Poly Haven CC0 maps/bakes (`rock_wall_09`, `worn_rock_natural_01`, `wooden_planks`, `metal_plate_02`, `slate_floor_03`) from the v1 kit/house. Exact source metadata and hashes are retained. Old glass stays opaque, as in v1. Fascia/sign nameboards are intentionally blank.
