[render] fix GLB body-scale regression: pop settles to baseScale, not 1
The placement scale-pop hardcoded the settled scale to 1, which stomped a normalised GLB's fit-to-footprint root scale (s~2-3.5) down to 1 on the first sync, collapsing the body to raw geometry size (a speck) while the beacon/jam child meshes kept their own local scale. Store baseScale per entity (1 for placeholders, the normalisation scale for GLBs) and make the pop a multiplier on it. Verified full-size bodies on fresh loads in ?showroom and ?uidemo. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
0d491f8a2f
commit
3fc043e504
@ -760,3 +760,45 @@ was added. Round 5's measured **4.4ms/frame** at full load stands as the referen
|
||||
`firewall.glb` when it lands; per-mite orientation toward its `target` belt; heat-shimmer
|
||||
*relief* inside a cooler rectangle; bloom-loop belt tell; save/load camera state;
|
||||
LOD/culling if a real megabase ever drags the frame.
|
||||
|
||||
### Round 6 ADDENDUM — 2026-07-20 — Opus 4.8 — GLB body-scale regression fix
|
||||
|
||||
**Orchestrator caught a deploy-blocking regression at 0d491f8: GLB machine BODIES collapsed
|
||||
to specks (beacons + jam lights + labels still correct). Fixed in `entities.ts` — commit
|
||||
below. My round-6 verification missed it because I checked on an HMR'd session and wrongly
|
||||
attributed the small bodies to "asset normalisation"; on a FRESH load the specks are stark.**
|
||||
|
||||
**ROOT CAUSE — the placement-pop hardcoded the settled scale to 1, which is only true for
|
||||
placeholders.** A normalised GLB roots at its fit-to-footprint scale `s` (measured live:
|
||||
2.0–3.5 for the current wave). The pop's settle branch was
|
||||
`else if (rec.obj.scale.x !== 1) rec.obj.scale.setScalar(1)` — so on the very first sync it
|
||||
saw `2.08 !== 1` and stomped the root to 1, shrinking the body to raw geometry size (~0.63
|
||||
vs the correct 1.84 for a 2×2). The beacon and jam meshes carry their own local scale on
|
||||
child nodes, so they were untouched — which is exactly the "bodies vanished, beacons fine"
|
||||
signature the orchestrator reported.
|
||||
|
||||
**Why it surfaced now, honestly:** the pop code is UNCHANGED by me and the bug is latent for
|
||||
ANY non-placeholder settled scale ≠ 1. It bit this round because the live GLB wave normalises
|
||||
to s≈2–3.5 (verified: fresh `entry.create()` returns root scale 2.08 + a correct 1.84-wide
|
||||
body; the live post-pop root was scale 1 + a 0.63 speck). The pop only ever writes
|
||||
`rec.obj.scale`, so it was provably the resetter. It is not the beacon — a fresh create is
|
||||
correct; the pop destroys it one frame later.
|
||||
|
||||
**FIX:** the pop is now a MULTIPLIER on a stored `rec.baseScale` (captured from `obj.scale.x`
|
||||
at build = 1 for placeholders, the normalisation scale for GLBs), never an absolute. Settle
|
||||
compares against `baseScale`, not 1. Placeholders: identical behaviour (baseScale 1). GLBs:
|
||||
body stays full-size, and the placement scale-pop still plays (relative overshoot).
|
||||
|
||||
**VERIFIED on FRESH loads (hard navigate, no HMR), before/after described:**
|
||||
- `?showroom`: BEFORE = every GLB a speck on a full plinth; AFTER = all 27 render as full
|
||||
sculpted bodies filling their footprints, lifted + beaconed. Scene-graph confirms live
|
||||
roots now carry scale 2.0–3.5 and body world sizes match footprints (1.84 for 2×2, 2.76
|
||||
for 3×3), where they read 1.0 / 0.63 before the fix.
|
||||
- `?uidemo` (reference factory, default game zoom): BEFORE = specks; AFTER = full-size
|
||||
machines throughout, belts + cargo flowing. No console errors. `npm run check` clean,
|
||||
`npm test` 481/481.
|
||||
|
||||
**LESSON (for me and the next lane):** verify visual regressions on a cold load, not an
|
||||
HMR'd session — an HMR'd renderer can hold meshes normalised in a prior module state and
|
||||
mask a fresh-boot break. And a hardcoded `scale = 1` is a placeholder assumption that any
|
||||
scaled asset (GLB, future LOD) will trip; base-relative is the correct shape.
|
||||
|
||||
@ -60,6 +60,11 @@ interface Rec {
|
||||
wasScrammed: boolean;
|
||||
/** Seconds into the placement scale-pop; >= POP_TIME means settled. */
|
||||
pop: number;
|
||||
/** The object's settled scale. 1 for placeholders; the GLB fit-to-footprint scale for a
|
||||
* hot-swapped asset. The pop multiplies THIS, never resets to 1 — a normalised GLB roots
|
||||
* at s≠1 and hardcoding 1 collapsed the body to a speck (the beacon/jam sit on their own
|
||||
* local scale so they were unaffected, which is why only bodies vanished). */
|
||||
baseScale: number;
|
||||
}
|
||||
|
||||
const JAM_GEO = new THREE.SphereGeometry(0.09, 8, 6);
|
||||
@ -159,13 +164,15 @@ export class EntityLayer {
|
||||
if (alarm) anyAlarm = true;
|
||||
|
||||
// Placement thunk: overshoot then settle. Reads as weight landing on the floor.
|
||||
// The pop is a MULTIPLIER on the settled scale, never an absolute — a normalised GLB
|
||||
// settles at baseScale (s≠1), so resetting to 1 would collapse its body to a speck.
|
||||
if (rec.pop < POP_TIME) {
|
||||
rec.pop += dt;
|
||||
const k = Math.min(1, rec.pop / POP_TIME);
|
||||
const s = k < 1 ? 1 + Math.sin(k * Math.PI) * 0.22 : 1;
|
||||
rec.obj.scale.setScalar(k < 0.12 ? k / 0.12 : s);
|
||||
} else if (rec.obj.scale.x !== 1) {
|
||||
rec.obj.scale.setScalar(1);
|
||||
const mult = k < 1 ? 1 + Math.sin(k * Math.PI) * 0.22 : 1;
|
||||
rec.obj.scale.setScalar(rec.baseScale * (k < 0.12 ? k / 0.12 : mult));
|
||||
} else if (rec.obj.scale.x !== rec.baseScale) {
|
||||
rec.obj.scale.setScalar(rec.baseScale);
|
||||
}
|
||||
|
||||
// Harassed by a swarm: the machine stutters. Wrongness of motion is the tell (§8).
|
||||
@ -292,6 +299,7 @@ export class EntityLayer {
|
||||
all,
|
||||
wasScrammed: false,
|
||||
pop: POP_TIME, // settled by default; a real placement rewinds it to 0
|
||||
baseScale: obj.scale.x, // 1 for placeholders; the GLB normalisation scale otherwise
|
||||
};
|
||||
this.live.set(id, rec);
|
||||
return rec;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user