LANES/PLAN.md — verdict, GODVERSE pipeline architecture, shared contracts, 3GOD security note LANES/LANE1-*.md — Godot: grab/slide/smash record ritual + find-the-misfiled-disc mode (owns game/) LANES/LANE2-*.md — meshgod cell-fracture stage + Destroyulator prop batch -> 3GOD (owns ~/meshgod) LANES/LANE3-*.md — thriftgod-based web smash toy, Rapier physics, 3GOD props (owns web/) LANES/KICKOFF.md — per-lane opening prompts + collision-safety rules Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
75 lines
4.5 KiB
Markdown
75 lines
4.5 KiB
Markdown
# LANE 2 — Asset pipeline: cell-fracture stage + Destroyulator prop batch
|
||
|
||
**Owns:** `~/Documents/meshgod` (SEPARATE repo — not the destroyulator monorepo).
|
||
**For:** an Opus 4.8 session. **Runs on:** M3 Ultra; Blender at `/Applications/Blender.app`.
|
||
|
||
## Objective
|
||
|
||
Give the meshgod factory a **fracture stage** so props arrive pre-shattered for smashing,
|
||
then batch-generate Destroyulator's workplace props and push them to 3GOD. This upgrades
|
||
Lanes 1 & 3 from "single-box smashable" to real shard-by-shard destruction.
|
||
|
||
## What already exists (read first)
|
||
|
||
- `meshgod/finish.py` + `scripts/finish_glb.py` — the **headless-Blender subprocess pattern
|
||
to copy**: launches `/Applications/Blender.app` `--background --python <script> -- <args>`,
|
||
parses a `FINISH_RESULT:{json}` line from stdout. Finishing does join→solidify (watertight!)
|
||
→decimate→brighten→normalize→export GLB.
|
||
- `meshgod/batch.py` — resumable manifest runner (`python3 -m meshgod.batch manifest <f.json>
|
||
--out <dir>`, content-hashed IDs, checkpoints, `--workers`).
|
||
- `meshgod/pipeline.py`, `config.py` — the OpenRouter→fal.ai→finish flow. **Cost is real**
|
||
(~$0.10–0.55/asset); fal key in gitignored `open.txt`. Check remaining credit before a big batch.
|
||
- 3GOD push: `MESHGOD/scripts/test_3god_push.py` (on M1) guards the depot auth/slug contract;
|
||
find/mirror the actual push helper meshgod uses to POST a finished GLB to digalot.fyi/3god.
|
||
|
||
## Deliverables
|
||
|
||
### 1. `meshgod/scripts/fracture_glb.py` — headless Blender cell-fracture
|
||
Mirror `finish_glb.py`'s structure exactly (arg parsing, `FRACTURE_RESULT:{json}` stdout line).
|
||
- Input: a finished watertight GLB + `--chunks N` (default 12) + `--out <path>`.
|
||
- Enable the **Cell Fracture** addon (`bpy.ops.preferences.addon_enable(module="object_fracture_cell")`)
|
||
and run `bpy.ops.object.add_fracture_cell_objects(source_limit=N, ...)` on the imported mesh.
|
||
(Blender 5.1 — verify the addon module name; if renamed/removed, fall back to a Voronoi
|
||
geometry-nodes or `boolean`-based split, but Cell Fracture is preferred.)
|
||
- Each chunk: recenter its origin to its own bounds center (so it can become a rigid body),
|
||
keep the parent's material.
|
||
- Export **all chunks as a single `<name>.fractured.glb`** whose root's direct children are the
|
||
chunk meshes named `chunk_00…chunk_NN` (SHARED-CONTRACT #2 in PLAN.md). Report chunk count +
|
||
whether any chunk is non-manifold.
|
||
|
||
### 2. `meshgod/fracture.py` (module) + CLI
|
||
`python3 -m meshgod.fracture <in.glb> --chunks 12 --out <out.fractured.glb>` — thin wrapper
|
||
that subprocess-launches the script (same pattern as `finish.py`). Optionally add a
|
||
`--fracture` flag to `batch.py` so a manifest entry can request `"fracture": {"chunks": 12}`
|
||
and get both `<name>.glb` + `<name>.fractured.glb` out.
|
||
|
||
### 3. `meshgod/manifests/destroyulator.json` — the prop batch
|
||
Workplace hero props, real-metre `height_m` + tri budgets. Include at least:
|
||
office **printer** (the boss!), office desk, monitor/CRT, desk phone, filing cabinet,
|
||
water cooler, office chair, ceiling fluorescent light, coffee mug, potted plant, wall clock,
|
||
cardboard box; record-store extras: turntable, amp/speaker, cash register, wall shelf.
|
||
Each entry: `{name, prompt, height_m, tris, fracture:{chunks}}`. ~16 assets ≈ $3–8, ~30 min.
|
||
**Confirm the fal budget covers it before running; if low, do the top 6 first.**
|
||
|
||
### 4. Push finished + fractured GLBs to 3GOD
|
||
Use meshgod's existing depot-push path. Land both the intact and `.fractured.glb` on the
|
||
digalot.fyi/3god shelf so Lanes 1 & 3 can pull them by slug.
|
||
|
||
## Acceptance
|
||
- `fracture_glb.py` on one finished GLB (e.g. `outputs/robot_game.glb`) yields a
|
||
`.fractured.glb` with ≥8 chunk children named `chunk_*`; verify by loading it in Blender
|
||
headless and printing child count + names.
|
||
- The manifest runs (or a 2-asset subset does) end-to-end: intact + fractured GLBs on disk,
|
||
watertight, correct scale, pushed to 3GOD (`GET /api/list` shows the new slugs).
|
||
|
||
## Gotchas
|
||
- Cell Fracture needs the mesh to be a single manifold object; run it AFTER finish's solidify.
|
||
- fal costs money per asset and the key is shared/rotating — read `open.txt`, don't hardcode,
|
||
and cap batch size to the remaining credit.
|
||
- Keep chunk counts modest (8–16). Hundreds of chunks tank the consuming physics engines.
|
||
|
||
## Definition of done
|
||
Fracture stage works and is documented; `destroyulator.json` (or its top-6 subset) generated,
|
||
finished, fractured, and pushed to 3GOD; committed + pushed to meshgod's own remote.
|
||
Post the list of produced slugs so Lanes 1 & 3 can consume them.
|