@flighthq/physics2d 0.3.0 → 0.3.1-next.1041.35b950c
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/dist/broadphase.js +38 -18
- package/dist/broadphase.js.map +1 -1
- package/dist/joints.d.ts.map +1 -1
- package/dist/joints.js +41 -38
- package/dist/joints.js.map +1 -1
- package/dist/massProperties.d.ts.map +1 -1
- package/dist/massProperties.js +16 -1
- package/dist/massProperties.js.map +1 -1
- package/dist/step.d.ts.map +1 -1
- package/dist/step.js +106 -84
- package/dist/step.js.map +1 -1
- package/dist/worldQueries.d.ts.map +1 -1
- package/dist/worldQueries.js +80 -48
- package/dist/worldQueries.js.map +1 -1
- package/package.json +5 -5
- package/src/broadphase.test.ts +29 -0
- package/src/joints.test.ts +45 -0
- package/src/massProperties.test.ts +31 -0
- package/src/step.test.ts +23 -0
- package/src/worldQueries.test.ts +30 -0
package/dist/worldQueries.js
CHANGED
|
@@ -28,22 +28,28 @@ export function queryPhysics2DPoint(world, x, y, out, filter) {
|
|
|
28
28
|
out.hitCount = 0;
|
|
29
29
|
if (!Number.isFinite(x) || !Number.isFinite(y))
|
|
30
30
|
return;
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
const collider = body.colliders[colliderIndex];
|
|
40
|
-
if (!passesColliderFilter(collider, filter))
|
|
31
|
+
const scratch = acquirePhysics2DQueryScratch();
|
|
32
|
+
try {
|
|
33
|
+
synchronizePhysics2DBroadphase(world);
|
|
34
|
+
world.index.querySpatialPoint(x, y, scratch.candidateBodies);
|
|
35
|
+
scratch.candidateBodies.sort(compareNumbers);
|
|
36
|
+
for (const bodyIndex of scratch.candidateBodies) {
|
|
37
|
+
const body = findPhysics2DBody(world, bodyIndex);
|
|
38
|
+
if (body === null || !passesBodyFilter(body, filter))
|
|
41
39
|
continue;
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
40
|
+
for (let colliderIndex = 0; colliderIndex < body.colliders.length; colliderIndex++) {
|
|
41
|
+
const collider = body.colliders[colliderIndex];
|
|
42
|
+
if (!passesColliderFilter(collider, filter))
|
|
43
|
+
continue;
|
|
44
|
+
if (!getCollisionShapeContainsPoint(collider.world, x, y))
|
|
45
|
+
continue;
|
|
46
|
+
writeQueryHit(out, body, collider, colliderIndex);
|
|
47
|
+
}
|
|
45
48
|
}
|
|
46
49
|
}
|
|
50
|
+
finally {
|
|
51
|
+
releasePhysics2DQueryScratch(scratch);
|
|
52
|
+
}
|
|
47
53
|
}
|
|
48
54
|
// Writes every exact collider intersection with `origin + direction * fraction`, ordered nearest
|
|
49
55
|
// first. `maxFraction` turns the unbounded ray into a finite sweep without requiring direction to be
|
|
@@ -66,28 +72,34 @@ function queryPhysics2DRayInternal(world, originX, originY, directionX, directio
|
|
|
66
72
|
maxFraction < 0) {
|
|
67
73
|
return;
|
|
68
74
|
}
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
const collider = body.colliders[colliderIndex];
|
|
78
|
-
if (!passesColliderFilter(collider, filter))
|
|
79
|
-
continue;
|
|
80
|
-
if (!raycastCollisionShape(collider.world, originX, originY, directionX, directionY, raycastHitScratch, maxFraction)) {
|
|
75
|
+
const scratch = acquirePhysics2DQueryScratch();
|
|
76
|
+
try {
|
|
77
|
+
synchronizePhysics2DBroadphase(world);
|
|
78
|
+
world.index.querySpatialRay(originX, originY, directionX, directionY, scratch.candidateBodies);
|
|
79
|
+
scratch.candidateBodies.sort(compareNumbers);
|
|
80
|
+
for (const bodyIndex of scratch.candidateBodies) {
|
|
81
|
+
const body = findPhysics2DBody(world, bodyIndex);
|
|
82
|
+
if (body === null || !passesBodyFilter(body, filter))
|
|
81
83
|
continue;
|
|
84
|
+
for (let colliderIndex = 0; colliderIndex < body.colliders.length; colliderIndex++) {
|
|
85
|
+
const collider = body.colliders[colliderIndex];
|
|
86
|
+
if (!passesColliderFilter(collider, filter))
|
|
87
|
+
continue;
|
|
88
|
+
if (!raycastCollisionShape(collider.world, originX, originY, directionX, directionY, scratch.raycastHit, maxFraction)) {
|
|
89
|
+
continue;
|
|
90
|
+
}
|
|
91
|
+
if (closestOnly)
|
|
92
|
+
writeClosestRayHit(out, body, collider, colliderIndex, scratch.raycastHit);
|
|
93
|
+
else
|
|
94
|
+
writeRayHit(out, body, collider, colliderIndex, scratch.raycastHit);
|
|
82
95
|
}
|
|
83
|
-
if (closestOnly)
|
|
84
|
-
writeClosestRayHit(out, body, collider, colliderIndex, raycastHitScratch);
|
|
85
|
-
else
|
|
86
|
-
writeRayHit(out, body, collider, colliderIndex, raycastHitScratch);
|
|
87
96
|
}
|
|
97
|
+
if (!closestOnly)
|
|
98
|
+
sortLiveRayHits(out);
|
|
99
|
+
}
|
|
100
|
+
finally {
|
|
101
|
+
releasePhysics2DQueryScratch(scratch);
|
|
88
102
|
}
|
|
89
|
-
if (!closestOnly)
|
|
90
|
-
sortLiveRayHits(out);
|
|
91
103
|
}
|
|
92
104
|
// Writes every collider whose current world-space AABB overlaps `region`. The spatial index is over
|
|
93
105
|
// aggregate BODY bounds, so its candidates are refined per collider before publication: a region in
|
|
@@ -96,23 +108,29 @@ export function queryPhysics2DRegion(world, region, out, filter) {
|
|
|
96
108
|
out.hitCount = 0;
|
|
97
109
|
if (!isValidRegion(region))
|
|
98
110
|
return;
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
const collider = body.colliders[colliderIndex];
|
|
108
|
-
if (!passesColliderFilter(collider, filter))
|
|
109
|
-
continue;
|
|
110
|
-
writePhysics2DColliderBounds(collider, colliderBoundsScratch);
|
|
111
|
-
if (!boundsOverlap(colliderBoundsScratch, region))
|
|
111
|
+
const scratch = acquirePhysics2DQueryScratch();
|
|
112
|
+
try {
|
|
113
|
+
synchronizePhysics2DBroadphase(world);
|
|
114
|
+
world.index.querySpatialRegion(region, scratch.candidateBodies);
|
|
115
|
+
scratch.candidateBodies.sort(compareNumbers);
|
|
116
|
+
for (const bodyIndex of scratch.candidateBodies) {
|
|
117
|
+
const body = findPhysics2DBody(world, bodyIndex);
|
|
118
|
+
if (body === null || !passesBodyFilter(body, filter))
|
|
112
119
|
continue;
|
|
113
|
-
|
|
120
|
+
for (let colliderIndex = 0; colliderIndex < body.colliders.length; colliderIndex++) {
|
|
121
|
+
const collider = body.colliders[colliderIndex];
|
|
122
|
+
if (!passesColliderFilter(collider, filter))
|
|
123
|
+
continue;
|
|
124
|
+
writePhysics2DColliderBounds(collider, scratch.colliderBounds);
|
|
125
|
+
if (!boundsOverlap(scratch.colliderBounds, region))
|
|
126
|
+
continue;
|
|
127
|
+
writeQueryHit(out, body, collider, colliderIndex);
|
|
128
|
+
}
|
|
114
129
|
}
|
|
115
130
|
}
|
|
131
|
+
finally {
|
|
132
|
+
releasePhysics2DQueryScratch(scratch);
|
|
133
|
+
}
|
|
116
134
|
}
|
|
117
135
|
function writeClosestRayHit(out, body, collider, colliderIndex, source) {
|
|
118
136
|
if (out.hitCount === 0) {
|
|
@@ -222,7 +240,21 @@ function isValidRegion(region) {
|
|
|
222
240
|
function compareNumbers(a, b) {
|
|
223
241
|
return a - b;
|
|
224
242
|
}
|
|
225
|
-
|
|
226
|
-
const
|
|
227
|
-
|
|
243
|
+
function acquirePhysics2DQueryScratch() {
|
|
244
|
+
const scratch = physics2DQueryScratchPool.pop() ?? createPhysics2DQueryScratch();
|
|
245
|
+
scratch.candidateBodies.length = 0;
|
|
246
|
+
return scratch;
|
|
247
|
+
}
|
|
248
|
+
function createPhysics2DQueryScratch() {
|
|
249
|
+
return {
|
|
250
|
+
candidateBodies: [],
|
|
251
|
+
colliderBounds: { minX: 0, minY: 0, maxX: 0, maxY: 0 },
|
|
252
|
+
raycastHit: createCollisionRaycastHit(),
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
function releasePhysics2DQueryScratch(scratch) {
|
|
256
|
+
scratch.candidateBodies.length = 0;
|
|
257
|
+
physics2DQueryScratchPool.push(scratch);
|
|
258
|
+
}
|
|
259
|
+
const physics2DQueryScratchPool = [createPhysics2DQueryScratch()];
|
|
228
260
|
//# sourceMappingURL=worldQueries.js.map
|
package/dist/worldQueries.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"worldQueries.js","sourceRoot":"","sources":["../src/worldQueries.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,yBAAyB,EACzB,8BAA8B,EAC9B,qBAAqB,GACtB,MAAM,8BAA8B,CAAC;AAatC,OAAO,EAAE,8BAA8B,EAAE,MAAM,cAAc,CAAC;AAC9D,OAAO,EAAE,4BAA4B,EAAE,MAAM,qBAAqB,CAAC;AACnE,OAAO,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAE5C,MAAM,UAAU,0BAA0B;IACxC,OAAO;QACL,YAAY,EAAE,UAAU;QACxB,QAAQ,EAAE,UAAU;QACpB,cAAc,EAAE,IAAI;QACpB,cAAc,EAAE,IAAI;QACpB,gBAAgB,EAAE,IAAI;QACtB,aAAa,EAAE,IAAI;KACpB,CAAC;AACJ,CAAC;AAED,sGAAsG;AACtG,mGAAmG;AACnG,MAAM,UAAU,0BAA0B;IACxC,OAAO,EAAE,IAAI,EAAE,EAAE,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC;AACnC,CAAC;AAED,MAAM,UAAU,wBAAwB;IACtC,OAAO,EAAE,IAAI,EAAE,EAAE,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC;AACnC,CAAC;AAED,qGAAqG;AACrG,sGAAsG;AACtG,wGAAwG;AACxG,6BAA6B;AAC7B,MAAM,UAAU,mBAAmB,CACjC,KAAqB,EACrB,CAAS,EACT,CAAS,EACT,GAAyB,EACzB,MAAuC;IAEvC,GAAG,CAAC,QAAQ,GAAG,CAAC,CAAC;IACjB,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC;QAAE,OAAO;IACvD,8BAA8B,CAAC,KAAK,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"worldQueries.js","sourceRoot":"","sources":["../src/worldQueries.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@flighthq/physics2d",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.1-next.1041.35b950c",
|
|
4
4
|
"author": "Joshua Granick and other contributors",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -38,10 +38,10 @@
|
|
|
38
38
|
"clean:dist": "tsx ../../scripts/clean-package-dist.ts"
|
|
39
39
|
},
|
|
40
40
|
"dependencies": {
|
|
41
|
-
"@flighthq/collision": "0.3.
|
|
42
|
-
"@flighthq/math": "0.3.
|
|
43
|
-
"@flighthq/spatial": "0.3.
|
|
44
|
-
"@flighthq/types": "0.3.
|
|
41
|
+
"@flighthq/collision": "0.3.1-next.1041.35b950c",
|
|
42
|
+
"@flighthq/math": "0.3.1-next.1041.35b950c",
|
|
43
|
+
"@flighthq/spatial": "0.3.1-next.1041.35b950c",
|
|
44
|
+
"@flighthq/types": "0.3.1-next.1041.35b950c"
|
|
45
45
|
},
|
|
46
46
|
"devDependencies": {
|
|
47
47
|
"typescript": "^5.3.0"
|
package/src/broadphase.test.ts
CHANGED
|
@@ -6,6 +6,35 @@ import { addPhysics2DBody, createPhysics2DCollider, createPhysics2DWorld, create
|
|
|
6
6
|
const STONE = { density: 1, friction: 0.3, restitution: 0 };
|
|
7
7
|
|
|
8
8
|
describe('synchronizePhysics2DBroadphase', () => {
|
|
9
|
+
it('keeps published bounds isolated when an index callback synchronizes another world', () => {
|
|
10
|
+
const world = createPhysics2DWorld(0, 0);
|
|
11
|
+
const body = createRigidBody2D('dynamic', 2, 3);
|
|
12
|
+
body.colliders.push(createPhysics2DCollider({ kind: 'circle', radius: 1, x: 0, y: 0 }, STONE));
|
|
13
|
+
addPhysics2DBody(world, body);
|
|
14
|
+
|
|
15
|
+
const nestedWorld = createPhysics2DWorld(0, 0);
|
|
16
|
+
const nestedBody = createRigidBody2D('dynamic', 100, 200);
|
|
17
|
+
nestedBody.colliders.push(createPhysics2DCollider({ kind: 'circle', radius: 5, x: 0, y: 0 }, STONE));
|
|
18
|
+
addPhysics2DBody(nestedWorld, nestedBody);
|
|
19
|
+
|
|
20
|
+
let nestedCalls = 0;
|
|
21
|
+
let published = { minX: 0, minY: 0, maxX: 0, maxY: 0 };
|
|
22
|
+
world.index.updateSpatialObject = (_id, bounds) => {
|
|
23
|
+
nestedCalls++;
|
|
24
|
+
synchronizePhysics2DBroadphase(nestedWorld);
|
|
25
|
+
published = { minX: bounds.minX, minY: bounds.minY, maxX: bounds.maxX, maxY: bounds.maxY };
|
|
26
|
+
return true;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
synchronizePhysics2DBroadphase(world);
|
|
30
|
+
|
|
31
|
+
expect(nestedCalls).toBe(1);
|
|
32
|
+
expect(published.minX).toBe(1);
|
|
33
|
+
expect(published.minY).toBe(2);
|
|
34
|
+
expect(published.maxX).toBeCloseTo(3);
|
|
35
|
+
expect(published.maxY).toBeCloseTo(4);
|
|
36
|
+
});
|
|
37
|
+
|
|
9
38
|
it('publishes a body at its current pose', () => {
|
|
10
39
|
const world = createPhysics2DWorld(0, 0);
|
|
11
40
|
const body = createRigidBody2D('dynamic', 2, 3);
|
package/src/joints.test.ts
CHANGED
|
@@ -419,6 +419,51 @@ describe('joints built without their impulse accumulators', () => {
|
|
|
419
419
|
});
|
|
420
420
|
|
|
421
421
|
describe('physics2DDistanceJointSolver', () => {
|
|
422
|
+
it('keeps prepared axis and mass local when a joint getter prepares another world', () => {
|
|
423
|
+
const world = createPhysics2DWorld(0, 0);
|
|
424
|
+
const anchor = box(world, 'static', 0, 0);
|
|
425
|
+
const bob = box(world, 'dynamic', 2, 0);
|
|
426
|
+
const joint: Physics2DDistanceJoint = {
|
|
427
|
+
...baseJoint(Physics2DDistanceJointKind, anchor.index, bob.index),
|
|
428
|
+
length: 1,
|
|
429
|
+
frequencyHz: 0,
|
|
430
|
+
dampingRatio: 0,
|
|
431
|
+
};
|
|
432
|
+
|
|
433
|
+
const nestedWorld = createPhysics2DWorld(0, 0);
|
|
434
|
+
const nestedAnchor = box(nestedWorld, 'static', 0, 0);
|
|
435
|
+
const nestedBob = box(nestedWorld, 'dynamic', 0, 4);
|
|
436
|
+
const nestedJoint: Physics2DDistanceJoint = {
|
|
437
|
+
...baseJoint(Physics2DDistanceJointKind, nestedAnchor.index, nestedBob.index),
|
|
438
|
+
length: 3,
|
|
439
|
+
frequencyHz: 2,
|
|
440
|
+
dampingRatio: 0.5,
|
|
441
|
+
};
|
|
442
|
+
let impulse = 0;
|
|
443
|
+
let nestedCalls = 0;
|
|
444
|
+
Object.defineProperty(joint, 'impulse0', {
|
|
445
|
+
configurable: true,
|
|
446
|
+
enumerable: true,
|
|
447
|
+
get() {
|
|
448
|
+
if (nestedCalls === 0) {
|
|
449
|
+
nestedCalls++;
|
|
450
|
+
physics2DDistanceJointSolver.prepare(nestedWorld, nestedJoint, 1 / 60);
|
|
451
|
+
}
|
|
452
|
+
return impulse;
|
|
453
|
+
},
|
|
454
|
+
set(value: number) {
|
|
455
|
+
impulse = value;
|
|
456
|
+
},
|
|
457
|
+
});
|
|
458
|
+
|
|
459
|
+
physics2DDistanceJointSolver.prepare(world, joint, 1 / 60);
|
|
460
|
+
physics2DDistanceJointSolver.solve(world, joint);
|
|
461
|
+
|
|
462
|
+
expect(nestedCalls).toBe(1);
|
|
463
|
+
expect(bob.velocityX).toBeLessThan(0);
|
|
464
|
+
expect(bob.velocityY).toBeCloseTo(0);
|
|
465
|
+
});
|
|
466
|
+
|
|
422
467
|
it('holds a hanging body at the joint length instead of letting it fall', () => {
|
|
423
468
|
const world = createPhysics2DWorld();
|
|
424
469
|
registerPhysics2DJointSolver(world, Physics2DDistanceJointKind, physics2DDistanceJointSolver);
|
|
@@ -108,6 +108,37 @@ describe('computePhysics2DColliderMassData', () => {
|
|
|
108
108
|
});
|
|
109
109
|
|
|
110
110
|
describe('updateRigidBody2DMassData', () => {
|
|
111
|
+
it('keeps collider mass scratch isolated when a body getter updates another body', () => {
|
|
112
|
+
const target = body([collider({ kind: 'aabb', minX: -1, minY: -1, maxX: 1, maxY: 1 })]);
|
|
113
|
+
const nested = body([collider({ kind: 'circle', x: 10, y: 20, radius: 5 })]);
|
|
114
|
+
let centerX = 0;
|
|
115
|
+
let centerXReads = 0;
|
|
116
|
+
let nestedCalls = 0;
|
|
117
|
+
Object.defineProperty(target, 'centerX', {
|
|
118
|
+
configurable: true,
|
|
119
|
+
enumerable: true,
|
|
120
|
+
get() {
|
|
121
|
+
centerXReads++;
|
|
122
|
+
if (centerXReads === 1) {
|
|
123
|
+
nestedCalls++;
|
|
124
|
+
updateRigidBody2DMassData(nested);
|
|
125
|
+
}
|
|
126
|
+
return centerX;
|
|
127
|
+
},
|
|
128
|
+
set(value: number) {
|
|
129
|
+
centerX = value;
|
|
130
|
+
},
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
updateRigidBody2DMassData(target);
|
|
134
|
+
|
|
135
|
+
expect(nestedCalls).toBe(1);
|
|
136
|
+
expect(target.mass).toBeCloseTo(4);
|
|
137
|
+
expect(target.centerX).toBeCloseTo(0);
|
|
138
|
+
expect(target.centerY).toBeCloseTo(0);
|
|
139
|
+
expect(target.inertia).toBeCloseTo(8 / 3);
|
|
140
|
+
});
|
|
141
|
+
|
|
111
142
|
it('combines two colliders into one centre of mass and shifts their inertia onto it', () => {
|
|
112
143
|
const left = collider({ kind: 'aabb', minX: -3, minY: -1, maxX: -1, maxY: 1 });
|
|
113
144
|
const right = collider({ kind: 'aabb', minX: 1, minY: -1, maxX: 3, maxY: 1 });
|
package/src/step.test.ts
CHANGED
|
@@ -718,6 +718,29 @@ describe('sensor reporting between immovable bodies', () => {
|
|
|
718
718
|
});
|
|
719
719
|
|
|
720
720
|
describe('stepPhysics2D', () => {
|
|
721
|
+
it('keeps step scratch isolated when a broadphase callback steps another world', () => {
|
|
722
|
+
const world = createPhysics2DWorld(0, 0);
|
|
723
|
+
world.config.continuousCollision = false;
|
|
724
|
+
const fixed = ground(world);
|
|
725
|
+
const dynamic = box(world, 0, 0.4);
|
|
726
|
+
const nestedWorld = createPhysics2DWorld(0, 0);
|
|
727
|
+
nestedWorld.config.continuousCollision = false;
|
|
728
|
+
let nestedCalls = 0;
|
|
729
|
+
world.index.querySpatialPairs = (out) => {
|
|
730
|
+
out.length = 0;
|
|
731
|
+
out.push({ a: fixed.index, b: dynamic.index });
|
|
732
|
+
if (nestedCalls === 0) {
|
|
733
|
+
nestedCalls++;
|
|
734
|
+
stepPhysics2D(nestedWorld, 1 / 60);
|
|
735
|
+
}
|
|
736
|
+
};
|
|
737
|
+
|
|
738
|
+
stepPhysics2D(world, 1 / 60);
|
|
739
|
+
|
|
740
|
+
expect(nestedCalls).toBe(1);
|
|
741
|
+
expect(world.contacts).toHaveLength(1);
|
|
742
|
+
});
|
|
743
|
+
|
|
721
744
|
it('rejects invalid solver state before mutating the world', () => {
|
|
722
745
|
const world = createPhysics2DWorld();
|
|
723
746
|
const crate = box(world, 0, 2);
|
package/src/worldQueries.test.ts
CHANGED
|
@@ -39,6 +39,36 @@ describe('createPhysics2DRayResult', () => {
|
|
|
39
39
|
});
|
|
40
40
|
|
|
41
41
|
describe('queryPhysics2DPoint', () => {
|
|
42
|
+
it('keeps broadphase candidates isolated when a filter getter starts a nested query', () => {
|
|
43
|
+
const world = createPhysics2DWorld(0, 0);
|
|
44
|
+
const first = createRigidBody2D('dynamic', 0, 0);
|
|
45
|
+
const second = createRigidBody2D('dynamic', 0, 0);
|
|
46
|
+
first.colliders.push(createPhysics2DCollider({ kind: 'circle', radius: 1, x: 0, y: 0 }, STONE));
|
|
47
|
+
second.colliders.push(createPhysics2DCollider({ kind: 'circle', radius: 1, x: 0, y: 0 }, STONE));
|
|
48
|
+
addPhysics2DBody(world, first);
|
|
49
|
+
addPhysics2DBody(world, second);
|
|
50
|
+
const nestedWorld = createPhysics2DWorld(0, 0);
|
|
51
|
+
const filter = createPhysics2DQueryFilter();
|
|
52
|
+
let nestedCalls = 0;
|
|
53
|
+
Object.defineProperty(filter, 'includeDynamic', {
|
|
54
|
+
configurable: true,
|
|
55
|
+
enumerable: true,
|
|
56
|
+
get() {
|
|
57
|
+
if (nestedCalls === 0) {
|
|
58
|
+
nestedCalls++;
|
|
59
|
+
queryPhysics2DPoint(nestedWorld, 0, 0, createPhysics2DQueryResult());
|
|
60
|
+
}
|
|
61
|
+
return true;
|
|
62
|
+
},
|
|
63
|
+
});
|
|
64
|
+
const out = createPhysics2DQueryResult();
|
|
65
|
+
|
|
66
|
+
queryPhysics2DPoint(world, 0, 0, out, filter);
|
|
67
|
+
|
|
68
|
+
expect(nestedCalls).toBe(1);
|
|
69
|
+
expect(out.hits.slice(0, out.hitCount).map((hit) => hit.body)).toEqual([first, second]);
|
|
70
|
+
});
|
|
71
|
+
|
|
42
72
|
it('returns exact collider hits rather than broadphase-only body hits', () => {
|
|
43
73
|
const world = createPhysics2DWorld(0, 0);
|
|
44
74
|
const body = createRigidBody2D('dynamic', 0, 0, Math.PI / 4);
|