Correct PLAN3D asset inventory; log M0 contract additions

§2's paths were substantially wrong. Re-verified against the filesystem:
3D-STORE is at ~/Documents/Destroyulater/3D-STORE (its clean_glbs debris set is
real, just relocated), while 3D=models/, character_kit/, mixamo-fetch/ and FBX/
do not exist on this box at all. That last group is Lane D's whole animation
pipeline, so it's flagged loudly rather than quietly patched.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
m3ultra 2026-07-16 21:33:42 +10:00
parent 1049dece24
commit 868ea5699d
2 changed files with 122 additions and 23 deletions

View File

@ -18,10 +18,11 @@ canon; this file is the build canon.**
then work on branch `lane/<x>`. Push your branch; never force-push main. then work on branch `lane/<x>`. Push your branch; never force-push main.
- **Units:** meters, +Y up, world origin at yard center on the ground. Player height ~1.7 m. The yard is ~30×20 m. GLB exports: Y-up, meter scale, `*_v1.glb` naming into `web/world/models/`. - **Units:** meters, +Y up, world origin at yard center on the ground. Player height ~1.7 m. The yard is ~30×20 m. GLB exports: Y-up, meter scale, `*_v1.glb` naming into `web/world/models/`.
- **Asset copies rule (house rule from DJsim):** runtime models in `web/world/models/` - **Asset copies rule (house rule from DJsim):** runtime models in `web/world/models/`
are COPIES. Canonical sources stay in the shared libraries are COPIES. Canonical sources stay in the shared libraries — **see §2 for the
(`~/Documents/3D=models/`, `~/Documents/character_kit/`, `~/Documents/3D-STORE/`, verified paths, several of which are not what this plan originally claimed.**
`~/Documents/FBX/`). Never hand-edit a game-local GLB; rebuild at source and re-copy. Never hand-edit a game-local GLB; rebuild at source and re-copy.
Raw `.fbx`/`.blend` are gitignored; runtime asset is always `.glb`. Raw `.fbx`/`.blend` are gitignored (`.gitignore` enforces it); runtime asset is
always `.glb`.
- **Rigged characters:** follow 90sDJsim DEVMANUAL "rigged characters" rules — - **Rigged characters:** follow 90sDJsim DEVMANUAL "rigged characters" rules —
`SkeletonUtils.clone()` for instances, height-normalize by head-bone height, `SkeletonUtils.clone()` for instances, height-normalize by head-bone height,
never blind `setScalar`. The Mixamo pipeline is `~/Documents/mixamo-fetch/` never blind `setScalar`. The Mixamo pipeline is `~/Documents/mixamo-fetch/`
@ -70,18 +71,39 @@ wind-change event, repair hold. Port the *behavior*, retune the constants.
--- ---
## 2. Asset inventory (M1 Ultra, verified 2026-07-16) ## 2. Asset inventory (re-verified on `m3ultra` 2026-07-16 by Lane A)
**This table was wrong in the first draft and has been corrected against the
actual filesystem.** Several libraries it promised are not on this box at all.
Trust this table over any path you remember; if you find one of the missing
libraries somewhere, say so in THREADS.md rather than fixing it locally.
| Need | Have | Path | | Need | Have | Path |
|---|---|---| |---|---|---|
| three.js r175 + addons (GLTFLoader, SkeletonUtils…) | ✅ vendored | `~/Documents/90sDJsim/web/world/vendor/` | | three.js r175 + addons (GLTFLoader, SkeletonUtils…) | ✅ verified, now vendored in-repo | `web/world/vendor/` (copied from `~/Documents/90sDJsim/web/world/vendor/`) |
| Player character (small person) | ✅ rigged fleet | `~/Documents/90sDJsim/web/world/models/peds/` (man_casual_01-03, woman, elder…); canonical rigs `~/Documents/character_kit/` (hum_character.glb, female/); more in `~/Documents/3D=models/characters/` (53 people-normal + comical) | | Player character (small person) | ✅ 21 rigged peds | `~/Documents/90sDJsim/web/world/models/peds/` (man_casual_01-03, woman_casual_01-02, elder, hivis worker…) |
| Locomotion anims | ✅ | `~/Documents/FBX/` (Running, Falling, Crouch To Stand, Reaction…), `~/Documents/3D=models/animations/` (Walk, Start Walking, Happy Idle, Injured Walk…, 32 clips) | | Rigged-character loading rules | ✅ | `~/Documents/90sDJsim/DEVMANUAL.md` — Lane D: this is law |
| Missing anims (climb ladder, crank/wrench, dig, hammer) | fetch | `~/Documents/mixamo-fetch/` — add to wishlist, run fetcher | | Locomotion anims | ⚠️ **thin** | `~/Documents/90sDJsim/web/world/models/peds/idle.glb`, `walk.glb` are the only clips found. Run/Falling/Crouch-To-Stand are **not on this box** |
| Debris + yard clutter | ✅ perfect fits | `~/Documents/3D-STORE/clean_glbs/` (BlueCrate, BlackTub, WhiteTub, WoodenBin, LibraryTrolley…) + `~/Documents/3D=models/street-furniture/` (benches, streetlight, market_stall, food_cart, building_shell_01) | | Debris + yard clutter | ✅ exactly as promised, **new path** | `~/Documents/Destroyulater/3D-STORE/clean_glbs/` — BlueCrate_v2, BlackTub_v2, WhiteTub_v2, WoodenBin_v2, LibraryTrolley_v1, AirCon_v1 |
| Furniture/props (granny-flat interiors later) | ✅ | `~/Documents/3D=models/furniture/`, `props-scenes/` | | Scripted-Blender build idiom | ✅ **new path** | `~/Documents/Destroyulater/3D-STORE/build_booth_room_v23.py` (also `~/Documents/3dstore/`) |
| Trees, fence, house exterior, shed, garden bed, grass, shade-sail hardware | ❌ **GAP** | Lane E builds these (Blender is installed; house style is scripted builds — see `~/Documents/3D-STORE/build_booth_room_v23.py` for the idiom) | | Trees, fence, house exterior, shed, garden bed, grass, shade-sail hardware | ❌ **GAP** | Lane E builds these. Lane A has graybox stand-ins at the right scale and positions in `world.js` — match those and they drop straight in |
| Blender / Godot / UE 5.7 | ✅ installed | `/Applications`, `/Users/Shared/Epic Games/UE_5.7` (UE/Godot NOT used for this — three.js only) | | Blender | ✅ installed | `/Applications/Blender.app` |
| ~~`~/Documents/3D=models/`~~ (characters, 32 anim clips, street-furniture incl. `building_shell_01.glb`, furniture, props-scenes) | ❌ **DOES NOT EXIST** | searched `~` and `/Volumes` + Spotlight. Nothing at this path or any similar name |
| ~~`~/Documents/character_kit/`~~ (hum_character.glb, retarget pipeline) | ❌ **DOES NOT EXIST** | — |
| ~~`~/Documents/mixamo-fetch/`~~ (wishlist → fetch.cjs) | ❌ **DOES NOT EXIST** | closest is `~/Documents/mixamo_upload/` (`Hum_M_1_mixamo.fbx/.obj`) — an upload staging dir, not the fetcher |
| ~~`~/Documents/FBX/`~~ (Running, Falling, Crouch To Stand…) | ❌ **DOES NOT EXIST** | only Unreal's own internal `FBX` dirs match the name |
**Consequences, unresolved — Lane D is the one this hurts.** §5-D assumes the
`character_kit` retarget pipeline and a library of Mixamo clips. Neither is
here. The ped fleet and DEVMANUAL are real, so a walking character is still
reachable, but Run / Falling / Crouch-To-Stand / crank / dig have to come from
somewhere. Post in THREADS.md before burning a day looking for them.
**Open question:** PLAN3D §0 says the work happens on "the M1 Ultra
(`johnking@100.91.239.7`, Tailscale)", but this box is `m3ultra` and already has
`~/Documents/shades-laneB/` and `shades-laneE/` checked out, so lanes are in
fact running here. If the missing libraries live on that other machine, §0 needs
a decision about where lanes run — not just a path fix.
--- ---
@ -104,6 +126,9 @@ shades/
├── main.js # boot + game loop + phase machine (A) ├── main.js # boot + game loop + phase machine (A)
├── world.js # terrain, yard, props, lighting, sky (A) ├── world.js # terrain, yard, props, lighting, sky (A)
├── camera.js # third-person rig (A) ├── camera.js # third-person rig (A)
├── testkit.js # assert/fixedLoop harness (A)
├── tests/<lane>.test.js # ONE PER LANE — you own yours, nobody
│ # edits selftest.html (it just imports these)
├── sail.js # cloth sim, anchors, hardware, loads (B) ├── sail.js # cloth sim, anchors, hardware, loads (B)
├── rigging.js # prep-phase UI + hardware economy (B) ├── rigging.js # prep-phase UI + hardware economy (B)
├── weather.js # wind field, storm timeline, rain (C) ├── weather.js # wind field, storm timeline, rain (C)
@ -161,8 +186,8 @@ Determinism rule: `sail.js`, `weather.js`, `debris.js` take `(dt, t)` — no
`--selfcheck` flag runs a headless node-free check by printing the selftest `--selfcheck` flag runs a headless node-free check by printing the selftest
URL; keep it dumb), launch.json, contracts.js, and a walkable graybox yard: URL; keep it dumb), launch.json, contracts.js, and a walkable graybox yard:
30×20 m ground with gentle height variation, house shell along north edge 30×20 m ground with gentle height variation, house shell along north edge
(use `street-furniture/building_shell_01.glb` scaled, or graybox), 2 placeholder (graybox — `building_shell_01.glb` does not exist on this box, see §2),
trees, 2 posts, garden bed rect, boundary fence graybox. Third-person follow 2 placeholder trees, 2 posts, garden bed rect, boundary fence graybox. Third-person follow
camera (orbit on RMB, shoulder-follow default). Directional sun + hemisphere camera (orbit on RMB, shoulder-follow default). Directional sun + hemisphere
light, calm sky. **Merge to main fast — everyone rebases on this.** light, calm sky. **Merge to main fast — everyone rebases on this.**
2. HUD after M0: wind meter + arrow, corner load bars (world-anchored sprites), 2. HUD after M0: wind meter + arrow, corner load bars (world-anchored sprites),
@ -224,10 +249,12 @@ through house; selftest green after every merge.
1. Character: pick a ped from `90sDJsim/web/world/models/peds/` (copy into 1. Character: pick a ped from `90sDJsim/web/world/models/peds/` (copy into
`models/`, per copies-rule; man_casual_01 or woman — small relative to 4 m `models/`, per copies-rule; man_casual_01 or woman — small relative to 4 m
posts reads "small person"). Load with DEVMANUAL rig rules. Clips: Walk + posts reads "small person"). Load with DEVMANUAL rig rules.
Running + Happy Idle from the libraries; retarget/merge via character_kit ⚠️ **Clips are a live problem — read §2 before you start.** `character_kit/`,
pipeline. Fetch "Climbing Ladder", "Turning Key/crank", "Digging" via `mixamo-fetch/`, `FBX/` and `3D=models/animations/` are NOT on this box. The
mixamo-fetch wishlist for M3. only clips found are `peds/idle.glb` and `peds/walk.glb`. Walking is
reachable from those; Running / Falling / Crouch-To-Stand / crank / dig are
not sourced yet. Raise it in THREADS.md rather than hunting.
2. Controls: WASD relative to camera, walk/run (shift), acceleration + turn 2. Controls: WASD relative to camera, walk/run (shift), acceleration + turn
smoothing, anim state machine (idle/walk/run + one-shot interact). Gamepad smoothing, anim state machine (idle/walk/run + one-shot interact). Gamepad
optional. Slope clamp to terrain height. optional. Slope clamp to terrain height.
@ -245,8 +272,8 @@ through house; selftest green after every merge.
### Lane E — Nature & hardware assets (Blender, scripted; owns tools/blender/, models/) ### Lane E — Nature & hardware assets (Blender, scripted; owns tools/blender/, models/)
The gap lane. House idiom: **scripted Blender builds** (see The gap lane. House idiom: **scripted Blender builds** (see
`~/Documents/3D-STORE/build_booth_room_v23.py` and `racks_to_glb.py` for the `~/Documents/Destroyulater/3D-STORE/build_booth_room_v23.py` and
export pattern). One `tools/blender/build_yard_assets.py` that regenerates `racks_to_glb.py` for the export pattern — note the corrected path, §2). One `tools/blender/build_yard_assets.py` that regenerates
everything → `clean/` GLBs; commit script + GLBs. everything → `clean/` GLBs; commit script + GLBs.
Deliverables (meters, Y-up, low-poly stylized to match ped fleet, baked or Deliverables (meters, Y-up, low-poly stylized to match ped fleet, baked or
@ -265,8 +292,8 @@ flat colors, <15 k tris each):
`turnbuckle.glb` — tiny, but they're the fetish objects of the game; make `turnbuckle.glb` — tiny, but they're the fetish objects of the game; make
them read at 1 m distance. them read at 1 m distance.
8. `models/debris/`: copy + sanity-scale BlueCrate_v2, BlackTub_v2, WhiteTub_v2, 8. `models/debris/`: copy + sanity-scale BlueCrate_v2, BlackTub_v2, WhiteTub_v2,
WoodenBin_v2 from `3D-STORE/clean_glbs/`; add `tramp_01.glb` (trampoline!) WoodenBin_v2 from `~/Documents/Destroyulater/3D-STORE/clean_glbs/` (verified
if time. present, corrected path — §2); add `tramp_01.glb` (trampoline!) if time.
9. Grass: NOT geometry — ship a 4-tuft billboard atlas texture; Lane A instances. 9. Grass: NOT geometry — ship a 4-tuft billboard atlas texture; Lane A instances.
Acceptance: `blender -b -P tools/blender/build_yard_assets.py` regenerates all Acceptance: `blender -b -P tools/blender/build_yard_assets.py` regenerates all

View File

@ -4,3 +4,75 @@ One line per landed feature, contract change, or open question.
Format: `[lane letter] YYYY-MM-DD — note` Format: `[lane letter] YYYY-MM-DD — note`
[.] 2026-07-16 — repo seeded: DESIGN.md (canon), PLAN3D.md (build plan), prototype/ (2D reference, do not modify) [.] 2026-07-16 — repo seeded: DESIGN.md (canon), PLAN3D.md (build plan), prototype/ (2D reference, do not modify)
[A] 2026-07-16 — **M0 LANDED on main — rebase your lane onto it now.** stdlib `server.py` on :8801
(`--selfcheck` verifies the tree + prints URLs), `.claude/launch.json` → "shades3d", three r175
vendored in-repo at `web/world/vendor/` (no more reaching into 90sDJsim at runtime), `contracts.js`,
graybox 30×20 m yard, third-person camera, selftest harness. `python3 server.py` and it runs.
Selftest green: 18 pass / 4 skip (your lanes) in ~90 ms.
[A] 2026-07-16 — Yard layout is now FACT, build against it: 7 anchors, same shape as the prototype's —
h1/h2/h3 house fascia at x=-5/0/+5, y=2.6, z=-9.9 · t1 tree (-9, 3.2, 2) · t2 tree (8, 3.1, -2) ·
p1 post (-6.4, 3.9, 7.4) · p2 post (5.3, 3.9, 8) — posts are raked 8° away from yard centre.
Garden bed rect {x:1, z:2, w:6, d:4}. North (-Z) is the house edge. Sun sits in the NORTH
(Australian yard), elevation 55°, so sail shadows fall south onto the bed — and the house's
yard-facing wall is permanently backlit, which is correct and not a bug.
[A] 2026-07-16 — **CONTRACT ADDITIONS.** PLAN3D §4 didn't cover these and the code needs them. All are in
`contracts.js` with JSDoc. Shout here if any of them fight your lane:
· `world.heightAt(x,z) -> number` — ground height, closed-form, pure. Lane D clamps the player to
it, Lane C bounces debris off it.
· `world.gardenBed -> {x,z,w,d}` — the rect you pass to `sailRig.coverageOver()`.
· `world.sunDir -> Vector3` — unit vector from the GROUND **toward** the sun. Shade test is
`raycast(origin=groundPoint, direction=sunDir)`; a hit means shaded.
· `world.solids -> Object3D[]` — obstacles ONLY. **The ground is deliberately not in it** — use
`heightAt()`, it's exact and free. Raycasting 4800 terrain triangles a frame took the camera
selftest from 78 ms to 4088 ms before I pulled it out.
· `player.update(dt,t)` — main.js has to step the player from somewhere.
· `camera.yaw -> number` — Lane D, your WASD is relative to this.
· `game.on(type, fn)` with type `'phaseChange'``{from, to}`. §4 wrote it as
`game.on(phaseChange)`; implemented Emitter-style for consistency with `sailRig.events`.
· `checkContract(name, obj) -> string[]` — asserts a module matches its contract. This is the
merge tripwire; I run it on every lane's module after every merge.
[A] 2026-07-16 — **CONTRACT CLARIFICATION — Lane B read this one.** `anchor.sway(t)` returns the
**ABSOLUTE world position**, not an offset. It is exactly what you pin a cloth corner to:
`node.copy(anchor.sway(t))`. (The prototype's `anchorPos()` is the precedent.) House and post
anchors return a constant; tree anchors wander with the wind they stand in — that wander IS dynamic
load, and it's why a tree anchor is the scary choice. Each anchor owns its own scratch vector so two
anchors can never alias, but the vector is reused between calls on the same anchor: clone before you
store it. Asserted both ways in `js/tests/a.test.js`.
[A] 2026-07-16 — selftest.html is **import-only and nobody edits it**. Each lane owns
`web/world/js/tests/<letter>.test.js` — stubs are pre-created and currently `skip`, with your
PLAN3D asserts written into the header comment. Five lanes sharing one selftest.html would be the
single guaranteed merge conflict in this repo. Harness + assert helpers in `js/testkit.js`; drive
time with `fixedLoop()`, never rAF (rAF is throttled in a hidden tab — verified, the game loop
genuinely stalls at t=0.07 s there, so a rAF-driven selftest would be a lie).
[A] 2026-07-16 — main.js drives an M0 **placeholder capsule** that satisfies the Player contract, purely
so the camera has something to follow. Lane D: when player.js is ready, ping here — I'll swap the
factory call in boot() and delete the placeholder. You shouldn't need to touch main.js.
[A] 2026-07-16 — ⚠️ **PLAN3D §2's asset inventory was substantially wrong and is now corrected in-place.**
Verified against the filesystem on `m3ultra` (Spotlight + find over `~` and `/Volumes`):
· `3D-STORE` is at **`~/Documents/Destroyulater/3D-STORE/`**, not `~/Documents/3D-STORE/`.
`clean_glbs/` is there and does contain exactly the promised debris (BlueCrate_v2, BlackTub_v2,
WhiteTub_v2, WoodenBin_v2, LibraryTrolley_v1). `build_booth_room_v23.py` is there too, and also
at `~/Documents/3dstore/`. **Lane E: your inputs are real, just relocated.**
· **DOES NOT EXIST anywhere on this box:** `~/Documents/3D=models/` (characters, the 32 anim clips,
street-furniture incl. `building_shell_01.glb`, furniture, props-scenes), `~/Documents/character_kit/`,
`~/Documents/mixamo-fetch/`, `~/Documents/FBX/`.
· Real and verified: the 21-ped fleet at `90sDJsim/web/world/models/peds/`, and
`90sDJsim/DEVMANUAL.md`.
**Lane D, this lands on you:** §5-D assumed the character_kit retarget pipeline and a Mixamo clip
library; neither is here. The only clips I found are `peds/idle.glb` and `peds/walk.glb`. A walking
character is still reachable; Running / Falling / Crouch-To-Stand / crank / dig are not sourced.
Don't spend a day looking — answer is needed from whoever wrote §2.
[A] 2026-07-16 — ❓ **OPEN QUESTION, needs a human.** PLAN3D §0 says lanes run on "the M1 Ultra
(`johnking@100.91.239.7`, Tailscale)", but this box is `m3ultra` and already has
`~/Documents/shades-laneB/` and `shades-laneE/` checked out — so lanes are in fact running here, and
§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.