reason-machines/trending-skills1 file

Webphysics Avbd Engine

WebGPU rigid-body/soft-body physics engine based on the AVBD (Augmented Vertex Block Descent) solver

Specification
Skill ID
reason-machines/trending-skills/webphysics-avbd-engine
Publisher
reason-machines
Repository
trending-skills
Installs
0
Files
1
Synced
Sep 23, 2026
How to use it

Open any RiverX project, open the Skills panel in the chat, and search for this identifier. The files are fetched from the source repository at install time.

reason-machines/trending-skills/webphysics-avbd-engineInstalls these files
  • SKILL.md

What this skill tells the agent

webphysics-avbd-engine

Skill by ara.so — Daily 2026 Skills collection.

What It Does

webphysics is an experimental WebGPU-accelerated rigid-body and soft-body physics engine implementing the AVBD (Augmented Vertex Block Descent) solver from Giles et al. (2025). It runs entirely on the GPU using WebGPU compute shaders and supports:

  • Rigid-body simulation with contacts, friction, and joints
  • GPU broad-phase collision detection via LBVH (Linear BVH)
  • Narrow-phase manifold generation with warm-start persistence
  • Graph-coloring-based parallel body solves
  • Springs and soft-body constraints
  • Body sleeping/diagnostics
Browser support: Chrome only (requires WebGPU). This is an experimental proof-of-concept, not a production library.

Installation & Setup

git clone https://github.com/jure/webphysics.git
cd webphysics
npm install
npm run dev        # development server
npm run build      # production build

The dev server typically starts at http://localhost:5173 (Vite-based).

Project Structure

src/
├── physics/
│   ├── PhysicsEngine.ts          # Main orchestration: substep loop, init, step
│   └── gpu/
│       ├── avbdState.ts          # Primal/dual solve, coloring, velocity finalization
│       ├── broadPhase.ts         # LBVH broad-phase candidate generation
│       ├── contactGeneration.ts  # Narrow-phase manifolds, per-body constraint lists
│       ├── contactRecord.ts      # Warm-start state persistence
│       └── avbdState.ts          # Inertial targets, primal init, iteration
├── lvbh/
│   └── GPULBVHBuilder.ts         # GPU LBVH construction
└── ...

Core API Usage

Initializing the Physics Engine

import { PhysicsEngine } from './src/physics/PhysicsEngine';

// Requires an existing GPUDevice
const adapter = await navigator.gpu.requestAdapter();
const device = await adapter.requestDevice();

const engine = new PhysicsEngine(device);
await engine.init();

Adding Rigid Bodies

// Add a static ground plane
engine.addBody({
  type: 'box',
  position: [0, -1, 0],
  rotation: [0, 0, 0, 1],   // quaternion [x, y, z, w]
  halfExtents: [10, 0.5, 10],
  mass: 0,                   // 0 = static/infinite mass
  restitution: 0.3,
  friction: 0.5,
});

// Add a dynamic rigid box
engine.addBody({
  type: 'box',
  position: [0, 5, 0],
  rotation: [0, 0, 0, 1],
  halfExtents: [0.5, 0.5, 0.5],
  mass: 1.0,
  restitution: 0.2,
  friction: 0.6,
});

Stepping the Simulation

const TIMESTEP = 1 / 60;
const SUBSTEPS = 10;

function gameLoop(dt: number) {
  engine.step(dt, SUBSTEPS);
  // Read back positions for rendering
  const bodyStates = engine.getBodyStates();
  renderBodies(bodyStates);
  requestAnimationFrame(gameLoop);
}
requestAnimationFrame(gameLoop);

Reading Body State for Rendering

// After engine.step(), retrieve updated transforms
const states = engine.getBodyStates();
for (const state of states) {
  const { position, rotation, bodyIndex } = state;
  // position: [x, y, z]
  // rotation: quaternion [x, y, z, w]
  updateMeshTransform(bodyIndex, position, rotation);
}

Adding Joints / Constraints

// Distance joint between two bodies
engine.addJoint({
  type: 'distance',
  bodyA: 0,
  bodyB: 1,
  anchorA: [0, 0.5, 0],   // local-space anchor on body A
  anchorB: [0, -0.5, 0],  // local-space anchor on body B
  restLength: 1.0,
  stiffness: 1e4,
});

Adding Springs (Soft Bodies)

engine.addSpring({
  bodyA: 2,
  bodyB: 3,
  anchorA: [0, 0, 0],
  anchorB: [0, 0, 0],
  restLength: 0.8,
  stiffness: 500,
  damping: 10,
});

AVBD Pipeline Reference

The solver follows Algorithm 1 from the AVBD paper:

1. collision detection (x^t)
      ↓
