Particle Art

A compositing network whose medium is a million 3D particles: each node takes particles in and writes particles out. Sources decide what the population IS — File reads a DROPPED file, Scan seeds on the vertices of anything already in the view, Shape is an analytic emitter for a piece with nothing imported, and Data and Stream read a state-authored table of xyz points or a live feed. A drop is an INGEST, never an instruction: the file lands in a pool, and a File node subscribing to what it IS — the first mesh, the second table — is the only thing that consumes it. That is what makes a published piece interactive, because it cannot know the filename a viewer will drop, only that it wants a surface. The file arrives whole and unparsed, so the node decides what an OBJ means; a dropped mesh also appears in the scene because seeing what you dropped is the right default, and the pool is the durable record, so removing it from the scene does not discard it and Add to scene puts it back. A DROP IS SESSION-ONLY, though: the declaration is saved with the track and the bytes are not, so a pooled drop comes back named and empty and a File node reading it says so. Import the same file from the project assets instead — that entry keeps where it came from and is re-fetched on every load, which is the difference between a sketch and a piece that still works tomorrow. Forces are nodes rather than one global field, which is what makes the graph worth having: an attractor, a repeller, a vortex, wind or divergence-free curl-noise turbulence moves only the particles wired through it. Deformers displace position instead of velocity, and Snap home pulls every particle back toward its own seed vertex — that is what holds a scanned form together while the motion churns through it, and without it the whole piece collapses a few seconds in. Every node is inlined into ONE position pass and ONE velocity pass, so twenty-four nodes are two shaders and one draw call rather than twenty-four render-target pairs, which at a million particles would be 1.6 GB. There is therefore no per-node buffer to hand along, and a wire is a MASK: each source owns a slice of the texture and a node applies only to the sources that reach it, while a Mask node pushes a per-particle test onto everything downstream of it. Persistence is the default here, unlike Node Art's opt-in feedback — a simulation's buffers are its accumulated history — so the opt-in is its opposite, Reseed. Any number can be an expression over t instead, evaluated once a frame, so a force breathing on 20 * sin(t) costs nothing to rebuild; Field, Warp and Mask take a PER-PARTICLE expression instead, over px/py/pz, vx/vy/vz, age, life and a per-particle rnd, in the same vocabulary Code Art and Form Art already use. There is no code pane, because that grammar is the programmable surface: it is closed, so a new node kind can be declared from a track's own state and still genuinely render. Every random draw is seeded, so the same seed is the same artwork on every screen. Positions never come back to the CPU on the GPU tier — but a device that cannot serve float render targets gets the same graph integrated in JS at 20k particles instead of an empty canvas, brightened to hold the ink budget at the smaller population, and info() says which tier it is on and why. Ships empty, and Load is where a piece comes from: hello is three nodes, two-worlds is the one to read to see what a wire means, and fireflies is written entirely in expressions. Or ask for one.

Supported file formats: OBJ, PLY, STL, XYZ, PTS, CSV, TSV, TXT, DAT, ASC, 3MF, GLB, GLTF, FBX, STEP, STP, IGES, IGS, BREP, BRP, PCD, LAS, LAZ, X3D, ADPBREP, VZBREP