webphysics-avbd-engine

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

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "webphysics-avbd-engine" with this command: npx skills add aradotso/trending-skills/aradotso-trending-skills-webphysics-avbd-engine

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:

StageFile
Orchestrationsrc/physics/PhysicsEngine.ts
Broad phasesrc/physics/gpu/broadPhase.ts
Narrow phasesrc/physics/gpu/contactGeneration.ts
Contact recordssrc/physics/gpu/contactRecord.ts
AVBD solvesrc/physics/gpu/avbdState.ts
LBVH buildersrc/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
  • Not a drop-in npm package; must clone and integrate manually
  • Double-buffered position updates (for same-color conflict safety) not yet implemented — current path uses in-place colored body solve in avbdState.ts
  • Experimental API — breaking changes expected
  • No TypeScript type declarations exported for external use yet

References

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

General

openclaw-control-center

No summary provided by upstream source.

Repository SourceNeeds Review
General

ui-ux-pro-max-skill

No summary provided by upstream source.

Repository SourceNeeds Review
General

chrome-cdp-live-browser

No summary provided by upstream source.

Repository SourceNeeds Review
General

lightpanda-browser

No summary provided by upstream source.

Repository SourceNeeds Review