@woosh/meep-engine 2.157.0 → 2.158.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.
Files changed (60) hide show
  1. package/package.json +1 -1
  2. package/src/core/geom/3d/shape/PosedShape3D.d.ts +17 -0
  3. package/src/core/geom/3d/shape/PosedShape3D.d.ts.map +1 -1
  4. package/src/core/geom/3d/shape/PosedShape3D.js +50 -0
  5. package/src/engine/graphics/ecs/trail2d/Trail2D.d.ts.map +1 -1
  6. package/src/engine/graphics/ecs/trail2d/Trail2D.js +21 -0
  7. package/src/engine/graphics/ecs/trail2d/Trail2DFlags.d.ts +1 -0
  8. package/src/engine/graphics/ecs/trail2d/Trail2DFlags.js +9 -1
  9. package/src/engine/physics/fluid/FluidField.d.ts +53 -9
  10. package/src/engine/physics/fluid/FluidField.d.ts.map +1 -1
  11. package/src/engine/physics/fluid/FluidField.js +684 -600
  12. package/src/engine/physics/fluid/FluidSimulator.d.ts +53 -38
  13. package/src/engine/physics/fluid/FluidSimulator.d.ts.map +1 -1
  14. package/src/engine/physics/fluid/FluidSimulator.js +252 -178
  15. package/src/engine/physics/fluid/REVIEW_02_PLAN.md +155 -26
  16. package/src/engine/physics/fluid/ecs/FluidObstacle.d.ts +72 -0
  17. package/src/engine/physics/fluid/ecs/FluidObstacle.d.ts.map +1 -0
  18. package/src/engine/physics/fluid/ecs/FluidObstacle.js +97 -0
  19. package/src/engine/physics/fluid/ecs/FluidObstacleSystem.d.ts +117 -0
  20. package/src/engine/physics/fluid/ecs/FluidObstacleSystem.d.ts.map +1 -0
  21. package/src/engine/physics/fluid/ecs/FluidObstacleSystem.js +348 -0
  22. package/src/engine/physics/fluid/ecs/FluidSystem.d.ts +3 -3
  23. package/src/engine/physics/fluid/effector/GlobalFluidEffector.d.ts +62 -12
  24. package/src/engine/physics/fluid/effector/GlobalFluidEffector.d.ts.map +1 -1
  25. package/src/engine/physics/fluid/effector/GlobalFluidEffector.js +135 -38
  26. package/src/engine/physics/fluid/effector/ImpulseFluidEffector.d.ts.map +1 -1
  27. package/src/engine/physics/fluid/effector/ImpulseFluidEffector.js +85 -38
  28. package/src/engine/physics/fluid/effector/WakeFluidEffector.d.ts.map +1 -1
  29. package/src/engine/physics/fluid/effector/WakeFluidEffector.js +104 -50
  30. package/src/engine/physics/fluid/prototype.js +25 -1
  31. package/src/engine/physics/fluid/solver/v3_grid_sample_scalar_masked.d.ts +30 -0
  32. package/src/engine/physics/fluid/solver/v3_grid_sample_scalar_masked.d.ts.map +1 -0
  33. package/src/engine/physics/fluid/solver/v3_grid_sample_scalar_masked.js +92 -0
  34. package/src/engine/physics/fluid/solver/v3_mac_advect_maccormack_velocity.d.ts +42 -0
  35. package/src/engine/physics/fluid/solver/v3_mac_advect_maccormack_velocity.d.ts.map +1 -0
  36. package/src/engine/physics/fluid/solver/v3_mac_advect_maccormack_velocity.js +319 -0
  37. package/src/engine/physics/fluid/solver/v3_mac_advect_scalar.d.ts +53 -0
  38. package/src/engine/physics/fluid/solver/v3_mac_advect_scalar.d.ts.map +1 -0
  39. package/src/engine/physics/fluid/solver/v3_mac_advect_scalar.js +236 -0
  40. package/src/engine/physics/fluid/solver/v3_mac_advect_sl_velocity.d.ts +46 -0
  41. package/src/engine/physics/fluid/solver/v3_mac_advect_sl_velocity.d.ts.map +1 -0
  42. package/src/engine/physics/fluid/solver/v3_mac_advect_sl_velocity.js +217 -0
  43. package/src/engine/physics/fluid/solver/v3_mac_apply_vorticity_confinement.d.ts +40 -0
  44. package/src/engine/physics/fluid/solver/v3_mac_apply_vorticity_confinement.d.ts.map +1 -0
  45. package/src/engine/physics/fluid/solver/v3_mac_apply_vorticity_confinement.js +165 -0
  46. package/src/engine/physics/fluid/solver/v3_mac_clip_trace.d.ts +44 -0
  47. package/src/engine/physics/fluid/solver/v3_mac_clip_trace.d.ts.map +1 -0
  48. package/src/engine/physics/fluid/solver/v3_mac_clip_trace.js +95 -0
  49. package/src/engine/physics/fluid/solver/v3_mac_compute_divergence.d.ts +38 -0
  50. package/src/engine/physics/fluid/solver/v3_mac_compute_divergence.d.ts.map +1 -0
  51. package/src/engine/physics/fluid/solver/v3_mac_compute_divergence.js +77 -0
  52. package/src/engine/physics/fluid/solver/v3_mac_compute_face_solid.d.ts +52 -0
  53. package/src/engine/physics/fluid/solver/v3_mac_compute_face_solid.d.ts.map +1 -0
  54. package/src/engine/physics/fluid/solver/v3_mac_compute_face_solid.js +131 -0
  55. package/src/engine/physics/fluid/solver/v3_mac_subtract_pressure_gradient.d.ts +38 -0
  56. package/src/engine/physics/fluid/solver/v3_mac_subtract_pressure_gradient.d.ts.map +1 -0
  57. package/src/engine/physics/fluid/solver/v3_mac_subtract_pressure_gradient.js +104 -0
  58. package/src/engine/physics/fluid/effector/AmbientWindFluidEffector.d.ts +0 -41
  59. package/src/engine/physics/fluid/effector/AmbientWindFluidEffector.d.ts.map +0 -1
  60. package/src/engine/physics/fluid/effector/AmbientWindFluidEffector.js +0 -124
