@woosh/meep-engine 3.7.0 → 3.9.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 (45) hide show
  1. package/package.json +1 -1
  2. package/src/engine/physics/ccd/linear_sweep.d.ts +19 -4
  3. package/src/engine/physics/ccd/linear_sweep.d.ts.map +1 -1
  4. package/src/engine/physics/ccd/linear_sweep.js +214 -6
  5. package/src/engine/physics/ecs/PhysicsSystem.d.ts.map +1 -1
  6. package/src/engine/physics/ecs/PhysicsSystem.js +2277 -2266
  7. package/src/shade/renderer/rasterize/native/oit/shader_oit_blend.d.ts.map +1 -1
  8. package/src/shade/renderer/rasterize/native/oit/shader_oit_blend.js +5 -4
  9. package/src/shade/renderer/shader/chunk/math/chunk_magnitude_floor.d.ts +9 -0
  10. package/src/shade/renderer/shader/chunk/math/chunk_magnitude_floor.d.ts.map +1 -0
  11. package/src/shade/renderer/shader/chunk/math/chunk_magnitude_floor.js +16 -0
  12. package/src/shade/renderer/shader/chunk/math/complex/chunk_complex_magnitude_floor.d.ts +10 -0
  13. package/src/shade/renderer/shader/chunk/math/complex/chunk_complex_magnitude_floor.d.ts.map +1 -0
  14. package/src/shade/renderer/shader/chunk/math/complex/chunk_complex_magnitude_floor.js +17 -0
  15. package/src/shade/renderer/shader/chunk/math/complex/chunk_complex_solve_cubic_blinn.d.ts.map +1 -1
  16. package/src/shade/renderer/shader/chunk/math/complex/chunk_complex_solve_cubic_blinn.js +7 -1
  17. package/src/shade/renderer/shader/chunk/math/complex/chunk_complex_square_root.d.ts.map +1 -1
  18. package/src/shade/renderer/shader/chunk/math/complex/chunk_complex_square_root.js +9 -3
  19. package/src/shade/renderer/shader/chunk/math/polynomial/chunk_solve_cubic.d.ts.map +1 -1
  20. package/src/shade/renderer/shader/chunk/math/polynomial/chunk_solve_cubic.js +13 -7
  21. package/src/shade/renderer/shader/chunk/math/polynomial/chunk_solve_cubic_blinn_smallest.d.ts.map +1 -1
  22. package/src/shade/renderer/shader/chunk/math/polynomial/chunk_solve_cubic_blinn_smallest.js +13 -4
  23. package/src/shade/renderer/shader/chunk/math/polynomial/chunk_solve_quadratic.d.ts.map +1 -1
  24. package/src/shade/renderer/shader/chunk/math/polynomial/chunk_solve_quadratic.js +20 -13
  25. package/src/shade/renderer/shader/chunk/math/polynomial/chunk_solve_quartic_neumark.d.ts.map +1 -1
  26. package/src/shade/renderer/shader/chunk/math/polynomial/chunk_solve_quartic_neumark.js +8 -4
  27. package/src/shade/renderer/shader/chunk/mboit/NOTES.md +35 -1
  28. package/src/shade/renderer/shader/chunk/mboit/moments/geometric/chunk_compute_transmittance_from_2_trigonometric_moments.d.ts.map +1 -1
  29. package/src/shade/renderer/shader/chunk/mboit/moments/geometric/chunk_compute_transmittance_from_2_trigonometric_moments.js +18 -5
  30. package/src/shade/renderer/shader/chunk/mboit/moments/geometric/chunk_compute_transmittance_from_3_trigonometric_moments.d.ts.map +1 -1
  31. package/src/shade/renderer/shader/chunk/mboit/moments/geometric/chunk_compute_transmittance_from_3_trigonometric_moments.js +21 -8
  32. package/src/shade/renderer/shader/chunk/mboit/moments/geometric/chunk_compute_transmittance_from_4_trigonometric_moments.d.ts.map +1 -1
  33. package/src/shade/renderer/shader/chunk/mboit/moments/geometric/chunk_compute_transmittance_from_4_trigonometric_moments.js +25 -12
  34. package/src/shade/renderer/shader/chunk/mboit/moments/geometric/chunk_generate_trigonometric_moments_4.d.ts +6 -2
  35. package/src/shade/renderer/shader/chunk/mboit/moments/geometric/chunk_generate_trigonometric_moments_4.d.ts.map +1 -1
  36. package/src/shade/renderer/shader/chunk/mboit/moments/geometric/chunk_generate_trigonometric_moments_4.js +42 -35
  37. package/src/shade/renderer/shader/chunk/mboit/moments/power/chunk_compute_transmittance_from_4_power_moments.d.ts.map +1 -1
  38. package/src/shade/renderer/shader/chunk/mboit/moments/power/chunk_compute_transmittance_from_4_power_moments.js +18 -5
  39. package/src/shade/renderer/shader/chunk/mboit/moments/power/chunk_compute_transmittance_from_6_power_moments.d.ts.map +1 -1
  40. package/src/shade/renderer/shader/chunk/mboit/moments/power/chunk_compute_transmittance_from_6_power_moments.js +24 -9
  41. package/src/shade/renderer/shader/chunk/mboit/moments/power/chunk_compute_transmittance_from_8_power_moments.d.ts.map +1 -1
  42. package/src/shade/renderer/shader/chunk/mboit/moments/power/chunk_compute_transmittance_from_8_power_moments.js +29 -13
  43. package/src/shade/renderer/shader/chunk/mboit/moments/power/chunk_generate_power_moments_4.d.ts +12 -0
  44. package/src/shade/renderer/shader/chunk/mboit/moments/power/chunk_generate_power_moments_4.d.ts.map +1 -1
  45. package/src/shade/renderer/shader/chunk/mboit/moments/power/chunk_generate_power_moments_4.js +38 -48
