@woosh/meep-engine 2.147.0 → 2.148.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 (44) hide show
  1. package/package.json +1 -1
  2. package/src/core/math/spline/spline3_hermite_intersection_spline3_hermite.d.ts +4 -4
  3. package/src/core/math/spline/spline3_hermite_intersection_spline3_hermite.d.ts.map +1 -1
  4. package/src/core/math/spline/spline3_hermite_intersection_spline3_hermite.js +48 -52
  5. package/src/core/math/spline/spline3_hermite_intersection_spline3_hermite_2d.d.ts +23 -21
  6. package/src/core/math/spline/spline3_hermite_intersection_spline3_hermite_2d.d.ts.map +1 -1
  7. package/src/core/math/spline/spline3_hermite_intersection_spline3_hermite_2d.js +41 -406
  8. package/src/core/math/spline/spline3_hermite_intersection_spline3_hermite_nd.d.ts +5 -4
  9. package/src/core/math/spline/spline3_hermite_intersection_spline3_hermite_nd.d.ts.map +1 -1
  10. package/src/core/math/spline/spline3_hermite_intersection_spline3_hermite_nd.js +400 -395
  11. package/src/engine/physics/body/SolverBodyState.d.ts +142 -0
  12. package/src/engine/physics/body/SolverBodyState.d.ts.map +1 -0
  13. package/src/engine/physics/body/SolverBodyState.js +251 -0
  14. package/src/engine/physics/broadphase/generate_pairs.d.ts +2 -1
  15. package/src/engine/physics/broadphase/generate_pairs.d.ts.map +1 -1
  16. package/src/engine/physics/broadphase/generate_pairs.js +5 -3
  17. package/src/engine/physics/constraint/solve_constraints.d.ts.map +1 -1
  18. package/src/engine/physics/constraint/solve_constraints.js +691 -673
  19. package/src/engine/physics/ecs/PhysicsSystem.d.ts +21 -18
  20. package/src/engine/physics/ecs/PhysicsSystem.d.ts.map +1 -1
  21. package/src/engine/physics/ecs/PhysicsSystem.js +223 -91
  22. package/src/engine/physics/inertia/world_inverse_inertia.d.ts +23 -0
  23. package/src/engine/physics/inertia/world_inverse_inertia.d.ts.map +1 -1
  24. package/src/engine/physics/inertia/world_inverse_inertia.js +116 -77
  25. package/src/engine/physics/integration/integrate_position.d.ts +11 -1
  26. package/src/engine/physics/integration/integrate_position.d.ts.map +1 -1
  27. package/src/engine/physics/integration/integrate_position.js +97 -79
  28. package/src/engine/physics/integration/integrate_velocity.d.ts +12 -3
  29. package/src/engine/physics/integration/integrate_velocity.d.ts.map +1 -1
  30. package/src/engine/physics/integration/integrate_velocity.js +201 -160
  31. package/src/engine/physics/narrowphase/box_box_manifold.d.ts.map +1 -1
  32. package/src/engine/physics/narrowphase/box_box_manifold.js +750 -665
  33. package/src/engine/physics/narrowphase/box_triangle_contact.d.ts.map +1 -1
  34. package/src/engine/physics/narrowphase/box_triangle_contact.js +4 -34
  35. package/src/engine/physics/narrowphase/clip_against_axis_uv.d.ts +16 -0
  36. package/src/engine/physics/narrowphase/clip_against_axis_uv.d.ts.map +1 -0
  37. package/src/engine/physics/narrowphase/clip_against_axis_uv.js +49 -0
  38. package/src/engine/physics/narrowphase/narrowphase_step.d.ts.map +1 -1
  39. package/src/engine/physics/narrowphase/narrowphase_step.js +24 -3
  40. package/src/engine/physics/queries/raycast.d.ts.map +1 -1
  41. package/src/engine/physics/queries/raycast.js +7 -4
  42. package/src/engine/physics/solver/solve_contacts.d.ts +2 -2
  43. package/src/engine/physics/solver/solve_contacts.d.ts.map +1 -1
  44. package/src/engine/physics/solver/solve_contacts.js +1341 -1173
