reas_processing · particleSpring
Particle-Spring Cloth (Verlet + Hooke)
A rectangular grid of free particles is connected by Hooke's-law springs at rest length 'spacing'. Every step Verlet integrates positions (x_new = 2*x - x_prev + a*dt^2) with damping, then a small number of constraint-satisfaction iterations pulls every spring back to its rest length. Selected points are pinned as anchors (top row, bottom corners, optional center) so the mesh hangs and falls under gravity, like a Reas-era cloth net simulation.
Original: http://formandcode.com
▶ Try the live demo (JS port) ▶ Run reference.py via Pyodide 10 formulas have instant JS ports. The Pyodide path runs the actual Python in your browser — first load is ~6 MB, then instant.
Math essence
Velocity is implicit: v = (x - x_prev)*damping. Spring correction: d = ||p1-p0||; offset = (p1-p0)/d * (rest - d)*spring_k/2; distribute +/- offset between the two endpoints respecting anchor pinning. Fully vectorized over all edges via numpy.
Parameters
| Name | Type | Default | Range | Description |
|---|---|---|---|---|
dim | int | 500 | 200–1200 | Square canvas side length. |
grid_w | int | 32 | 4–80 | Particles per row. |
grid_h | int | 24 | 4–80 | Particles per column. |
spacing | float | 20 | 4–60 | Initial spring rest length (pixels). |
spring_k | float | 0.04 | 0.005–0.5 | Hooke stiffness for one constraint pass. |
damping | float | 0.985 | 0.7–0.999 | Velocity damping factor. |
gravity | float | 60 | 0–300 | Downward acceleration magnitude. |
constraint_iterations | int | 6 | 1–20 | Position-relaxation passes per tick. |
anchor_top | bool | true | — | Pin the top row of particles. |
anchor_bottom_corners | bool | true | — | Pin the bottom-left and bottom-right corners. |
center_anchor | bool | false | — | Also pin the geometric center node (creates a hammock). |
bg_color | tuple | 245,240,230 | — | |
link_color | tuple | 60,70,90 | — | |
node_color | tuple | 220,80,70 | — | |
line_alpha | float | 0.85 | 0.1–1 | |
seed | int | null | 0–999999 |
Reference
First 60 lines of reference.py. Full source:
library_external/reas_processing/particleSpring/reference.py
from __future__ import annotations
from typing import ClassVar
import numpy as np
class ParticleSpring:
"""Particle-spring mass network with Verlet integration.
A grid of free particles is connected to its 4-neighbors by linear
Hooke's-law springs at rest length ``spacing``. A handful of points
are marked as anchors (pinned to fixed positions). Per step:
integrate with Verlet (x_new = 2*x - x_prev + a*dt^2), then
relax each spring a fixed number of constraint iterations so the
structure settles toward its rest-length network.
"""
family: ClassVar[str] = "reas_processing"
sketch: ClassVar[str] = "particleSpring"
def __init__(
self,
dim: int = 500,
grid_w: int = 32,
grid_h: int = 24,
spacing: float = 20.0,
spring_k: float = 0.04,
damping: float = 0.985,
gravity: float = 60.0,
constraint_iterations: int = 6,
anchor_top: bool = True,
anchor_bottom_corners: bool = True,
center_anchor: bool = False,
bg_color: tuple[int, int, int] = (245, 240, 230),
link_color: tuple[int, int, int] = (60, 70, 90),
node_color: tuple[int, int, int] = (220, 80, 70),
line_alpha: float = 0.85,
seed: int | None = None,
) -> None:
self.dim = dim
self.grid_w = grid_w
self.grid_h = grid_h
self.spacing = spacing
self.spring_k = spring_k
self.damping = damping
self.gravity = gravity
self.constraint_iterations = constraint_iterations
self._anchor_top = anchor_top
self._anchor_bottom_corners = anchor_bottom_corners
self._center_anchor = center_anchor
self.bg_color = np.array(bg_color, dtype=np.float32)
self.link_color = np.array(link_color, dtype=np.float32)
self.node_color = np.array(node_color, dtype=np.float32)
self.line_alpha = line_alpha
self._seed = seed
self.reset()
def reset(self, seed: int | None = None) -> None:
if seed is not None: Try running it locally
The reference implementation is self-contained Python with numpy. Install the package and run:
python library_external/reas_processing/particleSpring/reference.py Need help? See Learn for the standard environment setup, or Playground for an in-browser sketchbook.
More from reas · processing
2-D Totalistic Cellular Automaton (Conway + variants)
reas_processing · wolframCA2D
Each cell looks at its 8 Moore neighbors and applies a totalistic rule.
Gray-Scott Reaction-Diffusion
reas_processing · grayScottRD
Two scalar species U and V diffuse on a square grid with rates Du and Dv and react with feed F and kill k.
Lindenmayer L-system + Turtle Rendering
reas_processing · lindenmayer
An axiom string is rewritten by parallel production rules for a fixed number of iterations, then interpreted by a 2-D turtle: 'F' walks forward, '+/-' turn left/right, '['/']' push/pop state.
Perlin Streamlines
reas_processing · perlinStreamlines
A 2-D vector field is sampled from one or more octaves of Perlin gradient noise.
Voronoi Diagram from Random Seeds
reas_processing · voronoi
Every pixel on the canvas is colored with the palette color of the seed point closest to it.
Wolfram Elementary 1-D Cellular Automaton
reas_processing · wolframCA1D
Each row of the canvas is one generation of a Wolfram elementary cellular automaton.