package/package.json CHANGED
@@ -6,7 +6,7 @@
6
6
  "description": "Pure JavaScript game engine. Fully featured and production ready.",
7
7
  "type": "module",
8
8
  "author": "Alexander Goldring",
9
- "version": "3.7.0",
9
+ "version": "3.9.0",
10
10
  "exports": {
11
11
  "./build/*": "./build/*",
12
12
  "./src/*": "./src/*",
@@ -31,6 +31,20 @@ export function ccd_sweep_segment(system: import("../ecs/PhysicsSystem.js").Phys
31
31
  z: number;
32
32
  w: number;
33
33
  }, fx: number, fy: number, fz: number, tx: number, ty: number, tz: number, exclude_entity: number, result: PhysicsSurfacePoint): number;
34
+ /**
35
+ * Take back the contacts {@link record_ccd_contact} wrote this step.
36
+ *
37
+ * Call at the END of the step, after `diff_manifolds` has read them AND after
38
+ * `ManifoldStore#advance_frame` has rolled them into each pair's had-contacts
39
+ * bit — see {@link record_ccd_contact} for why they must not survive into the
40
+ * next step's wake pass.
41
+ *
42
+ * A slot is only cleared while it still holds the pair it was written for:
43
+ * `advance_frame` can grace-evict a slot, and the id it frees is reusable.
44
+ *
45
+ * @param {import("../ecs/PhysicsSystem.js").PhysicsSystem} system
46
+ */
47
+ export function ccd_release_contacts(system: import("../ecs/PhysicsSystem.js").PhysicsSystem): void;
34
48
  /**
35
49
  * Post-solve continuous-collision pass over the awake set. For each awake
36
50
  * Dynamic body flagged {@link RigidBodyFlags.CCD} that moved more than
@@ -68,10 +82,11 @@ export function ccd_resolve(system: import("../ecs/PhysicsSystem.js").PhysicsSys
68
82
  * the substep solver has produced each body's final pose, sweep a CCD-flagged
69
83
  * fast mover's primary collider along its NET step translation
70
84
  * (start-of-step → final pose) using the existing {@link shape_cast} TOI engine.
71
- * On the first blocker, clamp the body to the contact pose and remove the
72
- * inbound normal component of its velocity (an inelastic stop) the next
73
- * discrete step then resolves the now-touching contact with the real
74
- * material / restitution.
85
+ * On the first blocker, clamp the body to the contact pose, remove the inbound
86
+ * normal component of its velocity (an inelastic stop), and RECORD the impact
87
+ * on the pair's manifold ({@link record_ccd_contact}) so this step's event diff
88
+ * reports it — the next discrete step then resolves the now-touching contact
89
+ * with the real material / restitution.
75
90
  *
76
91
  * Scope (v1, deliberate):
77
92
  * - LINEAR sweep only: the orientation is held fixed through the sweep (the
@@ -1 +1 @@
1
- {"version":3,"file":"linear_sweep.d.ts","sourceRoot":"","sources":["../../../../../src/engine/physics/ccd/linear_sweep.js"],"names":[],"mappings":"AA6HA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,0CAdW,OAAO,yBAAyB,EAAE,aAAa,SAC/C,OAAO,gDAAgD,EAAE,eAAe,YACxE;IAAC,CAAC,EAAC,MAAM,CAAC;IAAA,CAAC,EAAC,MAAM,CAAC;IAAA,CAAC,EAAC,MAAM,CAAC;IAAA,CAAC,EAAC,MAAM,CAAA;CAAC,MACrC,MAAM,MACN,MAAM,MACN,MAAM,MACN,MAAM,MACN,MAAM,MACN,MAAM,kBACN,MAAM,UAEN,mBAAmB,GACjB,MAAM,CA2ClB;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,oCAFW,OAAO,yBAAyB,EAAE,aAAa,QAwGzD;AAvTD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAEH;;;;;;;;;;;;;;;GAeG;AACH,qCAFU,MAAM,CAE2B;oCArDP,mCAAmC"}
1
+ {"version":3,"file":"linear_sweep.d.ts","sourceRoot":"","sources":["../../../../../src/engine/physics/ccd/linear_sweep.js"],"names":[],"mappings":"AAgKA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,0CAdW,OAAO,yBAAyB,EAAE,aAAa,SAC/C,OAAO,gDAAgD,EAAE,eAAe,YACxE;IAAC,CAAC,EAAC,MAAM,CAAC;IAAA,CAAC,EAAC,MAAM,CAAC;IAAA,CAAC,EAAC,MAAM,CAAC;IAAA,CAAC,EAAC,MAAM,CAAA;CAAC,MACrC,MAAM,MACN,MAAM,MACN,MAAM,MACN,MAAM,MACN,MAAM,MACN,MAAM,kBACN,MAAM,UAEN,mBAAmB,GACjB,MAAM,CA2ClB;AAuID;;;;;;;;;;;;GAYG;AACH,6CAFW,OAAO,yBAAyB,EAAE,aAAa,QAezD;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,oCAFW,OAAO,yBAAyB,EAAE,aAAa,QAoHzD;AArgBD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAEH;;;;;;;;;;;;;;;GAeG;AACH,qCAFU,MAAM,CAE2B;oCAtDP,mCAAmC"}
@@ -1,4 +1,6 @@
1
+ import { PosedShape3D } from "../../../core/geom/3d/shape/PosedShape3D.js";
1
2
  import { BODY_INDEX_ABSENT, body_id_index, pack_body_id } from "../body/BodyStorage.js";
3
+ import { combine_friction, combine_restitution } from "../contact/combine_material.js";
2
4
  import { BodyKind } from "../ecs/BodyKind.js";
3
5
  import { is_sensor } from "../ecs/is_sensor.js";
4
6
  import { RigidBodyFlags } from "../ecs/RigidBodyFlags.js";
@@ -20,10 +22,11 @@ import { shape_cast } from "../queries/shape_cast.js";
20
22
  * the substep solver has produced each body's final pose, sweep a CCD-flagged
21
23
  * fast mover's primary collider along its NET step translation
22
24
  * (start-of-step → final pose) using the existing {@link shape_cast} TOI engine.
23
- * On the first blocker, clamp the body to the contact pose and remove the
24
- * inbound normal component of its velocity (an inelastic stop) the next
25
- * discrete step then resolves the now-touching contact with the real
26
- * material / restitution.
25
+ * On the first blocker, clamp the body to the contact pose, remove the inbound
26
+ * normal component of its velocity (an inelastic stop), and RECORD the impact
27
+ * on the pair's manifold ({@link record_ccd_contact}) so this step's event diff
28
+ * reports it — the next discrete step then resolves the now-touching contact
29
+ * with the real material / restitution.
27
30
  *
28
31
  * Scope (v1, deliberate):
29
32
  * - LINEAR sweep only: the orientation is held fixed through the sweep (the
@@ -77,6 +80,27 @@ const _ray = {
77
80
  /** Sweep result reused across bodies inside {@link ccd_resolve}. */
