You are browsing as a guest. Sign up (or log in) to start making projects!

FaceFall

  • 5 Devlogs
  • 37 Total hours

Cool cloth simulation toy

Open comments for this post

13h 18m 48s logged

More ways to break the cloth

This update was mostly about adding interactive features.

The biggest one was cloth tearing. My first attempt never actually worked because the strain limiter prevented springs from stretching far enough to snap. The fix was checking the stretch before the limiter ran, then making sure tearing also removed the connected shear and bend springs so pieces actually separated instead of hanging by invisible links.

I also added:

  • A throwable physics ball that transfers momentum into the cloth.
  • Mouse grabbing so you can pull and fling the fabric around.
  • A live tension heatmap to show where the cloth is under stress.
  • Slow motion (down to 1/8×) and frame-by-frame stepping for debugging.

The ball ended up being my favourite feature. Throwing it through a pinned curtain now rips a hole through the fabric, the stress heatmap lights up around the impact, and the cloth keeps simulating normally afterwards.

Everything was backed up with new self-tests for tearing and ball collisions, and the original cloth behaviour stayed identical when the new features were disabled.

0
0
18
Ship #1

What I made

FaceFall is a real-time 3D cloth simulator written in C99. It simulates cloth falling over spheres, cubes, and arbitrary OBJ meshes, with a live preview and deterministic MP4 export at up to 4K 120 FPS.

What was challenging

Getting the cloth to actually behave like fabric. Most of the work went into making the simulation stable while adding self-collision, realistic aerodynamics, and reliable mesh collision without particles tunnelling through geometry or the cloth exploding.

What I'm proud of

I'm most proud that it feels believable. You can change cloth resolution, material, wind, and colliders, then export smooth 120 FPS videos, all from a single C source file.

How to test it

Build with build.bat and run facefall.exe. I recommend using a 64×64 or 128×128 cloth, trying each collider, toggling self-collision, changing the fabric presets, and exporting a 120 FPS video with V. You can also run facefall --selftest to verify the physics automatically.

  • 4 devlogs
  • 24h
  • 13.78x multiplier
Try project → See source code →
Open comments for this post

8h 54m 25s logged

FaceFall - Devlog #3

Making the cloth actually feel like cloth

This update was all about making the simulation feel physically believable instead of just stable. Some things worked exactly as I’d hoped, some didn’t, and one bug ended up explaining why cloth doesn’t really bounce.

Better aerodynamics

The old simulation only used simple linear drag, which meant the whole cloth slowed down evenly in every direction. It worked, but everything fell like it was moving through syrup.

I replaced that with per-triangle aerodynamic forces. Every triangle now generates drag based on its orientation and velocity, so the cloth behaves much more naturally. A flat sheet catches the air like a parachute, while an edge-on sheet slices straight through it.

The drag is also normalised so changing the cloth resolution doesn’t completely change the way it falls.

The difference is surprisingly noticeable. Around the one second mark the cloth now billows into a canopy before landing, something the old solver never managed.

Self collision

Another thing I wanted was proper self collision.

Previously, folds could pass straight through each other. I implemented a spatial hash so nearby particles can efficiently detect overlaps without checking every possible pair, keeping the cost close to linear even on larger simulations.

The first time I tried self collision a while ago it was unstable because I only corrected positions. This time every collision also updates particle velocity, so the solver no longer fights itself.

Folded cloth now stacks into proper layers instead of collapsing through itself.

Softer collisions

I also rewrote the collision response.

Instead of instantly pushing particles outside the collider, objects now behave like spring-damper surfaces. The cloth compresses slightly into the collision shell before settling, which produces much smoother landings and completely removed the tiny jitter I was previously working around.

The bounce bug

This ended up being the most interesting part of the update.

I originally wanted the cloth to bounce realistically, so I tried several different approaches. None of them looked right.

While debugging I found something strange. After impact, some particles still had positive upward velocity for frame after frame, yet they never actually moved.

The culprit was strain limiting.

Every correction was changing particle positions without updating their velocities, meaning momentum was effectively disappearing from the simulation. Once I applied the matching velocity correction alongside each positional fix, impacts started travelling naturally through the cloth as visible waves instead of vanishing.

Ironically, fixing that bug also answered the original question.

