Skip to content
Sample of Magneto Particles (Hodgin Magnetosphere)

hodgin_iquilezles · MagnetoParticles

Magneto Particles (Hodgin Magnetosphere)

Particles pulled and pushed by N orbiting magnetic anchors whose charges flip sign over time. Each particle feels a Coulomb-like 1/r^2 force from every anchor plus a tangential drift that gives trajectories a magnetic-field-line curvature. Particles trace a hue-cycling low-alpha stroke, producing the looping ribbon-like patterns Hodgin used in the iTunes Magnetosphere visualizer.

Original: https://roberthodgin.com/project/magnetosphere

▶ 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
hodgin_iquilezles
Source
hodgin × iquilezles
Evolution
particle
Render
path_tracing
Complexity
medium
Agents
1800
Year
2006
Author
Robert Hodgin (flight404)

Math essence

For each particle i and anchor j, add F = k * sign(q_j) * (anchor_j - pos_i) / ((r_ij^2 + eps)^(3/2)). Add a tangential component t_ij = perpendicular(F_radial) * q_j * tangential_drift. Integrate velocity with global drag and clamp to max_speed, draw a segment from previous to new position with a colour computed from per-particle hue in [0,1).

Parameters

Name Type Default Range Description
dim int 500 200–1000 Square canvas side length in pixels.
num int 1800 200–8000 Number of particles.
num_anchors int 6 1–16 Number of magnetic anchor points orbiting the centre.
anchor_strength float 180 20–600 Force constant k in the Coulomb-like term.
tangential_drift float 0.35 0–1.5 Strength of the perpendicular-to-radial drift that curves trajectories.
drag float 0.985 0.9–0.999 Per-frame multiplicative damping of velocity.
max_speed float 7 1–14 Speed clamp (px/frame).
trail_alpha int 32 4–96 Stroke alpha (0-255).
hue_jitter float 0.18 0–0.6 Per-frame random hue drift applied to each particle.

Reference

First 60 lines of reference.py. Full source: library_external/hodgin_iquilezles/MagnetoParticles/reference.py

from __future__ import annotations

from typing import ClassVar

import numpy as np


class MagnetoParticles:
    """Magneto Particles — Robert Hodgin (flight404) *Magnetosphere* lineage, 2006.

    Hodgin's *Magnetosphere* iTunes visualizer is a particle system in which
    every particle carries a small charge and is pulled/pushed by a small
    number of floating magnetic *anchors* whose charges oscillate over time.
    Particles trace a curved, color-tagged trail, producing the iconic
    looping magnetic-field-line look.

    The formula here uses N point sources with per-source attractive or
    repulsive Coulomb-like force  ``F = k * sign(charge) * r̂ / (r^2 + ε)``,
    adds a tangential drift for curvature, and accumulates a low-alpha
    stroke buffer.
    """

    family: ClassVar[str] = "hodgin_iquilezles"
    sketch: ClassVar[str] = "magnetoparticles"

    def __init__(
        self,
        dim: int = 500,
        num: int = 1800,
        num_anchors: int = 6,
        anchor_strength: float = 180.0,
        tangential_drift: float = 0.35,
        drag: float = 0.985,
        max_speed: float = 7.0,
        trail_alpha: int = 32,
        hue_jitter: float = 0.18,
        ink_color: tuple[int, int, int] = (255, 255, 255),
        background: tuple[int, int, int] = (6, 6, 12),
        **_,
    ) -> None:
        self.dim = dim
        self.num = num
        self.num_anchors = num_anchors
        self.anchor_strength = anchor_strength
        self.tangential_drift = tangential_drift
        self.drag = drag
        self.max_speed = max_speed
        self.trail_alpha = trail_alpha
        self.hue_jitter = hue_jitter
        self.ink_color = np.array(ink_color, dtype=np.float32)
        self.bg_color = np.array(background, dtype=np.float32)
        self.reset()

    def reset(self, seed: int | None = None) -> None:
        self.rng = np.random.default_rng(seed)
        self.x = self.rng.uniform(0, self.dim, size=self.num).astype(np.float32)
        self.y = self.rng.uniform(0, self.dim, size=self.num).astype(np.float32)
        a = self.rng.uniform(0, 2 * np.pi, size=self.num)
        s = self.rng.uniform(0.0, 1.5, size=self.num)
        self.vx = (s * np.cos(a)).astype(np.float32)

Try running it locally

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

python library_external/hodgin_iquilezles/MagnetoParticles/reference.py

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

More from hodgin × iquilezles

Sample of Boids Flock (Hodgin Murmuration)

Boids Flock (Hodgin Murmuration)

hodgin_iquilezles · BoidsFlock

A 2D flock of boids steered by Craig Reynolds' three classic rules (separation, alignment, cohesion) over a coarse spatial-hash neighbor query.

View →
Sample of Fractional Brownian Motion noise

Fractional Brownian Motion noise

hodgin_iquilezles · FBMNoise

Quilez's canonical fBM: a 2D value-noise base summed over N octaves whose frequency doubles and amplitude is multiplied by G = exp2(-H) per octave.

View →
Sample of Mulberry32 PRNG (stratified scatter)

Mulberry32 PRNG (stratified scatter)

hodgin_iquilezles · Mulberry32RNG

Mulberry32 is a tiny 32-bit-state pseudo-random number generator popularised in the demoscene and used pervasively by Quilez and other graphics programmers as the RNG inside procedural sketches.

View →
Sample of Saturn Rings (orbital resonance)

Saturn Rings (orbital resonance)

hodgin_iquilezles · SaturnRings

Thousands of particles are initialized in an annulus between inner_radius and outer_radius around a central mass, with circular orbital velocities v = sqrt(M/r).

View →
Sample of Smooth-Minimum SDF field

Smooth-Minimum SDF field

hodgin_iquilezles · SmoothMinSDF

Two animated 2D SDF primitives (a moving circle and a translating slab) are blended with Quilez's quadratic-polynomial smooth-minimum and rendered as a scalar field.

View →
Sample of Worley / Cellular Noise

Worley / Cellular Noise

hodgin_iquilezles · WorleyNoise

Quilez's classic 2D Worley noise: a unit grid of cells, each containing one pseudo-random feature point placed by a 2D integer hash.

View →

See all hodgin_iquilezles artworks →