dacha 0.18.0-alpha.8 → 0.18.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/build/contrib/components/index.d.ts +1 -0
- package/build/contrib/components/index.js +1 -0
- package/build/contrib/components/interpolation/index.d.ts +85 -0
- package/build/contrib/components/interpolation/index.js +101 -0
- package/build/contrib/components/rigid-body/index.d.ts +108 -14
- package/build/contrib/components/rigid-body/index.js +191 -22
- package/build/contrib/systems/animator/index.d.ts +3 -2
- package/build/contrib/systems/animator/index.js +6 -3
- package/build/contrib/systems/behavior-system/system.d.ts +4 -2
- package/build/contrib/systems/behavior-system/system.js +11 -3
- package/build/contrib/systems/behavior-system/types.d.ts +7 -10
- package/build/contrib/systems/character-controller/index.d.ts +4 -2
- package/build/contrib/systems/character-controller/index.js +22 -17
- package/build/contrib/systems/character-controller/one-way-validator.d.ts +15 -0
- package/build/contrib/systems/character-controller/one-way-validator.js +73 -0
- package/build/contrib/systems/game-stats-meter/index.d.ts +4 -3
- package/build/contrib/systems/game-stats-meter/index.js +11 -10
- package/build/contrib/systems/index.d.ts +2 -0
- package/build/contrib/systems/index.js +1 -0
- package/build/contrib/systems/interpolator/api.d.ts +40 -0
- package/build/contrib/systems/interpolator/api.js +70 -0
- package/build/contrib/systems/interpolator/index.d.ts +3 -0
- package/build/contrib/systems/interpolator/index.js +2 -0
- package/build/contrib/systems/interpolator/system.d.ts +31 -0
- package/build/contrib/systems/interpolator/system.js +96 -0
- package/build/contrib/systems/interpolator/tests/helpers.d.ts +13 -0
- package/build/contrib/systems/interpolator/tests/helpers.js +45 -0
- package/build/contrib/systems/interpolator/utils.d.ts +5 -0
- package/build/contrib/systems/interpolator/utils.js +41 -0
- package/build/contrib/systems/physics-system/api.d.ts +45 -1
- package/build/contrib/systems/physics-system/api.js +49 -0
- package/build/contrib/systems/physics-system/consts.d.ts +13 -0
- package/build/contrib/systems/physics-system/consts.js +17 -0
- package/build/contrib/systems/physics-system/physics-system.d.ts +2 -2
- package/build/contrib/systems/physics-system/physics-system.js +24 -4
- package/build/contrib/systems/physics-system/subsystems/collision-detection/dynamic-aabb-tree/index.d.ts +1 -1
- package/build/contrib/systems/physics-system/subsystems/collision-detection/dynamic-aabb-tree/index.js +21 -15
- package/build/contrib/systems/physics-system/subsystems/collision-detection/index.d.ts +11 -11
- package/build/contrib/systems/physics-system/subsystems/collision-detection/index.js +133 -125
- package/build/contrib/systems/physics-system/subsystems/collision-detection/intersection-checkers/box-box/check-boxes-intersection.js +5 -3
- package/build/contrib/systems/physics-system/subsystems/collision-detection/intersection-checkers/box-box/utils.d.ts +1 -0
- package/build/contrib/systems/physics-system/subsystems/collision-detection/intersection-checkers/box-box/utils.js +2 -1
- package/build/contrib/systems/physics-system/subsystems/collision-detection/intersection-checkers/box-capsule/check-box-and-capsule-intersection.js +4 -1
- package/build/contrib/systems/physics-system/subsystems/collision-detection/intersection-checkers/box-segment/check-box-and-segment-intersection.js +4 -2
- package/build/contrib/systems/physics-system/subsystems/collision-detection/intersection-checkers/common/points.d.ts +2 -0
- package/build/contrib/systems/physics-system/subsystems/collision-detection/intersection-checkers/common/points.js +16 -0
- package/build/contrib/systems/physics-system/subsystems/collision-detection/intersection-checkers/index.js +2 -0
- package/build/contrib/systems/physics-system/subsystems/collision-detection/intersection-checkers/tests/helpers.js +3 -14
- package/build/contrib/systems/physics-system/subsystems/collision-detection/query-utils.d.ts +5 -0
- package/build/contrib/systems/physics-system/subsystems/collision-detection/query-utils.js +97 -81
- package/build/contrib/systems/physics-system/subsystems/collision-detection/shape-cast-checkers/tests/helpers.js +2 -7
- package/build/contrib/systems/physics-system/subsystems/collision-detection/tests/assertions.d.ts +1 -0
- package/build/contrib/systems/physics-system/subsystems/collision-detection/tests/assertions.js +7 -0
- package/build/contrib/systems/physics-system/subsystems/collision-detection/types.d.ts +0 -15
- package/build/contrib/systems/physics-system/subsystems/collision-detection/utils.d.ts +3 -0
- package/build/contrib/systems/physics-system/subsystems/collision-detection/utils.js +9 -0
- package/build/contrib/systems/physics-system/subsystems/constraint-solver/contact-state-manager.d.ts +63 -0
- package/build/contrib/systems/physics-system/subsystems/constraint-solver/contact-state-manager.js +170 -0
- package/build/contrib/systems/physics-system/subsystems/constraint-solver/contact-utils.d.ts +5 -0
- package/build/contrib/systems/physics-system/subsystems/constraint-solver/contact-utils.js +41 -0
- package/build/contrib/systems/physics-system/subsystems/constraint-solver/impulse-utils.d.ts +16 -0
- package/build/contrib/systems/physics-system/subsystems/constraint-solver/impulse-utils.js +77 -0
- package/build/contrib/systems/physics-system/subsystems/constraint-solver/index.d.ts +53 -4
- package/build/contrib/systems/physics-system/subsystems/constraint-solver/index.js +334 -116
- package/build/contrib/systems/physics-system/subsystems/constraint-solver/one-way-validator.d.ts +11 -0
- package/build/contrib/{utils → systems/physics-system/subsystems/constraint-solver}/one-way-validator.js +22 -25
- package/build/contrib/systems/physics-system/subsystems/constraint-solver/sleep-support-tracker.d.ts +13 -0
- package/build/contrib/systems/physics-system/subsystems/constraint-solver/sleep-support-tracker.js +42 -0
- package/build/contrib/systems/physics-system/subsystems/constraint-solver/tests/helpers.d.ts +4 -0
- package/build/contrib/systems/physics-system/subsystems/constraint-solver/tests/helpers.js +20 -0
- package/build/contrib/systems/physics-system/subsystems/physics/index.d.ts +15 -4
- package/build/contrib/systems/physics-system/subsystems/physics/index.js +131 -53
- package/build/contrib/systems/physics-system/subsystems/physics/mass-properties.d.ts +2 -0
- package/build/contrib/systems/physics-system/subsystems/physics/mass-properties.js +55 -0
- package/build/contrib/systems/physics-system/tests/helpers.d.ts +5 -2
- package/build/contrib/systems/physics-system/tests/helpers.js +11 -2
- package/build/contrib/systems/physics-system/types.d.ts +18 -2
- package/build/contrib/systems/renderer/actor-render-tree.js +15 -6
- package/build/contrib/systems/renderer/filters/index.d.ts +1 -1
- package/build/contrib/systems/renderer/filters/index.js +1 -1
- package/build/contrib/systems/renderer/material/index.d.ts +2 -1
- package/build/contrib/systems/renderer/material/index.js +1 -1
- package/build/contrib/systems/renderer/renderer.d.ts +2 -2
- package/build/contrib/systems/renderer/renderer.js +3 -4
- package/build/contrib/systems/renderer/types.d.ts +0 -3
- package/build/engine/data-lib/index.d.ts +1 -1
- package/build/engine/data-lib/index.js +1 -1
- package/build/engine/data-lib/pool.d.ts +9 -0
- package/build/engine/data-lib/pool.js +19 -0
- package/build/engine/engine.js +4 -1
- package/build/engine/game-loop.d.ts +3 -1
- package/build/engine/game-loop.js +11 -8
- package/build/engine/math-lib/math/ops.d.ts +16 -0
- package/build/engine/math-lib/math/ops.js +25 -0
- package/build/engine/scene/scene-manager.d.ts +4 -1
- package/build/engine/scene/scene-manager.js +5 -1
- package/build/engine/system/index.d.ts +1 -1
- package/build/engine/system/system.d.ts +10 -11
- package/build/engine/system/system.js +5 -2
- package/build/engine/time.d.ts +54 -0
- package/build/engine/time.js +77 -0
- package/build/index.d.ts +2 -1
- package/package.json +1 -1
- package/build/contrib/systems/physics-system/subsystems/collision-detection/dispersion-calculator/index.d.ts +0 -11
- package/build/contrib/systems/physics-system/subsystems/collision-detection/dispersion-calculator/index.js +0 -41
- package/build/contrib/utils/one-way-validator.d.ts +0 -12
- package/build/engine/data-lib/sort/index.d.ts +0 -1
- package/build/engine/data-lib/sort/index.js +0 -1
- package/build/engine/data-lib/sort/insertion-sort.d.ts +0 -1
- package/build/engine/data-lib/sort/insertion-sort.js +0 -14
|
@@ -1,47 +1,42 @@
|
|
|
1
1
|
import { ActorQuery } from '../../../../../engine/actor';
|
|
2
|
-
import { Transform, Collider
|
|
2
|
+
import { Transform, Collider } from '../../../../components';
|
|
3
3
|
import { AddActor, RemoveActor } from '../../../../../engine/events';
|
|
4
|
-
import {
|
|
4
|
+
import { Pool } from '../../../../../engine/data-lib';
|
|
5
5
|
import { DynamicAABBTree } from './dynamic-aabb-tree';
|
|
6
6
|
import { geometryBuilders } from './geometry-builders';
|
|
7
7
|
import { aabbBuilders } from './aabb-builders';
|
|
8
8
|
import { intersectionCheckers } from './intersection-checkers';
|
|
9
|
-
import { DispersionCalculator } from './dispersion-calculator';
|
|
10
9
|
import { checkTransform, checkCollider, getOrientationData, } from './reorientation-checkers';
|
|
11
|
-
import { buildQueryProxy, buildActorQueryProxy, raycast, raycastAll, overlap, getOverlapQueryType, shapeCast, shapeCastAll, getShapeCastQueryType, getActorCastQueryType, } from './query-utils';
|
|
10
|
+
import { buildQueryProxy, buildActorQueryProxy, raycast, raycastAll, raycastEach, overlap, overlapEach, getOverlapQueryType, shapeCast, shapeCastAll, shapeCastEach, getShapeCastQueryType, getActorCastQueryType, makeCastHit, makeOverlapHit, } from './query-utils';
|
|
11
|
+
import { isStatic, isDisabled } from './utils';
|
|
12
12
|
export class CollisionDetectionSubsystem {
|
|
13
13
|
actorQuery;
|
|
14
|
-
axis;
|
|
15
14
|
queryTree;
|
|
16
15
|
proxiesByActorId;
|
|
17
16
|
proxyPairs;
|
|
18
17
|
contacts;
|
|
19
18
|
actorIdsToDelete;
|
|
20
19
|
collisionMatrix;
|
|
21
|
-
|
|
20
|
+
candidateBufferPool;
|
|
21
|
+
castHitPool;
|
|
22
|
+
overlapHitPool;
|
|
22
23
|
constructor(options) {
|
|
23
24
|
const settings = options.globalOptions.physics;
|
|
24
25
|
this.actorQuery = new ActorQuery({
|
|
25
26
|
scene: options.scene,
|
|
26
27
|
filter: [Collider, Transform],
|
|
27
28
|
});
|
|
28
|
-
this.axis = {
|
|
29
|
-
x: {
|
|
30
|
-
sortedList: [],
|
|
31
|
-
dispersionCalculator: new DispersionCalculator('x'),
|
|
32
|
-
},
|
|
33
|
-
y: {
|
|
34
|
-
sortedList: [],
|
|
35
|
-
dispersionCalculator: new DispersionCalculator('y'),
|
|
36
|
-
},
|
|
37
|
-
};
|
|
38
29
|
this.queryTree = new DynamicAABBTree();
|
|
39
30
|
this.proxiesByActorId = new Map();
|
|
40
31
|
this.proxyPairs = [];
|
|
41
32
|
this.contacts = [];
|
|
42
33
|
this.actorIdsToDelete = new Set();
|
|
43
34
|
this.collisionMatrix = settings?.collisionMatrix ?? {};
|
|
44
|
-
this.
|
|
35
|
+
this.candidateBufferPool = new Pool(() => [], (buffer) => {
|
|
36
|
+
buffer.length = 0;
|
|
37
|
+
});
|
|
38
|
+
this.castHitPool = new Pool(makeCastHit);
|
|
39
|
+
this.overlapHitPool = new Pool(makeOverlapHit);
|
|
45
40
|
this.actorQuery.getActors().forEach((actor) => this.addProxy(actor));
|
|
46
41
|
this.actorQuery.addEventListener(AddActor, this.handleActorAdd);
|
|
47
42
|
this.actorQuery.addEventListener(RemoveActor, this.handleActorRemove);
|
|
@@ -54,18 +49,15 @@ export class CollisionDetectionSubsystem {
|
|
|
54
49
|
}
|
|
55
50
|
raycast(params) {
|
|
56
51
|
const queryProxy = buildQueryProxy('ray', params);
|
|
57
|
-
this.
|
|
58
|
-
return raycast(queryProxy, this.queryCandidates);
|
|
52
|
+
return this.withCandidates(queryProxy, (candidates) => raycast(queryProxy, candidates));
|
|
59
53
|
}
|
|
60
54
|
raycastAll(params) {
|
|
61
55
|
const queryProxy = buildQueryProxy('ray', params);
|
|
62
|
-
this.
|
|
63
|
-
return raycastAll(queryProxy, this.queryCandidates);
|
|
56
|
+
return this.withCandidates(queryProxy, (candidates) => raycastAll(queryProxy, candidates));
|
|
64
57
|
}
|
|
65
58
|
overlapShape(params) {
|
|
66
59
|
const queryProxy = buildQueryProxy(params.shape.type, params);
|
|
67
|
-
this.
|
|
68
|
-
return overlap(params.shape.type, queryProxy, this.queryCandidates);
|
|
60
|
+
return this.withCandidates(queryProxy, (candidates) => overlap(params.shape.type, queryProxy, candidates));
|
|
69
61
|
}
|
|
70
62
|
overlapActor(params) {
|
|
71
63
|
const queryType = getOverlapQueryType(params);
|
|
@@ -73,20 +65,17 @@ export class CollisionDetectionSubsystem {
|
|
|
73
65
|
return [];
|
|
74
66
|
}
|
|
75
67
|
const queryProxy = buildActorQueryProxy(queryType, params);
|
|
76
|
-
this.
|
|
77
|
-
return overlap(queryType, queryProxy, this.queryCandidates);
|
|
68
|
+
return this.withCandidates(queryProxy, (candidates) => overlap(queryType, queryProxy, candidates));
|
|
78
69
|
}
|
|
79
70
|
shapeCast(params) {
|
|
80
71
|
const queryType = getShapeCastQueryType(params);
|
|
81
72
|
const queryProxy = buildQueryProxy(queryType, params);
|
|
82
|
-
this.
|
|
83
|
-
return shapeCast(queryType, queryProxy, this.queryCandidates);
|
|
73
|
+
return this.withCandidates(queryProxy, (candidates) => shapeCast(queryType, queryProxy, candidates));
|
|
84
74
|
}
|
|
85
75
|
shapeCastAll(params) {
|
|
86
76
|
const queryType = getShapeCastQueryType(params);
|
|
87
77
|
const queryProxy = buildQueryProxy(queryType, params);
|
|
88
|
-
this.
|
|
89
|
-
return shapeCastAll(queryType, queryProxy, this.queryCandidates);
|
|
78
|
+
return this.withCandidates(queryProxy, (candidates) => shapeCastAll(queryType, queryProxy, candidates));
|
|
90
79
|
}
|
|
91
80
|
castActor(params) {
|
|
92
81
|
const queryType = getActorCastQueryType(params);
|
|
@@ -94,8 +83,7 @@ export class CollisionDetectionSubsystem {
|
|
|
94
83
|
return null;
|
|
95
84
|
}
|
|
96
85
|
const queryProxy = buildActorQueryProxy(queryType, params);
|
|
97
|
-
this.
|
|
98
|
-
return shapeCast(queryType, queryProxy, this.queryCandidates);
|
|
86
|
+
return this.withCandidates(queryProxy, (candidates) => shapeCast(queryType, queryProxy, candidates));
|
|
99
87
|
}
|
|
100
88
|
castActorAll(params) {
|
|
101
89
|
const queryType = getActorCastQueryType(params);
|
|
@@ -103,8 +91,76 @@ export class CollisionDetectionSubsystem {
|
|
|
103
91
|
return [];
|
|
104
92
|
}
|
|
105
93
|
const queryProxy = buildActorQueryProxy(queryType, params);
|
|
106
|
-
this.
|
|
107
|
-
|
|
94
|
+
return this.withCandidates(queryProxy, (candidates) => shapeCastAll(queryType, queryProxy, candidates));
|
|
95
|
+
}
|
|
96
|
+
raycastEach(params, callback) {
|
|
97
|
+
const queryProxy = buildQueryProxy('ray', params);
|
|
98
|
+
this.withCandidates(queryProxy, (candidates) => {
|
|
99
|
+
const hit = this.castHitPool.acquire();
|
|
100
|
+
try {
|
|
101
|
+
raycastEach(queryProxy, candidates, hit, callback);
|
|
102
|
+
}
|
|
103
|
+
finally {
|
|
104
|
+
this.castHitPool.release(hit);
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
shapeCastEach(params, callback) {
|
|
109
|
+
const queryType = getShapeCastQueryType(params);
|
|
110
|
+
const queryProxy = buildQueryProxy(queryType, params);
|
|
111
|
+
this.withCandidates(queryProxy, (candidates) => {
|
|
112
|
+
const hit = this.castHitPool.acquire();
|
|
113
|
+
try {
|
|
114
|
+
shapeCastEach(queryType, queryProxy, candidates, hit, callback);
|
|
115
|
+
}
|
|
116
|
+
finally {
|
|
117
|
+
this.castHitPool.release(hit);
|
|
118
|
+
}
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
overlapEach(params, callback) {
|
|
122
|
+
const queryProxy = buildQueryProxy(params.shape.type, params);
|
|
123
|
+
this.withCandidates(queryProxy, (candidates) => {
|
|
124
|
+
const hit = this.overlapHitPool.acquire();
|
|
125
|
+
try {
|
|
126
|
+
overlapEach(params.shape.type, queryProxy, candidates, hit, callback);
|
|
127
|
+
}
|
|
128
|
+
finally {
|
|
129
|
+
this.overlapHitPool.release(hit);
|
|
130
|
+
}
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
castActorEach(params, callback) {
|
|
134
|
+
const queryType = getActorCastQueryType(params);
|
|
135
|
+
if (!queryType) {
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
const queryProxy = buildActorQueryProxy(queryType, params);
|
|
139
|
+
this.withCandidates(queryProxy, (candidates) => {
|
|
140
|
+
const hit = this.castHitPool.acquire();
|
|
141
|
+
try {
|
|
142
|
+
shapeCastEach(queryType, queryProxy, candidates, hit, callback);
|
|
143
|
+
}
|
|
144
|
+
finally {
|
|
145
|
+
this.castHitPool.release(hit);
|
|
146
|
+
}
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
overlapActorEach(params, callback) {
|
|
150
|
+
const queryType = getOverlapQueryType(params);
|
|
151
|
+
if (!queryType) {
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
const queryProxy = buildActorQueryProxy(queryType, params);
|
|
155
|
+
this.withCandidates(queryProxy, (candidates) => {
|
|
156
|
+
const hit = this.overlapHitPool.acquire();
|
|
157
|
+
try {
|
|
158
|
+
overlapEach(queryType, queryProxy, candidates, hit, callback);
|
|
159
|
+
}
|
|
160
|
+
finally {
|
|
161
|
+
this.overlapHitPool.release(hit);
|
|
162
|
+
}
|
|
163
|
+
});
|
|
108
164
|
}
|
|
109
165
|
handleActorAdd = (event) => {
|
|
110
166
|
this.addProxy(event.actor);
|
|
@@ -138,10 +194,6 @@ export class CollisionDetectionSubsystem {
|
|
|
138
194
|
layer: collider.layer,
|
|
139
195
|
};
|
|
140
196
|
proxy.treeEntryId = this.queryTree.insert(aabb, proxy);
|
|
141
|
-
this.axis.x.dispersionCalculator.addToSample(aabb);
|
|
142
|
-
this.addToSortedList(proxy, 'x');
|
|
143
|
-
this.axis.y.dispersionCalculator.addToSample(aabb);
|
|
144
|
-
this.addToSortedList(proxy, 'y');
|
|
145
197
|
this.proxiesByActorId.set(actor.id, proxy);
|
|
146
198
|
}
|
|
147
199
|
updateProxy(actor) {
|
|
@@ -150,70 +202,34 @@ export class CollisionDetectionSubsystem {
|
|
|
150
202
|
const geometry = geometryBuilders[collider.shape.type](collider, transform);
|
|
151
203
|
const aabb = aabbBuilders[collider.shape.type](geometry);
|
|
152
204
|
const proxy = this.proxiesByActorId.get(actor.id);
|
|
153
|
-
const prevAABB = proxy.aabb;
|
|
154
205
|
proxy.aabb = aabb;
|
|
155
206
|
proxy.geometry = geometry;
|
|
156
207
|
proxy.orientationData = getOrientationData(actor);
|
|
157
208
|
proxy.layer = collider.layer;
|
|
158
209
|
this.queryTree.update(proxy.treeEntryId, aabb);
|
|
159
|
-
this.axis.x.dispersionCalculator.removeFromSample(prevAABB);
|
|
160
|
-
this.axis.x.dispersionCalculator.addToSample(aabb);
|
|
161
|
-
this.updateSortedList(proxy, 'x');
|
|
162
|
-
this.axis.y.dispersionCalculator.removeFromSample(prevAABB);
|
|
163
|
-
this.axis.y.dispersionCalculator.addToSample(aabb);
|
|
164
|
-
this.updateSortedList(proxy, 'y');
|
|
165
|
-
}
|
|
166
|
-
addToSortedList(proxy, axis) {
|
|
167
|
-
const min = { value: proxy.aabb.min[axis], proxy };
|
|
168
|
-
const max = { value: proxy.aabb.max[axis], proxy };
|
|
169
|
-
this.axis[axis].sortedList.push(min, max);
|
|
170
|
-
proxy.edges ??= {};
|
|
171
|
-
proxy.edges[axis] = [min, max];
|
|
172
|
-
}
|
|
173
|
-
updateSortedList(proxy, axis) {
|
|
174
|
-
const [min, max] = proxy.edges[axis];
|
|
175
|
-
min.value = proxy.aabb.min[axis];
|
|
176
|
-
min.proxy = proxy;
|
|
177
|
-
max.value = proxy.aabb.max[axis];
|
|
178
|
-
max.proxy = proxy;
|
|
179
|
-
}
|
|
180
|
-
clearSortedList(axis) {
|
|
181
|
-
this.axis[axis].sortedList = this.axis[axis].sortedList.filter((item) => !this.actorIdsToDelete.has(item.proxy.actor.id));
|
|
182
|
-
}
|
|
183
|
-
getAxes() {
|
|
184
|
-
const xDispersion = this.axis.x.dispersionCalculator.getDispersion();
|
|
185
|
-
const yDispersion = this.axis.y.dispersionCalculator.getDispersion();
|
|
186
|
-
return xDispersion >= yDispersion ? ['x', 'y'] : ['y', 'x'];
|
|
187
|
-
}
|
|
188
|
-
areStaticBodies(proxy1, proxy2) {
|
|
189
|
-
const { actor: actor1 } = proxy1;
|
|
190
|
-
const { actor: actor2 } = proxy2;
|
|
191
|
-
const rigidBody1 = actor1.getComponent(RigidBody);
|
|
192
|
-
const rigidBody2 = actor2.getComponent(RigidBody);
|
|
193
|
-
return rigidBody1?.type === 'static' && rigidBody2?.type === 'static';
|
|
194
|
-
}
|
|
195
|
-
testAABB(proxy1, proxy2, axis) {
|
|
196
|
-
const aabb1 = proxy1.aabb;
|
|
197
|
-
const aabb2 = proxy2.aabb;
|
|
198
|
-
return (aabb1.max[axis] >= aabb2.min[axis] && aabb1.min[axis] <= aabb2.max[axis]);
|
|
199
210
|
}
|
|
200
211
|
testCollisionLayers(proxy1, proxy2) {
|
|
201
|
-
return this.collisionMatrix[proxy1.layer]?.[proxy2.layer] ??
|
|
212
|
+
return (this.collisionMatrix[proxy1.layer]?.[proxy2.layer] ??
|
|
213
|
+
this.collisionMatrix[proxy2.layer]?.[proxy1.layer] ??
|
|
214
|
+
true);
|
|
202
215
|
}
|
|
203
|
-
|
|
204
|
-
const
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
216
|
+
withCandidates(queryProxy, run) {
|
|
217
|
+
const candidates = this.candidateBufferPool.acquire();
|
|
218
|
+
try {
|
|
219
|
+
this.collectQueryCandidates(queryProxy, candidates);
|
|
220
|
+
return run(candidates);
|
|
221
|
+
}
|
|
222
|
+
finally {
|
|
223
|
+
this.candidateBufferPool.release(candidates);
|
|
224
|
+
}
|
|
209
225
|
}
|
|
210
|
-
collectQueryCandidates(queryProxy) {
|
|
226
|
+
collectQueryCandidates(queryProxy, out) {
|
|
211
227
|
let candidateIndex = 0;
|
|
212
228
|
this.queryTree.query(queryProxy.aabb, (proxy) => {
|
|
213
229
|
if (queryProxy.excludedActors?.has(proxy.actor)) {
|
|
214
230
|
return;
|
|
215
231
|
}
|
|
216
|
-
if (
|
|
232
|
+
if (isDisabled(proxy)) {
|
|
217
233
|
return;
|
|
218
234
|
}
|
|
219
235
|
if (queryProxy.layer !== undefined &&
|
|
@@ -223,44 +239,40 @@ export class CollisionDetectionSubsystem {
|
|
|
223
239
|
if (queryProxy.actorFilter && !queryProxy.actorFilter(proxy.actor)) {
|
|
224
240
|
return;
|
|
225
241
|
}
|
|
226
|
-
|
|
242
|
+
out[candidateIndex] = proxy;
|
|
227
243
|
candidateIndex += 1;
|
|
228
244
|
});
|
|
229
|
-
|
|
245
|
+
out.length = candidateIndex;
|
|
230
246
|
}
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
let proxyPairIndex = 0;
|
|
237
|
-
for (const item of sortedList) {
|
|
238
|
-
const { proxy } = item;
|
|
239
|
-
if (!activeProxies.has(proxy)) {
|
|
240
|
-
activeProxies.forEach((activeProxy) => {
|
|
241
|
-
if (!this.testState(proxy, activeProxy)) {
|
|
242
|
-
return;
|
|
243
|
-
}
|
|
244
|
-
if (!this.testAABB(proxy, activeProxy, secondAxis)) {
|
|
245
|
-
return;
|
|
246
|
-
}
|
|
247
|
-
if (this.areStaticBodies(proxy, activeProxy)) {
|
|
248
|
-
return;
|
|
249
|
-
}
|
|
250
|
-
if (!this.testCollisionLayers(proxy, activeProxy)) {
|
|
251
|
-
return;
|
|
252
|
-
}
|
|
253
|
-
this.proxyPairs[proxyPairIndex] = [proxy, activeProxy];
|
|
254
|
-
proxyPairIndex += 1;
|
|
255
|
-
});
|
|
256
|
-
activeProxies.add(proxy);
|
|
247
|
+
collectPairs() {
|
|
248
|
+
let pairIndex = 0;
|
|
249
|
+
this.proxiesByActorId.forEach((proxy) => {
|
|
250
|
+
if (isStatic(proxy)) {
|
|
251
|
+
return;
|
|
257
252
|
}
|
|
258
|
-
|
|
259
|
-
|
|
253
|
+
if (isDisabled(proxy)) {
|
|
254
|
+
return;
|
|
260
255
|
}
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
256
|
+
this.queryTree.query(proxy.aabb, (other) => {
|
|
257
|
+
if (other === proxy) {
|
|
258
|
+
return;
|
|
259
|
+
}
|
|
260
|
+
// Deduplicate dynamic-dynamic pairs
|
|
261
|
+
if (!isStatic(other) && proxy.treeEntryId >= other.treeEntryId) {
|
|
262
|
+
return;
|
|
263
|
+
}
|
|
264
|
+
if (isDisabled(other)) {
|
|
265
|
+
return;
|
|
266
|
+
}
|
|
267
|
+
if (!this.testCollisionLayers(proxy, other)) {
|
|
268
|
+
return;
|
|
269
|
+
}
|
|
270
|
+
this.proxyPairs[pairIndex] = [proxy, other];
|
|
271
|
+
pairIndex += 1;
|
|
272
|
+
});
|
|
273
|
+
});
|
|
274
|
+
if (this.proxyPairs.length > pairIndex) {
|
|
275
|
+
this.proxyPairs.length = pairIndex;
|
|
264
276
|
}
|
|
265
277
|
}
|
|
266
278
|
checkOnIntersection(proxyPair) {
|
|
@@ -291,13 +303,9 @@ export class CollisionDetectionSubsystem {
|
|
|
291
303
|
if (this.actorIdsToDelete.size === 0) {
|
|
292
304
|
return;
|
|
293
305
|
}
|
|
294
|
-
this.clearSortedList('x');
|
|
295
|
-
this.clearSortedList('y');
|
|
296
306
|
this.actorIdsToDelete.forEach((id) => {
|
|
297
307
|
const proxy = this.proxiesByActorId.get(id);
|
|
298
308
|
this.queryTree.remove(proxy.treeEntryId);
|
|
299
|
-
this.axis.x.dispersionCalculator.removeFromSample(proxy.aabb);
|
|
300
|
-
this.axis.y.dispersionCalculator.removeFromSample(proxy.aabb);
|
|
301
309
|
this.proxiesByActorId.delete(id);
|
|
302
310
|
});
|
|
303
311
|
this.actorIdsToDelete.clear();
|
|
@@ -310,7 +318,7 @@ export class CollisionDetectionSubsystem {
|
|
|
310
318
|
}
|
|
311
319
|
this.updateProxy(actor);
|
|
312
320
|
});
|
|
313
|
-
this.
|
|
321
|
+
this.collectPairs();
|
|
314
322
|
let contactIndex = 0;
|
|
315
323
|
this.proxyPairs.forEach((proxyPair) => {
|
|
316
324
|
const intersection = this.checkOnIntersection(proxyPair);
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { orientNormal } from '../common/normals';
|
|
2
|
-
import {
|
|
2
|
+
import { sortPoints } from '../common/points';
|
|
3
|
+
import { findMinBoxesOverlap, buildContactPoints, OVERLAP_TIE_EPSILON, } from './utils';
|
|
3
4
|
/**
|
|
4
5
|
* Checks box colliders for intersection.
|
|
5
6
|
*
|
|
@@ -17,7 +18,7 @@ export const checkBoxesIntersection = (geometry1, geometry2) => {
|
|
|
17
18
|
if (overlap2 === false) {
|
|
18
19
|
return false;
|
|
19
20
|
}
|
|
20
|
-
const isArg1Reference = overlap1.overlap <= overlap2.overlap;
|
|
21
|
+
const isArg1Reference = overlap1.overlap <= overlap2.overlap + OVERLAP_TIE_EPSILON;
|
|
21
22
|
const referenceGeometry = isArg1Reference ? geometry1 : geometry2;
|
|
22
23
|
const incidentGeometry = isArg1Reference ? geometry2 : geometry1;
|
|
23
24
|
const referenceOverlap = isArg1Reference ? overlap1 : overlap2;
|
|
@@ -26,9 +27,10 @@ export const checkBoxesIntersection = (geometry1, geometry2) => {
|
|
|
26
27
|
if (!isArg1Reference) {
|
|
27
28
|
referenceNormal.multiplyNumber(-1);
|
|
28
29
|
}
|
|
30
|
+
const contactPoints = buildContactPoints(referenceGeometry, referenceNormal, incidentGeometry);
|
|
29
31
|
return {
|
|
30
32
|
normal,
|
|
31
33
|
penetration: referenceOverlap.overlap,
|
|
32
|
-
contactPoints:
|
|
34
|
+
contactPoints: sortPoints(contactPoints, normal),
|
|
33
35
|
};
|
|
34
36
|
};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Vector2 } from '../../../../../../../engine/math-lib';
|
|
2
2
|
import type { BoxGeometry, Point } from '../../types';
|
|
3
3
|
export declare const CONTACT_EPSILON = 0.0001;
|
|
4
|
+
export declare const OVERLAP_TIE_EPSILON = 0.0001;
|
|
4
5
|
export declare const MAX_CONTACT_POINTS = 2;
|
|
5
6
|
export interface AxisOverlap {
|
|
6
7
|
axis: Vector2;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Vector2, VectorOps } from '../../../../../../../engine/math-lib';
|
|
2
2
|
import { getProjectionOverlap, projectPolygon } from '../common/projections';
|
|
3
3
|
export const CONTACT_EPSILON = 1e-4;
|
|
4
|
+
export const OVERLAP_TIE_EPSILON = 1e-4;
|
|
4
5
|
export const MAX_CONTACT_POINTS = 2;
|
|
5
6
|
/**
|
|
6
7
|
* Runs the SAT pass for one box's face normals against another box.
|
|
@@ -22,7 +23,7 @@ export const findMinBoxesOverlap = (geometry1, geometry2) => {
|
|
|
22
23
|
if (overlap === false) {
|
|
23
24
|
return false;
|
|
24
25
|
}
|
|
25
|
-
if (overlap < minOverlap) {
|
|
26
|
+
if (overlap < minOverlap - OVERLAP_TIE_EPSILON) {
|
|
26
27
|
minOverlap = overlap;
|
|
27
28
|
bestAxis = axis;
|
|
28
29
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { orientNormal } from '../common/normals';
|
|
2
|
+
import { sortPoints } from '../common/points';
|
|
2
3
|
import { buildBoxCapsuleIntersection } from './utils';
|
|
3
4
|
/**
|
|
4
5
|
* Checks a box against a capsule.
|
|
@@ -23,8 +24,10 @@ export const checkBoxAndCapsuleIntersection = (box, capsule) => {
|
|
|
23
24
|
if (!intersection) {
|
|
24
25
|
return false;
|
|
25
26
|
}
|
|
27
|
+
const normal = orientNormal(intersection.normal, box.center, capsule.center);
|
|
26
28
|
return {
|
|
27
29
|
...intersection,
|
|
28
|
-
normal
|
|
30
|
+
normal,
|
|
31
|
+
contactPoints: sortPoints(intersection.contactPoints, normal),
|
|
29
32
|
};
|
|
30
33
|
};
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { buildBoxSegmentContactPoints, findMinBoxSegmentOverlap, } from './utils';
|
|
2
2
|
import { orientNormal } from '../common/normals';
|
|
3
|
+
import { sortPoints } from '../common/points';
|
|
3
4
|
/**
|
|
4
5
|
* Checks a box against a segment.
|
|
5
6
|
*
|
|
@@ -17,9 +18,10 @@ export const checkBoxAndSegmentIntersection = (box, segment) => {
|
|
|
17
18
|
if (contactPoints.length === 0) {
|
|
18
19
|
return false;
|
|
19
20
|
}
|
|
21
|
+
const normal = orientNormal(overlap.axis.clone(), box.center, segment.center);
|
|
20
22
|
return {
|
|
21
|
-
normal
|
|
23
|
+
normal,
|
|
22
24
|
penetration: overlap.overlap,
|
|
23
|
-
contactPoints,
|
|
25
|
+
contactPoints: sortPoints(contactPoints, normal),
|
|
24
26
|
};
|
|
25
27
|
};
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
+
import type { Vector2 } from '../../../../../../../engine/math-lib';
|
|
1
2
|
import type { Point } from '../../types';
|
|
2
3
|
export declare const arePointsEqual: (point1: Point, point2: Point) => boolean;
|
|
3
4
|
export declare const lerpPoint: (point1: Point, point2: Point, value: number) => Point;
|
|
4
5
|
export declare const getDistanceSquared: (point1: Point, point2: Point) => number;
|
|
6
|
+
export declare const sortPoints: (points: Point[], normal: Vector2) => Point[];
|
|
@@ -5,3 +5,19 @@ export const lerpPoint = (point1, point2, value) => ({
|
|
|
5
5
|
y: point1.y + (point2.y - point1.y) * value,
|
|
6
6
|
});
|
|
7
7
|
export const getDistanceSquared = (point1, point2) => (point1.x - point2.x) ** 2 + (point1.y - point2.y) ** 2;
|
|
8
|
+
export const sortPoints = (points, normal) => {
|
|
9
|
+
if (points.length !== 2) {
|
|
10
|
+
return points;
|
|
11
|
+
}
|
|
12
|
+
const tangentX = -normal.y;
|
|
13
|
+
const tangentY = normal.x;
|
|
14
|
+
const projection1 = points[0].x * tangentX + points[0].y * tangentY;
|
|
15
|
+
const projection2 = points[1].x * tangentX + points[1].y * tangentY;
|
|
16
|
+
if (projection1 <= projection2) {
|
|
17
|
+
return points;
|
|
18
|
+
}
|
|
19
|
+
const point = points[0];
|
|
20
|
+
points[0] = points[1];
|
|
21
|
+
points[1] = point;
|
|
22
|
+
return points;
|
|
23
|
+
};
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { sortPoints } from './common/points';
|
|
1
2
|
import { checkBoxAndCapsuleIntersection } from './box-capsule/check-box-and-capsule-intersection';
|
|
2
3
|
import { checkBoxAndCircleIntersection } from './box-circle/check-box-and-circle-intersection';
|
|
3
4
|
import { checkBoxAndSegmentIntersection } from './box-segment/check-box-and-segment-intersection';
|
|
@@ -18,6 +19,7 @@ const swapArgs = (checker) => {
|
|
|
18
19
|
return false;
|
|
19
20
|
}
|
|
20
21
|
intersection.normal.multiplyNumber(-1);
|
|
22
|
+
sortPoints(intersection.contactPoints, intersection.normal);
|
|
21
23
|
return intersection;
|
|
22
24
|
};
|
|
23
25
|
};
|
|
@@ -5,6 +5,7 @@ import { buildCircleGeometry } from '../../geometry-builders/build-circle-geomet
|
|
|
5
5
|
import { buildPointGeometry } from '../../geometry-builders/build-point-geometry';
|
|
6
6
|
import { buildRayGeometry } from '../../geometry-builders/build-ray-geometry';
|
|
7
7
|
import { buildSegmentGeometry } from '../../geometry-builders/build-segment-geometry';
|
|
8
|
+
import { expectHit } from '../../tests/assertions';
|
|
8
9
|
export const createBoxGeometry = (centerX, centerY, sizeX, sizeY) => {
|
|
9
10
|
return createRotatedBoxGeometry(centerX, centerY, sizeX, sizeY, 0);
|
|
10
11
|
};
|
|
@@ -71,20 +72,8 @@ export const expectToBeClose = (point, x, y, digits = 6) => {
|
|
|
71
72
|
expect(point.x).toBeCloseTo(x, digits);
|
|
72
73
|
expect(point.y).toBeCloseTo(y, digits);
|
|
73
74
|
};
|
|
74
|
-
export const expectIntersection = (intersection) =>
|
|
75
|
-
|
|
76
|
-
if (intersection === false) {
|
|
77
|
-
throw new Error('Expected intersection, received false');
|
|
78
|
-
}
|
|
79
|
-
return intersection;
|
|
80
|
-
};
|
|
81
|
-
export const expectCastHit = (hit) => {
|
|
82
|
-
expect(hit).not.toBe(false);
|
|
83
|
-
if (hit === false) {
|
|
84
|
-
throw new Error('Expected cast hit, received false');
|
|
85
|
-
}
|
|
86
|
-
return hit;
|
|
87
|
-
};
|
|
75
|
+
export const expectIntersection = (intersection) => expectHit(intersection, 'intersection');
|
|
76
|
+
export const expectCastHit = (hit) => expectHit(hit, 'cast hit');
|
|
88
77
|
export const sortPoints = (points) => [...points].sort((point1, point2) => {
|
|
89
78
|
if (point1.x !== point2.x) {
|
|
90
79
|
return point1.x - point2.x;
|
package/build/contrib/systems/physics-system/subsystems/collision-detection/query-utils.d.ts
CHANGED
|
@@ -10,9 +10,14 @@ export declare function buildActorQueryProxy(type: OverlapQueryType, params: Ove
|
|
|
10
10
|
export declare const getOverlapQueryType: (params: OverlapActorParams) => OverlapQueryType | null;
|
|
11
11
|
export declare const getShapeCastQueryType: (params: ShapeCastParams) => ShapeCastQueryType;
|
|
12
12
|
export declare const getActorCastQueryType: (params: CastActorParams) => ShapeCastQueryType | null;
|
|
13
|
+
export declare const makeCastHit: () => CastHit;
|
|
14
|
+
export declare const makeOverlapHit: () => OverlapHit;
|
|
13
15
|
export declare const overlap: (type: OverlapQueryType, queryProxy: QueryProxy, proxies: Iterable<ActorProxy>) => OverlapHit[];
|
|
14
16
|
export declare const raycast: (queryProxy: QueryProxy, proxies: Iterable<ActorProxy>) => CastHit | null;
|
|
15
17
|
export declare const raycastAll: (queryProxy: QueryProxy, proxies: Iterable<ActorProxy>) => CastHit[];
|
|
16
18
|
export declare const shapeCast: (type: ShapeCastQueryType, queryProxy: QueryProxy, proxies: Iterable<ActorProxy>) => CastHit | null;
|
|
17
19
|
export declare const shapeCastAll: (type: ShapeCastQueryType, queryProxy: QueryProxy, proxies: Iterable<ActorProxy>) => CastHit[];
|
|
20
|
+
export declare const raycastEach: (queryProxy: QueryProxy, proxies: Iterable<ActorProxy>, hit: CastHit, callback: (hit: CastHit) => void) => void;
|
|
21
|
+
export declare const shapeCastEach: (type: ShapeCastQueryType, queryProxy: QueryProxy, proxies: Iterable<ActorProxy>, hit: CastHit, callback: (hit: CastHit) => void) => void;
|
|
22
|
+
export declare const overlapEach: (type: OverlapQueryType, queryProxy: QueryProxy, proxies: Iterable<ActorProxy>, hit: OverlapHit, callback: (hit: OverlapHit) => void) => void;
|
|
18
23
|
export {};
|