@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.
- package/package.json +1 -1
- package/src/core/geom/3d/shape/PosedShape3D.d.ts +17 -0
- package/src/core/geom/3d/shape/PosedShape3D.d.ts.map +1 -1
- package/src/core/geom/3d/shape/PosedShape3D.js +50 -0
- package/src/engine/graphics/ecs/trail2d/Trail2D.d.ts.map +1 -1
- package/src/engine/graphics/ecs/trail2d/Trail2D.js +21 -0
- package/src/engine/graphics/ecs/trail2d/Trail2DFlags.d.ts +1 -0
- package/src/engine/graphics/ecs/trail2d/Trail2DFlags.js +9 -1
- package/src/engine/physics/fluid/FluidField.d.ts +53 -9
- package/src/engine/physics/fluid/FluidField.d.ts.map +1 -1
- package/src/engine/physics/fluid/FluidField.js +684 -600
- package/src/engine/physics/fluid/FluidSimulator.d.ts +53 -38
- package/src/engine/physics/fluid/FluidSimulator.d.ts.map +1 -1
- package/src/engine/physics/fluid/FluidSimulator.js +252 -178
- package/src/engine/physics/fluid/REVIEW_02_PLAN.md +155 -26
- package/src/engine/physics/fluid/ecs/FluidObstacle.d.ts +72 -0
- package/src/engine/physics/fluid/ecs/FluidObstacle.d.ts.map +1 -0
- package/src/engine/physics/fluid/ecs/FluidObstacle.js +97 -0
- package/src/engine/physics/fluid/ecs/FluidObstacleSystem.d.ts +117 -0
- package/src/engine/physics/fluid/ecs/FluidObstacleSystem.d.ts.map +1 -0
- package/src/engine/physics/fluid/ecs/FluidObstacleSystem.js +348 -0
- package/src/engine/physics/fluid/ecs/FluidSystem.d.ts +3 -3
- package/src/engine/physics/fluid/effector/GlobalFluidEffector.d.ts +62 -12
- package/src/engine/physics/fluid/effector/GlobalFluidEffector.d.ts.map +1 -1
- package/src/engine/physics/fluid/effector/GlobalFluidEffector.js +135 -38
- package/src/engine/physics/fluid/effector/ImpulseFluidEffector.d.ts.map +1 -1
- package/src/engine/physics/fluid/effector/ImpulseFluidEffector.js +85 -38
- package/src/engine/physics/fluid/effector/WakeFluidEffector.d.ts.map +1 -1
- package/src/engine/physics/fluid/effector/WakeFluidEffector.js +104 -50
- package/src/engine/physics/fluid/prototype.js +25 -1
- package/src/engine/physics/fluid/solver/v3_grid_sample_scalar_masked.d.ts +30 -0
- package/src/engine/physics/fluid/solver/v3_grid_sample_scalar_masked.d.ts.map +1 -0
- package/src/engine/physics/fluid/solver/v3_grid_sample_scalar_masked.js +92 -0
- package/src/engine/physics/fluid/solver/v3_mac_advect_maccormack_velocity.d.ts +42 -0
- package/src/engine/physics/fluid/solver/v3_mac_advect_maccormack_velocity.d.ts.map +1 -0
- package/src/engine/physics/fluid/solver/v3_mac_advect_maccormack_velocity.js +319 -0
- package/src/engine/physics/fluid/solver/v3_mac_advect_scalar.d.ts +53 -0
- package/src/engine/physics/fluid/solver/v3_mac_advect_scalar.d.ts.map +1 -0
- package/src/engine/physics/fluid/solver/v3_mac_advect_scalar.js +236 -0
- package/src/engine/physics/fluid/solver/v3_mac_advect_sl_velocity.d.ts +46 -0
- package/src/engine/physics/fluid/solver/v3_mac_advect_sl_velocity.d.ts.map +1 -0
- package/src/engine/physics/fluid/solver/v3_mac_advect_sl_velocity.js +217 -0
- package/src/engine/physics/fluid/solver/v3_mac_apply_vorticity_confinement.d.ts +40 -0
- package/src/engine/physics/fluid/solver/v3_mac_apply_vorticity_confinement.d.ts.map +1 -0
- package/src/engine/physics/fluid/solver/v3_mac_apply_vorticity_confinement.js +165 -0
- package/src/engine/physics/fluid/solver/v3_mac_clip_trace.d.ts +44 -0
- package/src/engine/physics/fluid/solver/v3_mac_clip_trace.d.ts.map +1 -0
- package/src/engine/physics/fluid/solver/v3_mac_clip_trace.js +95 -0
- package/src/engine/physics/fluid/solver/v3_mac_compute_divergence.d.ts +38 -0
- package/src/engine/physics/fluid/solver/v3_mac_compute_divergence.d.ts.map +1 -0
- package/src/engine/physics/fluid/solver/v3_mac_compute_divergence.js +77 -0
- package/src/engine/physics/fluid/solver/v3_mac_compute_face_solid.d.ts +52 -0
- package/src/engine/physics/fluid/solver/v3_mac_compute_face_solid.d.ts.map +1 -0
- package/src/engine/physics/fluid/solver/v3_mac_compute_face_solid.js +131 -0
- package/src/engine/physics/fluid/solver/v3_mac_subtract_pressure_gradient.d.ts +38 -0
- package/src/engine/physics/fluid/solver/v3_mac_subtract_pressure_gradient.d.ts.map +1 -0
- package/src/engine/physics/fluid/solver/v3_mac_subtract_pressure_gradient.js +104 -0
- package/src/engine/physics/fluid/effector/AmbientWindFluidEffector.d.ts +0 -41
- package/src/engine/physics/fluid/effector/AmbientWindFluidEffector.d.ts.map +0 -1
- 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
|
-
}
|