debris: delete the dead sail.nodes seam — sail._applyDebris is the one contact model
The SPRINT2-era duck-typed path (if sail.nodes → applyToSail) has been dead since decision 5 chose option b, and was a double-apply waiting for the day anyone exposed .nodes. The sail key on step()'s world arg is accepted and ignored, documented. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
9d6db356d7
commit
b7a069069d
@ -182,7 +182,8 @@ export function createDebris(o = {}) {
|
|||||||
/**
|
/**
|
||||||
* @param {number} dt fixed step
|
* @param {number} dt fixed step
|
||||||
* @param {number} t storm time
|
* @param {number} t storm time
|
||||||
* @param {object} [world] {player, sail} — both optional, both duck-typed
|
* @param {object} [world] {player} — optional, duck-typed. (A `sail` key is
|
||||||
|
* accepted and ignored: debris-vs-sail is sail.js's `_applyDebris`.)
|
||||||
*/
|
*/
|
||||||
step(dt, t, world = {}) {
|
step(dt, t, world = {}) {
|
||||||
// storm JSON drives the spawns; poll the window so nothing is missed
|
// storm JSON drives the spawns; poll the window so nothing is missed
|
||||||
@ -194,7 +195,6 @@ export function createDebris(o = {}) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const player = world.player;
|
const player = world.player;
|
||||||
const sail = world.sail;
|
|
||||||
|
|
||||||
for (let i = pieces.length - 1; i >= 0; i--) {
|
for (let i = pieces.length - 1; i >= 0; i--) {
|
||||||
const p = pieces[i];
|
const p = pieces[i];
|
||||||
@ -269,10 +269,11 @@ export function createDebris(o = {}) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- sphere vs sail nodes: impulse ---
|
// debris-vs-sail lives in sail.js (`_applyDebris` reads `debris.pieces`
|
||||||
// Duck-typed: lights up the moment Lane B exposes nodes, silent until
|
// each step — SPRINT2 decision 5, option b). The old duck-typed seam
|
||||||
// then. See THREADS — B owns sail.js, so this is the seam we agreed on.
|
// here (`if (sail.nodes) applyToSail(...)`) is deleted, not dormant:
|
||||||
if (sail && sail.nodes) applyToSail(p, sail);
|
// had Lane B ever exposed `.nodes`, every hit would have been applied
|
||||||
|
// TWICE through two different contact models.
|
||||||
|
|
||||||
if (p.y < groundAt(p.x, p.z) - 5 || Math.abs(p.x) > bounds.x || Math.abs(p.z) > bounds.z) {
|
if (p.y < groundAt(p.x, p.z) - 5 || Math.abs(p.x) > bounds.x || Math.abs(p.z) > bounds.z) {
|
||||||
despawn(p);
|
despawn(p);
|
||||||
@ -292,33 +293,5 @@ export function createDebris(o = {}) {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Shove any cloth node the piece is intersecting, and lose some of the piece's
|
|
||||||
* own momentum doing it. Expects sail.nodes: [{x,y,z,px,py,pz}] (verlet, so we
|
|
||||||
* move position and let the integrator turn it into velocity).
|
|
||||||
*/
|
|
||||||
function applyToSail(p, sail) {
|
|
||||||
const nodes = sail.nodes;
|
|
||||||
const reach = p.r + 0.15;
|
|
||||||
const reachSq = reach * reach;
|
|
||||||
let hits = 0;
|
|
||||||
for (let i = 0; i < nodes.length; i++) {
|
|
||||||
const n = nodes[i];
|
|
||||||
const dx = n.x - p.x, dy = n.y - p.y, dz = n.z - p.z;
|
|
||||||
const dsq = dx * dx + dy * dy + dz * dz;
|
|
||||||
if (dsq > reachSq || dsq < 1e-9) continue;
|
|
||||||
const d = Math.sqrt(dsq);
|
|
||||||
// push the node out to the sphere surface along the contact normal
|
|
||||||
const push = (reach - d) / d;
|
|
||||||
n.x += dx * push; n.y += dy * push; n.z += dz * push;
|
|
||||||
hits++;
|
|
||||||
}
|
|
||||||
if (hits) {
|
|
||||||
const drag = Math.min(0.5, (hits * p.mass) / 400);
|
|
||||||
p.vx *= 1 - drag; p.vy *= 1 - drag; p.vz *= 1 - drag;
|
|
||||||
if (sail.onDebrisHit) sail.onDebrisHit(p, hits);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return debris;
|
return debris;
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user