2. broad phase (LBVH)         → src/lvbh/GPULBVHBuilder.ts
      ↓
3. narrow phase + warm start  → src/physics/gpu/contactGeneration.ts
      ↓
4. per-body constraint lists  → src/physics/gpu/avbdState.ts
      ↓
5. graph coloring             → src/physics/gpu/avbdState.ts
      ↓
6. inertial target y, primal init, warm-start α/γ
      ↓
7. [loop] colored primal body solve (approx Hessian)
      ↓
8. [loop] dual + stiffness update
      ↓
9. finalize velocities

Key files per stage: | Stage | File | |-------|------| | Orchestration | src/physics/PhysicsEngine.ts | | Broad phase | src/physics/gpu/broadPhase.ts | | Narrow phase | src/physics/gpu/contactGeneration.ts | | Contact records | src/physics/gpu/contactRecord.ts | | AVBD solve | src/physics/gpu/avbdState.ts | | LBVH builder | src/lvbh/GPULBVHBuilder.ts |

Configuration Patterns

Solver Parameters

// Passed during engine construction or step
engine.step(dt, substeps, {
  gravity: [0, -9.81, 0],
  iterations: 10,          // AVBD inner iterations per substep
  restitutionThreshold: 1.0,
});

Tuning Stability

  • Increase substeps (e.g., 20) for stiff stacks or fast-moving bodies
  • Increase iterations for better constraint convergence
  • Use mass: 0 for static bodies (never moves, acts as infinite mass)
  • Lower stiffness values for softer, more stable joints
  • Set restitution: 0 + high friction for non-bouncy stacking

Common Patterns

Stack of Boxes

const groundIndex = engine.addBody({
  type: 'box',
  position: [0, 0, 0],
  halfExtents: [5, 0.25, 5],
  mass: 0,
  friction: 0.7,
  restitution: 0.1,
});

for (let i = 0; i < 8; i++) {
  engine.addBody({
    type: 'box',
    position: [0, 0.5 + i * 1.05, 0],
    halfExtents: [0.5, 0.5, 0.5],
    mass: 1.0,
    friction: 0.5,
    restitution: 0.1,
  });
}

Pendulum Chain with Distance Joints

let prevIndex = engine.addBody({
  type: 'box', position: [0, 5, 0],
  halfExtents: [0.1, 0.1, 0.1], mass: 0,
  friction: 0, restitution: 0,
});

for (let i = 1; i <= 5; i++) {
  const curr = engine.addBody({
    type: 'box', position: [0, 5 - i, 0],
    halfExtents: [0.15, 0.15, 0.15], mass: 1.0,
    friction: 0.1, restitution: 0,
  });
  engine.addJoint({
    type: 'distance',
    bodyA: prevIndex, bodyB: curr,
    anchorA: [0, -0.15, 0], anchorB: [0, 0.15, 0],
    restLength: 0.7,
    stiffness: 1e5,
  });
  prevIndex = curr;
}

Integrate with Three.js Rendering

import * as THREE from 'three';

const meshes: THREE.Mesh[] = [];

function syncPhysicsToRender() {
  const states = engine.getBodyStates();
  states.forEach((state, i) => {
    if (!meshes[i]) return;
    meshes[i].position.set(...state.position);
    meshes[i].quaternion.set(
      state.rotation[0], state.rotation[1],
      state.rotation[2], state.rotation[3]
    );
  });
}

function animate() {
  engine.step(1 / 60, 10);
  syncPhysicsToRender();
  renderer.render(scene, camera);
  requestAnimationFrame(animate);
}

Troubleshooting

WebGPU Not Available

Error: navigator.gpu is undefined
  • Only Chrome 113+ supports WebGPU by default
  • Enable via chrome://flags/#enable-unsafe-webgpu on older versions
  • Firefox/Safari do not currently support WebGPU

Simulation Explodes / Bodies Flying Off

  • Reduce timestep or increase substeps
  • Lower joint stiffness values
  • Ensure static bodies have mass: 0
  • Check that halfExtents are positive and non-zero

Bodies Sinking Through Ground

  • Increase iterations (try 15–20)
  • Increase substeps
  • Check collision shape sizing matches visual mesh

Performance Issues

  • This is a Chrome-only WebGPU project; GPU driver issues can cause slowdowns
  • Reduce body count or iteration count
  • Check chrome://gpu to ensure hardware acceleration is active

Build Errors

# Ensure Node.js >= 18
node --version
# Clear cache
rm -rf node_modules dist
npm install
npm run build

Limitations & Roadmap Notes

  • Chrome only — no Firefox/Safari support yet

Use this skill in a project

Open any RiverX project, search the Skills panel for reason-machines/trending-skills/webphysics-avbd-engine, and install it in one click.

Use this skill