Real cloth barely bounces.

Once the sheet starts draping over a sphere, the hanging fabric absorbs almost all of the remaining energy. Even with perfect restitution the cloth only lifted a few centimetres before settling again.

Because of that, the default fabric presets now use very low restitution values. Silk barely rebounds at all, while leather keeps a little more energy.

Higher frame rate

The simulator now runs internally at 120 FPS.

Preview mode still displays at 60 FPS by stepping the simulation twice per frame, while exports run at the full rate. Renders take longer, but the smoother motion is absolutely worth it, especially during impact.

Current state

This update made the simulation feel much closer to real fabric.

The cloth now catches the air properly, folded layers no longer pass through each other, collisions are smoother, and the behaviour after impact looks far more convincing than before.

It also reminded me that sometimes the most realistic result isn’t the one you expect. After spending hours trying to make the cloth bounce, the correct answer turned out to be that real cloth… mostly doesn’t.

0
0
8
Open comments for this post

2h 1m 48s logged

Going back to basics

After trying a few more “realistic” cloth techniques, I realised I’d made the simulation worse instead of better.

The biggest problems were all my own:

  • Self-collision pushed overlapping particles apart in position space without changing their velocity, so the springs immediately snapped them back and the whole cloth could launch itself across the scene.
  • Replacing bend springs with angle constraints made the cloth feel soft and unstable because the position-based constraints were fighting the force-based spring solver.
  • Per-triangle aerodynamic forces changed the way the cloth fell and settled, but not for the better.

Sometimes the simplest solution really is the right one.

I rolled the simulator back to the model that was already producing the best results:

  • Structural, shear, and bend springs
  • Per-particle wind
  • Linear air drag
  • Strain limiting as the only position correction

I removed self-collision and the angle-based bending entirely. Fabric presets now just adjust the bend spring stiffness, so materials like silk and leather still behave differently without adding unnecessary complexity. The settings menu was cleaned up to match.

The rendering improvements all stayed, including the updated shader, high-resolution offscreen exports (1080p, 1440p and 4K), and the quality-of-life improvements to the presets and UI.

I also added a --selftest mode that automatically runs a standard cloth drop onto the sphere and checks that the simulation stays stable. It verifies that particle positions remain finite, the cloth doesn’t explode or fling itself away, and structural springs stay within the configured strain limit.

0
0
9
Open comments for this post

1h 36m 8s logged

FaceFall — Devlog #2

2026-07-04 — The cloth was invisible the whole time

This update started with one simple bug report:

“the cloth barely renders and it keeps clipping into the model.”

It turned out to be three completely different problems.

By the end of today I’d rebuilt the renderer, rewritten parts of the collision system, doubled the maximum cloth resolution to 128x128, added adjustable cloth and collider sizes, and accidentally made the entire simulation explode into NaNs.

The invisible cloth

At first I assumed the renderer or lighting was broken.

It wasn’t.

The real problem was raylib’s batching. I disabled backface culling before submitting the cloth geometry, but re-enabled it before the batch was actually flushed to the GPU. The simulation itself was perfectly fine, but almost the entire cloth was getting backface-culled before it ever reached the screen.

The fix was simply flushing the render batch before and after changing the GPU state so the cloth was actually drawn with culling disabled.

While I was there I also rewrote the lighting. Instead of flat shading per quad, the cloth now generates smooth per-vertex normals and uses simple Gouraud shading. The difference is huge, especially on higher resolutions.

The clipping bug

The second issue was much harder.

The first problem was that my collision shell was far too thin. At lower resolutions the particles stayed outside the collider, but the rendered surface between them could still cut straight through the mesh. I fixed that by scaling the collision shell with particle spacing so coarse cloth stays slightly further away from the surface.

That solved part of it.

The bigger issue only showed up against thin meshes. Sometimes a particle could move completely through the object in a single step, and because the collision system only looked at the particle’s final position it would happily push it out of the wrong side.

The solution was switching to continuous collision detection. Every particle now stores its previous position, and I sweep that movement against the mesh instead of only checking where it ended up.

The explosion

My first implementation of continuous collision looked perfect.

For about three seconds.

Then the cloth completely disappeared.

