@woosh/meep-engine 2.153.0 → 2.154.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/ConvexHullShape3D.d.ts +112 -0
- package/src/core/geom/3d/shape/ConvexHullShape3D.d.ts.map +1 -0
- package/src/core/geom/3d/shape/ConvexHullShape3D.js +325 -0
- package/src/engine/graphics/ecs/trail2d/Trail2D.d.ts +4 -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/physics/PLAN.md +4 -4
- package/src/engine/physics/body/BodyStorage.d.ts +3 -1
- package/src/engine/physics/body/BodyStorage.d.ts.map +1 -1
- package/src/engine/physics/body/BodyStorage.js +452 -450
- package/src/engine/physics/body/SolverBodyState.d.ts.map +1 -1
- package/src/engine/physics/body/SolverBodyState.js +6 -5
- package/src/engine/physics/broadphase/generate_pairs.d.ts.map +1 -1
- package/src/engine/physics/broadphase/generate_pairs.js +9 -1
- package/src/engine/physics/ccd/linear_sweep.d.ts.map +1 -1
- package/src/engine/physics/ccd/linear_sweep.js +237 -238
- package/src/engine/physics/computeInterceptPoint.d.ts.map +1 -1
- package/src/engine/physics/computeInterceptPoint.js +8 -3
- package/src/engine/physics/contact/ManifoldStore.d.ts +0 -16
- package/src/engine/physics/contact/ManifoldStore.d.ts.map +1 -1
- package/src/engine/physics/contact/ManifoldStore.js +1 -38
- package/src/engine/physics/ecs/BodyKind.d.ts +3 -2
- package/src/engine/physics/ecs/BodyKind.d.ts.map +1 -1
- package/src/engine/physics/ecs/BodyKind.js +25 -24
- package/src/engine/physics/ecs/PhysicsEvents.d.ts +4 -5
- package/src/engine/physics/ecs/PhysicsEvents.d.ts.map +1 -1
- package/src/engine/physics/ecs/PhysicsEvents.js +15 -16
- package/src/engine/physics/ecs/PhysicsSystem.d.ts +5 -30
- package/src/engine/physics/ecs/PhysicsSystem.d.ts.map +1 -1
- package/src/engine/physics/ecs/PhysicsSystem.js +13 -45
- package/src/engine/physics/ecs/RigidBodySerializationAdapter.d.ts.map +1 -1
- package/src/engine/physics/ecs/RigidBodySerializationAdapter.js +85 -81
- package/src/engine/physics/ecs/is_sensor.d.ts +18 -0
- package/src/engine/physics/ecs/is_sensor.d.ts.map +1 -0
- package/src/engine/physics/ecs/is_sensor.js +27 -0
- package/src/engine/physics/events/ContactEventBuffer.d.ts +2 -1
- package/src/engine/physics/events/ContactEventBuffer.d.ts.map +1 -1
- package/src/engine/physics/events/ContactEventBuffer.js +84 -83
- package/src/engine/physics/gjk/gjk.d.ts +0 -26
- package/src/engine/physics/gjk/gjk.d.ts.map +1 -1
- package/src/engine/physics/gjk/gjk.js +3 -52
- package/src/engine/physics/gjk/gjk_epa_penetration.d.ts +16 -0
- package/src/engine/physics/gjk/gjk_epa_penetration.d.ts.map +1 -0
- package/src/engine/physics/gjk/gjk_epa_penetration.js +255 -0
- package/src/engine/physics/gjk/minkowski_support.d.ts +4 -9
- package/src/engine/physics/gjk/minkowski_support.d.ts.map +1 -1
- package/src/engine/physics/gjk/minkowski_support.js +70 -75
- package/src/engine/physics/gjk/mpr.d.ts +1 -1
- package/src/engine/physics/gjk/mpr.d.ts.map +1 -1
- package/src/engine/physics/gjk/mpr.js +362 -344
- package/src/engine/physics/island/IslandBuilder.d.ts.map +1 -1
- package/src/engine/physics/island/IslandBuilder.js +431 -428
- package/src/engine/physics/narrowphase/box_box_manifold.d.ts.map +1 -1
- package/src/engine/physics/narrowphase/box_box_manifold.js +4 -81
- package/src/engine/physics/narrowphase/box_triangle_contact.d.ts.map +1 -1
- package/src/engine/physics/narrowphase/box_triangle_contact.js +4 -39
- package/src/engine/physics/narrowphase/capsule_contacts.d.ts.map +1 -1
- package/src/engine/physics/narrowphase/capsule_contacts.js +459 -462
- package/src/engine/physics/narrowphase/clip_against_axis_uv.d.ts.map +1 -1
- package/src/engine/physics/narrowphase/clip_against_axis_uv.js +4 -1
- package/src/engine/physics/narrowphase/convex_convex_manifold.d.ts +83 -0
- package/src/engine/physics/narrowphase/convex_convex_manifold.d.ts.map +1 -0
- package/src/engine/physics/narrowphase/convex_convex_manifold.js +425 -0
- package/src/engine/physics/narrowphase/convex_decomposition.d.ts +32 -0
- package/src/engine/physics/narrowphase/convex_decomposition.d.ts.map +1 -0
- package/src/engine/physics/narrowphase/convex_decomposition.js +293 -0
- package/src/engine/physics/narrowphase/mesh_convex_hull.d.ts +41 -0
- package/src/engine/physics/narrowphase/mesh_convex_hull.d.ts.map +1 -0
- package/src/engine/physics/narrowphase/mesh_convex_hull.js +106 -0
- package/src/engine/physics/narrowphase/mesh_mesh_tet_manifold.d.ts +8 -0
- package/src/engine/physics/narrowphase/mesh_mesh_tet_manifold.d.ts.map +1 -0
- package/src/engine/physics/narrowphase/mesh_mesh_tet_manifold.js +117 -0
- package/src/engine/physics/narrowphase/narrowphase_step.d.ts.map +1 -1
- package/src/engine/physics/narrowphase/narrowphase_step.js +105 -102
- package/src/engine/physics/narrowphase/reduce_manifold_contacts.d.ts +29 -0
- package/src/engine/physics/narrowphase/reduce_manifold_contacts.d.ts.map +1 -0
- package/src/engine/physics/narrowphase/reduce_manifold_contacts.js +69 -0
- package/src/engine/physics/narrowphase/refine_ray_concave.d.ts.map +1 -1
- package/src/engine/physics/narrowphase/refine_ray_concave.js +152 -145
- package/src/engine/physics/narrowphase/sphere_box_contact.d.ts.map +1 -1
- package/src/engine/physics/narrowphase/sphere_box_contact.js +132 -123
- package/src/engine/physics/queries/overlap_shape.d.ts.map +1 -1
- package/src/engine/physics/queries/overlap_shape.js +16 -17
- package/src/engine/physics/queries/raycast.d.ts +5 -0
- package/src/engine/physics/queries/raycast.d.ts.map +1 -1
- package/src/engine/physics/queries/raycast.js +16 -8
- package/src/engine/physics/queries/shape_cast.d.ts.map +1 -1
- package/src/engine/physics/queries/shape_cast.js +13 -7
- package/src/engine/physics/solver/solve_contacts.d.ts.map +1 -1
- package/src/engine/physics/solver/solve_contacts.js +8 -11
- package/src/engine/physics/vehicle/RaycastVehicle.d.ts.map +1 -1
- package/src/engine/physics/vehicle/RaycastVehicle.js +339 -333
- package/src/engine/physics/gjk/expanding_polytope_algorithm.d.ts +0 -13
- package/src/engine/physics/gjk/expanding_polytope_algorithm.d.ts.map +0 -1
- package/src/engine/physics/gjk/expanding_polytope_algorithm.js +0 -399
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SolverBodyState.d.ts","sourceRoot":"","sources":["../../../../../src/engine/physics/body/SolverBodyState.js"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoDG;AAEH,+CAA+C;AAC/C,6BAA8B;AAC9B,oFAAoF;AACpF,4BAA6B;AAC7B,4BAA6B;AAC7B,4BAA6B;AAC7B,oFAAoF;AACpF,uBAAwB;AACxB,uBAAwB;AACxB,uBAAwB;AACxB,uBAAwB;AACxB,kCAAkC;AAClC,yBAA0B;AAC1B,yBAA0B;AAC1B,0BAA2B;AAC3B,mCAAmC;AACnC,0BAA2B;AAC3B,0BAA2B;AAC3B,0BAA2B;AAE3B,wBAAwB;AACxB,4BAA6B;AAE7B;IACI,uCAoCC;IAjCG;;;OAGG;IACH,MAFU,YAAY,CAEwB;IAE9C;;;;;OAKG;IACH,gBAAkC;IAElC;;;;OAIG;IACH,mBAAsC;IAEtC,eAAe;IACf,yBAAyB;IAEzB;;;;OAIG;IACH,cAAc;IAEd,eAAe;IACf,mBAAqB;IAGzB;;;OAGG;IACH,6BAEC;IAED;;;;;OAKG;IACH,WAFW,MAAM,QAiBhB;IAED;;;;;;;;OAQG;IACH,YAJW,MAAM,6CA8ChB;IAED;;;;;;;OAOG;IACH,gBAFW,WAAW,QAoBrB;IAED;;;OAGG;IACH,
|
|
1
|
+
{"version":3,"file":"SolverBodyState.d.ts","sourceRoot":"","sources":["../../../../../src/engine/physics/body/SolverBodyState.js"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoDG;AAEH,+CAA+C;AAC/C,6BAA8B;AAC9B,oFAAoF;AACpF,4BAA6B;AAC7B,4BAA6B;AAC7B,4BAA6B;AAC7B,oFAAoF;AACpF,uBAAwB;AACxB,uBAAwB;AACxB,uBAAwB;AACxB,uBAAwB;AACxB,kCAAkC;AAClC,yBAA0B;AAC1B,yBAA0B;AAC1B,0BAA2B;AAC3B,mCAAmC;AACnC,0BAA2B;AAC3B,0BAA2B;AAC3B,0BAA2B;AAE3B,wBAAwB;AACxB,4BAA6B;AAE7B;IACI,uCAoCC;IAjCG;;;OAGG;IACH,MAFU,YAAY,CAEwB;IAE9C;;;;;OAKG;IACH,gBAAkC;IAElC;;;;OAIG;IACH,mBAAsC;IAEtC,eAAe;IACf,yBAAyB;IAEzB;;;;OAIG;IACH,cAAc;IAEd,eAAe;IACf,mBAAqB;IAGzB;;;OAGG;IACH,6BAEC;IAED;;;;;OAKG;IACH,WAFW,MAAM,QAiBhB;IAED;;;;;;;;OAQG;IACH,YAJW,MAAM,6CA8ChB;IAED;;;;;;;OAOG;IACH,gBAFW,WAAW,QAoBrB;IAED;;;OAGG;IACH,eAeC;CACJ"}
|
|
@@ -238,11 +238,12 @@ export class SolverBodyState {
|
|
|
238
238
|
const next_data = new Float64Array(cap * SBS_STRIDE);
|
|
239
239
|
const next_stamp = new Int32Array(cap);
|
|
240
240
|
const next_gathered = new Uint32Array(cap);
|
|
241
|
-
// No need to copy `data` — it is fully repopulated by `gather` each
|
|
242
|
-
//
|
|
243
|
-
//
|
|
244
|
-
//
|
|
245
|
-
|
|
241
|
+
// No need to copy `data` — it is fully repopulated by `gather` each step
|
|
242
|
+
// before any read. `__stamp` is intentionally NOT copied either: a fresh
|
|
243
|
+
// zero-filled array plus the live `__gen` (always >= 1 after begin's gen
|
|
244
|
+
// roll) makes every slot read as un-gathered, which is exactly what the
|
|
245
|
+
// grown region needs; copying stale gen values back in would be dead work
|
|
246
|
+
// (they are all < the live gen anyway).
|
|
246
247
|
this.data = next_data;
|
|
247
248
|
this.__stamp = next_stamp;
|
|
248
249
|
this.__gathered = next_gathered;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generate_pairs.d.ts","sourceRoot":"","sources":["../../../../../src/engine/physics/broadphase/generate_pairs.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"generate_pairs.d.ts","sourceRoot":"","sources":["../../../../../src/engine/physics/broadphase/generate_pairs.js"],"names":[],"mappings":"AAOA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,uIATW,MAAM,MAAM;IAAC,QAAQ,WAAW;IAAC,SAAS,YAAY;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAC,CAAC,CAAC,+CAElF,MAAM,OAAO,MAAM,KAAK,OAAO,oCAqFhD"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { assert } from "../../../core/assert.js";
|
|
2
2
|
import { bvh_query_user_data_overlaps_aabb } from "../../../core/bvh2/bvh3/query/bvh_query_user_data_overlaps_aabb.js";
|
|
3
|
+
import { pack_body_id } from "../body/BodyStorage.js";
|
|
3
4
|
|
|
4
5
|
const scratch_aabb = new Float64Array(6);
|
|
5
6
|
const candidates = new Uint32Array(1024);
|
|
@@ -56,7 +57,7 @@ export function generate_pairs(
|
|
|
56
57
|
if (list === undefined || list.length === 0) continue;
|
|
57
58
|
|
|
58
59
|
const gen = storage.generation_at(body_idx);
|
|
59
|
-
const my_packed = (body_idx
|
|
60
|
+
const my_packed = pack_body_id(body_idx, gen); // single-source the bit layout
|
|
60
61
|
|
|
61
62
|
for (let k = 0; k < list.length; k++) {
|
|
62
63
|
const node = list[k].bvhNode;
|
|
@@ -73,6 +74,12 @@ export function generate_pairs(
|
|
|
73
74
|
// past the buffer end, so the loop below would read `undefined`
|
|
74
75
|
// candidates and build garbage pairs. Guard the buffer size.
|
|
75
76
|
assert.lessThan(n, candidates.length, 'generate_pairs: dynamic broadphase overflowed the candidate buffer');
|
|
77
|
+
// Production-safe clamp: the assert is stripped at bundle time, so
|
|
78
|
+
// without this an overflowing query (count past the buffer) would read
|
|
79
|
+
// `undefined` candidates and fabricate NaN-keyed garbage pairs. Drop
|
|
80
|
+
// the overflow deterministically — the fat AABBs persist, so any
|
|
81
|
+
// missed pair is re-detected next frame.
|
|
82
|
+
if (n > candidates.length) n = candidates.length;
|
|
76
83
|
for (let c = 0; c < n; c++) {
|
|
77
84
|
const other = candidates[c];
|
|
78
85
|
if (other === my_packed) continue;
|
|
@@ -94,6 +101,7 @@ export function generate_pairs(
|
|
|
94
101
|
scratch_aabb
|
|
95
102
|
);
|
|
96
103
|
assert.lessThan(n, candidates.length, 'generate_pairs: static broadphase overflowed the candidate buffer');
|
|
104
|
+
if (n > candidates.length) n = candidates.length; // prod-safe clamp (see dynamic loop above)
|
|
97
105
|
for (let c = 0; c < n; c++) {
|
|
98
106
|
const other = candidates[c];
|
|
99
107
|
const idA = my_packed < other ? my_packed : other;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"linear_sweep.d.ts","sourceRoot":"","sources":["../../../../../src/engine/physics/ccd/linear_sweep.js"],"names":[],"mappings":"AA8FA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,0CAbW,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,UACN,mBAAmB,GACjB,MAAM,CAmClB;AAED;;;;;;;;;;;;;GAaG;AACH,oCAFW,OAAO,yBAAyB,EAAE,aAAa,
|
|
1
|
+
{"version":3,"file":"linear_sweep.d.ts","sourceRoot":"","sources":["../../../../../src/engine/physics/ccd/linear_sweep.js"],"names":[],"mappings":"AA8FA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,0CAbW,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,UACN,mBAAmB,GACjB,MAAM,CAmClB;AAED;;;;;;;;;;;;;GAaG;AACH,oCAFW,OAAO,yBAAyB,EAAE,aAAa,QAuEzD;AAtOD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAEH;;;;;;;;;;;;;;;GAeG;AACH,qCAFU,MAAM,CAE2B;oCArDP,mCAAmC"}
|
|
@@ -1,238 +1,237 @@
|
|
|
1
|
-
import { Ray3 } from "../../../core/geom/3d/ray/Ray3.js";
|
|
2
|
-
import { BodyKind } from "../ecs/BodyKind.js";
|
|
3
|
-
import { RigidBodyFlags } from "../ecs/RigidBodyFlags.js";
|
|
4
|
-
import { PhysicsSurfacePoint } from "../queries/PhysicsSurfacePoint.js";
|
|
5
|
-
import { shape_cast } from "../queries/shape_cast.js";
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* Continuous collision detection — linear shape-cast (the "speculative margin
|
|
9
|
-
* floor, upgraded to an opt-in per-body sweep" item from PLAN.md).
|
|
10
|
-
*
|
|
11
|
-
* The discrete pipeline detects contacts by overlap at step boundaries: a body
|
|
12
|
-
* that moves more than its own thickness in one step can start a step on one
|
|
13
|
-
* side of a thin wall and end on the other, never overlapping it on any frame
|
|
14
|
-
* the broadphase samples — it tunnels. The speculative fat-AABB margin
|
|
15
|
-
* (`compute_fat_world_aabb`) covers moderate speeds; genuinely fast movers
|
|
16
|
-
* (bullets, dropped debris, a body flung by an explosion) need a swept test.
|
|
17
|
-
*
|
|
18
|
-
* Approach (Box2D `b2_continuousPhysics`-style conservative advancement): after
|
|
19
|
-
* the substep solver has produced each body's final pose, sweep a CCD-flagged
|
|
20
|
-
* fast mover's primary collider along its NET step translation
|
|
21
|
-
* (start-of-step → final pose) using the existing {@link shape_cast} TOI engine.
|
|
22
|
-
* On the first blocker, clamp the body to the contact pose and remove the
|
|
23
|
-
* inbound normal component of its velocity (an inelastic stop) — the next
|
|
24
|
-
* discrete step then resolves the now-touching contact with the real
|
|
25
|
-
* material / restitution.
|
|
26
|
-
*
|
|
27
|
-
* Scope (v1, deliberate):
|
|
28
|
-
* - LINEAR sweep only: the orientation is held fixed through the sweep (the
|
|
29
|
-
* per-step angular motion is small at the fixed-step rate).
|
|
30
|
-
* - PRIMARY same-entity collider: a compound body sweeps its first collider;
|
|
31
|
-
* child-entity colliders (whose transform is synced outside the step) are
|
|
32
|
-
* not swept.
|
|
33
|
-
* - EXACT against static geometry (the static BVH holds tight, never-moved
|
|
34
|
-
* leaves); APPROXIMATE against other dynamic bodies (they have moved this
|
|
35
|
-
* step too, but the sweep sees their start-of-step broadphase AABBs) — the
|
|
36
|
-
* speculative-margin floor for the dynamic-vs-dynamic case.
|
|
37
|
-
* - The CCD stop itself is inelastic; the impact does not bounce. Restitution
|
|
38
|
-
* applies on the next discrete contact.
|
|
39
|
-
*/
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* Minimum per-step displacement (metres) before a CCD sweep is worth running.
|
|
43
|
-
* Its ONLY job is to skip a body that didn't meaningfully move — a resting /
|
|
44
|
-
* sleeping-soon body whose displacement is sub-millimetre jitter — which avoids
|
|
45
|
-
* a degenerate zero-length sweep and saves the query cost.
|
|
46
|
-
*
|
|
47
|
-
* It must NOT be tied to the body's own size. Tunnelling risk is governed by the
|
|
48
|
-
* *obstacle's* thickness, not the mover's: a 2 m sphere drifting at 0.5 m/step
|
|
49
|
-
* still passes clean through a 1 cm floor. A small absolute slop catches that;
|
|
50
|
-
* gating on a fraction of the body's extent would (wrongly) wait until the body
|
|
51
|
-
* moved more than its own radius and miss every thin-obstacle tunnel below that
|
|
52
|
-
* speed. The discrete narrowphase still owns any obstacle thicker than a body's
|
|
53
|
-
* per-step move, so CCD reliably prevents tunnelling of obstacles thicker than
|
|
54
|
-
* this slop.
|
|
55
|
-
* @type {number}
|
|
56
|
-
*/
|
|
57
|
-
export const CCD_MIN_SWEEP_DISTANCE = 1e-3;
|
|
58
|
-
|
|
59
|
-
/**
|
|
60
|
-
* Impact distances at or below this (metres) mean the body was already
|
|
61
|
-
* overlapping the target at the start of the step — i.e. a resting / sliding
|
|
62
|
-
* contact the discrete solver owns, not a tunnel. The sweep ignores these so
|
|
63
|
-
* CCD never clamps a body to a surface it is merely sitting or sliding on.
|
|
64
|
-
* @type {number}
|
|
65
|
-
*/
|
|
66
|
-
const CCD_INITIAL_OVERLAP_EPS = 1e-6;
|
|
67
|
-
|
|
68
|
-
// ── Module scratch ──────────────────────────────────────────────────────────
|
|
69
|
-
// CCD runs inside the step loop; reuse buffers so the pass allocates nothing.
|
|
70
|
-
|
|
71
|
-
/** Swept ray, re-seeded per sweep (origin, unit direction, tMax). */
|
|
72
|
-
const _ray = new Ray3();
|
|
73
|
-
|
|
74
|
-
/** Sweep result reused across bodies inside {@link ccd_resolve}. */
|
|
75
|
-
const _hit = new PhysicsSurfacePoint();
|
|
76
|
-
|
|
77
|
-
/**
|
|
78
|
-
* Entity whose colliders the current sweep must ignore (the moving body's own).
|
|
79
|
-
* Module-scoped so {@link _exclude_self} stays a stable, non-allocating
|
|
80
|
-
* reference handed to {@link shape_cast}.
|
|
81
|
-
* @type {number}
|
|
82
|
-
*/
|
|
83
|
-
let _exclude_entity = -1;
|
|
84
|
-
|
|
85
|
-
/**
|
|
86
|
-
* Self-exclusion filter for the sweep: drop candidates owned by the moving
|
|
87
|
-
* body's own entity (otherwise the body would "hit itself" at `t = 0`).
|
|
88
|
-
* @param {number} entity
|
|
89
|
-
* @returns {boolean}
|
|
90
|
-
*/
|
|
91
|
-
function _exclude_self(entity) {
|
|
92
|
-
return entity !== _exclude_entity;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
/**
|
|
96
|
-
* Sweep `shape` (held at the fixed `rotation`) linearly from `(fx,fy,fz)` to
|
|
97
|
-
* `(tx,ty,tz)` through both broadphase trees, ignoring colliders owned by
|
|
98
|
-
* `exclude_entity`.
|
|
99
|
-
*
|
|
100
|
-
* Returns the traversable fraction of the segment in `[0, 1]`: `1` means the
|
|
101
|
-
* path is clear; a value `< 1` means a blocker was hit at that fraction and
|
|
102
|
-
* `result` has been filled — `result.position` is the swept-shape centre at
|
|
103
|
-
* first contact, `result.normal` is the blocker's outward surface normal
|
|
104
|
-
* (B → A), `result.entity` / `result.body_id` the blocker.
|
|
105
|
-
*
|
|
106
|
-
* @param {import("../ecs/PhysicsSystem.js").PhysicsSystem} system
|
|
107
|
-
* @param {import("../../../core/geom/3d/shape/AbstractShape3D.js").AbstractShape3D} shape
|
|
108
|
-
* @param {{x:number,y:number,z:number,w:number}} rotation fixed orientation
|
|
109
|
-
* @param {number} fx
|
|
110
|
-
* @param {number} fy
|
|
111
|
-
* @param {number} fz
|
|
112
|
-
* @param {number} tx
|
|
113
|
-
* @param {number} ty
|
|
114
|
-
* @param {number} tz
|
|
115
|
-
* @param {number} exclude_entity entity to ignore (the swept body itself)
|
|
116
|
-
* @param {PhysicsSurfacePoint} result populated on hit; untouched on a clear path
|
|
117
|
-
* @returns {number} traversable fraction in [0, 1]
|
|
118
|
-
*/
|
|
119
|
-
export function ccd_sweep_segment(
|
|
120
|
-
system, shape, rotation,
|
|
121
|
-
fx, fy, fz, tx, ty, tz,
|
|
122
|
-
exclude_entity, result,
|
|
123
|
-
) {
|
|
124
|
-
const dx = tx - fx;
|
|
125
|
-
const dy = ty - fy;
|
|
126
|
-
const dz = tz - fz;
|
|
127
|
-
const len = Math.sqrt(dx * dx + dy * dy + dz * dz);
|
|
128
|
-
if (len === 0) return 1;
|
|
129
|
-
|
|
130
|
-
const inv = 1 / len;
|
|
131
|
-
_ray[0] = fx; _ray[1] = fy; _ray[2] = fz;
|
|
132
|
-
_ray[3] = dx * inv; _ray[4] = dy * inv; _ray[5] = dz * inv;
|
|
133
|
-
_ray[6] = len; // tMax in metres — direction is unit length
|
|
134
|
-
|
|
135
|
-
_exclude_entity = exclude_entity;
|
|
136
|
-
if (!shape_cast(system, _ray, shape, rotation, result, _exclude_self)) {
|
|
137
|
-
return 1;
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
// An impact at t ≈ 0 means the swept shape was already overlapping the
|
|
141
|
-
// target at the segment start — a resting / sliding contact, not a tunnel.
|
|
142
|
-
// The discrete solver owns it; clamping here would freeze a body onto a
|
|
143
|
-
// surface it is sitting or sliding on. Treat as a clear path.
|
|
144
|
-
if (result.t <= CCD_INITIAL_OVERLAP_EPS) return 1;
|
|
145
|
-
|
|
146
|
-
// result.t is the impact distance along the unit direction; normalise to a
|
|
147
|
-
// segment fraction. shape_cast reports the just-SEPARATING side of its
|
|
148
|
-
// bisection, so the swept shape at `result.t` is provably not overlapping —
|
|
149
|
-
// safe to place the body there.
|
|
150
|
-
const frac = result.t * inv;
|
|
151
|
-
return frac < 1 ? frac : 1;
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
/**
|
|
155
|
-
* Post-solve continuous-collision pass over the awake set. For each awake
|
|
156
|
-
* Dynamic body flagged {@link RigidBodyFlags.CCD} that moved more than
|
|
157
|
-
* {@link CCD_MIN_SWEEP_DISTANCE} this step, sweep its primary collider along the
|
|
158
|
-
* step's net translation and stop it at the first blocker (clamp pose + remove
|
|
159
|
-
* inbound normal velocity).
|
|
160
|
-
*
|
|
161
|
-
* Start-of-step positions are captured into `system.__ccd_start_pos` (3 doubles
|
|
162
|
-
* per body index) before the substep loop; this pass reads the final pose from
|
|
163
|
-
* the live Transform. Iterates the awake list in storage order, so it is
|
|
164
|
-
* deterministic.
|
|
165
|
-
*
|
|
166
|
-
* @param {import("../ecs/PhysicsSystem.js").PhysicsSystem} system
|
|
167
|
-
*/
|
|
168
|
-
export function ccd_resolve(system) {
|
|
169
|
-
const storage = system.storage;
|
|
170
|
-
const count = storage.awake_count;
|
|
171
|
-
const lists = system.__body_collider_lists;
|
|
172
|
-
const start = system.__ccd_start_pos;
|
|
173
|
-
const CCD = RigidBodyFlags.CCD;
|
|
174
|
-
|
|
175
|
-
for (let i = 0; i < count; i++) {
|
|
176
|
-
const idx = storage.awake_at(i);
|
|
177
|
-
|
|
178
|
-
const rb = system.__bodies[idx];
|
|
179
|
-
if (rb === undefined) continue;
|
|
180
|
-
if ((rb.flags & CCD) === 0) continue;
|
|
181
|
-
if (rb.kind !== BodyKind.Dynamic) continue;
|
|
182
|
-
|
|
183
|
-
const list = lists[idx];
|
|
184
|
-
if (list === undefined || list.length === 0) continue;
|
|
185
|
-
const primary = list[0];
|
|
186
|
-
const tr = primary.transform;
|
|
187
|
-
const p = tr.position;
|
|
188
|
-
|
|
189
|
-
const base = idx * 3;
|
|
190
|
-
const sx = start[base];
|
|
191
|
-
const sy = start[base + 1];
|
|
192
|
-
const sz = start[base + 2];
|
|
193
|
-
const ex = p[0];
|
|
194
|
-
const ey = p[1];
|
|
195
|
-
const ez = p[2];
|
|
196
|
-
|
|
197
|
-
const dx = ex - sx;
|
|
198
|
-
const dy = ey - sy;
|
|
199
|
-
const dz = ez - sz;
|
|
200
|
-
const disp2 = dx * dx + dy * dy + dz * dz;
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
//
|
|
204
|
-
//
|
|
205
|
-
//
|
|
206
|
-
//
|
|
207
|
-
//
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
const
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
);
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
//
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
//
|
|
225
|
-
//
|
|
226
|
-
//
|
|
227
|
-
//
|
|
228
|
-
|
|
229
|
-
const
|
|
230
|
-
const
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
lv[
|
|
234
|
-
lv[
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
}
|
|
1
|
+
import { Ray3 } from "../../../core/geom/3d/ray/Ray3.js";
|
|
2
|
+
import { BodyKind } from "../ecs/BodyKind.js";
|
|
3
|
+
import { RigidBodyFlags } from "../ecs/RigidBodyFlags.js";
|
|
4
|
+
import { PhysicsSurfacePoint } from "../queries/PhysicsSurfacePoint.js";
|
|
5
|
+
import { shape_cast } from "../queries/shape_cast.js";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Continuous collision detection — linear shape-cast (the "speculative margin
|
|
9
|
+
* floor, upgraded to an opt-in per-body sweep" item from PLAN.md).
|
|
10
|
+
*
|
|
11
|
+
* The discrete pipeline detects contacts by overlap at step boundaries: a body
|
|
12
|
+
* that moves more than its own thickness in one step can start a step on one
|
|
13
|
+
* side of a thin wall and end on the other, never overlapping it on any frame
|
|
14
|
+
* the broadphase samples — it tunnels. The speculative fat-AABB margin
|
|
15
|
+
* (`compute_fat_world_aabb`) covers moderate speeds; genuinely fast movers
|
|
16
|
+
* (bullets, dropped debris, a body flung by an explosion) need a swept test.
|
|
17
|
+
*
|
|
18
|
+
* Approach (Box2D `b2_continuousPhysics`-style conservative advancement): after
|
|
19
|
+
* the substep solver has produced each body's final pose, sweep a CCD-flagged
|
|
20
|
+
* fast mover's primary collider along its NET step translation
|
|
21
|
+
* (start-of-step → final pose) using the existing {@link shape_cast} TOI engine.
|
|
22
|
+
* On the first blocker, clamp the body to the contact pose and remove the
|
|
23
|
+
* inbound normal component of its velocity (an inelastic stop) — the next
|
|
24
|
+
* discrete step then resolves the now-touching contact with the real
|
|
25
|
+
* material / restitution.
|
|
26
|
+
*
|
|
27
|
+
* Scope (v1, deliberate):
|
|
28
|
+
* - LINEAR sweep only: the orientation is held fixed through the sweep (the
|
|
29
|
+
* per-step angular motion is small at the fixed-step rate).
|
|
30
|
+
* - PRIMARY same-entity collider: a compound body sweeps its first collider;
|
|
31
|
+
* child-entity colliders (whose transform is synced outside the step) are
|
|
32
|
+
* not swept.
|
|
33
|
+
* - EXACT against static geometry (the static BVH holds tight, never-moved
|
|
34
|
+
* leaves); APPROXIMATE against other dynamic bodies (they have moved this
|
|
35
|
+
* step too, but the sweep sees their start-of-step broadphase AABBs) — the
|
|
36
|
+
* speculative-margin floor for the dynamic-vs-dynamic case.
|
|
37
|
+
* - The CCD stop itself is inelastic; the impact does not bounce. Restitution
|
|
38
|
+
* applies on the next discrete contact.
|
|
39
|
+
*/
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Minimum per-step displacement (metres) before a CCD sweep is worth running.
|
|
43
|
+
* Its ONLY job is to skip a body that didn't meaningfully move — a resting /
|
|
44
|
+
* sleeping-soon body whose displacement is sub-millimetre jitter — which avoids
|
|
45
|
+
* a degenerate zero-length sweep and saves the query cost.
|
|
46
|
+
*
|
|
47
|
+
* It must NOT be tied to the body's own size. Tunnelling risk is governed by the
|
|
48
|
+
* *obstacle's* thickness, not the mover's: a 2 m sphere drifting at 0.5 m/step
|
|
49
|
+
* still passes clean through a 1 cm floor. A small absolute slop catches that;
|
|
50
|
+
* gating on a fraction of the body's extent would (wrongly) wait until the body
|
|
51
|
+
* moved more than its own radius and miss every thin-obstacle tunnel below that
|
|
52
|
+
* speed. The discrete narrowphase still owns any obstacle thicker than a body's
|
|
53
|
+
* per-step move, so CCD reliably prevents tunnelling of obstacles thicker than
|
|
54
|
+
* this slop.
|
|
55
|
+
* @type {number}
|
|
56
|
+
*/
|
|
57
|
+
export const CCD_MIN_SWEEP_DISTANCE = 1e-3;
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Impact distances at or below this (metres) mean the body was already
|
|
61
|
+
* overlapping the target at the start of the step — i.e. a resting / sliding
|
|
62
|
+
* contact the discrete solver owns, not a tunnel. The sweep ignores these so
|
|
63
|
+
* CCD never clamps a body to a surface it is merely sitting or sliding on.
|
|
64
|
+
* @type {number}
|
|
65
|
+
*/
|
|
66
|
+
const CCD_INITIAL_OVERLAP_EPS = 1e-6;
|
|
67
|
+
|
|
68
|
+
// ── Module scratch ──────────────────────────────────────────────────────────
|
|
69
|
+
// CCD runs inside the step loop; reuse buffers so the pass allocates nothing.
|
|
70
|
+
|
|
71
|
+
/** Swept ray, re-seeded per sweep (origin, unit direction, tMax). */
|
|
72
|
+
const _ray = new Ray3();
|
|
73
|
+
|
|
74
|
+
/** Sweep result reused across bodies inside {@link ccd_resolve}. */
|
|
75
|
+
const _hit = new PhysicsSurfacePoint();
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Entity whose colliders the current sweep must ignore (the moving body's own).
|
|
79
|
+
* Module-scoped so {@link _exclude_self} stays a stable, non-allocating
|
|
80
|
+
* reference handed to {@link shape_cast}.
|
|
81
|
+
* @type {number}
|
|
82
|
+
*/
|
|
83
|
+
let _exclude_entity = -1;
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Self-exclusion filter for the sweep: drop candidates owned by the moving
|
|
87
|
+
* body's own entity (otherwise the body would "hit itself" at `t = 0`).
|
|
88
|
+
* @param {number} entity
|
|
89
|
+
* @returns {boolean}
|
|
90
|
+
*/
|
|
91
|
+
function _exclude_self(entity) {
|
|
92
|
+
return entity !== _exclude_entity;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Sweep `shape` (held at the fixed `rotation`) linearly from `(fx,fy,fz)` to
|
|
97
|
+
* `(tx,ty,tz)` through both broadphase trees, ignoring colliders owned by
|
|
98
|
+
* `exclude_entity`.
|
|
99
|
+
*
|
|
100
|
+
* Returns the traversable fraction of the segment in `[0, 1]`: `1` means the
|
|
101
|
+
* path is clear; a value `< 1` means a blocker was hit at that fraction and
|
|
102
|
+
* `result` has been filled — `result.position` is the swept-shape centre at
|
|
103
|
+
* first contact, `result.normal` is the blocker's outward surface normal
|
|
104
|
+
* (B → A), `result.entity` / `result.body_id` the blocker.
|
|
105
|
+
*
|
|
106
|
+
* @param {import("../ecs/PhysicsSystem.js").PhysicsSystem} system
|
|
107
|
+
* @param {import("../../../core/geom/3d/shape/AbstractShape3D.js").AbstractShape3D} shape
|
|
108
|
+
* @param {{x:number,y:number,z:number,w:number}} rotation fixed orientation
|
|
109
|
+
* @param {number} fx
|
|
110
|
+
* @param {number} fy
|
|
111
|
+
* @param {number} fz
|
|
112
|
+
* @param {number} tx
|
|
113
|
+
* @param {number} ty
|
|
114
|
+
* @param {number} tz
|
|
115
|
+
* @param {number} exclude_entity entity to ignore (the swept body itself)
|
|
116
|
+
* @param {PhysicsSurfacePoint} result populated on hit; untouched on a clear path
|
|
117
|
+
* @returns {number} traversable fraction in [0, 1]
|
|
118
|
+
*/
|
|
119
|
+
export function ccd_sweep_segment(
|
|
120
|
+
system, shape, rotation,
|
|
121
|
+
fx, fy, fz, tx, ty, tz,
|
|
122
|
+
exclude_entity, result,
|
|
123
|
+
) {
|
|
124
|
+
const dx = tx - fx;
|
|
125
|
+
const dy = ty - fy;
|
|
126
|
+
const dz = tz - fz;
|
|
127
|
+
const len = Math.sqrt(dx * dx + dy * dy + dz * dz);
|
|
128
|
+
if (len === 0) return 1;
|
|
129
|
+
|
|
130
|
+
const inv = 1 / len;
|
|
131
|
+
_ray[0] = fx; _ray[1] = fy; _ray[2] = fz;
|
|
132
|
+
_ray[3] = dx * inv; _ray[4] = dy * inv; _ray[5] = dz * inv;
|
|
133
|
+
_ray[6] = len; // tMax in metres — direction is unit length
|
|
134
|
+
|
|
135
|
+
_exclude_entity = exclude_entity;
|
|
136
|
+
if (!shape_cast(system, _ray, shape, rotation, result, _exclude_self)) {
|
|
137
|
+
return 1;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// An impact at t ≈ 0 means the swept shape was already overlapping the
|
|
141
|
+
// target at the segment start — a resting / sliding contact, not a tunnel.
|
|
142
|
+
// The discrete solver owns it; clamping here would freeze a body onto a
|
|
143
|
+
// surface it is sitting or sliding on. Treat as a clear path.
|
|
144
|
+
if (result.t <= CCD_INITIAL_OVERLAP_EPS) return 1;
|
|
145
|
+
|
|
146
|
+
// result.t is the impact distance along the unit direction; normalise to a
|
|
147
|
+
// segment fraction. shape_cast reports the just-SEPARATING side of its
|
|
148
|
+
// bisection, so the swept shape at `result.t` is provably not overlapping —
|
|
149
|
+
// safe to place the body there.
|
|
150
|
+
const frac = result.t * inv;
|
|
151
|
+
return frac < 1 ? frac : 1;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Post-solve continuous-collision pass over the awake set. For each awake
|
|
156
|
+
* Dynamic body flagged {@link RigidBodyFlags.CCD} that moved more than
|
|
157
|
+
* {@link CCD_MIN_SWEEP_DISTANCE} this step, sweep its primary collider along the
|
|
158
|
+
* step's net translation and stop it at the first blocker (clamp pose + remove
|
|
159
|
+
* inbound normal velocity).
|
|
160
|
+
*
|
|
161
|
+
* Start-of-step positions are captured into `system.__ccd_start_pos` (3 doubles
|
|
162
|
+
* per body index) before the substep loop; this pass reads the final pose from
|
|
163
|
+
* the live Transform. Iterates the awake list in storage order, so it is
|
|
164
|
+
* deterministic.
|
|
165
|
+
*
|
|
166
|
+
* @param {import("../ecs/PhysicsSystem.js").PhysicsSystem} system
|
|
167
|
+
*/
|
|
168
|
+
export function ccd_resolve(system) {
|
|
169
|
+
const storage = system.storage;
|
|
170
|
+
const count = storage.awake_count;
|
|
171
|
+
const lists = system.__body_collider_lists;
|
|
172
|
+
const start = system.__ccd_start_pos;
|
|
173
|
+
const CCD = RigidBodyFlags.CCD;
|
|
174
|
+
|
|
175
|
+
for (let i = 0; i < count; i++) {
|
|
176
|
+
const idx = storage.awake_at(i);
|
|
177
|
+
|
|
178
|
+
const rb = system.__bodies[idx];
|
|
179
|
+
if (rb === undefined) continue;
|
|
180
|
+
if ((rb.flags & CCD) === 0) continue;
|
|
181
|
+
if (rb.kind !== BodyKind.Dynamic) continue;
|
|
182
|
+
|
|
183
|
+
const list = lists[idx];
|
|
184
|
+
if (list === undefined || list.length === 0) continue;
|
|
185
|
+
const primary = list[0];
|
|
186
|
+
const tr = primary.transform;
|
|
187
|
+
const p = tr.position;
|
|
188
|
+
|
|
189
|
+
const base = idx * 3;
|
|
190
|
+
const sx = start[base];
|
|
191
|
+
const sy = start[base + 1];
|
|
192
|
+
const sz = start[base + 2];
|
|
193
|
+
const ex = p[0];
|
|
194
|
+
const ey = p[1];
|
|
195
|
+
const ez = p[2];
|
|
196
|
+
|
|
197
|
+
const dx = ex - sx;
|
|
198
|
+
const dy = ey - sy;
|
|
199
|
+
const dz = ez - sz;
|
|
200
|
+
const disp2 = dx * dx + dy * dy + dz * dz;
|
|
201
|
+
|
|
202
|
+
// Motion gate: skip a body that barely moved (resting / negligible
|
|
203
|
+
// jitter) — avoids a degenerate sweep and the query cost. NOT tied to
|
|
204
|
+
// body size: a body tunnels a thin obstacle at speeds well below its
|
|
205
|
+
// own extent, so the threshold is a small absolute slop. A resting /
|
|
206
|
+
// sliding body that does clear it is still safe — the sweep ignores its
|
|
207
|
+
// initial-overlap contact (see CCD_INITIAL_OVERLAP_EPS).
|
|
208
|
+
if (disp2 <= CCD_MIN_SWEEP_DISTANCE * CCD_MIN_SWEEP_DISTANCE) continue;
|
|
209
|
+
|
|
210
|
+
const shape = primary.collider.shape;
|
|
211
|
+
const frac = ccd_sweep_segment(
|
|
212
|
+
system, shape, tr.rotation,
|
|
213
|
+
sx, sy, sz, ex, ey, ez,
|
|
214
|
+
primary.entity, _hit,
|
|
215
|
+
);
|
|
216
|
+
if (frac >= 1) continue; // clear path — no tunnelling this step
|
|
217
|
+
|
|
218
|
+
// Clamp the body to the first-contact pose (swept-shape centre at the
|
|
219
|
+
// TOI), so it cannot end the step on the far side of the blocker.
|
|
220
|
+
const hp = _hit.position;
|
|
221
|
+
p.set(hp[0], hp[1], hp[2]);
|
|
222
|
+
|
|
223
|
+
// Remove the inbound normal component of velocity (inelastic stop).
|
|
224
|
+
// `_hit.normal` is the blocker's outward surface normal; the body is
|
|
225
|
+
// moving into it (v·n < 0). Zeroing that component leaves the tangential
|
|
226
|
+
// slide intact and never adds energy. The next discrete step applies the
|
|
227
|
+
// real restitution / friction on the established contact.
|
|
228
|
+
const n = _hit.normal;
|
|
229
|
+
const lv = rb.linearVelocity;
|
|
230
|
+
const vn = lv[0] * n[0] + lv[1] * n[1] + lv[2] * n[2];
|
|
231
|
+
if (vn < 0) {
|
|
232
|
+
lv[0] -= vn * n[0];
|
|
233
|
+
lv[1] -= vn * n[1];
|
|
234
|
+
lv[2] -= vn * n[2];
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"computeInterceptPoint.d.ts","sourceRoot":"","sources":["../../../../src/engine/physics/computeInterceptPoint.js"],"names":[],"mappings":"AASA;;;;;;;;;GASG;AACH,+HAHW,MAAM,GACL,OAAO,
|
|
1
|
+
{"version":3,"file":"computeInterceptPoint.d.ts","sourceRoot":"","sources":["../../../../src/engine/physics/computeInterceptPoint.js"],"names":[],"mappings":"AASA;;;;;;;;;GASG;AACH,+HAHW,MAAM,GACL,OAAO,CA8DlB"}
|
|
@@ -60,9 +60,14 @@ export function computeInterceptPoint(
|
|
|
60
60
|
|
|
61
61
|
if (t >= 0) {
|
|
62
62
|
|
|
63
|
-
|
|
64
|
-
result
|
|
65
|
-
|
|
63
|
+
// Single write, computed from the inputs up front, so it is correct
|
|
64
|
+
// even when `result` aliases `target` (a copy-then-add would read
|
|
65
|
+
// `target` after overwriting it, doubling the velocity term).
|
|
66
|
+
result.set(
|
|
67
|
+
target.x + targetVelocity.x * t,
|
|
68
|
+
target.y + targetVelocity.y * t,
|
|
69
|
+
target.z + targetVelocity.z * t,
|
|
70
|
+
);
|
|
66
71
|
|
|
67
72
|
return true;
|
|
68
73
|
|
|
@@ -82,7 +82,6 @@ export class ManifoldStore {
|
|
|
82
82
|
__high_water: number;
|
|
83
83
|
__data: Float64Array;
|
|
84
84
|
__meta: Uint32Array;
|
|
85
|
-
__slot_axis: Float64Array;
|
|
86
85
|
__pair_index: PairUint32Map;
|
|
87
86
|
__live_slots: Uint32Array;
|
|
88
87
|
__live_pos: Int32Array;
|
|
@@ -268,21 +267,6 @@ export class ManifoldStore {
|
|
|
268
267
|
* @returns {Float64Array}
|
|
269
268
|
*/
|
|
270
269
|
get data_buffer(): Float64Array;
|
|
271
|
-
/**
|
|
272
|
-
* Per-slot cached GJK separating axis buffer. Hot-path GJK callers
|
|
273
|
-
* pass this together with {@link slot_axis_offset} to
|
|
274
|
-
* `gjk_with_axis(...)` so the cached axis seeds the next iteration.
|
|
275
|
-
* Buffer identity is stable until grow.
|
|
276
|
-
* @returns {Float64Array}
|
|
277
|
-
*/
|
|
278
|
-
get slot_axis_buffer(): Float64Array;
|
|
279
|
-
/**
|
|
280
|
-
* Float offset into {@link slot_axis_buffer} where this slot's
|
|
281
|
-
* cached axis lives (3 floats: x, y, z).
|
|
282
|
-
* @param {number} slot
|
|
283
|
-
* @returns {number}
|
|
284
|
-
*/
|
|
285
|
-
slot_axis_offset(slot: number): number;
|
|
286
270
|
/**
|
|
287
271
|
* Word offset into {@link data_buffer} where the first contact of `slot`
|
|
288
272
|
* begins. Subsequent contacts within the slot are at
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ManifoldStore.d.ts","sourceRoot":"","sources":["../../../../../src/engine/physics/contact/ManifoldStore.js"],"names":[],"mappings":"AAGA;;;;;GAKG;AACH,wCAFU,MAAM,CAE2B;AAE3C;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,6BAFU,MAAM,CAEiB;AAEjC;;;;GAIG;AACH,wCAFU,MAAM,CAE4B;AAE5C;;;GAGG;AACH,+BAFU,MAAM,CAE2D;AAyB3E;;;GAGG;AACH,mCAFU,MAAM,CAEuB;AAIvC;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH;IAEI;;OAEG;IACH,+BAFW,MAAM,
|
|
1
|
+
{"version":3,"file":"ManifoldStore.d.ts","sourceRoot":"","sources":["../../../../../src/engine/physics/contact/ManifoldStore.js"],"names":[],"mappings":"AAGA;;;;;GAKG;AACH,wCAFU,MAAM,CAE2B;AAE3C;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,6BAFU,MAAM,CAEiB;AAEjC;;;;GAIG;AACH,wCAFU,MAAM,CAE4B;AAE5C;;;GAGG;AACH,+BAFU,MAAM,CAE2D;AAyB3E;;;GAGG;AACH,mCAFU,MAAM,CAEuB;AAIvC;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH;IAEI;;OAEG;IACH,+BAFW,MAAM,EAqBhB;IAjBG,mBAA+C;IAC/C,qBAAqB;IAErB,qBAAkE;IAClE,oBAAiE;IAEjE,4BAA0D;IAG1D,0BAAoD;IACpD,uBAAiD;IAEjD,qBAAqB;IAGrB,yBAAmD;IACnD,qBAAqB;IAGzB;;OAEG;IACH,oBAEC;IAED;;OAEG;IACH,uBAEC;IAED;;;;;;;OAOG;IACH,UAJW,MAAM,OACN,MAAM,GACJ,MAAM,CAKlB;IAED;;;;;;;;OAQG;IACH,aAJW,MAAM,OACN,MAAM,GACJ,MAAM,CAwBlB;IAED;;;OAGG;IACH,YAHW,MAAM,GACJ,MAAM,CAIlB;IAED;;;OAGG;IACH,YAHW,MAAM,GACJ,MAAM,CAIlB;IAED;;;OAGG;IACH,oBAHW,MAAM,GACJ,MAAM,CAIlB;IAED;;;OAGG;IACH,iBAHW,MAAM,GACJ,OAAO,CAInB;IAED;;;OAGG;IACH,uBAHW,MAAM,GACJ,OAAO,CAInB;IAED;;;;;OAKG;IACH,WAHW,MAAM,GACJ,MAAM,CAIlB;IAED;;;;;OAKG;IACH,qBAFW,MAAM,QAQhB;IAED;;;;;;;;;;;;;OAaG;IACH,mBAFW,MAAM,QAKhB;IAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA6BG;IACH,kBAnBW,MAAM,OACN,MAAM,OACN,MAAM,OACN,MAAM,OACN,MAAM,OACN,MAAM,OACN,MAAM,OACN,MAAM,MACN,MAAM,MACN,MAAM,MACN,MAAM,SACN,MAAM,eACN,MAAM,aAGN,MAAM,gBAEN,MAAM,QAwBhB;IAED;;;;;OAKG;IACH,kBAJW,MAAM,OACN,MAAM,GACJ,MAAM,CAIlB;IAED;;;;;OAKG;IACH,qBAJW,MAAM,OACN,MAAM,GACJ,MAAM,CAIlB;IAED;;;;;;;;;;;;;;;OAeG;IACH,qBAHW,MAAM,OACN,MAAM,QAOhB;IAED;;;;;OAKG;IACH,oBAJW,MAAM,OACN,MAAM,GACJ,MAAM,CAIlB;IAED;;;;;;OAMG;IACH,kBALW,MAAM,OACN,MAAM,OACN,MAAM,EAAE,GAAC,YAAY,cACrB,MAAM,QAOhB;IAED;;;;;;OAMG;IACH,uBAJW,MAAM,OACN,MAAM,GACJ,MAAM,CAIlB;IAED,iEAAiE;IACjE,uBADY,MAAM,OAAe,MAAM,GAAgB,MAAM,CAG5D;IAED,iEAAiE;IACjE,uBADY,MAAM,OAAe,MAAM,GAAgB,MAAM,CAG5D;IAED,iEAAiE;IACjE,oBADY,MAAM,OAAe,MAAM,GAAgB,MAAM,CAG5D;IAED;;;;;OAKG;IACH,gCAEC;IAED;;;;;;OAMG;IACH,uBAHW,MAAM,GACJ,MAAM,CAIlB;IAED;;;OAGG;IACH,sBA6BC;IAED;;;OAGG;IACH,wBAcC;IAED;;;OAGG;IACH,uBAkBC;IAED;;OAEG;IACH,eA8BC;IAED;;;OAGG;IACH,oBAaC;IAED;;;OAGG;IACH,mBAqBC;CACJ;8BA3lBqD,2CAA2C"}
|