helix_noise/lib.rs
1//! # Helix Noise
2//!
3//! A divergence-free **helical (Beltrami) spectral flow-field** noise. The field is an analytic
4//! sum of divergence-free helical modes, so it can be evaluated grid-free at any point in space
5//! and time and its curl (vorticity) and vector potential come out in closed form. Handy for
6//! curl-noise particle advection, smoke and fluid-looking motion, procedural vector textures,
7//! and GPU flow shaders.
8//!
9//! This crate is a port of the JavaScript `helix-noise` library with numerical parity: the
10//! deterministic `mulberry32` mode-construction stream is bit-identical, so a field built with
11//! the same options and seed reproduces the reference values to floating-point tolerance.
12//!
13//! The crate has **zero runtime dependencies** and no threads or I/O in the hot path, so it
14//! compiles cleanly to WebAssembly.
15//!
16//! ## Quickstart
17//!
18//! ```
19//! use helix_noise::{HelixField, HelixOptions};
20//!
21//! let field = HelixField::new(HelixOptions { seed: 42, modes: 48, ..Default::default() });
22//!
23//! // Velocity at a point.
24//! let u = field.sample(1.0, 2.0, 3.0);
25//!
26//! // Velocity animated in time.
27//! let u_t = field.sample_t(1.0, 2.0, 3.0, 0.5);
28//!
29//! // Velocity + vorticity in one pass.
30//! let (u, w) = field.sample_uw(1.0, 2.0, 3.0, 0.0);
31//! # let _ = (u, w, u_t);
32//! ```
33//!
34//! ## Custom spectrum
35//!
36//! ```
37//! use helix_noise::{HelixField, HelixOptions};
38//! let field = HelixField::new(HelixOptions {
39//! spectrum: Some(Box::new(|k: f64| (-k).exp())),
40//! ..Default::default()
41//! });
42//! # let _ = field.sample(0.0, 0.0, 0.0);
43//! ```
44//!
45//! ## Obstacles (free-slip boundary)
46//!
47//! ```
48//! use helix_noise::{HelixField, HelixOptions, BoundaryOptions};
49//! let field = HelixField::new(HelixOptions::default());
50//! let bounded = field.with_boundary(
51//! |x: f64, y: f64, z: f64| ((x - 3.0).powi(2) + (y - 3.0).powi(2) + (z - 3.0).powi(2)).sqrt() - 1.2,
52//! BoundaryOptions { thickness: 0.9, ..Default::default() },
53//! );
54//! let u = bounded.sample(2.0, 2.0, 2.0, 0.0);
55//! # let _ = u;
56//! ```
57//!
58//! ## Scope
59//!
60//! Covers both engines — the spectral [`HelixField`] and the sparse-atom [`HelixAtoms`] — plus
61//! the free-slip SDF boundary (which wraps either) and the GLSL/shader emitter. The atom-engine
62//! GLSL emitter of the JS reference is a documented follow-up and not yet ported.
63
64mod atoms;
65mod boundary;
66mod constants;
67mod field;
68mod glsl;
69mod rng;
70
71pub use atoms::{AtomOptions, HelixAtoms, ScalarField3};
72pub use boundary::{BoundaryOptions, BoundedField, VectorPotential};
73pub use constants::{ga, HelixOptions, Layout, SpectrumFn, TAU, VERSION};
74pub use field::{HelixField, ModeSnapshot};
75pub use glsl::GlslOptions;
76pub use rng::Mulberry32;