@@ -1,160 +1,201 @@
1
- import { BodyKind } from "../ecs/BodyKind.js";
2
- import { world_inverse_inertia_apply } from "../inertia/world_inverse_inertia.js";
3
-
4
- const scratch_angular = new Float64Array(3);
5
-
6
- /**
7
- * Semi-implicit Euler velocity integration for a single rigid body.
8
- *
9
- * For Dynamic bodies:
10
- * - gravity (scaled by `gravityScale`) and the accumulated force are converted
11
- * to a velocity delta via `1/mass`,
12
- * - accumulated torque is converted to angular acceleration via the
13
- * world-frame inverse inertia (R · diag(I_local) · R^T applied to τ),
14
- * - linear and angular damping are applied as a stable implicit decay
15
- * `v *= 1 / (1 + d·dt)` (Box2D / Bullet recipe — never goes negative, no
16
- * `exp()` call on the hot path),
17
- * - the force / torque accumulators are zeroed afterwards.
18
- *
19
- * Kinematic and Static bodies are skipped — their velocity is the
20
- * user / animation system's responsibility.
21
- *
22
- * @param {RigidBody} rb
23
- * @param {Transform} transform used to rotate body-frame inertia into world
24
- * @param {number} gx world gravity x
25
- * @param {number} gy world gravity y
26
- * @param {number} gz world gravity z
27
- * @param {number} dt step size in seconds
28
- */
29
- export function integrate_velocity(rb, transform, gx, gy, gz, dt) {
30
- const af = rb.accumulatedForce;
31
- const at = rb.accumulatedTorque;
32
-
33
- if (rb.kind !== BodyKind.Dynamic) {
34
- // Direct indexing no observer listens to body-internal accumulators.
35
- af[0] = 0; af[1] = 0; af[2] = 0;
36
- at[0] = 0; at[1] = 0; at[2] = 0;
37
- return;
38
- }
39
-
40
- const inv_m = rb.mass > 0 ? 1 / rb.mass : 0;
41
- const gs = rb.gravityScale;
42
-
43
- // Linear velocity update: v += (F * invM + g * gravityScale) * dt
44
- const lv = rb.linearVelocity;
45
- let lvx = lv[0] + (af[0] * inv_m + gx * gs) * dt;
46
- let lvy = lv[1] + (af[1] * inv_m + gy * gs) * dt;
47
- let lvz = lv[2] + (af[2] * inv_m + gz * gs) * dt;
48
-
49
- if (rb.linearDamping > 0) {
50
- const k = 1 / (1 + rb.linearDamping * dt);
51
- lvx *= k;
52
- lvy *= k;
53
- lvz *= k;
54
- }
55
- lv[0] = lvx; lv[1] = lvy; lv[2] = lvz;
56
-
57
- // Angular velocity update: ω += I_world⁻¹ · τ · dt
58
- const av = rb.angularVelocity;
59
- let avx = av[0];
60
- let avy = av[1];
61
- let avz = av[2];
62
- if (at[0] !== 0 || at[1] !== 0 || at[2] !== 0) {
63
- world_inverse_inertia_apply(scratch_angular, 0, rb.inverseInertiaLocal, transform.rotation, at[0], at[1], at[2]);
64
- avx += scratch_angular[0] * dt;
65
- avy += scratch_angular[1] * dt;
66
- avz += scratch_angular[2] * dt;
67
- }
68
-
69
- if (rb.angularDamping > 0) {
70
- const k = 1 / (1 + rb.angularDamping * dt);
71
- avx *= k;
72
- avy *= k;
73
- avz *= k;
74
- }
75
- av[0] = avx; av[1] = avy; av[2] = avz;
76
-
77
- af[0] = 0; af[1] = 0; af[2] = 0;
78
- at[0] = 0; at[1] = 0; at[2] = 0;
79
- }
80
-
81
- /**
82
- * Apply the accumulated force / torque to velocity over a step `dt`, then
83
- * zero the accumulators. Gravity and damping are NOT applied here.
84
- *
85
- * The "once per outer step" half of the TGS integrator: a user force is a
86
- * per-frame budget that must land in full exactly once, independent of
87
- * substep count. Gravity is the continuous field re-applied every substep
88
- * by {@link integrate_velocity_gravity}.
89
- *
90
- * @param {RigidBody} rb
91
- * @param {Transform} transform used to rotate body-frame inertia into world
92
- * @param {number} dt full outer-step size in seconds
93
- */
94
- export function integrate_velocity_forces(rb, transform, dt) {
95
- const af = rb.accumulatedForce;
96
- const at = rb.accumulatedTorque;
97
-
98
- if (rb.kind !== BodyKind.Dynamic) {
99
- af[0] = 0; af[1] = 0; af[2] = 0;
100
- at[0] = 0; at[1] = 0; at[2] = 0;
101
- return;
102
- }
103
-
104
- const inv_m = rb.mass > 0 ? 1 / rb.mass : 0;
105
-
106
- const lv = rb.linearVelocity;
107
- lv[0] += af[0] * inv_m * dt;
108
- lv[1] += af[1] * inv_m * dt;
109
- lv[2] += af[2] * inv_m * dt;
110
-
111
- if (at[0] !== 0 || at[1] !== 0 || at[2] !== 0) {
112
- world_inverse_inertia_apply(scratch_angular, 0, rb.inverseInertiaLocal, transform.rotation, at[0], at[1], at[2]);
113
- const av = rb.angularVelocity;
114
- av[0] += scratch_angular[0] * dt;
115
- av[1] += scratch_angular[1] * dt;
116
- av[2] += scratch_angular[2] * dt;
117
- }
118
-
119
- af[0] = 0; af[1] = 0; af[2] = 0;
120
- at[0] = 0; at[1] = 0; at[2] = 0;
121
- }
122
-
123
- /**
124
- * Apply gravity and velocity damping over a (sub)step `dt`. Does NOT touch
125
- * the force / torque accumulators (consumed once by
126
- * {@link integrate_velocity_forces}).
127
- *
128
- * The "every substep" half of the TGS integrator. Per substep the body sees
129
- * only `g·h` of gravity, which the per-substep contact warm-start + solve
130
- * cancels exactly — keeping a resting stack at zero velocity. Damping is the
131
- * stable implicit decay `v *= 1/(1 + d·dt)` applied at the substep `dt`.
132
- *
133
- * @param {RigidBody} rb
134
- * @param {Transform} transform (unused; signature symmetry with the family)
135
- * @param {number} gx @param {number} gy @param {number} gz world gravity
136
- * @param {number} dt sub-step size in seconds
137
- */
138
- export function integrate_velocity_gravity(rb, transform, gx, gy, gz, dt) {
139
- if (rb.kind !== BodyKind.Dynamic) {
140
- return;
141
- }
142
-
143
- const gs = rb.gravityScale;
144
- const lv = rb.linearVelocity;
145
- let lvx = lv[0] + gx * gs * dt;
146
- let lvy = lv[1] + gy * gs * dt;
147
- let lvz = lv[2] + gz * gs * dt;
148
-
149
- if (rb.linearDamping > 0) {
150
- const k = 1 / (1 + rb.linearDamping * dt);
151
- lvx *= k; lvy *= k; lvz *= k;
152
- }
153
- lv[0] = lvx; lv[1] = lvy; lv[2] = lvz;
154
-
155
- if (rb.angularDamping > 0) {
156
- const av = rb.angularVelocity;
157
- const k = 1 / (1 + rb.angularDamping * dt);
158
- av[0] *= k; av[1] *= k; av[2] *= k;
159
- }
160
- }
1
+ import { SBS_AV_X, SBS_AV_Y, SBS_AV_Z, SBS_LV_X, SBS_LV_Y, SBS_LV_Z, } from "../body/SolverBodyState.js";
2
+ import { BodyKind } from "../ecs/BodyKind.js";
3
+ import { world_inverse_inertia_apply } from "../inertia/world_inverse_inertia.js";
4
+
5
+ const scratch_angular = new Float64Array(3);
6
+
7
+ /**
8
+ * Semi-implicit Euler velocity integration for a single rigid body.
9
+ *
10
+ * For Dynamic bodies:
11
+ * - gravity (scaled by `gravityScale`) and the accumulated force are converted
12
+ * to a velocity delta via `1/mass`,
13
+ * - accumulated torque is converted to angular acceleration via the
14
+ * world-frame inverse inertia (R · diag(I_local) · R^T applied to τ),
15
+ * - linear and angular damping are applied as a stable implicit decay
16
+ * `v *= 1 / (1 + d·dt)` (Box2D / Bullet recipe — never goes negative, no
17
+ * `exp()` call on the hot path),
18
+ * - the force / torque accumulators are zeroed afterwards.
19
+ *
20
+ * Kinematic and Static bodies are skipped — their velocity is the
21
+ * user / animation system's responsibility.
22
+ *
23
+ * @param {RigidBody} rb
24
+ * @param {Transform} transform used to rotate body-frame inertia into world
25
+ * @param {number} gx world gravity x
26
+ * @param {number} gy world gravity y
27
+ * @param {number} gz world gravity z
28
+ * @param {number} dt step size in seconds
29
+ */
30
+ export function integrate_velocity(rb, transform, gx, gy, gz, dt) {
31
+ const af = rb.accumulatedForce;
32
+ const at = rb.accumulatedTorque;
33
+
34
+ if (rb.kind !== BodyKind.Dynamic) {
35
+ // Direct indexing no observer listens to body-internal accumulators.
36
+ af[0] = 0; af[1] = 0; af[2] = 0;
37
+ at[0] = 0; at[1] = 0; at[2] = 0;
38
+ return;
39
+ }
40
+
41
+ const inv_m = rb.mass > 0 ? 1 / rb.mass : 0;
42
+ const gs = rb.gravityScale;
43
+
44
+ // Linear velocity update: v += (F * invM + g * gravityScale) * dt
45
+ const lv = rb.linearVelocity;
46
+ let lvx = lv[0] + (af[0] * inv_m + gx * gs) * dt;
47
+ let lvy = lv[1] + (af[1] * inv_m + gy * gs) * dt;
48
+ let lvz = lv[2] + (af[2] * inv_m + gz * gs) * dt;
49
+
50
+ if (rb.linearDamping > 0) {
51
+ const k = 1 / (1 + rb.linearDamping * dt);
52
+ lvx *= k;
53
+ lvy *= k;
54
+ lvz *= k;
55
+ }
56
+ lv[0] = lvx; lv[1] = lvy; lv[2] = lvz;
57
+
58
+ // Angular velocity update: ω += I_world⁻¹ · τ · dt
59
+ const av = rb.angularVelocity;
60
+ let avx = av[0];
61
+ let avy = av[1];
62
+ let avz = av[2];
63
+ if (at[0] !== 0 || at[1] !== 0 || at[2] !== 0) {
64
+ world_inverse_inertia_apply(scratch_angular, 0, rb.inverseInertiaLocal, transform.rotation, at[0], at[1], at[2]);
65
+ avx += scratch_angular[0] * dt;
66
+ avy += scratch_angular[1] * dt;
67
+ avz += scratch_angular[2] * dt;
68
+ }
69
+
70
+ if (rb.angularDamping > 0) {
71
+ const k = 1 / (1 + rb.angularDamping * dt);
72
+ avx *= k;
73
+ avy *= k;
74
+ avz *= k;
75
+ }
76
+ av[0] = avx; av[1] = avy; av[2] = avz;
77
+
78
+ af[0] = 0; af[1] = 0; af[2] = 0;
79
+ at[0] = 0; at[1] = 0; at[2] = 0;
80
+ }
81
+
82
+ /**
83
+ * Apply the accumulated force / torque to velocity over a step `dt`, then
84
+ * zero the accumulators. Gravity and damping are NOT applied here.
85
+ *
86
+ * The "once per outer step" half of the TGS integrator: a user force is a
87
+ * per-frame budget that must land in full exactly once, independent of
88
+ * substep count. Gravity is the continuous field re-applied every substep
89
+ * by {@link integrate_velocity_gravity}.
90
+ *
91
+ * @param {RigidBody} rb
92
+ * @param {Transform} transform used to rotate body-frame inertia into world
93
+ * @param {number} dt full outer-step size in seconds
94
+ */
95
+ export function integrate_velocity_forces(rb, transform, dt) {
96
+ const af = rb.accumulatedForce;
97
+ const at = rb.accumulatedTorque;
98
+
99
+ if (rb.kind !== BodyKind.Dynamic) {
100
+
101
+ af[0] = 0;
102
+ af[1] = 0;
103
+ af[2] = 0;
104
+
105
+ at[0] = 0;
106
+ at[1] = 0;
107
+ at[2] = 0;
108
+
109
+ return;
110
+ }
111
+
112
+ const inv_m = rb.mass > 0 ? 1 / rb.mass : 0;
113
+
114
+ const lv = rb.linearVelocity;
115
+ lv[0] += af[0] * inv_m * dt;
116
+ lv[1] += af[1] * inv_m * dt;
117
+ lv[2] += af[2] * inv_m * dt;
118
+
119
+ if (at[0] !== 0 || at[1] !== 0 || at[2] !== 0) {
120
+
121
+ world_inverse_inertia_apply(
122
+ scratch_angular, 0,
123
+ rb.inverseInertiaLocal, transform.rotation,
124
+ at[0],
125
+ at[1],
126
+ at[2]
127
+ );
128
+
129
+ const av = rb.angularVelocity;
130
+
131
+ av[0] += scratch_angular[0] * dt;
132
+ av[1] += scratch_angular[1] * dt;
133
+ av[2] += scratch_angular[2] * dt;
134
+ }
135
+
136
+ af[0] = 0;
137
+ af[1] = 0;
138
+ af[2] = 0;
139
+
140
+ at[0] = 0;
141
+ at[1] = 0;
142
+ at[2] = 0;
143
+ }
144
+
145
+ /**
146
+ * Apply gravity and velocity damping over a (sub)step `dt`. Does NOT touch
147
+ * the force / torque accumulators (consumed once by
148
+ * {@link integrate_velocity_forces}).
149
+ *
150
+ * The "every substep" half of the TGS integrator. Per substep the body sees
151
+ * only `g·h` of gravity, which the per-substep contact warm-start + solve
152
+ * cancels exactly — keeping a resting stack at zero velocity. Damping is the
153
+ * stable implicit decay `v *= 1/(1 + d·dt)` applied at the substep `dt`.
154
+ *
155
+ * Velocity (and the damping it applies) lives in the data-oriented
156
+ * {@link SolverBodyState} for the duration of the substep loop; this reads and
157
+ * writes that span by `base`. The body's configuration (kind / gravityScale /
158
+ * damping coefficients) is still read from the `RigidBody` — cheap, once per
159
+ * body per substep, and unchanged across the step.
160
+ *
161
+ * @param {Float64Array} ss solver-body-state data array
162
+ * @param {number} base `body_index * SBS_STRIDE`
163
+ * @param {RigidBody} rb
164
+ * @param {number} gx
165
+ * @param {number} gy
166
+ * @param {number} gz world gravity
167
+ * @param {number} dt sub-step size in seconds
168
+ */
169
+ export function integrate_velocity_gravity(ss, base, rb, gx, gy, gz, dt) {
170
+ if (rb.kind !== BodyKind.Dynamic) {
171
+ return;
172
+ }
173
+
174
+ const gs = rb.gravityScale;
175
+
176
+ let lvx = ss[base + SBS_LV_X] + gx * gs * dt;
177
+ let lvy = ss[base + SBS_LV_Y] + gy * gs * dt;
178
+ let lvz = ss[base + SBS_LV_Z] + gz * gs * dt;
179
+
180
+ if (rb.linearDamping > 0) {
181
+ const k = 1 / (1 + rb.linearDamping * dt);
182
+
183
+ lvx *= k;
184
+ lvy *= k;
185
+ lvz *= k;
186
+ }
187
+
188
+ ss[base + SBS_LV_X] = lvx;
189
+ ss[base + SBS_LV_Y] = lvy;
190
+ ss[base + SBS_LV_Z] = lvz;
191
+
192
+ if (rb.angularDamping > 0) {
193
+
194
+ const k = 1 / (1 + rb.angularDamping * dt);
195
+
196
+ ss[base + SBS_AV_X] *= k;
197
+ ss[base + SBS_AV_Y] *= k;
198
+ ss[base + SBS_AV_Z] *= k;
199
+
200
+ }
201
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"box_box_manifold.d.ts","sourceRoot":"","sources":["../../../../../src/engine/physics/narrowphase/box_box_manifold.js"],"names":[],"mappings":"AAqJA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,sCAvBW,MAAM,EAAE,GAAC,YAAY,MACrB,MAAM,MACN,MAAM,MACN,MAAM,OACN,MAAM,OACN,MAAM,OACN,MAAM,OACN,MAAM,OACN,MAAM,OACN,MAAM,OACN,MAAM,MACN,MAAM,MACN,MAAM,MACN,MAAM,OACN,MAAM,OACN,MAAM,OACN,MAAM,OACN,MAAM,OACN,MAAM,OACN,MAAM,OACN,MAAM,GACJ,OAAO,CA8anB;AA3hBD;;;GAGG;AACH,iCAFU,MAAM,CAEoD"}
1
+ {"version":3,"file":"box_box_manifold.d.ts","sourceRoot":"","sources":["../../../../../src/engine/physics/narrowphase/box_box_manifold.js"],"names":[],"mappings":"AAgHA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,sCAvBW,MAAM,EAAE,GAAC,YAAY,MACrB,MAAM,MACN,MAAM,MACN,MAAM,OACN,MAAM,OACN,MAAM,OACN,MAAM,OACN,MAAM,OACN,MAAM,OACN,MAAM,OACN,MAAM,MACN,MAAM,MACN,MAAM,MACN,MAAM,OACN,MAAM,OACN,MAAM,OACN,MAAM,OACN,MAAM,OACN,MAAM,OACN,MAAM,OACN,MAAM,GACJ,OAAO,CAghBnB;AArlBD;;;GAGG;AACH,iCAFU,MAAM,CAEoD"}