§ 3.03
← studies·R&D study · 2026·Houdini · Simulation · Geomorphology

Meandering river — oxbows from shortest paths

A Houdini simulation in which a single curve develops into a meandering river over many frames. Each frame a curvature signal pushes the channel sideways; oxbow lakes appear when a shortest-path step through a graph of nearby segments finds a shorter route across a loop, leaving the abandoned arc behind. The same step that updates the channel produces the topology change.

// 1 · intuition

Real rivers bend through a short feedback loop:

The simulation translates that loop into geometry. A curvature signal picks the direction every point on the curve should be pushed, and a small set of topology rules handles the cut-offs at the right moment.

// 2 · approach

Pipeline:

init curve  ──►  per-frame solver  ──►  river + accumulated oxbows

Initial curve

A straight line, evenly resampled, with a few layers of noise displacement applied across the middle. The displacement weight tapers to zero at both ends so the endpoints stay anchored from the start. This wobbled line is the seed the solver evolves from.

Each solver step

Compute the offset direction. The signed mean curvature of the current channel is measured and combined with the local tangent into a per-point displacement vector — a lateral push with a small downstream component. The push is again weighted to zero at the endpoints, so the channel only moves in its interior.

Push and reconnect. The displacement is added to each point. Nearby point pairs are then connected with shortcut edges, but only when they sit within a small search radius and their tangents are close to parallel. The parallel-tangent condition keeps the connection step local; without it, distant points across the canvas can also fall within the radius and get wired together.

Find the new channel. Shortest-path is run from start to end on the augmented graph.

The same shortest-path step that updates the channel also separates the oxbow from it, so the topology change happens as part of the ordinary update.

Smooth and pin. A few rounds of blur and smooth keep the channel readable. A final pass identifies the channel's two endpoints by neighbour count — a real endpoint has exactly one neighbour — and locks them back to their initial positions. Oxbows are closed loops, so they have no one-neighbour points and stay out of this pass.

Old oxbows accumulate in the output, so a long run shows the river drifting across the canvas with the previous channels visible behind it.

// 3 · properties
// 4 · side experiment · closed loops

I tried the same approach on a closed curve — a ring-shaped river with no start and no end. Mixed result:

A working closed-loop version would need three different pieces: an arc-length-integrated upstream curvature signal (a simplified Howard–Knutson), Taubin smoothing in place of plain Laplacian so the ring doesn't contract toward its centroid, and a graph-theoretic ring-splitting routine in place of shortest-path. That is a separate project.

// 5 · process · 6 images
← back to studies