It turned out I had created an energy feedback loop where particles bounced between both sides of thin geometry until the simulation exploded into NaNs.

Instead of pushing particles to a new position after a collision, I now simply restore their previous valid position and remove the inward velocity. It’s slightly more conservative, but completely stable.

Bigger simulations

With collision working properly again I increased the maximum cloth resolution from 64x64 to 128x128.

That pushed the simulation to over 16,000 particles, nearly 100,000 springs, and roughly 32,000 rendered triangles.

To keep performance reasonable I added a simple spatial grid for mesh collisions so particles only test nearby triangles instead of the entire mesh every substep.

The result is still effectively real-time, even at the highest resolution.

New settings

The settings menu also picked up a couple of new options:

  • Adjustable cloth size
  • Adjustable collider size

Changing either one rebuilds the simulation immediately, updates the collision data, and automatically reframes the camera so everything stays visible.

Current state

FaceFall is finally starting to feel like a proper tool rather than just a physics demo.

The renderer looks significantly better, collisions are much more reliable, larger simulations run comfortably, and exporting deterministic comparison clips is now almost entirely hands-off.

There’s still plenty left to do, especially around self-collision, but it’s getting much closer to the project I originally imagined.

0
0
9
Open comments for this post

11h 15m 22s logged

Dev Log #1 - FaceFall

I started FaceFall because I kept seeing those short videos where a cloth drops over the same object at different mesh resolutions, but I don’t know how to use things like Blender to make them myself. The difference between a 2x2 sheet and a dense mesh is surprisingly satisfying, and I wanted to build my own version from scratch instead of relying on an existing physics engine.

The goal isn’t just to make another cloth simulator. The mesh density is the whole point. At really low resolutions the cloth behaves more like a stiff piece of cardboard, while higher resolutions start producing proper folds, ripples, and believable draping.

Reference: https://www.youtube.com/shorts/s_G2gBbWYF0

What’s working

So far I’ve built a complete cloth simulator in a single C99 source file using raylib.

Current features include:

  • Mass-spring cloth simulation
  • Structural, shear, and bending springs
  • Hooke’s law with damping
  • Semi-implicit Euler integration
  • Runtime cloth resolutions from 2x2 up to 64x64
  • Sphere, cube, and arbitrary OBJ mesh colliders
  • Three application modes:
    • Settings
    • Live preview
    • Deterministic render/export
  • Direct ffmpeg export to MP4

At this point it’s less of a physics experiment and more of a small content creation pipeline. I can recreate the exact same simulation with different resolutions and export identical camera angles for comparison videos.

Challenges

The biggest challenge early on was stability. Increasing spring stiffness quickly caused the simulation to explode, so I ended up basing the number of simulation substeps on the spring frequency instead of using a fixed timestep.

The cloth also stretched far too much at first and looked more like rubber than fabric. Adding strain limiting made a huge difference and stopped the structural springs from over-extending.

Collision was easily the hardest part. Spheres and cubes weren’t too bad, but arbitrary OBJ meshes became a rabbit hole of closest-point tests, broad-phase checks, collision response, and trying to stop particles tunnelling straight through thin geometry.

I also spent longer than I’d like fighting Windows. Exporting raw frames through ffmpeg would randomly corrupt the output until I realised _popen needed to be opened in binary mode.

Current bug

The biggest thing I’m still working through is sphere collision.

Most of the time it behaves exactly how I’d expect, but every now and then parts of the cloth clip into the sphere instead of settling over the surface. Once a few particles end up inside the collider the cloth starts rendering incorrectly, so it’s pretty obvious when it happens.

I’m fairly confident the issue isn’t the spring solver anymore. The collision detection itself is finding the contacts, but the positional correction isn’t always pushing particles completely back outside the sphere. That’s the main thing I want to fix before moving on.

What’s next

Once the collision is reliable I want to polish the visuals and start generating comparison clips at different mesh densities.

That’s really the whole reason I started this project. Seeing the exact same cloth drop change from a rigid, blocky sheet into something that actually looks like fabric is surprisingly satisfying, and now I finally have a tool that lets me create those videos however I want.

0
0
7

Delete project?

Are you sure you want to permanently delete this project? This action cannot be undone.

All devlogs, followers, and associated data will be removed.

Followers

Loading…