§ 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:
- Flow erodes the outer bank of a curve, pushing the channel further outward.
- Over time the bend grows and the curvature exaggerates.
- Two non-adjacent stretches eventually drift close enough that the flow takes a shortcut, cuts the neck, and leaves the abandoned arc behind as an oxbow lake.
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.
- When a shortcut wins, that path becomes the new channel — a tighter route through what was a wider loop.
- The bypassed loop, no longer on the path, becomes the new oxbow.
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
- Long-running stability. The solver has no fixed length. Once balanced, it can keep going for thousands of frames, and the shape continues to mature as it runs.
- Topology change inside the update step. Oxbow formation uses the same shortcut-edge plus shortest-path step that produces each new channel, so a separate self-intersection check is unnecessary.
- A small set of knobs. Displacement strength, smoothing strength, and the search radius and cone angle for shortcut connection are the main parameters. Together they set how aggressively the river rewrites itself each frame.
// 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:
- ✓ The closed topology is preserved through the solver chain, and the feedback loop still evolves the curve.
- ✗ The lateral-displacement signal assumes an upstream / downstream direction. On a closed loop it instead pulls the whole ring toward its centroid, so the curve shrinks rather than meandering.
- ✗ Shortest-path doesn't apply to oxbow formation on a closed loop. A ring has no start or end, so there is no defined path to find; splitting one ring into two would need a different graph operation.
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