Friday, March 6, 2026

A Simple Cloth Simulation in Julia — Inspired by My Son’s Blender Experiments

Four years ago, I watched my son Ridit, in class V at that time, experimenting with cloth and soft-body simulations in Blender. At that time he was deeply interested in learning how modern graphics tools simulate physical behaviour such as cloth, smoke, and rigid body dynamics.

One of his experiments is captured in this video:


Watching him explore Blender’s simulation tools sparked a thought in my mind:

Could I reproduce a simplified cloth simulation myself using code?

Years later, while exploring scientific computing with Julia, I decided to attempt exactly that.

The result is a small but interesting Verlet-integration based cloth simulation written entirely in Julia.


Why Verlet Integration?

In physics simulations used in games and graphics engines, Verlet integration is very popular because:

• It is simple
• It is numerically stable
• It does not explicitly require velocity storage

Many cloth simulators in early game engines relied on this technique.

The basic idea is:

$$
x_{new} = x_{current} + (x_{current} - x_{previous}) + a\Delta t^2
$$

Where:

  • (x_{current}) → current position

  • (x_{previous}) → previous position

  • (a) → acceleration (gravity, wind etc.)



Representing Cloth as a Grid

A cloth can be represented as a grid of particles connected by constraints.

Each particle stores:

  • Current position

  • Previous position

Neighbouring particles are connected by distance constraints that maintain the cloth structure.

o---o---o---o
|   |   |   |
o---o---o---o
|   |   |   |
o---o---o---o

Some particles are pinned so the cloth does not fall entirely.


The Julia Implementation

Below is the Julia program that simulates the cloth.

using LinearAlgebra
using Plots

nx = 25
ny = 20
spacing = 0.2
dt = 0.02
steps = 300
gravity = [0.0,-9.8]

# Create grid
pos = [ [i*spacing, j*spacing] for j in 1:ny, i in 1:nx ]
prev = deepcopy(pos)

# Pin top row
pinned = [(i,ny) for i in 1:nx]

constraints = []

for j in 1:ny
for i in 1:nx
if i < nx
push!(constraints, ((i,j),(i+1,j)))
end
if j < ny
push!(constraints, ((i,j),(i,j+1)))
end
end
end

function verlet_step(step)

wind = [2*sin(0.05*step),0.0]

for j in 1:ny
for i in 1:nx

if (i,j) in pinned
continue
end

temp = pos[j,i]

accel = gravity + wind

pos[j,i] = pos[j,i] + (pos[j,i]-prev[j,i]) + accel*dt^2

prev[j,i] = temp
end
end
end

function satisfy_constraints()

for ((i1,j1),(i2,j2)) in constraints

p1 = pos[j1,i1]
p2 = pos[j2,i2]

delta = p2 - p1
dist = norm(delta)

rest = spacing
diff = (dist-rest)/dist

if !((i1,j1) in pinned)
pos[j1,i1] += delta*0.5*diff
end

if !((i2,j2) in pinned)
pos[j2,i2] -= delta*0.5*diff
end
end
end

anim = @animate for step in 1:steps

verlet_step(step)

for k in 1:6
satisfy_constraints()
end

x = [pos[j,i][1] for j in 1:ny, i in 1:nx]
y = [pos[j,i][2] for j in 1:ny, i in 1:nx]

scatter(x,y,legend=false,xlim=(0,6),ylim=(-5,6),markersize=3)
end

gif(anim,"cloth.gif",fps=30)


And here is the video if we run this application.



What the Simulation Does

The simulation includes:

1. Gravity

gravity = [0.0,-9.8]

Every particle experiences downward acceleration.


2. Wind Force

wind = [2*sin(0.05*step),0.0]

A sinusoidal wind creates cloth fluttering.


3. Constraint Relaxation

Multiple iterations enforce distance constraints so the cloth maintains its shape.

for k in 1:6
    satisfy_constraints()
end

This technique is commonly used in Position Based Dynamics.


Visual Result

The script generates an animated GIF showing a cloth hanging from the top row while wind and gravity deform it dynamically.

Even with a few dozen lines of code, we get a convincing physical effect.


What Makes Julia Interesting for Graphics Simulation

Working with Julia gives several advantages:

• Fast numerical computation
• Simple array operations
• Easy prototyping for physics simulations
• Smooth transition from mathematics to implementation

This makes it attractive for engineers exploring scientific computing, graphics, and simulation together.


A Personal Reflection

This small experiment reminded me of the moment I watched my son exploring cloth simulation in Blender years ago.

Back then he was experimenting visually.
Today I tried to rebuild the physics underneath that visual tool.

Sometimes inspiration in engineering does not come from textbooks — it comes from watching curiosity in the next generation.

And that curiosity often pushes us to explore deeper layers of science and software.