@codexo/exojs-physics 0.15.3 → 0.16.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/README.md +51 -23
- package/dist/esm/Aabb.d.ts +6 -10
- package/dist/esm/Aabb.d.ts.map +1 -0
- package/dist/esm/Aabb.js +9 -5
- package/dist/esm/Aabb.js.map +1 -1
- package/dist/esm/Collider.d.ts +62 -10
- package/dist/esm/Collider.d.ts.map +1 -0
- package/dist/esm/Collider.js +263 -157
- package/dist/esm/Collider.js.map +1 -1
- package/dist/esm/ContactGraph.d.ts +51 -5
- package/dist/esm/ContactGraph.d.ts.map +1 -0
- package/dist/esm/ContactGraph.js +282 -223
- package/dist/esm/ContactGraph.js.map +1 -1
- package/dist/esm/ContactModifier.d.ts +85 -0
- package/dist/esm/ContactModifier.d.ts.map +1 -0
- package/dist/esm/ContactModifier.js +49 -0
- package/dist/esm/ContactModifier.js.map +1 -0
- package/dist/esm/PhysicsBody.d.ts +56 -22
- package/dist/esm/PhysicsBody.d.ts.map +1 -0
- package/dist/esm/PhysicsBody.js +461 -443
- package/dist/esm/PhysicsBody.js.map +1 -1
- package/dist/esm/PhysicsWorld.d.ts +276 -43
- package/dist/esm/PhysicsWorld.d.ts.map +1 -0
- package/dist/esm/PhysicsWorld.js +890 -626
- package/dist/esm/PhysicsWorld.js.map +1 -1
- package/dist/esm/TimeStepper.d.ts +3 -2
- package/dist/esm/TimeStepper.d.ts.map +1 -0
- package/dist/esm/TimeStepper.js +56 -67
- package/dist/esm/TimeStepper.js.map +1 -1
- package/dist/esm/backend/NativePhysicsBackend.d.ts +8 -4
- package/dist/esm/backend/NativePhysicsBackend.d.ts.map +1 -0
- package/dist/esm/backend/NativePhysicsBackend.js +48 -41
- package/dist/esm/backend/NativePhysicsBackend.js.map +1 -1
- package/dist/esm/backend/PhysicsBackend.d.ts +9 -2
- package/dist/esm/backend/PhysicsBackend.d.ts.map +1 -0
- package/dist/esm/binding/BindingRegistry.d.ts +25 -4
- package/dist/esm/binding/BindingRegistry.d.ts.map +1 -0
- package/dist/esm/binding/BindingRegistry.js +70 -36
- package/dist/esm/binding/BindingRegistry.js.map +1 -1
- package/dist/esm/binding/PhysicsBinding.d.ts +22 -5
- package/dist/esm/binding/PhysicsBinding.d.ts.map +1 -0
- package/dist/esm/binding/PhysicsBinding.js +46 -21
- package/dist/esm/binding/PhysicsBinding.js.map +1 -1
- package/dist/esm/broadphase/AabbTreeBroadPhase.d.ts +68 -0
- package/dist/esm/broadphase/AabbTreeBroadPhase.d.ts.map +1 -0
- package/dist/esm/broadphase/AabbTreeBroadPhase.js +149 -0
- package/dist/esm/broadphase/AabbTreeBroadPhase.js.map +1 -0
- package/dist/esm/broadphase/BroadPhase.d.ts +7 -4
- package/dist/esm/broadphase/BroadPhase.d.ts.map +1 -0
- package/dist/esm/broadphase/index.d.ts +2 -1
- package/dist/esm/broadphase/index.d.ts.map +1 -0
- package/dist/esm/collision/CollisionProxy.d.ts +3 -2
- package/dist/esm/collision/CollisionProxy.d.ts.map +1 -0
- package/dist/esm/collision/Manifold.d.ts +5 -4
- package/dist/esm/collision/Manifold.d.ts.map +1 -0
- package/dist/esm/collision/Manifold.js +34 -25
- package/dist/esm/collision/Manifold.js.map +1 -1
- package/dist/esm/collision/chainAdjacency.d.ts +29 -0
- package/dist/esm/collision/chainAdjacency.d.ts.map +1 -0
- package/dist/esm/collision/chainAdjacency.js +44 -0
- package/dist/esm/collision/chainAdjacency.js.map +1 -0
- package/dist/esm/collision/dispatch.d.ts +35 -0
- package/dist/esm/collision/dispatch.d.ts.map +1 -0
- package/dist/esm/collision/dispatch.js +58 -0
- package/dist/esm/collision/dispatch.js.map +1 -0
- package/dist/esm/collision/index.d.ts +2 -0
- package/dist/esm/collision/index.d.ts.map +1 -0
- package/dist/esm/collision/narrowphase.d.ts +5 -2
- package/dist/esm/collision/narrowphase.d.ts.map +1 -0
- package/dist/esm/collision/narrowphase.js +524 -399
- package/dist/esm/collision/narrowphase.js.map +1 -1
- package/dist/esm/collision/segments.d.ts +19 -0
- package/dist/esm/collision/segments.d.ts.map +1 -0
- package/dist/esm/collision/segments.js +36 -0
- package/dist/esm/collision/segments.js.map +1 -0
- package/dist/esm/collision/sweep.d.ts +35 -0
- package/dist/esm/collision/sweep.d.ts.map +1 -0
- package/dist/esm/collision/sweep.js +437 -0
- package/dist/esm/collision/sweep.js.map +1 -0
- package/dist/esm/debug/PhysicsDebugDraw.d.ts +23 -4
- package/dist/esm/debug/PhysicsDebugDraw.d.ts.map +1 -0
- package/dist/esm/debug/PhysicsDebugDraw.js +230 -188
- package/dist/esm/debug/PhysicsDebugDraw.js.map +1 -1
- package/dist/esm/debug/index.d.ts +1 -0
- package/dist/esm/debug/index.d.ts.map +1 -0
- package/dist/esm/debug/index.js +3 -2
- package/dist/esm/events.d.ts +1 -0
- package/dist/esm/events.d.ts.map +1 -0
- package/dist/esm/index.d.ts +1 -0
- package/dist/esm/index.d.ts.map +1 -0
- package/dist/esm/index.js +24 -19
- package/dist/esm/joints/DistanceJoint.d.ts +4 -3
- package/dist/esm/joints/DistanceJoint.d.ts.map +1 -0
- package/dist/esm/joints/DistanceJoint.js +160 -172
- package/dist/esm/joints/DistanceJoint.js.map +1 -1
- package/dist/esm/joints/Joint.d.ts +5 -4
- package/dist/esm/joints/Joint.d.ts.map +1 -0
- package/dist/esm/joints/Joint.js +23 -21
- package/dist/esm/joints/Joint.js.map +1 -1
- package/dist/esm/joints/MouseJoint.d.ts +8 -7
- package/dist/esm/joints/MouseJoint.d.ts.map +1 -0
- package/dist/esm/joints/MouseJoint.js +132 -133
- package/dist/esm/joints/MouseJoint.js.map +1 -1
- package/dist/esm/joints/PrismaticJoint.d.ts +5 -4
- package/dist/esm/joints/PrismaticJoint.d.ts.map +1 -0
- package/dist/esm/joints/PrismaticJoint.js +211 -240
- package/dist/esm/joints/PrismaticJoint.js.map +1 -1
- package/dist/esm/joints/RevoluteJoint.d.ts +4 -3
- package/dist/esm/joints/RevoluteJoint.d.ts.map +1 -0
- package/dist/esm/joints/RevoluteJoint.js +191 -213
- package/dist/esm/joints/RevoluteJoint.js.map +1 -1
- package/dist/esm/joints/WeldJoint.d.ts +3 -2
- package/dist/esm/joints/WeldJoint.d.ts.map +1 -0
- package/dist/esm/joints/WeldJoint.js +156 -152
- package/dist/esm/joints/WeldJoint.js.map +1 -1
- package/dist/esm/joints/WheelJoint.d.ts +4 -3
- package/dist/esm/joints/WheelJoint.d.ts.map +1 -0
- package/dist/esm/joints/WheelJoint.js +228 -255
- package/dist/esm/joints/WheelJoint.js.map +1 -1
- package/dist/esm/math.d.ts +6 -9
- package/dist/esm/math.d.ts.map +1 -0
- package/dist/esm/math.js +37 -39
- package/dist/esm/math.js.map +1 -1
- package/dist/esm/physicsBuildInfo.d.ts +1 -0
- package/dist/esm/physicsBuildInfo.d.ts.map +1 -0
- package/dist/esm/physicsBuildInfo.js +6 -4
- package/dist/esm/physicsBuildInfo.js.map +1 -1
- package/dist/esm/public.d.ts +8 -3
- package/dist/esm/public.d.ts.map +1 -0
- package/dist/esm/query/QueryEngine.d.ts +56 -12
- package/dist/esm/query/QueryEngine.d.ts.map +1 -0
- package/dist/esm/query/QueryEngine.js +494 -237
- package/dist/esm/query/QueryEngine.js.map +1 -1
- package/dist/esm/query/SpatialIndex.d.ts +34 -0
- package/dist/esm/query/SpatialIndex.d.ts.map +1 -0
- package/dist/esm/shapes/AnyShape.d.ts +9 -4
- package/dist/esm/shapes/AnyShape.d.ts.map +1 -0
- package/dist/esm/shapes/BoxShape.d.ts +2 -1
- package/dist/esm/shapes/BoxShape.d.ts.map +1 -0
- package/dist/esm/shapes/BoxShape.js +37 -25
- package/dist/esm/shapes/BoxShape.js.map +1 -1
- package/dist/esm/shapes/CapsuleShape.d.ts +30 -0
- package/dist/esm/shapes/CapsuleShape.d.ts.map +1 -0
- package/dist/esm/shapes/CapsuleShape.js +88 -0
- package/dist/esm/shapes/CapsuleShape.js.map +1 -0
- package/dist/esm/shapes/ChainEdgeShape.d.ts +30 -0
- package/dist/esm/shapes/ChainEdgeShape.d.ts.map +1 -0
- package/dist/esm/shapes/ChainEdgeShape.js +66 -0
- package/dist/esm/shapes/ChainEdgeShape.js.map +1 -0
- package/dist/esm/shapes/ChainShape.d.ts +52 -0
- package/dist/esm/shapes/ChainShape.d.ts.map +1 -0
- package/dist/esm/shapes/ChainShape.js +85 -0
- package/dist/esm/shapes/ChainShape.js.map +1 -0
- package/dist/esm/shapes/CircleShape.d.ts +3 -4
- package/dist/esm/shapes/CircleShape.d.ts.map +1 -0
- package/dist/esm/shapes/CircleShape.js +27 -26
- package/dist/esm/shapes/CircleShape.js.map +1 -1
- package/dist/esm/shapes/PolygonShape.d.ts +7 -8
- package/dist/esm/shapes/PolygonShape.d.ts.map +1 -0
- package/dist/esm/shapes/PolygonShape.js +131 -162
- package/dist/esm/shapes/PolygonShape.js.map +1 -1
- package/dist/esm/shapes/SegmentShape.d.ts +31 -0
- package/dist/esm/shapes/SegmentShape.d.ts.map +1 -0
- package/dist/esm/shapes/SegmentShape.js +62 -0
- package/dist/esm/shapes/SegmentShape.js.map +1 -0
- package/dist/esm/shapes/Shape.d.ts +28 -17
- package/dist/esm/shapes/Shape.d.ts.map +1 -0
- package/dist/esm/shapes/Shape.js +12 -13
- package/dist/esm/shapes/Shape.js.map +1 -1
- package/dist/esm/shapes/convexParts.d.ts +21 -0
- package/dist/esm/shapes/convexParts.d.ts.map +1 -0
- package/dist/esm/shapes/convexParts.js +26 -0
- package/dist/esm/shapes/convexParts.js.map +1 -0
- package/dist/esm/shapes/decompose.d.ts +24 -0
- package/dist/esm/shapes/decompose.d.ts.map +1 -0
- package/dist/esm/shapes/decompose.js +272 -0
- package/dist/esm/shapes/decompose.js.map +1 -0
- package/dist/esm/shapes/index.d.ts +4 -0
- package/dist/esm/shapes/index.d.ts.map +1 -0
- package/dist/esm/solver/ContactSolver.d.ts +12 -5
- package/dist/esm/solver/ContactSolver.d.ts.map +1 -0
- package/dist/esm/solver/ContactSolver.js +425 -471
- package/dist/esm/solver/ContactSolver.js.map +1 -1
- package/dist/esm/solver/tolerances.d.ts +34 -0
- package/dist/esm/solver/tolerances.d.ts.map +1 -0
- package/dist/esm/solver/tolerances.js +38 -0
- package/dist/esm/solver/tolerances.js.map +1 -0
- package/dist/esm/sort.d.ts +5 -4
- package/dist/esm/sort.d.ts.map +1 -0
- package/dist/esm/sort.js +41 -51
- package/dist/esm/sort.js.map +1 -1
- package/dist/esm/types.d.ts +4 -8
- package/dist/esm/types.d.ts.map +1 -0
- package/dist/esm/types.js +15 -17
- package/dist/esm/types.js.map +1 -1
- package/package.json +6 -6
- package/dist/esm/broadphase/SweepAndPrune.d.ts +0 -15
- package/dist/esm/broadphase/SweepAndPrune.js +0 -77
- package/dist/esm/broadphase/SweepAndPrune.js.map +0 -1
- package/dist/esm/debug/index.js.map +0 -1
- package/dist/esm/index.js.map +0 -1
|
@@ -8,15 +8,15 @@ export interface ManifoldPoint {
|
|
|
8
8
|
penetration: number;
|
|
9
9
|
/**
|
|
10
10
|
* Stable feature id identifying which geometric features produced this point.
|
|
11
|
-
* Constant across frames while the contact features are unchanged
|
|
12
|
-
* for warm-starting the solver later
|
|
11
|
+
* Constant across frames while the contact features are unchanged - the basis
|
|
12
|
+
* for warm-starting the solver later.
|
|
13
13
|
*/
|
|
14
14
|
id: number;
|
|
15
15
|
}
|
|
16
16
|
/**
|
|
17
17
|
* A contact manifold: the collision normal (oriented from collider A toward
|
|
18
|
-
* collider B) plus 1
|
|
19
|
-
* calls
|
|
18
|
+
* collider B) plus 1-2 contact points. A `Manifold` is reused across narrow-phase
|
|
19
|
+
* calls - it preallocates its two points and `reset()`s `pointCount` to 0. The
|
|
20
20
|
* generation here is forward-looking work for the dynamics solver; in this
|
|
21
21
|
* collision/query release it drives debug draw and validates the narrow phase.
|
|
22
22
|
*/
|
|
@@ -31,3 +31,4 @@ export declare class Manifold {
|
|
|
31
31
|
/** Clear the manifold for reuse. */
|
|
32
32
|
reset(): void;
|
|
33
33
|
}
|
|
34
|
+
//# sourceMappingURL=Manifold.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Manifold.d.ts","sourceRoot":"","sources":["../../../src/collision/Manifold.ts"],"names":[],"mappings":"AAAA,4CAA4C;AAC5C,MAAM,WAAW,aAAa;IAC5B,sCAAsC;IACtC,CAAC,EAAE,MAAM,CAAC;IACV,sCAAsC;IACtC,CAAC,EAAE,MAAM,CAAC;IACV,qCAAqC;IACrC,WAAW,EAAE,MAAM,CAAC;IACpB;;;;OAIG;IACH,EAAE,EAAE,MAAM,CAAC;CACZ;AAED;;;;;;GAMG;AACH,qBAAa,QAAQ;IACnB,wCAAwC;IACjC,OAAO,SAAK;IACnB,wCAAwC;IACjC,OAAO,SAAK;IACnB,6DAA6D;IACtD,UAAU,SAAK;IAEtB,SAAgB,MAAM,EAAE,SAAS,CAAC,aAAa,EAAE,aAAa,CAAC,CAG7D;IAEF,oCAAoC;IAC7B,KAAK,IAAI,IAAI;CAKrB"}
|
|
@@ -1,28 +1,37 @@
|
|
|
1
|
+
//#region src/collision/Manifold.ts
|
|
1
2
|
/**
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
}
|
|
3
|
+
* A contact manifold: the collision normal (oriented from collider A toward
|
|
4
|
+
* collider B) plus 1-2 contact points. A `Manifold` is reused across narrow-phase
|
|
5
|
+
* calls - it preallocates its two points and `reset()`s `pointCount` to 0. The
|
|
6
|
+
* generation here is forward-looking work for the dynamics solver; in this
|
|
7
|
+
* collision/query release it drives debug draw and validates the narrow phase.
|
|
8
|
+
*/
|
|
9
|
+
var Manifold = class {
|
|
10
|
+
/** Collision normal X (unit, A → B). */
|
|
11
|
+
normalX = 0;
|
|
12
|
+
/** Collision normal Y (unit, A → B). */
|
|
13
|
+
normalY = 0;
|
|
14
|
+
/** Number of valid entries in {@link points} (0, 1 or 2). */
|
|
15
|
+
pointCount = 0;
|
|
16
|
+
points = [{
|
|
17
|
+
x: 0,
|
|
18
|
+
y: 0,
|
|
19
|
+
penetration: 0,
|
|
20
|
+
id: 0
|
|
21
|
+
}, {
|
|
22
|
+
x: 0,
|
|
23
|
+
y: 0,
|
|
24
|
+
penetration: 0,
|
|
25
|
+
id: 0
|
|
26
|
+
}];
|
|
27
|
+
/** Clear the manifold for reuse. */
|
|
28
|
+
reset() {
|
|
29
|
+
this.pointCount = 0;
|
|
30
|
+
this.normalX = 0;
|
|
31
|
+
this.normalY = 0;
|
|
32
|
+
}
|
|
33
|
+
};
|
|
26
34
|
|
|
35
|
+
//#endregion
|
|
27
36
|
export { Manifold };
|
|
28
|
-
//# sourceMappingURL=Manifold.js.map
|
|
37
|
+
//# sourceMappingURL=Manifold.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Manifold.js","sources":["
|
|
1
|
+
{"version":3,"file":"Manifold.js","names":[],"sources":["../../../src/collision/Manifold.ts"],"sourcesContent":["/** A single point of a {@link Manifold}. */\nexport interface ManifoldPoint {\n /** World-space contact position X. */\n x: number;\n /** World-space contact position Y. */\n y: number;\n /** Penetration depth in px (≥ 0). */\n penetration: number;\n /**\n * Stable feature id identifying which geometric features produced this point.\n * Constant across frames while the contact features are unchanged - the basis\n * for warm-starting the solver later.\n */\n id: number;\n}\n\n/**\n * A contact manifold: the collision normal (oriented from collider A toward\n * collider B) plus 1-2 contact points. A `Manifold` is reused across narrow-phase\n * calls - it preallocates its two points and `reset()`s `pointCount` to 0. The\n * generation here is forward-looking work for the dynamics solver; in this\n * collision/query release it drives debug draw and validates the narrow phase.\n */\nexport class Manifold {\n /** Collision normal X (unit, A → B). */\n public normalX = 0;\n /** Collision normal Y (unit, A → B). */\n public normalY = 0;\n /** Number of valid entries in {@link points} (0, 1 or 2). */\n public pointCount = 0;\n\n public readonly points: readonly [ManifoldPoint, ManifoldPoint] = [\n { x: 0, y: 0, penetration: 0, id: 0 },\n { x: 0, y: 0, penetration: 0, id: 0 },\n ];\n\n /** Clear the manifold for reuse. */\n public reset(): void {\n this.pointCount = 0;\n this.normalX = 0;\n this.normalY = 0;\n }\n}\n"],"mappings":";;;;;;;;AAuBA,IAAa,WAAb,MAAsB;;CAEpB,AAAO,UAAU;;CAEjB,AAAO,UAAU;;CAEjB,AAAO,aAAa;CAEpB,AAAgB,SAAkD,CAChE;EAAE,GAAG;EAAG,GAAG;EAAG,aAAa;EAAG,IAAI;CAAE,GACpC;EAAE,GAAG;EAAG,GAAG;EAAG,aAAa;EAAG,IAAI;CAAE,CACtC;;CAGA,AAAO,QAAc;EACnB,KAAK,aAAa;EAClB,KAAK,UAAU;EACf,KAAK,UAAU;CACjB;AACF"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { CollisionProxy } from './CollisionProxy';
|
|
2
|
+
/**
|
|
3
|
+
* Adjacency filter for a chain edge: `true` when this edge owns the contact
|
|
4
|
+
* whose outward normal is `(nx, ny)`. Any other shape admits everything.
|
|
5
|
+
*
|
|
6
|
+
* A chain is one-sided, so a normal pointing into the solid side is never this
|
|
7
|
+
* edge's. Beyond that, the normals around a shared vertex are partitioned by
|
|
8
|
+
* proximity: the edge whose own normal is closest to the contact normal keeps
|
|
9
|
+
* the contact, and its neighbours drop it. That is what removes internal vertex
|
|
10
|
+
* snagging - a body sliding onto the next edge stops producing a contact against
|
|
11
|
+
* the previous one, instead of receiving two contradicting normals at the seam -
|
|
12
|
+
* while a body wedged in a concave corner still keeps one contact per wall,
|
|
13
|
+
* because each wall's own normal is the closest one there.
|
|
14
|
+
*
|
|
15
|
+
* A tie (collinear edges) is kept by both, which is what lets a straight run of
|
|
16
|
+
* chain edges carry a box across the join. A free end has no neighbour on that
|
|
17
|
+
* side and admits the whole half-plane, so a body can pass around it.
|
|
18
|
+
*
|
|
19
|
+
* The neighbour normals are reconstructed from the stored rotations rather than
|
|
20
|
+
* cached in world space: rotating this edge's world normal by the (transform
|
|
21
|
+
* invariant) angle to a neighbour's is exact and needs no second sync pass.
|
|
22
|
+
*
|
|
23
|
+
* The discrete narrow phase and the sweep both apply it, so a fast body meets
|
|
24
|
+
* the same one-sided, seam-free chain a slow one does.
|
|
25
|
+
*
|
|
26
|
+
* @internal
|
|
27
|
+
*/
|
|
28
|
+
export declare const chainEdgeAdmits: (proxy: CollisionProxy, nx: number, ny: number) => boolean;
|
|
29
|
+
//# sourceMappingURL=chainAdjacency.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chainAdjacency.d.ts","sourceRoot":"","sources":["../../../src/collision/chainAdjacency.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAEvD;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,eAAO,MAAM,eAAe,GAAI,OAAO,cAAc,EAAE,IAAI,MAAM,EAAE,IAAI,MAAM,KAAG,OAsB/E,CAAC"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { ChainEdgeShape } from "../shapes/ChainEdgeShape.js";
|
|
2
|
+
|
|
3
|
+
//#region src/collision/chainAdjacency.ts
|
|
4
|
+
/**
|
|
5
|
+
* Adjacency filter for a chain edge: `true` when this edge owns the contact
|
|
6
|
+
* whose outward normal is `(nx, ny)`. Any other shape admits everything.
|
|
7
|
+
*
|
|
8
|
+
* A chain is one-sided, so a normal pointing into the solid side is never this
|
|
9
|
+
* edge's. Beyond that, the normals around a shared vertex are partitioned by
|
|
10
|
+
* proximity: the edge whose own normal is closest to the contact normal keeps
|
|
11
|
+
* the contact, and its neighbours drop it. That is what removes internal vertex
|
|
12
|
+
* snagging - a body sliding onto the next edge stops producing a contact against
|
|
13
|
+
* the previous one, instead of receiving two contradicting normals at the seam -
|
|
14
|
+
* while a body wedged in a concave corner still keeps one contact per wall,
|
|
15
|
+
* because each wall's own normal is the closest one there.
|
|
16
|
+
*
|
|
17
|
+
* A tie (collinear edges) is kept by both, which is what lets a straight run of
|
|
18
|
+
* chain edges carry a box across the join. A free end has no neighbour on that
|
|
19
|
+
* side and admits the whole half-plane, so a body can pass around it.
|
|
20
|
+
*
|
|
21
|
+
* The neighbour normals are reconstructed from the stored rotations rather than
|
|
22
|
+
* cached in world space: rotating this edge's world normal by the (transform
|
|
23
|
+
* invariant) angle to a neighbour's is exact and needs no second sync pass.
|
|
24
|
+
*
|
|
25
|
+
* The discrete narrow phase and the sweep both apply it, so a fast body meets
|
|
26
|
+
* the same one-sided, seam-free chain a slow one does.
|
|
27
|
+
*
|
|
28
|
+
* @internal
|
|
29
|
+
*/
|
|
30
|
+
const chainEdgeAdmits = (proxy, nx, ny) => {
|
|
31
|
+
const shape = proxy.shape;
|
|
32
|
+
if (!(shape instanceof ChainEdgeShape)) return true;
|
|
33
|
+
const ownX = proxy.worldNormals[0];
|
|
34
|
+
const ownY = proxy.worldNormals[1];
|
|
35
|
+
const own = nx * ownX + ny * ownY;
|
|
36
|
+
if (own <= 0) return false;
|
|
37
|
+
const cross = ownX * ny - ownY * nx;
|
|
38
|
+
if (shape.hasPrevious && shape.previousCos * own + shape.previousSin * cross > own) return false;
|
|
39
|
+
return !(shape.hasNext && shape.nextCos * own + shape.nextSin * cross > own);
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
//#endregion
|
|
43
|
+
export { chainEdgeAdmits };
|
|
44
|
+
//# sourceMappingURL=chainAdjacency.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chainAdjacency.js","names":[],"sources":["../../../src/collision/chainAdjacency.ts"],"sourcesContent":["import { ChainEdgeShape } from '../shapes/ChainEdgeShape';\nimport type { CollisionProxy } from './CollisionProxy';\n\n/**\n * Adjacency filter for a chain edge: `true` when this edge owns the contact\n * whose outward normal is `(nx, ny)`. Any other shape admits everything.\n *\n * A chain is one-sided, so a normal pointing into the solid side is never this\n * edge's. Beyond that, the normals around a shared vertex are partitioned by\n * proximity: the edge whose own normal is closest to the contact normal keeps\n * the contact, and its neighbours drop it. That is what removes internal vertex\n * snagging - a body sliding onto the next edge stops producing a contact against\n * the previous one, instead of receiving two contradicting normals at the seam -\n * while a body wedged in a concave corner still keeps one contact per wall,\n * because each wall's own normal is the closest one there.\n *\n * A tie (collinear edges) is kept by both, which is what lets a straight run of\n * chain edges carry a box across the join. A free end has no neighbour on that\n * side and admits the whole half-plane, so a body can pass around it.\n *\n * The neighbour normals are reconstructed from the stored rotations rather than\n * cached in world space: rotating this edge's world normal by the (transform\n * invariant) angle to a neighbour's is exact and needs no second sync pass.\n *\n * The discrete narrow phase and the sweep both apply it, so a fast body meets\n * the same one-sided, seam-free chain a slow one does.\n *\n * @internal\n */\nexport const chainEdgeAdmits = (proxy: CollisionProxy, nx: number, ny: number): boolean => {\n const shape = proxy.shape;\n\n if (!(shape instanceof ChainEdgeShape)) {\n return true;\n }\n\n const ownX = proxy.worldNormals[0]!;\n const ownY = proxy.worldNormals[1]!;\n const own = nx * ownX + ny * ownY;\n\n if (own <= 0) {\n return false;\n }\n\n const cross = ownX * ny - ownY * nx;\n\n if (shape.hasPrevious && shape.previousCos * own + shape.previousSin * cross > own) {\n return false;\n }\n\n return !(shape.hasNext && shape.nextCos * own + shape.nextSin * cross > own);\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6BA,MAAa,mBAAmB,OAAuB,IAAY,OAAwB;CACzF,MAAM,QAAQ,MAAM;CAEpB,IAAI,EAAE,iBAAiB,iBACrB,OAAO;CAGT,MAAM,OAAO,MAAM,aAAa;CAChC,MAAM,OAAO,MAAM,aAAa;CAChC,MAAM,MAAM,KAAK,OAAO,KAAK;CAE7B,IAAI,OAAO,GACT,OAAO;CAGT,MAAM,QAAQ,OAAO,KAAK,OAAO;CAEjC,IAAI,MAAM,eAAe,MAAM,cAAc,MAAM,MAAM,cAAc,QAAQ,KAC7E,OAAO;CAGT,OAAO,EAAE,MAAM,WAAW,MAAM,UAAU,MAAM,MAAM,UAAU,QAAQ;AAC1E"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { ShapeType } from '../shapes/Shape';
|
|
2
|
+
/**
|
|
3
|
+
* Canonical order of the shape kinds, roundest first. Two things depend on it
|
|
4
|
+
* and nothing else should: a pair table stores each unordered pair once, under
|
|
5
|
+
* the lower kind, and a mixed pair is always solved with the lower kind as the
|
|
6
|
+
* first operand plus a flip flag that reverses the resulting normal. One
|
|
7
|
+
* implementation per pair, never two mirrored copies.
|
|
8
|
+
*
|
|
9
|
+
* Inserting a kind changes only which slot a pair lands in, never which
|
|
10
|
+
* implementation runs.
|
|
11
|
+
*/
|
|
12
|
+
export declare const shapeKindOrder: Readonly<Record<ShapeType, number>>;
|
|
13
|
+
export declare const shapeKindCount: number;
|
|
14
|
+
/**
|
|
15
|
+
* Flat `kind × kind` table. Symmetric tables fill only the upper triangle and
|
|
16
|
+
* are read through {@link symmetricEntry}; ordered ones (a sweep distinguishes
|
|
17
|
+
* the moving operand from the target) fill both halves and are read directly
|
|
18
|
+
* with {@link orderedEntry}.
|
|
19
|
+
*/
|
|
20
|
+
export type PairTable<T> = Array<T | undefined>;
|
|
21
|
+
/** Build a table holding one entry per **unordered** pair. */
|
|
22
|
+
export declare const symmetricTable: <T>(entries: ReadonlyArray<readonly [ShapeType, ShapeType, T]>) => PairTable<T>;
|
|
23
|
+
/** Build a table holding one entry per **ordered** pair. */
|
|
24
|
+
export declare const orderedTable: <T>(entries: ReadonlyArray<readonly [ShapeType, ShapeType, T]>) => PairTable<T>;
|
|
25
|
+
/**
|
|
26
|
+
* Entry for the unordered pair `(first, second)`. `undefined` means the pair is
|
|
27
|
+
* deliberately unsupported - callers must treat that as "no contact", never as
|
|
28
|
+
* an approximation.
|
|
29
|
+
*/
|
|
30
|
+
export declare const symmetricEntry: <T>(table: PairTable<T>, first: ShapeType, second: ShapeType) => T | undefined;
|
|
31
|
+
/** `true` when the operands have to be swapped to reach the canonical order. */
|
|
32
|
+
export declare const needsFlip: (first: ShapeType, second: ShapeType) => boolean;
|
|
33
|
+
/** Entry for the ordered pair `(first, second)`; see {@link symmetricEntry} on `undefined`. */
|
|
34
|
+
export declare const orderedEntry: <T>(table: PairTable<T>, first: ShapeType, second: ShapeType) => T | undefined;
|
|
35
|
+
//# sourceMappingURL=dispatch.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dispatch.d.ts","sourceRoot":"","sources":["../../../src/collision/dispatch.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAEjD;;;;;;;;;GASG;AACH,eAAO,MAAM,cAAc,EAAE,QAAQ,CAAC,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,CAS9D,CAAC;AAEF,eAAO,MAAM,cAAc,QAAqC,CAAC;AAEjE;;;;;GAKG;AACH,MAAM,MAAM,SAAS,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC;AAYhD,8DAA8D;AAC9D,eAAO,MAAM,cAAc,GAAI,CAAC,EAAE,SAAS,aAAa,CAAC,SAAS,CAAC,SAAS,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,KAAG,SAAS,CAAC,CAAC,CAWzG,CAAC;AAEF,4DAA4D;AAC5D,eAAO,MAAM,YAAY,GAAI,CAAC,EAAE,SAAS,aAAa,CAAC,SAAS,CAAC,SAAS,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,KAAG,SAAS,CAAC,CAAC,CAQvG,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,cAAc,GAAI,CAAC,EAAE,OAAO,SAAS,CAAC,CAAC,CAAC,EAAE,OAAO,SAAS,EAAE,QAAQ,SAAS,KAAG,CAAC,GAAG,SAKhG,CAAC;AAEF,gFAAgF;AAChF,eAAO,MAAM,SAAS,GAAI,OAAO,SAAS,EAAE,QAAQ,SAAS,KAAG,OAAyD,CAAC;AAE1H,+FAA+F;AAC/F,eAAO,MAAM,YAAY,GAAI,CAAC,EAAE,OAAO,SAAS,CAAC,CAAC,CAAC,EAAE,OAAO,SAAS,EAAE,QAAQ,SAAS,KAAG,CAAC,GAAG,SACvB,CAAC"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
//#region src/collision/dispatch.ts
|
|
2
|
+
/**
|
|
3
|
+
* Canonical order of the shape kinds, roundest first. Two things depend on it
|
|
4
|
+
* and nothing else should: a pair table stores each unordered pair once, under
|
|
5
|
+
* the lower kind, and a mixed pair is always solved with the lower kind as the
|
|
6
|
+
* first operand plus a flip flag that reverses the resulting normal. One
|
|
7
|
+
* implementation per pair, never two mirrored copies.
|
|
8
|
+
*
|
|
9
|
+
* Inserting a kind changes only which slot a pair lands in, never which
|
|
10
|
+
* implementation runs.
|
|
11
|
+
*/
|
|
12
|
+
const shapeKindOrder = {
|
|
13
|
+
circle: 0,
|
|
14
|
+
capsule: 1,
|
|
15
|
+
segment: 2,
|
|
16
|
+
polygon: 3,
|
|
17
|
+
chain: 4
|
|
18
|
+
};
|
|
19
|
+
const shapeKindCount = Object.keys(shapeKindOrder).length;
|
|
20
|
+
const emptyTable = () => {
|
|
21
|
+
const table = [];
|
|
22
|
+
for (let i = 0; i < shapeKindCount * shapeKindCount; i++) table.push(void 0);
|
|
23
|
+
return table;
|
|
24
|
+
};
|
|
25
|
+
/** Build a table holding one entry per **unordered** pair. */
|
|
26
|
+
const symmetricTable = (entries) => {
|
|
27
|
+
const table = emptyTable();
|
|
28
|
+
for (const [first, second, value] of entries) {
|
|
29
|
+
const a = shapeKindOrder[first];
|
|
30
|
+
const b = shapeKindOrder[second];
|
|
31
|
+
table[Math.min(a, b) * shapeKindCount + Math.max(a, b)] = value;
|
|
32
|
+
}
|
|
33
|
+
return table;
|
|
34
|
+
};
|
|
35
|
+
/** Build a table holding one entry per **ordered** pair. */
|
|
36
|
+
const orderedTable = (entries) => {
|
|
37
|
+
const table = emptyTable();
|
|
38
|
+
for (const [first, second, value] of entries) table[shapeKindOrder[first] * shapeKindCount + shapeKindOrder[second]] = value;
|
|
39
|
+
return table;
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* Entry for the unordered pair `(first, second)`. `undefined` means the pair is
|
|
43
|
+
* deliberately unsupported - callers must treat that as "no contact", never as
|
|
44
|
+
* an approximation.
|
|
45
|
+
*/
|
|
46
|
+
const symmetricEntry = (table, first, second) => {
|
|
47
|
+
const a = shapeKindOrder[first];
|
|
48
|
+
const b = shapeKindOrder[second];
|
|
49
|
+
return table[Math.min(a, b) * shapeKindCount + Math.max(a, b)];
|
|
50
|
+
};
|
|
51
|
+
/** `true` when the operands have to be swapped to reach the canonical order. */
|
|
52
|
+
const needsFlip = (first, second) => shapeKindOrder[first] > shapeKindOrder[second];
|
|
53
|
+
/** Entry for the ordered pair `(first, second)`; see {@link symmetricEntry} on `undefined`. */
|
|
54
|
+
const orderedEntry = (table, first, second) => table[shapeKindOrder[first] * shapeKindCount + shapeKindOrder[second]];
|
|
55
|
+
|
|
56
|
+
//#endregion
|
|
57
|
+
export { needsFlip, orderedEntry, orderedTable, shapeKindCount, shapeKindOrder, symmetricEntry, symmetricTable };
|
|
58
|
+
//# sourceMappingURL=dispatch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dispatch.js","names":[],"sources":["../../../src/collision/dispatch.ts"],"sourcesContent":["import type { ShapeType } from '../shapes/Shape';\n\n/**\n * Canonical order of the shape kinds, roundest first. Two things depend on it\n * and nothing else should: a pair table stores each unordered pair once, under\n * the lower kind, and a mixed pair is always solved with the lower kind as the\n * first operand plus a flip flag that reverses the resulting normal. One\n * implementation per pair, never two mirrored copies.\n *\n * Inserting a kind changes only which slot a pair lands in, never which\n * implementation runs.\n */\nexport const shapeKindOrder: Readonly<Record<ShapeType, number>> = {\n circle: 0,\n capsule: 1,\n segment: 2,\n polygon: 3,\n // A chain never reaches the narrow phase itself: a chain collider is solved\n // through its per-edge child proxies, which are segments carrying adjacency.\n // The slot exists so the tables stay total over `ShapeType`, and stays empty.\n chain: 4,\n};\n\nexport const shapeKindCount = Object.keys(shapeKindOrder).length;\n\n/**\n * Flat `kind × kind` table. Symmetric tables fill only the upper triangle and\n * are read through {@link symmetricEntry}; ordered ones (a sweep distinguishes\n * the moving operand from the target) fill both halves and are read directly\n * with {@link orderedEntry}.\n */\nexport type PairTable<T> = Array<T | undefined>;\n\nconst emptyTable = <T>(): PairTable<T> => {\n const table: PairTable<T> = [];\n\n for (let i = 0; i < shapeKindCount * shapeKindCount; i++) {\n table.push(undefined);\n }\n\n return table;\n};\n\n/** Build a table holding one entry per **unordered** pair. */\nexport const symmetricTable = <T>(entries: ReadonlyArray<readonly [ShapeType, ShapeType, T]>): PairTable<T> => {\n const table = emptyTable<T>();\n\n for (const [first, second, value] of entries) {\n const a = shapeKindOrder[first];\n const b = shapeKindOrder[second];\n\n table[Math.min(a, b) * shapeKindCount + Math.max(a, b)] = value;\n }\n\n return table;\n};\n\n/** Build a table holding one entry per **ordered** pair. */\nexport const orderedTable = <T>(entries: ReadonlyArray<readonly [ShapeType, ShapeType, T]>): PairTable<T> => {\n const table = emptyTable<T>();\n\n for (const [first, second, value] of entries) {\n table[shapeKindOrder[first] * shapeKindCount + shapeKindOrder[second]] = value;\n }\n\n return table;\n};\n\n/**\n * Entry for the unordered pair `(first, second)`. `undefined` means the pair is\n * deliberately unsupported - callers must treat that as \"no contact\", never as\n * an approximation.\n */\nexport const symmetricEntry = <T>(table: PairTable<T>, first: ShapeType, second: ShapeType): T | undefined => {\n const a = shapeKindOrder[first];\n const b = shapeKindOrder[second];\n\n return table[Math.min(a, b) * shapeKindCount + Math.max(a, b)];\n};\n\n/** `true` when the operands have to be swapped to reach the canonical order. */\nexport const needsFlip = (first: ShapeType, second: ShapeType): boolean => shapeKindOrder[first] > shapeKindOrder[second];\n\n/** Entry for the ordered pair `(first, second)`; see {@link symmetricEntry} on `undefined`. */\nexport const orderedEntry = <T>(table: PairTable<T>, first: ShapeType, second: ShapeType): T | undefined =>\n table[shapeKindOrder[first] * shapeKindCount + shapeKindOrder[second]];\n"],"mappings":";;;;;;;;;;;AAYA,MAAa,iBAAsD;CACjE,QAAQ;CACR,SAAS;CACT,SAAS;CACT,SAAS;CAIT,OAAO;AACT;AAEA,MAAa,iBAAiB,OAAO,KAAK,cAAc,CAAC,CAAC;AAU1D,MAAM,mBAAoC;CACxC,MAAM,QAAsB,CAAC;CAE7B,KAAK,IAAI,IAAI,GAAG,IAAI,iBAAiB,gBAAgB,KACnD,MAAM,KAAK,MAAS;CAGtB,OAAO;AACT;;AAGA,MAAa,kBAAqB,YAA6E;CAC7G,MAAM,QAAQ,WAAc;CAE5B,KAAK,MAAM,CAAC,OAAO,QAAQ,UAAU,SAAS;EAC5C,MAAM,IAAI,eAAe;EACzB,MAAM,IAAI,eAAe;EAEzB,MAAM,KAAK,IAAI,GAAG,CAAC,IAAI,iBAAiB,KAAK,IAAI,GAAG,CAAC,KAAK;CAC5D;CAEA,OAAO;AACT;;AAGA,MAAa,gBAAmB,YAA6E;CAC3G,MAAM,QAAQ,WAAc;CAE5B,KAAK,MAAM,CAAC,OAAO,QAAQ,UAAU,SACnC,MAAM,eAAe,SAAS,iBAAiB,eAAe,WAAW;CAG3E,OAAO;AACT;;;;;;AAOA,MAAa,kBAAqB,OAAqB,OAAkB,WAAqC;CAC5G,MAAM,IAAI,eAAe;CACzB,MAAM,IAAI,eAAe;CAEzB,OAAO,MAAM,KAAK,IAAI,GAAG,CAAC,IAAI,iBAAiB,KAAK,IAAI,GAAG,CAAC;AAC9D;;AAGA,MAAa,aAAa,OAAkB,WAA+B,eAAe,SAAS,eAAe;;AAGlH,MAAa,gBAAmB,OAAqB,OAAkB,WACrE,MAAM,eAAe,SAAS,iBAAiB,eAAe"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/collision/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EAAE,QAAQ,EAAE,KAAK,aAAa,EAAE,MAAM,YAAY,CAAC;AAC1D,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AACrD,OAAO,EAAE,KAAK,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC"}
|
|
@@ -3,8 +3,10 @@ import type { Manifold } from './Manifold';
|
|
|
3
3
|
/**
|
|
4
4
|
* Generate the contact manifold for `a` vs `b`, writing into `manifold` and
|
|
5
5
|
* returning `true` when the colliders touch. The manifold normal is oriented
|
|
6
|
-
* from `a` toward `b`.
|
|
7
|
-
*
|
|
6
|
+
* from `a` toward `b`.
|
|
7
|
+
*
|
|
8
|
+
* A pair with no entry in the table is deliberately unsupported and reports no
|
|
9
|
+
* contact rather than an approximation.
|
|
8
10
|
*/
|
|
9
11
|
export declare const collide: (a: CollisionProxy, b: CollisionProxy, manifold: Manifold) => boolean;
|
|
10
12
|
/**
|
|
@@ -12,3 +14,4 @@ export declare const collide: (a: CollisionProxy, b: CollisionProxy, manifold: M
|
|
|
12
14
|
* Exact for the circle/circle, circle/polygon and polygon/polygon pairs.
|
|
13
15
|
*/
|
|
14
16
|
export declare const testOverlap: (a: CollisionProxy, b: CollisionProxy) => boolean;
|
|
17
|
+
//# sourceMappingURL=narrowphase.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"narrowphase.d.ts","sourceRoot":"","sources":["../../../src/collision/narrowphase.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAGvD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAmB3C;;;;;;;GAOG;AACH,eAAO,MAAM,OAAO,GAAI,GAAG,cAAc,EAAE,GAAG,cAAc,EAAE,UAAU,QAAQ,KAAG,OA0BlF,CAAC;AAkdF;;;GAGG;AACH,eAAO,MAAM,WAAW,GAAI,GAAG,cAAc,EAAE,GAAG,cAAc,KAAG,OAUlE,CAAC"}
|