@triforge/fluid-core 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,98 @@
1
+ import { MACGrid } from './MACGrid.js';
2
+ export interface FLIPSimulatorOptions {
3
+ /**
4
+ * Grid resolution along each axis.
5
+ * Higher = more detail, higher cost. Default 24.
6
+ * Blender: Fluid > Resolution Divisions.
7
+ */
8
+ resolution?: number;
9
+ /**
10
+ * World-space size of the fluid domain cube.
11
+ * Default 2 (a 2×2×2 metre box).
12
+ */
13
+ domainSize?: number;
14
+ /**
15
+ * World-space origin (bottom-left-front corner of the domain).
16
+ * Default [−1, −1, −1].
17
+ */
18
+ origin?: [number, number, number];
19
+ /**
20
+ * Number of fluid particles. Default 2000.
21
+ * Blender: Fluid > Particle Count.
22
+ */
23
+ particleCount?: number;
24
+ /**
25
+ * FLIP blend factor [0–1].
26
+ * 1 = pure FLIP (energetic, noisy), 0 = pure PIC (damped, stable).
27
+ * 0.95 matches Blender's default. Blender: Fluid > FLIP Ratio.
28
+ */
29
+ flipRatio?: number;
30
+ /** Gravity vector [x,y,z]. Default [0,−9.8,0]. */
31
+ gravity?: [number, number, number];
32
+ /** Pressure solver maximum iterations. Default 80. */
33
+ solverMaxIter?: number;
34
+ /** Pressure solver convergence tolerance. Default 1e-4. */
35
+ solverTolerance?: number;
36
+ /** Simulation substeps per frame. Default 3. */
37
+ substeps?: number;
38
+ }
39
+ /**
40
+ * FLIPSimulator — full FLIP (Fluid-Implicit-Particle) fluid simulation.
41
+ *
42
+ * Implements the Zhu & Bridson 2005 FLIP algorithm:
43
+ * 1. Transfer particle velocities → MAC grid (P2G, trilinear splat)
44
+ * 2. Apply body forces (gravity) on grid
45
+ * 3. Enforce solid boundary conditions
46
+ * 4. Solve pressure Poisson equation (conjugate gradient)
47
+ * 5. Subtract pressure gradient from grid velocity (projection)
48
+ * 6. Transfer grid velocity change back to particles (G2P, FLIP blend)
49
+ * 7. Advect particles through the corrected velocity field
50
+ *
51
+ * All parameters live in `parameters` for GSAP/st-keyframe animation.
52
+ *
53
+ * ```typescript
54
+ * const sim = new FLIPSimulator({ resolution: 20, particleCount: 1500 })
55
+ * sim.fillBox(-0.5, -0.5, -0.5, 0.5, 0.5, 0.5)
56
+ *
57
+ * // Each frame:
58
+ * sim.step(dt)
59
+ * const pts = sim.getPositions() // Float32Array [x,y,z, x,y,z, ...]
60
+ * ```
61
+ */
62
+ export declare class FLIPSimulator {
63
+ parameters: Record<string, number>;
64
+ readonly particleCount: number;
65
+ private readonly _grid;
66
+ private readonly _particles;
67
+ private readonly _b;
68
+ private readonly _x;
69
+ private readonly _nx;
70
+ private readonly _ny;
71
+ private readonly _nz;
72
+ constructor(opts?: FLIPSimulatorOptions);
73
+ /**
74
+ * Fill a world-space axis-aligned box with fluid particles.
75
+ * Particles are distributed using a jittered grid to avoid clumping.
76
+ * Multiple calls accumulate particles (capped at particleCount).
77
+ */
78
+ fillBox(x0: number, y0: number, z0: number, x1: number, y1: number, z1: number): void;
79
+ /** Advance the simulation by `dt` seconds (call once per frame, e.g. dt=1/60). */
80
+ step(dt: number): void;
81
+ private _substep;
82
+ private _p2g;
83
+ private _splatToFace;
84
+ private _pressureSolve;
85
+ private _g2p;
86
+ private _interpOld;
87
+ private _advect;
88
+ private _clampParticles;
89
+ /** Returns particle positions as a flat Float32Array [x,y,z, x,y,z, ...]. */
90
+ getPositions(): Float32Array;
91
+ /** Returns particle velocities as a flat Float32Array [vx,vy,vz, ...]. */
92
+ getVelocities(): Float32Array;
93
+ /** Number of live particles. */
94
+ get liveCount(): number;
95
+ /** The underlying MAC grid (for advanced use / surface reconstruction). */
96
+ get grid(): MACGrid;
97
+ }
98
+ //# sourceMappingURL=FLIPSimulator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FLIPSimulator.d.ts","sourceRoot":"","sources":["../src/FLIPSimulator.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AAEtC,MAAM,WAAW,oBAAoB;IACnC;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAA;IAEnB;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAA;IAEnB;;;OAGG;IACH,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAA;IAEjC;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAA;IAEtB;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,CAAA;IAElB,kDAAkD;IAClD,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAA;IAElC,sDAAsD;IACtD,aAAa,CAAC,EAAE,MAAM,CAAA;IAEtB,2DAA2D;IAC3D,eAAe,CAAC,EAAE,MAAM,CAAA;IAExB,gDAAgD;IAChD,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB;AAQD;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,qBAAa,aAAa;IACxB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAElC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAA;IAC9B,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAS;IAC/B,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAgB;IAG3C,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAe;IAClC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAe;IAClC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAQ;IAC5B,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAQ;IAC5B,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAQ;gBAEhB,IAAI,GAAE,oBAAyB;IA8B3C;;;;OAIG;IACH,OAAO,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAClC,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,IAAI;IAqBjD,kFAAkF;IAClF,IAAI,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI;IAMtB,OAAO,CAAC,QAAQ;IAwChB,OAAO,CAAC,IAAI;IAsBZ,OAAO,CAAC,YAAY;IA0BpB,OAAO,CAAC,cAAc;IAgHtB,OAAO,CAAC,IAAI;IAwBZ,OAAO,CAAC,UAAU;IAoBlB,OAAO,CAAC,OAAO;IAQf,OAAO,CAAC,eAAe;IAmBvB,6EAA6E;IAC7E,YAAY,IAAI,YAAY;IAU5B,0EAA0E;IAC1E,aAAa,IAAI,YAAY;IAU7B,gCAAgC;IAChC,IAAI,SAAS,IAAI,MAAM,CAAkC;IAEzD,2EAA2E;IAC3E,IAAI,IAAI,IAAI,OAAO,CAAsB;CAC1C"}
@@ -0,0 +1,404 @@
1
+ import pcg from 'conjugate-gradient';
2
+ import { MACGrid } from './MACGrid.js';
3
+ /**
4
+ * FLIPSimulator — full FLIP (Fluid-Implicit-Particle) fluid simulation.
5
+ *
6
+ * Implements the Zhu & Bridson 2005 FLIP algorithm:
7
+ * 1. Transfer particle velocities → MAC grid (P2G, trilinear splat)
8
+ * 2. Apply body forces (gravity) on grid
9
+ * 3. Enforce solid boundary conditions
10
+ * 4. Solve pressure Poisson equation (conjugate gradient)
11
+ * 5. Subtract pressure gradient from grid velocity (projection)
12
+ * 6. Transfer grid velocity change back to particles (G2P, FLIP blend)
13
+ * 7. Advect particles through the corrected velocity field
14
+ *
15
+ * All parameters live in `parameters` for GSAP/st-keyframe animation.
16
+ *
17
+ * ```typescript
18
+ * const sim = new FLIPSimulator({ resolution: 20, particleCount: 1500 })
19
+ * sim.fillBox(-0.5, -0.5, -0.5, 0.5, 0.5, 0.5)
20
+ *
21
+ * // Each frame:
22
+ * sim.step(dt)
23
+ * const pts = sim.getPositions() // Float32Array [x,y,z, x,y,z, ...]
24
+ * ```
25
+ */
26
+ export class FLIPSimulator {
27
+ constructor(opts = {}) {
28
+ const res = opts.resolution ?? 24;
29
+ const domainSize = opts.domainSize ?? 2;
30
+ const origin = opts.origin ?? [-1, -1, -1];
31
+ const h = domainSize / res;
32
+ this._nx = res;
33
+ this._ny = res;
34
+ this._nz = res;
35
+ this._grid = new MACGrid(res, res, res, h, origin[0], origin[1], origin[2]);
36
+ this.particleCount = opts.particleCount ?? 2000;
37
+ this._particles = [];
38
+ this._b = new Float64Array(res * res * res);
39
+ this._x = new Float64Array(res * res * res);
40
+ const g = opts.gravity ?? [0, -9.8, 0];
41
+ this.parameters = {
42
+ flipRatio: opts.flipRatio ?? 0.95,
43
+ gravityX: g[0],
44
+ gravityY: g[1],
45
+ gravityZ: g[2],
46
+ substeps: opts.substeps ?? 3,
47
+ solverMaxIter: opts.solverMaxIter ?? 80,
48
+ solverTolerance: opts.solverTolerance ?? 1e-4,
49
+ };
50
+ }
51
+ // ── Particle placement ────────────────────────────────────────────────────
52
+ /**
53
+ * Fill a world-space axis-aligned box with fluid particles.
54
+ * Particles are distributed using a jittered grid to avoid clumping.
55
+ * Multiple calls accumulate particles (capped at particleCount).
56
+ */
57
+ fillBox(x0, y0, z0, x1, y1, z1) {
58
+ this._particles.length = 0;
59
+ const h = this._grid.h;
60
+ const pph = 2; // particles per cell per axis (2³ = 8 per cell, standard FLIP)
61
+ const sp = h / pph;
62
+ for (let z = z0; z < z1; z += sp)
63
+ for (let y = y0; y < y1; y += sp)
64
+ for (let x = x0; x < x1; x += sp) {
65
+ if (this._particles.length >= this.particleCount)
66
+ break;
67
+ this._particles.push({
68
+ x: x + sp * Math.random(),
69
+ y: y + sp * Math.random(),
70
+ z: z + sp * Math.random(),
71
+ vx: 0, vy: 0, vz: 0,
72
+ });
73
+ }
74
+ }
75
+ // ── Main step ─────────────────────────────────────────────────────────────
76
+ /** Advance the simulation by `dt` seconds (call once per frame, e.g. dt=1/60). */
77
+ step(dt) {
78
+ const substeps = Math.max(1, Math.round(this.parameters.substeps));
79
+ const subDt = dt / substeps;
80
+ for (let s = 0; s < substeps; s++)
81
+ this._substep(subDt);
82
+ }
83
+ _substep(dt) {
84
+ const grid = this._grid;
85
+ const { nx, ny, nz, h } = grid;
86
+ // 1. Mark cells as fluid / air based on particle positions
87
+ const fluidSet = new Set();
88
+ for (const p of this._particles) {
89
+ const i = Math.floor((p.x - grid.ox) / h);
90
+ const j = Math.floor((p.y - grid.oy) / h);
91
+ const k = Math.floor((p.z - grid.oz) / h);
92
+ if (i >= 1 && i < nx - 1 && j >= 1 && j < ny - 1 && k >= 1 && k < nz - 1)
93
+ fluidSet.add(grid.idx(i, j, k));
94
+ }
95
+ grid.markCells((i, j, k) => fluidSet.has(grid.idx(i, j, k)));
96
+ // 2. P2G — splat particle velocities to grid faces
97
+ grid.clearVelocities();
98
+ this._p2g();
99
+ grid.normalizeWeights();
100
+ grid.saveVelocities();
101
+ // 3. Body forces + boundary
102
+ grid.applyGravity(this.parameters.gravityX, this.parameters.gravityY, this.parameters.gravityZ, dt);
103
+ grid.enforceBoundary();
104
+ // 4. Pressure projection
105
+ this._pressureSolve(dt);
106
+ // 5. G2P — transfer corrected grid velocities back to particles (FLIP blend)
107
+ this._g2p();
108
+ // 6. Advect particles
109
+ this._advect(dt);
110
+ // 7. Clamp particles inside domain
111
+ this._clampParticles();
112
+ }
113
+ // ── P2G (particle → grid) ─────────────────────────────────────────────────
114
+ _p2g() {
115
+ const grid = this._grid;
116
+ const { nx, ny, nz, h, ox, oy, oz } = grid;
117
+ for (const p of this._particles) {
118
+ // U faces (i-½, j, k) — offset by (0, h/2, h/2)
119
+ this._splatToFace(grid.u, grid.uW, p.vx, p.x - ox, p.y - oy - 0.5 * h, p.z - oz - 0.5 * h, nx + 1, ny, nz, h);
120
+ // V faces (i, j-½, k) — offset by (h/2, 0, h/2)
121
+ this._splatToFace(grid.v, grid.vW, p.vy, p.x - ox - 0.5 * h, p.y - oy, p.z - oz - 0.5 * h, nx, ny + 1, nz, h);
122
+ // W faces (i, j, k-½) — offset by (h/2, h/2, 0)
123
+ this._splatToFace(grid.w, grid.wW, p.vz, p.x - ox - 0.5 * h, p.y - oy - 0.5 * h, p.z - oz, nx, ny, nz + 1, h);
124
+ }
125
+ }
126
+ _splatToFace(arr, wArr, val, lx, ly, lz, Nx, Ny, Nz, h) {
127
+ let fi = lx / h, fj = ly / h, fk = lz / h;
128
+ fi = Math.max(0, Math.min(Nx - 1.0001, fi));
129
+ fj = Math.max(0, Math.min(Ny - 1.0001, fj));
130
+ fk = Math.max(0, Math.min(Nz - 1.0001, fk));
131
+ const i0 = Math.floor(fi), i1 = i0 + 1;
132
+ const j0 = Math.floor(fj), j1 = j0 + 1;
133
+ const k0 = Math.floor(fk), k1 = k0 + 1;
134
+ const tx = fi - i0, ty = fj - j0, tz = fk - k0;
135
+ const idx = (i, j, k) => i + Nx * (j + Ny * k);
136
+ const w000 = (1 - tx) * (1 - ty) * (1 - tz);
137
+ arr[idx(i0, j0, k0)] += w000 * val;
138
+ wArr[idx(i0, j0, k0)] += w000;
139
+ const w100 = tx * (1 - ty) * (1 - tz);
140
+ arr[idx(i1, j0, k0)] += w100 * val;
141
+ wArr[idx(i1, j0, k0)] += w100;
142
+ const w010 = (1 - tx) * ty * (1 - tz);
143
+ arr[idx(i0, j1, k0)] += w010 * val;
144
+ wArr[idx(i0, j1, k0)] += w010;
145
+ const w110 = tx * ty * (1 - tz);
146
+ arr[idx(i1, j1, k0)] += w110 * val;
147
+ wArr[idx(i1, j1, k0)] += w110;
148
+ const w001 = (1 - tx) * (1 - ty) * tz;
149
+ arr[idx(i0, j0, k1)] += w001 * val;
150
+ wArr[idx(i0, j0, k1)] += w001;
151
+ const w101 = tx * (1 - ty) * tz;
152
+ arr[idx(i1, j0, k1)] += w101 * val;
153
+ wArr[idx(i1, j0, k1)] += w101;
154
+ const w011 = (1 - tx) * ty * tz;
155
+ arr[idx(i0, j1, k1)] += w011 * val;
156
+ wArr[idx(i0, j1, k1)] += w011;
157
+ const w111 = tx * ty * tz;
158
+ arr[idx(i1, j1, k1)] += w111 * val;
159
+ wArr[idx(i1, j1, k1)] += w111;
160
+ }
161
+ // ── Pressure projection ───────────────────────────────────────────────────
162
+ _pressureSolve(dt) {
163
+ const grid = this._grid;
164
+ const { nx, ny, nz, h } = grid;
165
+ const N = nx * ny * nz;
166
+ const invH2 = 1.0 / (h * h);
167
+ // Build RHS: b[i] = div(u)[i] / dt (standard incompressible projection)
168
+ this._b.fill(0);
169
+ for (let k = 1; k < nz - 1; k++)
170
+ for (let j = 1; j < ny - 1; j++)
171
+ for (let i = 1; i < nx - 1; i++) {
172
+ const ci = grid.idx(i, j, k);
173
+ if (grid.cellType[ci] !== 1)
174
+ continue;
175
+ const div = (grid.u[grid.uIdx(i + 1, j, k)] - grid.u[grid.uIdx(i, j, k)]) / h
176
+ + (grid.v[grid.vIdx(i, j + 1, k)] - grid.v[grid.vIdx(i, j, k)]) / h
177
+ + (grid.w[grid.wIdx(i, j, k + 1)] - grid.w[grid.wIdx(i, j, k)]) / h;
178
+ this._b[ci] = div / dt;
179
+ }
180
+ this._x.fill(0);
181
+ const cellType = grid.cellType;
182
+ const idxFn = (i, j, k) => grid.idx(i, j, k);
183
+ // A = discrete positive-definite Laplacian (1/h² per neighbour pair)
184
+ const A = {
185
+ rowCount: N,
186
+ get: (row, _col) => {
187
+ if (cellType[row] !== 1)
188
+ return 1;
189
+ const kk = Math.floor(row / (nx * ny));
190
+ const rem = row - kk * nx * ny;
191
+ const jj = Math.floor(rem / nx);
192
+ const ii = rem - jj * nx;
193
+ let d = 0;
194
+ if (ii > 0 && cellType[idxFn(ii - 1, jj, kk)] !== 2)
195
+ d += invH2;
196
+ if (ii < nx - 1 && cellType[idxFn(ii + 1, jj, kk)] !== 2)
197
+ d += invH2;
198
+ if (jj > 0 && cellType[idxFn(ii, jj - 1, kk)] !== 2)
199
+ d += invH2;
200
+ if (jj < ny - 1 && cellType[idxFn(ii, jj + 1, kk)] !== 2)
201
+ d += invH2;
202
+ if (kk > 0 && cellType[idxFn(ii, jj, kk - 1)] !== 2)
203
+ d += invH2;
204
+ if (kk < nz - 1 && cellType[idxFn(ii, jj, kk + 1)] !== 2)
205
+ d += invH2;
206
+ return d > 0 ? d : 1;
207
+ },
208
+ apply: (xVec, out) => {
209
+ out.fill(0);
210
+ for (let k2 = 0; k2 < nz; k2++)
211
+ for (let j2 = 0; j2 < ny; j2++)
212
+ for (let i2 = 0; i2 < nx; i2++) {
213
+ const ci = idxFn(i2, j2, k2);
214
+ if (cellType[ci] !== 1) {
215
+ out[ci] = xVec[ci];
216
+ continue;
217
+ }
218
+ let sum = 0, cnt = 0;
219
+ if (i2 > 0 && cellType[idxFn(i2 - 1, j2, k2)] !== 2) {
220
+ sum += xVec[idxFn(i2 - 1, j2, k2)];
221
+ cnt++;
222
+ }
223
+ if (i2 < nx - 1 && cellType[idxFn(i2 + 1, j2, k2)] !== 2) {
224
+ sum += xVec[idxFn(i2 + 1, j2, k2)];
225
+ cnt++;
226
+ }
227
+ if (j2 > 0 && cellType[idxFn(i2, j2 - 1, k2)] !== 2) {
228
+ sum += xVec[idxFn(i2, j2 - 1, k2)];
229
+ cnt++;
230
+ }
231
+ if (j2 < ny - 1 && cellType[idxFn(i2, j2 + 1, k2)] !== 2) {
232
+ sum += xVec[idxFn(i2, j2 + 1, k2)];
233
+ cnt++;
234
+ }
235
+ if (k2 > 0 && cellType[idxFn(i2, j2, k2 - 1)] !== 2) {
236
+ sum += xVec[idxFn(i2, j2, k2 - 1)];
237
+ cnt++;
238
+ }
239
+ if (k2 < nz - 1 && cellType[idxFn(i2, j2, k2 + 1)] !== 2) {
240
+ sum += xVec[idxFn(i2, j2, k2 + 1)];
241
+ cnt++;
242
+ }
243
+ out[ci] = invH2 * (cnt * xVec[ci] - sum);
244
+ }
245
+ },
246
+ };
247
+ try {
248
+ pcg(A, this._b, this._x, this.parameters.solverTolerance, Math.round(this.parameters.solverMaxIter));
249
+ }
250
+ catch (_) { /* degenerate — keep zero pressure */ }
251
+ // Guard against NaN (degenerate geometry — no fluid cells, etc.)
252
+ for (let i = 0; i < this._x.length; i++) {
253
+ if (!isFinite(this._x[i])) {
254
+ this._x.fill(0);
255
+ break;
256
+ }
257
+ }
258
+ // Subtract pressure gradient — loop over faces (each face updated exactly once)
259
+ // U-faces: (i, j, k) for i in [1, nx-1]
260
+ for (let k = 0; k < nz; k++)
261
+ for (let j = 0; j < ny; j++)
262
+ for (let i = 1; i < nx; i++) {
263
+ const cL = grid.idx(i - 1, j, k);
264
+ const cR = grid.idx(i, j, k);
265
+ if ((cellType[cL] === 1 || cellType[cR] === 1) &&
266
+ cellType[cL] !== 2 && cellType[cR] !== 2) {
267
+ grid.u[grid.uIdx(i, j, k)] -= dt * (this._x[cR] - this._x[cL]) / h;
268
+ }
269
+ }
270
+ // V-faces: (i, j, k) for j in [1, ny-1]
271
+ for (let k = 0; k < nz; k++)
272
+ for (let j = 1; j < ny; j++)
273
+ for (let i = 0; i < nx; i++) {
274
+ const cB = grid.idx(i, j - 1, k);
275
+ const cT = grid.idx(i, j, k);
276
+ if ((cellType[cB] === 1 || cellType[cT] === 1) &&
277
+ cellType[cB] !== 2 && cellType[cT] !== 2) {
278
+ grid.v[grid.vIdx(i, j, k)] -= dt * (this._x[cT] - this._x[cB]) / h;
279
+ }
280
+ }
281
+ // W-faces: (i, j, k) for k in [1, nz-1]
282
+ for (let k = 1; k < nz; k++)
283
+ for (let j = 0; j < ny; j++)
284
+ for (let i = 0; i < nx; i++) {
285
+ const cN = grid.idx(i, j, k - 1);
286
+ const cF = grid.idx(i, j, k);
287
+ if ((cellType[cN] === 1 || cellType[cF] === 1) &&
288
+ cellType[cN] !== 2 && cellType[cF] !== 2) {
289
+ grid.w[grid.wIdx(i, j, k)] -= dt * (this._x[cF] - this._x[cN]) / h;
290
+ }
291
+ }
292
+ grid.enforceBoundary();
293
+ }
294
+ // ── G2P (grid → particle) ─────────────────────────────────────────────────
295
+ _g2p() {
296
+ const grid = this._grid;
297
+ const ratio = this.parameters.flipRatio;
298
+ for (const p of this._particles) {
299
+ // New grid velocity at particle position
300
+ const nu = grid.interpU(p.x, p.y, p.z);
301
+ const nv = grid.interpV(p.x, p.y, p.z);
302
+ const nw = grid.interpW(p.x, p.y, p.z);
303
+ // Old grid velocity at particle position (before pressure solve)
304
+ const ou = this._interpOld(grid.uOld, p.x - grid.ox, p.y - grid.oy - 0.5 * grid.h, p.z - grid.oz - 0.5 * grid.h, grid.nx + 1, grid.ny, grid.nz);
305
+ const ov = this._interpOld(grid.vOld, p.x - grid.ox - 0.5 * grid.h, p.y - grid.oy, p.z - grid.oz - 0.5 * grid.h, grid.nx, grid.ny + 1, grid.nz);
306
+ const ow = this._interpOld(grid.wOld, p.x - grid.ox - 0.5 * grid.h, p.y - grid.oy - 0.5 * grid.h, p.z - grid.oz, grid.nx, grid.ny, grid.nz + 1);
307
+ // FLIP: particle velocity += (new - old) grid velocity
308
+ // PIC: particle velocity = new grid velocity
309
+ // Blend
310
+ p.vx = ratio * (p.vx + nu - ou) + (1 - ratio) * nu;
311
+ p.vy = ratio * (p.vy + nv - ov) + (1 - ratio) * nv;
312
+ p.vz = ratio * (p.vz + nw - ow) + (1 - ratio) * nw;
313
+ }
314
+ }
315
+ _interpOld(arr, lx, ly, lz, Nx, Ny, Nz) {
316
+ const h = this._grid.h;
317
+ let fi = lx / h, fj = ly / h, fk = lz / h;
318
+ fi = Math.max(0, Math.min(Nx - 1.0001, fi));
319
+ fj = Math.max(0, Math.min(Ny - 1.0001, fj));
320
+ fk = Math.max(0, Math.min(Nz - 1.0001, fk));
321
+ const i0 = Math.floor(fi), i1 = i0 + 1;
322
+ const j0 = Math.floor(fj), j1 = j0 + 1;
323
+ const k0 = Math.floor(fk), k1 = k0 + 1;
324
+ const tx = fi - i0, ty = fj - j0, tz = fk - k0;
325
+ const idx = (i, j, k) => i + Nx * (j + Ny * k);
326
+ return (1 - tz) * ((1 - ty) * ((1 - tx) * arr[idx(i0, j0, k0)] + tx * arr[idx(i1, j0, k0)]) +
327
+ ty * ((1 - tx) * arr[idx(i0, j1, k0)] + tx * arr[idx(i1, j1, k0)])) +
328
+ tz * ((1 - ty) * ((1 - tx) * arr[idx(i0, j0, k1)] + tx * arr[idx(i1, j0, k1)]) +
329
+ ty * ((1 - tx) * arr[idx(i0, j1, k1)] + tx * arr[idx(i1, j1, k1)]));
330
+ }
331
+ // ── Advection ─────────────────────────────────────────────────────────────
332
+ _advect(dt) {
333
+ for (const p of this._particles) {
334
+ p.x += p.vx * dt;
335
+ p.y += p.vy * dt;
336
+ p.z += p.vz * dt;
337
+ }
338
+ }
339
+ _clampParticles() {
340
+ const { ox, oy, oz, nx, ny, nz, h } = this._grid;
341
+ const margin = h * 0.5;
342
+ const xMin = ox + margin, xMax = ox + nx * h - margin;
343
+ const yMin = oy + margin, yMax = oy + ny * h - margin;
344
+ const zMin = oz + margin, zMax = oz + nz * h - margin;
345
+ for (const p of this._particles) {
346
+ if (p.x < xMin) {
347
+ p.x = xMin;
348
+ if (p.vx < 0)
349
+ p.vx = 0;
350
+ }
351
+ if (p.x > xMax) {
352
+ p.x = xMax;
353
+ if (p.vx > 0)
354
+ p.vx = 0;
355
+ }
356
+ if (p.y < yMin) {
357
+ p.y = yMin;
358
+ if (p.vy < 0)
359
+ p.vy = 0;
360
+ }
361
+ if (p.y > yMax) {
362
+ p.y = yMax;
363
+ if (p.vy > 0)
364
+ p.vy = 0;
365
+ }
366
+ if (p.z < zMin) {
367
+ p.z = zMin;
368
+ if (p.vz < 0)
369
+ p.vz = 0;
370
+ }
371
+ if (p.z > zMax) {
372
+ p.z = zMax;
373
+ if (p.vz > 0)
374
+ p.vz = 0;
375
+ }
376
+ }
377
+ }
378
+ // ── Output ────────────────────────────────────────────────────────────────
379
+ /** Returns particle positions as a flat Float32Array [x,y,z, x,y,z, ...]. */
380
+ getPositions() {
381
+ const out = new Float32Array(this._particles.length * 3);
382
+ for (let i = 0; i < this._particles.length; i++) {
383
+ out[i * 3] = this._particles[i].x;
384
+ out[i * 3 + 1] = this._particles[i].y;
385
+ out[i * 3 + 2] = this._particles[i].z;
386
+ }
387
+ return out;
388
+ }
389
+ /** Returns particle velocities as a flat Float32Array [vx,vy,vz, ...]. */
390
+ getVelocities() {
391
+ const out = new Float32Array(this._particles.length * 3);
392
+ for (let i = 0; i < this._particles.length; i++) {
393
+ out[i * 3] = this._particles[i].vx;
394
+ out[i * 3 + 1] = this._particles[i].vy;
395
+ out[i * 3 + 2] = this._particles[i].vz;
396
+ }
397
+ return out;
398
+ }
399
+ /** Number of live particles. */
400
+ get liveCount() { return this._particles.length; }
401
+ /** The underlying MAC grid (for advanced use / surface reconstruction). */
402
+ get grid() { return this._grid; }
403
+ }
404
+ //# sourceMappingURL=FLIPSimulator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FLIPSimulator.js","sourceRoot":"","sources":["../src/FLIPSimulator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,35 @@
1
+ /**
2
+ * FluidEmitter — defines a region that spawns fluid particles.
3
+ * Blender: Fluid > Emitter object.
4
+ *
5
+ * Used to spawn batches of particles from SPHSimulator.spawnFrom(emitter).
6
+ */
7
+ export interface FluidEmitterOptions {
8
+ /** World-space position [x,y,z]. Default [0,0,0]. */
9
+ position?: [number, number, number];
10
+ /** Spawn radius. Default 0.5. */
11
+ radius?: number;
12
+ /** Initial velocity of spawned particles [x,y,z]. Default [0,0,0]. */
13
+ velocity?: [number, number, number];
14
+ /** Jitter applied to initial velocity. Default 0.1. */
15
+ jitter?: number;
16
+ }
17
+ export declare class FluidEmitter {
18
+ parameters: {
19
+ posX: number;
20
+ posY: number;
21
+ posZ: number;
22
+ radius: number;
23
+ velX: number;
24
+ velY: number;
25
+ velZ: number;
26
+ jitter: number;
27
+ };
28
+ enabled: boolean;
29
+ constructor(opts?: FluidEmitterOptions);
30
+ /** Sample a random spawn position within the emitter sphere. */
31
+ samplePosition(): [number, number, number];
32
+ /** Sample initial velocity with jitter. */
33
+ sampleVelocity(): [number, number, number];
34
+ }
35
+ //# sourceMappingURL=FluidEmitter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FluidEmitter.d.ts","sourceRoot":"","sources":["../src/FluidEmitter.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,WAAW,mBAAmB;IAClC,qDAAqD;IACrD,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAA;IACnC,iCAAiC;IACjC,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,sEAAsE;IACtE,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAA;IACnC,uDAAuD;IACvD,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAED,qBAAa,YAAY;IACvB,UAAU,EAAE;QACV,IAAI,EAAM,MAAM,CAAA;QAChB,IAAI,EAAM,MAAM,CAAA;QAChB,IAAI,EAAM,MAAM,CAAA;QAChB,MAAM,EAAI,MAAM,CAAA;QAChB,IAAI,EAAM,MAAM,CAAA;QAChB,IAAI,EAAM,MAAM,CAAA;QAChB,IAAI,EAAM,MAAM,CAAA;QAChB,MAAM,EAAI,MAAM,CAAA;KACjB,CAAA;IAED,OAAO,UAAO;gBAEF,IAAI,GAAE,mBAAwB;IAW1C,gEAAgE;IAChE,cAAc,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC;IAY1C,2CAA2C;IAC3C,cAAc,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC;CAQ3C"}
@@ -0,0 +1,35 @@
1
+ export class FluidEmitter {
2
+ constructor(opts = {}) {
3
+ this.enabled = true;
4
+ const p = opts.position ?? [0, 0, 0];
5
+ const v = opts.velocity ?? [0, 0, 0];
6
+ this.parameters = {
7
+ posX: p[0], posY: p[1], posZ: p[2],
8
+ radius: opts.radius ?? 0.5,
9
+ velX: v[0], velY: v[1], velZ: v[2],
10
+ jitter: opts.jitter ?? 0.1,
11
+ };
12
+ }
13
+ /** Sample a random spawn position within the emitter sphere. */
14
+ samplePosition() {
15
+ const r = this.parameters.radius * Math.cbrt(Math.random());
16
+ const theta = Math.random() * Math.PI * 2;
17
+ const phi = Math.acos(2 * Math.random() - 1);
18
+ const sinPhi = Math.sin(phi);
19
+ return [
20
+ this.parameters.posX + r * sinPhi * Math.cos(theta),
21
+ this.parameters.posY + r * sinPhi * Math.sin(theta),
22
+ this.parameters.posZ + r * Math.cos(phi),
23
+ ];
24
+ }
25
+ /** Sample initial velocity with jitter. */
26
+ sampleVelocity() {
27
+ const j = this.parameters.jitter;
28
+ return [
29
+ this.parameters.velX + (Math.random() - 0.5) * j * 2,
30
+ this.parameters.velY + (Math.random() - 0.5) * j * 2,
31
+ this.parameters.velZ + (Math.random() - 0.5) * j * 2,
32
+ ];
33
+ }
34
+ }
35
+ //# sourceMappingURL=FluidEmitter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FluidEmitter.js","sourceRoot":"","sources":["../src/FluidEmitter.ts"],"names":[],"mappings":"AAiBA,MAAM,OAAO,YAAY;IAcvB,YAAY,OAA4B,EAAE;QAF1C,YAAO,GAAG,IAAI,CAAA;QAGZ,MAAM,CAAC,GAAG,IAAI,CAAC,QAAQ,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAA;QACpC,MAAM,CAAC,GAAG,IAAI,CAAC,QAAQ,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAA;QACpC,IAAI,CAAC,UAAU,GAAG;YAChB,IAAI,EAAI,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;YACpC,MAAM,EAAE,IAAI,CAAC,MAAM,IAAI,GAAG;YAC1B,IAAI,EAAI,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;YACpC,MAAM,EAAE,IAAI,CAAC,MAAM,IAAI,GAAG;SAC3B,CAAA;IACH,CAAC;IAED,gEAAgE;IAChE,cAAc;QACZ,MAAM,CAAC,GAAG,IAAI,CAAC,UAAU,CAAC,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAA;QAC3D,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,EAAE,GAAG,IAAI,CAAC,EAAE,GAAG,CAAC,CAAA;QACzC,MAAM,GAAG,GAAK,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAA;QAC9C,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;QAC5B,OAAO;YACL,IAAI,CAAC,UAAU,CAAC,IAAI,GAAG,CAAC,GAAG,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC;YACnD,IAAI,CAAC,UAAU,CAAC,IAAI,GAAG,CAAC,GAAG,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC;YACnD,IAAI,CAAC,UAAU,CAAC,IAAI,GAAG,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;SACzC,CAAA;IACH,CAAC;IAED,2CAA2C;IAC3C,cAAc;QACZ,MAAM,CAAC,GAAG,IAAI,CAAC,UAAU,CAAC,MAAM,CAAA;QAChC,OAAO;YACL,IAAI,CAAC,UAAU,CAAC,IAAI,GAAG,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC;YACpD,IAAI,CAAC,UAAU,CAAC,IAAI,GAAG,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC;YACpD,IAAI,CAAC,UAAU,CAAC,IAAI,GAAG,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC;SACrD,CAAA;IACH,CAAC;CACF"}