clone

an endless marble-race generator in the browser; the url is the seed, so every track can be shared

main
marbles / tools / physics-debug / ribbon-bisect.ts
ribbon-bisect.ts 1.6K
1import {2 PhysicsEngine,3 type PhysicsModule,4} from "/Users/dami/Developer/marbles/src/client/physics/engine.ts";5const factory =6 (await import("/Users/dami/Developer/marbles/static/dist/box3d.mjs"))7 .default as () => Promise<PhysicsModule>;89async function drop(name: string, vertices: number[], indices: number[]) {10 const m = await factory();11 const engine = new PhysicsEngine(m);12 engine.addSegment(0, [{ kind: "mesh", vertices, indices }]);13 engine.spawnMarble(0, [0.5, 1, 0.2], [0, 0, 0]);14 for (let i = 0; i < 120; i++) engine.step(1 / 60);15 const st = engine.state();16 console.log(17 `${name}: y=${st.pos[1].toFixed(3)} ${st.pos[1] > 0 ? "OK" : "FELL"}`,18 );19}2021// 1. The known-good square, via the engine path (winding [0,2,1]).22await drop("square-engine", [-2, 0, -2, 2, 0, -2, 2, 0, 2, -2, 0, 2], [23 0,24 2,25 1,26 0,27 3,28 2,29]);30// 2. Two-ring flat strip, 3 profile points each, ribbon-style indices.31// Rings along +x (travel), profile along +z. ribbonOf winding:32// (a, b+1, b), (a, a+1, b+1) per quad.33{34 const v: number[] = [];35 for (const x of [0, 2]) for (const z of [-1, 0, 1]) v.push(x, 0, z);36 const N = 3;37 const idx: number[] = [];38 const a = 0, b = N;39 for (let j = 0; j < N - 1; j++) {40 idx.push(a + j, b + j + 1, b + j);41 idx.push(a + j, a + j + 1, b + j + 1);42 }43 await drop("mini-ribbon", v, idx);44 // 3. Same but opposite winding.45 const idx2: number[] = [];46 for (let j = 0; j < N - 1; j++) {47 idx2.push(a + j, b + j, b + j + 1);48 idx2.push(a + j, b + j + 1, a + j + 1);49 }50 await drop("mini-ribbon-flip", v, idx2);51}