GPU beams and elastic rebound — v27 Create a flexible straight beam whose positions and rotations are solved on the GPU. Rendered geometry also reads GPU buffers directly. Use it for cantilever boards, springy rods and load/recovery experiments. Stable Cosserat formulation; this is not the AVBD or cloth solver. Create and wait for readiness before dropping a CS body onto it. await createGPUBeam("board", { start:{x:-2,y:1.2,z:0}, end:{x:2,y:1.2,z:0}, nodes:25, clampNodes:3, nodeMass:.25, stretchRigidity:100000, bendRigidity:2000, damping:.5, width:.45, thickness:.11 }); var state = await getGPUBeamState("board"); state.beam.ready Register an existing CS sphere so contact pushes both the sphere and beam. await addGPUBeamBody("board", "ball"); Beam endpoints, pins and forces use Unity-world coordinates. The legacy stock CS object API mirrors X: load("sphere","ball",-1.3,1.65,0) places the sphere at Unity-world x=+1.3, near this board's free end. CS object.pos.x and setPosition use that same mirrored convention. Do not put the load near the clamped end by mixing the two coordinate systems. Y and Z agree. Set a sustained force on one beam node. Zero removes the force; this is not a repeated position edit or an impulse. Indices start at zero. setGPUBeamForce("board", 24, 0, -20, 0); setGPUBeamForce("board", 24, 0, 0, 0); Tune stiffness and damping. EA is axial rigidity (N), EI bending rigidity (N m²). Damping is velocity decay per second. Lower damping gives stronger spring-back. Node count, node mass, rest endpoints and initial clamp require recreation. setGPUBeam("board", {bendRigidity:2000, damping:.5}); Move a kinematic pin or release an added pin. Initial rotational clamp nodes cannot be released individually. Recreate with clampNodes:0 for an unclamped rod. setGPUBeamPin("board", 12, 0, 1.2, 0); setGPUBeamPin("board", 12, 0, 1.2, 0, false); Pause, resume, reset or remove. Reset clears forces, restores rest geometry and pins, and keeps registered bodies. It does not reposition or stop those bodies. pauseGPUBeam("board"); startGPUBeam("board"); await resetGPUBeam("board"); removeGPUBeamBody("board", "ball"); removeGPUBeam("board"); Inspect current numerical state and contact. The small asynchronous snapshots support coupling and diagnostics; rendering never waits for them. var result = await getGPUBeamState("board"); result.beam.tip result.beam.tipDeflection result.beam.overlap result.beam.maxOverlap result.beam.sampleAge result.beam.maxStretch result.beam.finite result.beam.error Current scope - 4..64 nodes per straight-rest beam, at most 8 beams. Default 25 nodes, 32 iterations, 2 substeps. FixedUpdate must be at most 40 ms; 10 ms gave tighter contact in the native tests. Changing the whole game's physics clock is not part of this API. - Registered contact requires an enabled non-trigger SphereCollider with a Rigidbody. Normal-only, frictionless capsule-centerline contact; the visible rectangular width is not a full plank collider. Start with centered spheres. - Existing body mass, constraints, interpolation and physics script are preserved. Queued Rigidbody forces are included in predicted body motion. A stock prefab with its physics component disabled will not apply CS acc commands; do not assume a changed JS value proves a force reached Unity. A kinematic body can drive the rod but does not receive a physics reaction. - Pins are kinematic targets, not dynamic attachments. No rod self-collision, arbitrary-mesh contact, fracture, plasticity or calibrated continuum stress. - Stale GPU samples suspend rod stepping and increment staleSteps; nonfinite states stop it with an error. Inspect these rather than claiming a pass from FPS alone. Warm it before enabling a falling body. - A static load bends the board to equilibrium. To demonstrate spring-back, load it and then release the load. Do not fake the result with an upward impulse, a per-frame transform, or a replacement animation. Native evidence and browser status The 2026-11-04 Unity/Metal regression passed 1 kg and 4 kg loads at 10/20 ms physics steps, plus a freely moving sphere. About 60 FPS; peak overlap below 7 mm. The 1 kg vertical-guide launch test used 40, 80 and 120 N sustained downward loads, then removed them. At 120 N the ball rose 0.929 m from its compressed position and was measured moving upward at 2.44 m/s out of contact. This is elastic rebound, not a launch impulse. These are bounded test results, not a guarantee for every mass, geometry, load or GPU. Chrome/WebGPU acceptance, 2026-11-04 The saved Elastic Diving Board activity uses a stock 1 kg sphere and a vertical CS configurable-joint guide. A sustained downward force on beam node 20 loads the board; Release removes it. No upward impulse is applied. Measured rise from the loaded position: 0.52 m at 80 N (peak overlap 8.6 mm), 0.77 m at 120 N (peak overlap 10.9 mm). About 60 FPS on this Mac. The free sphere rolls off the sloped beam; returning to the guide resets it correctly. Full-page restoration, reset and repeated launches passed. These are bounded game-demo checks. Re-run-safe setup: initialize stock object/joint variables to null; wait for load callbacks; freeze while arranging; allow the shared-memory placement to reach Unity before creating a joint so its anchors use the new positions. Remove a previous named joint before rebuilding the demo. The stock sphere's physics component is disabled in its prefab, so the demonstration loads the board directly with setGPUBeamForce instead of relying on sphere.acc. Native evidence: GPU_CLOTH.txt and runtime-beam CSVs. Browser evidence: cs-science-framework/beam-release-20261104/tests/browser.json. Check getGPUCapabilities().gpuBeams after refreshing Game; Run alone does not replace the player. Browser integration retains the centered-sphere scope above.