three-nebula is a magical 3D particle engine for the web. I maintain it, and v13.3.0 (Helix) is the first of a few releases working back toward the library's original design goals. This one is additive and backward-compatible, so it is a safe bump.
The engineering theme this release is determinism. Two new behaviors and four new emission zones all produce the same output given the same seed, which matters a lot when you want reproducible scenes, snapshot testing, or editor previews that do not drift between runs.
The first behavior, Vortex, applies a tangential swirl around an axis with optional inward or outward pull and radial falloff. It acts directly on particle velocity rather than going through the Force path, which means it sidesteps the internal Force x100 scaling quirk and stays predictable. The second, CurlNoise, drives particles with the curl of a Perlin field. The curl of a vector field is divergence-free, so particles roil without clumping into sinks. The noise is seeded through mulberry32 rather than Math.random, so nothing in the pipeline reaches for global nondeterministic state.
The four new zones (RingZone, DiscZone, CylinderZone, ConeZone) sample uniformly and are axis-aligned to +Y. Ring and Disc are planar emission zones, while Cone and Cylinder are solid and work as true 3D CrossZone boundaries. All five new types round-trip through System.fromJSON, and the debug renderer draws wireframes for the new zones, so serialization and tooling stay in step with the runtime.
Release notes and full changelog are here: https://github.com/creativelifeform/three-nebula/releases/tag/v13.3.0
I would be curious what people think about the seeded-RNG approach for a library like this. Threading an explicit seed everywhere instead of Math.random adds a little API surface, but it is what makes the JSON round-trip and snapshot tests reliable. Have you handled determinism differently in your own simulation or animation code?