78
81
  const _hit = new PhysicsSurfacePoint();
79
82
 
83
+ /**
84
+ * The swept shape held at its CLAMPED pose, for the contact-witness support
85
+ * query in {@link record_ccd_contact}.
86
+ * @type {PosedShape3D}
87
+ */
88
+ const _clamped = new PosedShape3D();
89
+
90
+ /** Contact witness written by {@link _clamped}'s support query. */
91
+ const _witness = new Float64Array(3);
92
+
93
+ /**
94
+ * Slots {@link record_ccd_contact} wrote this step, as `(slot, idA, idB)`
95
+ * triples, for {@link ccd_release_contacts} to take back out again. Grows by
96
+ * doubling; module-scoped so the pass allocates nothing in steady state.
97
+ * @type {Uint32Array}
98
+ */
99
+ let _written = new Uint32Array(3 * 16);
100
+
101
+ /** Number of triples currently in {@link _written}. */
102
+ let _written_count = 0;
103
+
80
104
  /**
81
105
  * CCD-eligible body indices of the current pass, ordered by ENTITY id.
82
106
  * Grows by doubling; module-scoped so the pass allocates nothing in steady
@@ -109,7 +133,13 @@ let _self_body_id = -1;
109
133
  * volume (same rule and rationale as {@link raycast});
110
134
  * - layer/mask + the user contact filter via `system.__pair_filter`, so CCD
111
135
  * never clamps a body onto geometry the discrete solver would not
112
- * collide it with.
136
+ * collide it with. Asked in ENTITY-CANONICAL order, which is the order
137
+ * `generate_pairs` asks in: layer/mask is symmetric, but the user callback
138
+ * is handed `(entityA, entityB, colliderA, colliderB)` and need not be, so
139
+ * asking in sweep order let a filter accept for CCD what the broadphase
140
+ * had rejected. The sweep then clamped the body onto geometry the discrete
141
+ * pipeline had no pair for — and, once the sweep began reporting its own
142
+ * impacts ({@link record_ccd_contact}), raised contact events for it.
113
143
  *
114
144
  * @param {number} entity candidate body's entity
115
145
  * @param {Collider} collider candidate body's primary collider
@@ -119,7 +149,12 @@ let _self_body_id = -1;
119
149
  function _ccd_filter(entity, collider, body_id) {
120
150
  if (body_id === _self_body_id) return false;
121
151
  if (is_sensor(_system.__bodies[body_id_index(body_id)], collider)) return false;
122
- if (_self_body_id !== -1 && !_system.__pair_filter(_self_body_id, body_id)) return false;
152
+ if (_self_body_id !== -1) {
153
+ const self_entity = _system.storage.entity_at(body_id_index(_self_body_id));
154
+ const a = self_entity < entity ? _self_body_id : body_id;
155
+ const b = self_entity < entity ? body_id : _self_body_id;
156
+ if (!_system.__pair_filter(a, b)) return false;
157
+ }
123
158
  return true;
124
159
  }
125
160
 
@@ -193,6 +228,167 @@ export function ccd_sweep_segment(
193
228
  return frac < 1 ? frac : 1;
194
229
  }
195
230
 
231
+ /**
232
+ * Record the impact the sweep just resolved as a contact on the pair's
233
+ * manifold, so this step's event diff reports it.
234
+ *
235
+ * ## Why the sweep has to report its own impacts
236
+ *
237
+ * The clamp parks the body on the just-SEPARATING side of the TOI bisection —
238
+ * {@link shape_cast} reports `t_lo`, the last sample proven NOT to overlap, and
239
+ * that is exactly the property the clamp relies on. The discrete narrowphase
240
+ * emits a contact only for STRICTLY POSITIVE penetration. So the pose CCD
241
+ * produces is, by construction, the one pose the narrowphase calls "not
242
+ * touching": a body stopped dead by the sweep raised no ContactBegin, and kept
243
+ * raising none for as long as it sat there.
244
+ *
245
+ * That it ever appeared to work at all was luck about which side of tangency
246
+ * the bisection landed on. A sphere driven at a box's FACE came to rest ~1e-7 m
247
+ * INSIDE it — `gjk`'s own tolerance against a flat support — and the NEXT
248
+ * step's narrowphase found that sliver and fired a step late. The same sphere,
249
+ * same speed, driven at the same box's CORNER came to rest a few µm CLEAR of
250
+ * it, and nothing was ever reported: the body sat there blocked and silent for
251
+ * as long as it was stepped. Same sweep, same stopping step, same geometric
252
+ * distance, opposite answers — split by the rounding rather than by the
253
+ * feature, and reproducing identically through the closed-form sphere-box path,
254
+ * so it was never about simplex quality on hulls.
255
+ *
256
+ * The sweep is the only part of the pipeline that SAW the impact: it happened
257
+ * mid-step, between two poses the discrete narrowphase never samples. So it is
258
+ * the part that has to report it. It knows the blocker, the pose at first
259
+ * contact, and the surface normal there — that is a contact, and it is written
260
+ * as one. The pass runs before the event diff, so the Begin lands on the step
261
+ * the impact happened rather than the step after it.
262
+ *
263
+ * ## What is written
264
+ *
265
+ * A single contact at depth ZERO. The sweep stopped the body ON the surface, so
266
+ * the pair is touching and the penetration is nothing; that is the honest depth
267
+ * and the one the solver's `PENETRATION_SLOP`-gated position bias ignores.
268
+ * Both witness points are the same point — at a tangency the two surfaces meet
269
+ * there — and `feature_id` is 0, no stable cross-frame feature, same as the
270
+ * narrowphase's own GJK + EPA fallback.
271
+ *
272
+ * The contact is a REPORT, not state, and {@link ccd_release_contacts} takes it
273
+ * back out at the end of the step — after the diff has read it and after
274
+ * `advance_frame` has rolled it into the pair's had-contacts bit, so the next
275
+ * step still resolves to Stay rather than a second Begin. Leaving it in the
276
+ * slot overnight is not harmless: `PhysicsSystem.__wake_pairs` runs before the
277
+ * narrowphase and wakes a sleeper LEVEL-triggered on `contact_count > 0`, so a
278
+ * body ground against a sleeping one re-woke it every step for a contact the
279
+ * solver never acts on (this pass runs after the solver), leaving it flickering
280
+ * awake and asleep instead of sleeping through it.
281
+ *
282
+ * A pair the narrowphase already resolved this step is left alone — its
283
+ * manifold is the better one, and only an impact the discrete pass could not
284
+ * see is this pass's to report.
285
+ *
286
+ * @param {import("../ecs/PhysicsSystem.js").PhysicsSystem} system
287
+ * @param {number} body_idx swept body's storage index
288
+ * @param {Collider} collider the swept (primary) collider
289
+ * @param {Transform} tr the swept body's transform, already clamped to the
290
+ * contact pose
291
+ * @param {PhysicsSurfacePoint} hit the sweep result that produced the clamp
292
+ */
293
+ function record_ccd_contact(system, body_idx, collider, tr, hit) {
294
+ const blocker_id = hit.body_id;
295
+
296
+ const storage = system.storage;
297
+ if (blocker_id < 0 || !storage.is_valid(blocker_id)) return;
298
+
299
+ const blocker_idx = body_id_index(blocker_id);
300
+ const self_id = pack_body_id(body_idx, storage.generation_at(body_idx));
301
+
302
+ // Entity-canonical roles, matching `generate_pairs`. The A/B assignment has
303
+ // to be the one the broadphase makes, or this pair gets a SECOND slot under
304
+ // the mirrored key and the two disagree about everything after.
305
+ const self_is_a = storage.entity_at(body_idx) < storage.entity_at(blocker_idx);
306
+ const idA = self_is_a ? self_id : blocker_id;
307
+ const idB = self_is_a ? blocker_id : self_id;
308
+
309
+ const manifolds = system.manifolds;
310
+ const slot = manifolds.acquire(idA, idB);
311
+ if (manifolds.contact_count(slot) > 0) return;
312
+
313
+ // `hit.normal` is the blocker's outward surface normal, pointing back at the
314
+ // swept body.
315
+ const n = hit.normal;
316
+
317
+ // Contact witness: the swept shape's own surface point facing the blocker,
318
+ // which is its support along −n (a sphere's near pole, a box's leading
319
+ // corner). Taking it from the MOVER rather than the blocker is what keeps it
320
+ // near the actual contact patch — a large blocker's support along a face
321
+ // axis is a corner metres away, which is why the narrowphase's EPA fallback
322
+ // refuses support witnesses and falls back to body centres.
323
+ _clamped.setup(collider.shape, tr.position, tr.rotation);
324
+ _clamped.support(_witness, 0, -n[0], -n[1], -n[2]);
325
+
326
+ const wx = _witness[0], wy = _witness[1], wz = _witness[2];
327
+
328
+ // Per-contact materials, combined exactly as `dispatch_pair` does.
329
+ const blocker_collider = system.__primary_collider(blocker_idx);
330
+ let friction = 0;
331
+ let restitution = 0;
332
+ if (blocker_collider !== null
333
+ && collider.friction !== undefined
334
+ && blocker_collider.friction !== undefined
335
+ ) {
336
+ friction = combine_friction(collider.friction, blocker_collider.friction);
337
+ restitution = combine_restitution(collider.restitution, blocker_collider.restitution);
338
+ }
339
+
340
+ // The stored normal points from the slot's OWN body B toward its body A.
341
+ const s = self_is_a ? 1 : -1;
342
+
343
+ manifolds.set_contact(
344
+ slot, 0,
345
+ wx, wy, wz,
346
+ wx, wy, wz,
347
+ n[0] * s, n[1] * s, n[2] * s,
348
+ 0, 0,
349
+ friction, restitution,
350
+ );
351
+
352
+ const w = _written_count * 3;
353
+ if (w === _written.length) {
354
+ const next = new Uint32Array(_written.length * 2);
355
+ next.set(_written);
356
+ _written = next;
357
+ }
358
+ _written[w] = slot;
359
+ _written[w + 1] = idA;
360
+ _written[w + 2] = idB;
361
+ _written_count++;
362
+ }
363
+
364
+ /**
365
+ * Take back the contacts {@link record_ccd_contact} wrote this step.
366
+ *
367
+ * Call at the END of the step, after `diff_manifolds` has read them AND after
368
+ * `ManifoldStore#advance_frame` has rolled them into each pair's had-contacts
369
+ * bit — see {@link record_ccd_contact} for why they must not survive into the
370
+ * next step's wake pass.
371
+ *
372
+ * A slot is only cleared while it still holds the pair it was written for:
373
+ * `advance_frame` can grace-evict a slot, and the id it frees is reusable.
374
+ *
375
+ * @param {import("../ecs/PhysicsSystem.js").PhysicsSystem} system
376
+ */
377
+ export function ccd_release_contacts(system) {
378
+ if (_written_count === 0) return;
379
+
380
+ const manifolds = system.manifolds;
381
+
382
+ for (let i = 0; i < _written_count; i++) {
383
+ const w = i * 3;
384
+ const slot = _written[w];
385
+ if (manifolds.find(_written[w + 1], _written[w + 2]) !== slot) continue;
386
+ manifolds.clear_contacts(slot);
387
+ }
388
+
389
+ _written_count = 0;
390
+ }
391
+
196
392
  /**
197
393
  * Post-solve continuous-collision pass over the awake set. For each awake
198
394
  * Dynamic body flagged {@link RigidBodyFlags.CCD} that moved more than
@@ -215,6 +411,12 @@ export function ccd_sweep_segment(
215
411
  * @param {import("../ecs/PhysicsSystem.js").PhysicsSystem} system
216
412
  */
