Skip to content
Sample of Gesture Driven Field

akten_quayola · GestureDrivenField

Gesture Driven Field

Particles advected through a vector field whose structure is driven by a synthetic gesture signal: a chain of sinusoids at integer-related frequencies. The field is curl-mixed with its own curl, then composited onto a long-tailed decay canvas — producing ribboned, swirling streaks reminiscent of Akten's interactive Body Paint installation and his collaboration with Quayola on Forms (2011), which uses extrapolation to visualise gesture-driven dynamics.

Original: https://www.memo.tv/works/bodypaint/

▶ 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.

Family
akten_quayola
Source
akten × quayola
Evolution
particle
Render
particle_streaks
Complexity
medium
Agents
600
Year
2009
Author
Memo Akten (memo.tv) — Body Paint / Forms lineage

Math essence

Synthetic gesture g(x, y, t) = sum_k a_k * cos/sin(f_k * x ± f_k * y + phase_k + omega_k * t). Velocity = curl_mix * curl(g) + (1 - curl_mix) * grad(g). Each particle position is updated modulo canvas size and its colour is painted with a 12% alpha and the canvas is decayed towards the background by (1 - decay) per step.

Parameters

Name Type Default Range Description
num_particles int 600 200–2000 Number of particles advected each frame.
dim int 512 256–1024 Output canvas side length.
num_chains int 6 3–10 Number of integer-ratio sinusoid chains in the gesture signal.
gesture_amp float 0.7 0.2–1.5 Amplitude scaling of the gesture field.
curl_mix float 0.35 0–1 Mix between curl-of-gesture (swirling) and gradient-of-gesture (directional).
decay float 0.965 0.85–0.999 Per-step retention of previous canvas (longer streaks at higher values).

Reference

First 60 lines of reference.py. Full source: library_external/akten_quayola/GestureDrivenField/reference.py

from __future__ import annotations

from typing import ClassVar

import numpy as np


class GestureDrivenField:
    """Gesture Driven Field — Memo Akten, *Body Paint* / *Forms* lineage.

    Akten's Body Paint (2009) interprets audience movement into fluid
    velocity; his collaboration with Quayola, *Forms* (2011), generalises
    the gesture → vector field coupling.  Here the gesture signal is
    synthetic:  a sum of sinusoids at small-integer frequencies, exactly
    the kind of "complex signal broken down into its basic elements at
    different frequencies" Akten describes in his SHM writings.  The
    field is the spatial gradient of that scalar gesture field, and
    particles are advected by it, leaving long-lived streaks.

    The result is a swirling, ribboned field reminiscent of Akten's
    interactive painting installations.
    """

    family: ClassVar[str] = "akten_quayola"
    sketch: ClassVar[str] = "GestureDrivenField"

    def __init__(
        self,
        num_particles: int = 1500,
        dim: int = 512,
        num_chains: int = 6,
        gesture_amp: float = 2.5,
        curl_mix: float = 0.5,
        decay: float = 0.985,
        seed: int | None = None,
        background: tuple[int, int, int] = (10, 8, 18),
        **_,
    ) -> None:
        self.num_particles = int(num_particles)
        self.dim = int(dim)
        self.num_chains = int(num_chains)
        self.gesture_amp = float(gesture_amp)
        self.curl_mix = float(np.clip(curl_mix, 0.0, 1.0))
        self.decay = float(np.clip(decay, 0.8, 0.999))
        self.bg_color = np.array(background, dtype=np.float32)
        self.reset(seed=seed)

    def reset(self, seed: int | None = None) -> None:
        self.rng = np.random.default_rng(seed)
        self.t = 0.0
        ratios = np.array([1.0, 2.0, 3.0, 4.0, 5.0, 6.0], dtype=np.float32)
        idx = self.rng.integers(0, len(ratios), size=self.num_chains)
        self.freqs = ratios[idx]
        self.phases = self.rng.uniform(0.0, np.pi * 2.0, size=self.num_chains).astype(np.float32)
        self.amps = self.rng.uniform(0.4, 1.0, size=self.num_chains).astype(np.float32)
        self.positions = self.rng.uniform(0.0, 1.0, size=(self.num_particles, 2)).astype(np.float32)
        self.hues = self.rng.uniform(0.0, 1.0, size=self.num_particles).astype(np.float32)
        self.canvas = np.tile(self.bg_color, (self.dim, self.dim, 1))

    def step(self, n: int = 1) -> None:

Try running it locally

The reference implementation is self-contained Python with numpy. Install the package and run:

python library_external/akten_quayola/GestureDrivenField/reference.py

Need help? See Learn for the standard environment setup, or Playground for an in-browser sketchbook.

More from akten × quayola

Sample of Lissajous 3D

Lissajous 3D

akten_quayola · Lissajous3D

A three-dimensional Lissajous figure rendered as a single precision line drawing on a deep field.

View →
Sample of Mechanical Flower Spline

Mechanical Flower Spline

akten_quayola · MechanicalFlowerSpline

A 2D petal-radius spline r(θ) = r0 + A*cos(p*θ + δ) + B*cos(q*θ) swept 360° around a vertical Y axis to form a procedural flower-like 3D surface, then orthographically projected and depth-shaded.

View →
Sample of Pleated Fabric

Pleated Fabric

akten_quayola · PleatedFabric

A textile grid whose vertical coordinate follows z = A * envelope(y) * sin(2π f x + phase(t)), projected obliquely onto a 2D canvas so the folds read as parallel ridges of light.

View →
Sample of Simple Harmonic Motion

Simple Harmonic Motion

akten_quayola · SimpleHarmonicMotion

A 100x100 grid of damped harmonic oscillators driven by a periodic central impulse.

View →
Sample of Strata Landscape

Strata Landscape

akten_quayola · StrataLandscape

A geological landscape rendered as N horizontal strata stacked vertically, each band displaced by a slowly growing sinusoid and shaded with its own hue.

View →
Sample of Wave Interference

Wave Interference

akten_quayola · WaveInterference

N drifting point sources emit circular sinusoidal waves whose superposition is tone-mapped into a stormy ocean-like field.

View →

See all akten_quayola artworks →