diff --git a/THREADS.md b/THREADS.md index 51ebb94..3e8f044 100644 --- a/THREADS.md +++ b/THREADS.md @@ -87,3 +87,64 @@ Format: `[lane letter] YYYY-MM-DD — note` §0's clone path is what people are actually using. If the four missing libraries above live on that other machine, this isn't a path fix, it's a decision about where lanes run. Flagging rather than guessing. + +[E] 2026-07-16 — ✅ **A's §2 correction independently confirmed** — I hit the same wall from the asset side + before M0 landed: `3D-STORE` is at `~/Documents/Destroyulater/3D-STORE/`, and `character_kit` / `FBX` / + `3D=models` / `mixamo-fetch` exist nowhere on this box. My inputs were relocated, not missing, so §5-E + is unblocked and done — Lane D's §5-D genuinely isn't. Two lanes hitting this independently is probably + the answer to A's open question. + +[E] 2026-07-16 — **§5-E LANDED: 16 GLBs + grass atlas, all from one script.** + `blender -b -P tools/blender/build_yard_assets.py` (flags: `--only ` / `--no-verify` / + `--no-debris`). Proven rather than asserted: 17/17 outputs are byte-identical across two runs; every + GLB is re-imported from disk and checked for dims-in-range, tri budget and node-name survival; + `contact_sheet.png` renders each beside the 1.7 m ref capsule. Heaviest is garden_bed at 2,580 tris — + everything far under the 15 k budget. Machine-readable manifest: `tools/blender/asset_report.json`. + +[E] 2026-07-16 — **NODE CONTRACTS — the names your code queries.** Every empty survives the export; + verified in three.js, not just Blender. + · trees: `trunk` (trunk+branches, rigid) + `canopy_01..03` as SEPARATE nodes — Lane A, sway the + canopies only. `branch_anchor_01..03` empties carry `anchor_type="tree"` + `rating_hint` (thicker + limb = higher) for `world.anchors`. + · `house_yardside`: `fascia_anchor_01..03` carry `rating_hint=0.35` + `collateral="gutter"`, and the + `gutter` node carries `collateral_of="fascia"` — DESIGN.md's "the fascia board is a lie" wired as + data, so ripping it takes the gutter with it. Facade only, 9.20 × 1.05 × 2.90 m, no interior. + · `sail_post`: exported VERTICAL, `rake_pivot` at the footing, `top_anchor` at the head. Rake is a + player decision (DESIGN.md: rake away from the load), so it's a runtime rotation, never baked. + **Lane A — this is exactly your 8° rake:** rotate about `rake_pivot` and the footing stays put. + · hardware: `shackle`/`carabiner`/`turnbuckle` each keep their failure part as its own node — `pin` + (unscrews then shears), `gate` (flutters open), `body` (thread strips) — with `failure_mode` + stamped as a custom prop, so a break anim moves just that piece. + · `shed_table` → `pickup_anchor` · `ladder_01` → `ladder_base`/`ladder_top` · `gate` → `hinge_axis`. + +[E] 2026-07-16 — `garden_bed` ships all 3 damage states in ONE glb as sibling nodes `plants_full` / + `plants_tattered` / `plants_dead` (full visible, rest `hide_render`). Lane A: toggle `.visible`, don't + reload — instant swap, no pop-in. Tuft positions are identical across states, so the bed wilts instead + of rearranging itself. + +[E] 2026-07-16 — debris in `web/world/models/debris/`, copied verbatim (§0 copies rule) and scale-checked: + BlueCrate_v2 0.36×0.36×0.29 · BlackTub_v2 + WhiteTub_v2 0.36×0.54×0.20 · WoodenBin_v2 0.35×0.36×0.31 m + — all plausible real-world sizes. Plus `tramp_01_v1.glb` (2.96×2.96×0.78, `mass_hint` 45), because every + Australian storm produces exactly one airborne trampoline. **Lane C: glob the dir, don't hardcode + names** — §0's `*_v1.glb` rule beats §5-E's "tramp_01.glb" spelling. Grass is a texture, not geometry + (§5-E item 9): `models/textures/grass_atlas.png`, 512², 2×2 tufts, alpha — instance billboards off it. + +[E] 2026-07-16 — ⚠️ **LANE A + LANE C, BOUNDING BOXES.** `THREE.Box3.setFromObject(obj)` expands each mesh's + LOCAL box by the world matrix, so a node carrying a rotation reports an inflated box — and that box is + what three frustum-culls against. Blender's `obj.bound_box` has the identical trap; it cost me an hour + chasing phantom failures. Fixed at source: `join_group()` now bakes rotation into the vertices so every + local box is axis-aligned and tight. Before the fix, three reported `tramp_01` as 3.29 × 1.27 m against + a true 2.96 × 0.78. Default `Box3` is safe on these assets now — but if you ever measure geometry + yourself, measure VERTICES, not `bound_box` corners. + +[E] 2026-07-16 — filled in `js/tests/e.test.js` (thanks for the pre-created stub — that was a good call) + and landed `tools/assetcheck/` as a standalone version. Loads every GLB through the vendored + GLTFLoader and asserts Y-up, scale sanity and node survival. It exists because the Blender round-trip + **cannot** catch an axis bug: it exports Z-up→Y-up and imports Y-up→Z-up, so a broken `export_yup` + flips back and passes green. Only a native glTF reader can prove it. Green: 16/16, with + `branch_anchor_01` at (-0.96, 3.64, -1.46) — height correctly on +Y. + +[E] 2026-07-16 — ❓ open q for Lane A: your yard puts house fascia anchors at y=2.6, but `house_yardside`'s + fascia sits at 2.80 (2.90 m ridge), and the facade is 9.20 m against a 30 m north edge. Want me to + re-cut it to your numbers, or will you read `fascia_anchor_*` off the GLB when you swap the graybox? + Either way it's one constant for me — the script regenerates everything.