217
413
  export function ccd_resolve(system) {
414
+ // Each pass owns its own report list. Dropped rather than carried if a
415
+ // caller never got round to releasing the previous one, so a slot id can
416
+ // never be cleared a step after it was written (or for a pair that has
417
+ // since been reallocated onto it).
418
+ _written_count = 0;
419
+
218
420
  const storage = system.storage;
219
421
  const count = storage.awake_count;
220
422
  const lists = system.__body_collider_lists;
@@ -315,5 +517,11 @@ export function ccd_resolve(system) {
315
517
  lv[1] -= vn * n[1];
316
518
  lv[2] -= vn * n[2];
317
519
  }
520
+
521
+ // Tell the world it happened. The clamp above is the whole of the
522
+ // collision — the discrete narrowphase samples step boundaries and this
523
+ // impact was between two of them — so without this the body is stopped
524
+ // dead and nothing is ever told. See {@link record_ccd_contact}.
525
+ record_ccd_contact(system, idx, primary.collider, tr, _hit);
318
526
  }
319
527
  }
@@ -1 +1 @@
1
- {"version":3,"file":"PhysicsSystem.d.ts","sourceRoot":"","sources":["../../../../../src/engine/physics/ecs/PhysicsSystem.js"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"PhysicsSystem.d.ts","sourceRoot":"","sources":["../../../../../src/engine/physics/ecs/PhysicsSystem.js"],"names":[],"mappings":"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"}