Back to Logs
2026-02-19

Physics Deep Dive: Building Realistic Ragdoll Laundry

How we used Rapier physics engine to make cloth fall naturally.

Creating realistic physics for falling laundry was one of the most satisfying parts of building Laundry Sort. Here's how we made those clothes tumble just right.

The Physics Challenge

A simple cube falling straight down isn't interesting. But a piece of laundry tumbling randomly, with realistic bounces and friction? That's where the magic happens. We needed:

  1. Realistic Mass & Gravity: Clothes should feel light but still fall steadily
  2. Friction Against Surfaces: So they don't slide forever on the bins
  3. Collision Detection: Accurate detection to know when a piece lands in the correct bin
  4. Angular Momentum: So they spin and rotate naturally as they fall

Rapier Physics Engine

We chose Rapier (integrated via @react-three/rapier) because it's:

  • Written in Rust and compiled to WebAssembly for blazing-fast performance
  • Perfect for web-based 3D physics
  • Easy to integrate with React Three Fiber
  • Incredibly stable and accurate

Setting Up Physics for Laundry

// Each laundry piece uses a RigidBody with custom physics parameters
<RigidBody 
  colliders="hull"           // Convex hull collision
  restitution={0.6}          // Bounce factor
  friction={0.4}             // How much it sticks when sliding
  linearDamping={0.1}        // Air resistance
  angularDamping={0.3}       // Spin dampening
>
  {/* Mesh and colliders */}
</RigidBody>

Key Parameters Explained

  • Restitution (0.6): Controls bounciness. Lower = duller thuds, higher = super bouncy. We wanted clothes to feel light but not bouncy like rubber balls.
  • Friction (0.4): How much resistance when sliding. This prevents clothes from sliding endlessly across bin surfaces.
  • Linear Damping (0.1): Simulates air resistance. Makes falling feel more natural than instant acceleration.
  • Angular Damping (0.3): Prevents spinning forever. Real clothes settle their rotation relatively quickly.

Collision Detection & Sorting

The real trick is knowing when a piece lands in the correct bin:

onCollisionEnter={({ other }) => {
  const otherName = other.rigidBodyObject?.name || '';
  const colorMatch = COLOR_NAMES.find(c => otherName.includes(c));
  
  if (colorMatch && colorMatch === color) {
    // Correct bin!
    onSorted(true);
  } else if (COLOR_NAMES.some(c => otherName.includes(c))) {
    // Wrong bin
    onSorted(false);
  }
}}

We tag each bin with its color name, then check if the colliding object's color matches the bin. Simple, effective!

Performance Optimization

Rapier in WebAssembly is incredibly fast, but we still optimize:

  • Collision Culling: We limit the number of active laundry pieces to prevent physics from becoming a bottleneck
  • Memory Management: Old pieces are removed from the scene after 15 seconds to prevent memory leaks
  • Fixed Timestep: Rapier handles its own fixed timestep for stability

The Result

The combination of realistic physics, proper parameter tuning, and careful collision detection creates that satisfying thunk when a shirt lands in exactly the right bin. It feels good to sort laundry in Laundry Sort!

What aspects of physics-based game design interest you most? Let us know in the comments below!


End of Log