@@ -0,0 +1,104 @@
1
+ import { assert } from "../../../../core/assert.js";
2
+
3
+ /**
4
+ * Subtract the pressure gradient from a MAC velocity field in place — the
5
+ * face-exact counterpart of the collocated
6
+ * {@link v3_grid_subtract_pressure_gradient}:
7
+ *
8
+ * u(face) −= p(right cell) − p(left cell) (h = 1)
9
+ *
10
+ * Per face:
11
+ * - both adjacent cells fluid: subtract the pressure difference.
12
+ * - PINNED face (either adjacent cell solid): SKIPPED — its stored value is
13
+ * the wall's normal-velocity boundary condition (0 for static solids,
14
+ * the wall speed for movers; see {@link v3_mac_compute_face_solid}) and
15
+ * must survive the projection. Stray deposits are prevented upstream:
16
+ * the mask rebuild zeroes faces on every unpinned→pinned transition and
17
+ * every transport/effector kernel skips pinned faces.
18
+ * - domain-edge face (open boundary): the missing cell is the Dirichlet
19
+ * ghost p = 0, so interior pressure vents flow out through the face.
20
+ *
21
+ * Together with {@link v3_mac_compute_divergence} and the unchanged 7-point
22
+ * solve this forms an exact discrete Helmholtz projection: solve error aside,
23
+ * post-projection divergence is zero — including immediately beside walls,
24
+ * which the collocated form could only approximate.
25
+ *
26
+ * Face grid layout: see {@link v3_mac_compute_face_solid}.
27
+ *
28
+ * @param {Float32Array} vel_u Mutated in place, (res_x+1)·res_y·res_z.
29
+ * @param {Float32Array} vel_v Mutated in place, res_x·(res_y+1)·res_z.
30
+ * @param {Float32Array} vel_w Mutated in place, res_x·res_y·(res_z+1).
31
+ * @param {Float32Array|Float16Array} pressure Cell-centered, from the solve.
32
+ * @param {Uint8Array} face_solid_x From {@link v3_mac_compute_face_solid}.
33
+ * @param {Uint8Array} face_solid_y
34
+ * @param {Uint8Array} face_solid_z
35
+ * @param {number} res_x
36
+ * @param {number} res_y
37
+ * @param {number} res_z
38
+ */
39
+ export function v3_mac_subtract_pressure_gradient(vel_u, vel_v, vel_w, pressure, face_solid_x, face_solid_y, face_solid_z, res_x, res_y, res_z) {
40
+ const cell_count = res_x * res_y * res_z;
41
+ assert.greaterThanOrEqual(vel_u.length, (res_x + 1) * res_y * res_z, "vel_u covers grid");
42
+ assert.greaterThanOrEqual(vel_v.length, res_x * (res_y + 1) * res_z, "vel_v covers grid");
43
+ assert.greaterThanOrEqual(vel_w.length, res_x * res_y * (res_z + 1), "vel_w covers grid");
44
+ assert.greaterThanOrEqual(pressure.length, cell_count, "pressure covers grid");
45
+
46
+ const cell_slice = res_x * res_y;
47
+ const sx = res_x + 1;
48
+
49
+ // x-faces.
50
+ for (let z = 0; z < res_z; z++) {
51
+ const c_z = z * cell_slice;
52
+ const f_z = z * sx * res_y;
53
+ for (let y = 0; y < res_y; y++) {
54
+ const c_y = c_z + y * res_x;
55
+ const f_y = f_z + y * sx;
56
+ for (let x = 0; x <= res_x; x++) {
57
+ const f = f_y + x;
58
+ if (face_solid_x[f] !== 0) {
59
+ // Boundary condition — preserved, not zeroed.
60
+ continue;
61
+ }
62
+ const p_left = x === 0 ? 0 : pressure[c_y + x - 1];
63
+ const p_right = x === res_x ? 0 : pressure[c_y + x];
64
+ vel_u[f] -= p_right - p_left;
65
+ }
66
+ }
67
+ }
68
+
69
+ // y-faces.
70
+ for (let z = 0; z < res_z; z++) {
71
+ const c_z = z * cell_slice;
72
+ const f_z = z * res_x * (res_y + 1);
73
+ for (let y = 0; y <= res_y; y++) {
74
+ const f_y = f_z + y * res_x;
75
+ const c_below = c_z + (y - 1) * res_x;
76
+ const c_above = c_z + y * res_x;
77
+ for (let x = 0; x < res_x; x++) {
78
+ const f = f_y + x;
79
+ if (face_solid_y[f] !== 0) {
80
+ continue;
81
+ }
82
+ const p_below = y === 0 ? 0 : pressure[c_below + x];
83
+ const p_above = y === res_y ? 0 : pressure[c_above + x];
84
+ vel_v[f] -= p_above - p_below;
85
+ }
86
+ }
87
+ }
88
+
89
+ // z-faces.
90
+ for (let z = 0; z <= res_z; z++) {
91
+ const f_z = z * cell_slice;
92
+ const c_near = (z - 1) * cell_slice;
93
+ const c_far = z * cell_slice;
94
+ for (let i = 0; i < cell_slice; i++) {
95
+ const f = f_z + i;
96
+ if (face_solid_z[f] !== 0) {
97
+ continue;
98
+ }
99
+ const p_near = z === 0 ? 0 : pressure[c_near + i];
100
+ const p_far = z === res_z ? 0 : pressure[c_far + i];
101
+ vel_w[f] -= p_far - p_near;
102
+ }
103
+ }
104
+ }
@@ -1,41 +0,0 @@
1
- /**
2
- * Drives every fluid cell toward a target ambient wind velocity — the standard
3
- * way to model prevailing wind in a scrolling wind volume.
4
- *
5
- * Unlike {@link GlobalFluidEffector} (which integrates a constant ACCELERATION
6
- * and therefore grows the velocity without bound — incompressible projection
7
- * cannot oppose a uniform force), this effector relaxes the field toward a
8
- * fixed VELOCITY:
9
- *
10
- * v ← v + α · (target − v), α = 1 − exp(−rate · dt)
11
- *
12
- * The fixed point is exactly `target`; gusts and wakes splatted on top decay
13
- * back toward the ambient wind at `rate` per second. The exponential form is
14
- * frame-rate independent — two half-steps relax exactly as much as one full
15
- * step.
16
- *
17
- * `velocity` is in WORLD units per second. The `world_to_grid` matrix's linear
18
- * part converts it into the target field's grid-cell units at apply time, so
19
- * the same effector instance produces the same world-space wind on fields of
20
- * different `cell_size`.
21
- *
22
- * Solid cells are left untouched — the projection zeroes them anyway, and
23
- * skipping the write keeps the solid mask authoritative for effectors too.
24
- */
25
- export class AmbientWindFluidEffector extends AbstractFluidEffector {
26
- /**
27
- * Target wind velocity in WORLD units per second.
28
- * @type {[number, number, number]}
29
- */
30
- velocity: [number, number, number];
31
- /**
32
- * Relaxation rate toward {@link velocity}, per second. Higher = stiffer
33
- * wind that re-asserts itself quickly after disturbances; lower = gusts
34
- * and wakes linger. At rate `r`, a disturbance decays to ~37% in `1/r`
35
- * seconds. `0` disables the effector.
36
- * @type {number}
37
- */
38
- rate: number;
39
- }
40
- import { AbstractFluidEffector } from "./AbstractFluidEffector.js";
41
- //# sourceMappingURL=AmbientWindFluidEffector.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"AmbientWindFluidEffector.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/physics/fluid/effector/AmbientWindFluidEffector.js"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH;IAEI;;;OAGG;IACH,UAFU,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAEb;IAErB;;;;;;OAMG;IACH,MAFU,MAAM,CAEP;CAgFZ;sCAzHqC,4BAA4B"}
@@ -1,124 +0,0 @@
1
- import { combine_hash } from "../../../../core/collection/array/combine_hash.js";
2
- import { computeHashFloat } from "../../../../core/primitives/numbers/computeHashFloat.js";
3
- import { AbstractFluidEffector } from "./AbstractFluidEffector.js";
4
-
5
- /**
6
- * Drives every fluid cell toward a target ambient wind velocity — the standard
7
- * way to model prevailing wind in a scrolling wind volume.
8
- *
9
- * Unlike {@link GlobalFluidEffector} (which integrates a constant ACCELERATION
10
- * and therefore grows the velocity without bound — incompressible projection
11
- * cannot oppose a uniform force), this effector relaxes the field toward a
12
- * fixed VELOCITY:
13
- *
14
- * v ← v + α · (target − v), α = 1 − exp(−rate · dt)
15
- *
16
- * The fixed point is exactly `target`; gusts and wakes splatted on top decay
17
- * back toward the ambient wind at `rate` per second. The exponential form is
18
- * frame-rate independent — two half-steps relax exactly as much as one full
19
- * step.
20
- *
21
- * `velocity` is in WORLD units per second. The `world_to_grid` matrix's linear
22
- * part converts it into the target field's grid-cell units at apply time, so
23
- * the same effector instance produces the same world-space wind on fields of
24
- * different `cell_size`.
25
- *
26
- * Solid cells are left untouched — the projection zeroes them anyway, and
27
- * skipping the write keeps the solid mask authoritative for effectors too.
28
- */
29
- export class AmbientWindFluidEffector extends AbstractFluidEffector {
30
-
31
- /**
32
- * Target wind velocity in WORLD units per second.
33
- * @type {[number, number, number]}
34
- */
35
- velocity = [0, 0, 0];
36
-
37
- /**
38
- * Relaxation rate toward {@link velocity}, per second. Higher = stiffer
39
- * wind that re-asserts itself quickly after disturbances; lower = gusts
40
- * and wakes linger. At rate `r`, a disturbance decays to ~37% in `1/r`
41
- * seconds. `0` disables the effector.
42
- * @type {number}
43
- */
44
- rate = 1;
45
-
46
- /**
47
- * @param {FluidField} field
48
- * @param {number} dt
49
- * @param {Float32Array|number[]} world_to_grid Column-major 4×4 affine; only the
50
- * linear (upper-left 3×3) part is
51
- * used since velocity is a direction.
52
- */
53
- apply(field, dt, world_to_grid) {
54
- if (this.rate <= 0 || dt <= 0) {
55
- return;
56
- }
57
-
58
- const wx = this.velocity[0];
59
- const wy = this.velocity[1];
60
- const wz = this.velocity[2];
61
-
62
- // Direction-transform the world-space target into grid units.
63
- const m = world_to_grid;
64
- const tx = m[0] * wx + m[4] * wy + m[8] * wz;
65
- const ty = m[1] * wx + m[5] * wy + m[9] * wz;
66
- const tz = m[2] * wx + m[6] * wy + m[10] * wz;
67
-
68
- // Exact exponential relaxation factor for this dt.
69
- const alpha = 1 - Math.exp(-this.rate * dt);
70
-
71
- const vx = field.velocity_x;
72
- const vy = field.velocity_y;
73
- const vz = field.velocity_z;
74
- const solid = field.solid;
75
- const n = field.cellCount();
76
-
77
- for (let i = 0; i < n; i++) {
78
- if (solid[i] !== 0) {
79
- continue;
80
- }
81
- vx[i] += alpha * (tx - vx[i]);
82
- vy[i] += alpha * (ty - vy[i]);
83
- vz[i] += alpha * (tz - vz[i]);
84
- }
85
- }
86
-
87
- /**
88
- * @param {AbstractFluidEffector} other
89
- * @return {boolean}
90
- */
91
- equals(other) {
92
- if (other === this) {
93
- return true;
94
- }
95
- if (!(other instanceof AmbientWindFluidEffector)) {
96
- return false;
97
- }
98
- return this.rate === other.rate
99
- && this.velocity[0] === other.velocity[0]
100
- && this.velocity[1] === other.velocity[1]
101
- && this.velocity[2] === other.velocity[2];
102
- }
103
-
104
- /**
105
- * @return {number}
106
- */
107
- hash() {
108
- return combine_hash(
109
- computeHashFloat(this.velocity[0]),
110
- computeHashFloat(this.velocity[1]),
111
- computeHashFloat(this.velocity[2]),
112
- computeHashFloat(this.rate)
113
- );
114
- }
115
-
116
- /**
117
- * Position-free — applies to every cell of any field. Infinite bounds means
118
- * the broad-phase will never cull this effector.
119
- * @param {AABB3} out
120
- */
121
- getBoundingBox(out) {
122
- out.setInfiniteBounds();
123
- }
124
- }