@perplexdotgg/bounce 1.0.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/LICENSE +21 -0
- package/README.md +30 -0
- package/package.json +32 -0
- package/src/builders/ConvexHullBuilder.ts +437 -0
- package/src/builders/ConvexHullBuilder2d.ts +344 -0
- package/src/builders/ConvexHullBuilder3d.ts +1689 -0
- package/src/builders/HeightMapBuilder.ts +414 -0
- package/src/builders/TriangleMeshBuilder.ts +92 -0
- package/src/collision/CastShapesModule.ts +184 -0
- package/src/collision/CollideShapesModule.ts +152 -0
- package/src/collision/HeightMapCaster.ts +38 -0
- package/src/collision/HeightMapCollider.ts +33 -0
- package/src/collision/TriangleCaster.ts +249 -0
- package/src/collision/TriangleCollider.ts +308 -0
- package/src/collision/TriangleCollider2.ts +379 -0
- package/src/collision/activeEdge.ts +146 -0
- package/src/collision/cast/cast.ts +139 -0
- package/src/collision/cast/castCompoundVsCompound.ts +59 -0
- package/src/collision/cast/castCompoundVsConvex.ts +116 -0
- package/src/collision/cast/castConvexVsCompound.ts +123 -0
- package/src/collision/cast/castConvexVsConvex.ts +213 -0
- package/src/collision/cast/castConvexVsHeightMap.ts +73 -0
- package/src/collision/cast/castConvexVsTriangleMesh.ts +56 -0
- package/src/collision/cast/castRayVsCompound.ts +44 -0
- package/src/collision/cast/castRayVsConvex.ts +45 -0
- package/src/collision/cast/castRayVsHeightMap.ts +58 -0
- package/src/collision/cast/castRayVsTriangleMesh.ts +58 -0
- package/src/collision/closestPoints/closestPoints.ts +23 -0
- package/src/collision/closestPoints/computeBarycentricCoordinates2d.ts +32 -0
- package/src/collision/closestPoints/computeBarycentricCoordinates3d.ts +81 -0
- package/src/collision/closestPoints/computeClosestPointOnLine.ts +30 -0
- package/src/collision/closestPoints/computeClosestPointOnTetrahedron.ts +96 -0
- package/src/collision/closestPoints/computeClosestPointOnTriangle.ts +195 -0
- package/src/collision/closestPoints/isOriginOutsideOfPlane.ts +25 -0
- package/src/collision/closestPoints/isOriginOutsideOfTrianglePlanes.ts +72 -0
- package/src/collision/collide/collide.ts +146 -0
- package/src/collision/collide/collideCompoundVsCompound.ts +60 -0
- package/src/collision/collide/collideCompoundVsConvex.ts +59 -0
- package/src/collision/collide/collideCompoundVsHeightMap.ts +73 -0
- package/src/collision/collide/collideCompoundVsTriangleMesh.ts +56 -0
- package/src/collision/collide/collideConvexVsCompound.ts +57 -0
- package/src/collision/collide/collideConvexVsConvex.ts +225 -0
- package/src/collision/collide/collideConvexVsConvexImp.ts +236 -0
- package/src/collision/collide/collideConvexVsHeightMap.ts +53 -0
- package/src/collision/collide/collideConvexVsTriangleMesh.ts +58 -0
- package/src/collision/collide/collideHeightMapVsCompound.ts +69 -0
- package/src/collision/collide/collideHeightMapVsConvex.ts +53 -0
- package/src/collision/collide/collideSphereVsSphere.ts +81 -0
- package/src/collision/collide/collideTriangleMeshVsCompound.ts +58 -0
- package/src/collision/collide/collideTriangleMeshVsConvex.ts +58 -0
- package/src/collision/epa/EpaConvexHullBuilder.ts +397 -0
- package/src/collision/epa/StaticArray.ts +154 -0
- package/src/collision/epa/TriangleFactory.ts +32 -0
- package/src/collision/epa/arrays.ts +99 -0
- package/src/collision/epa/binaryHeap.ts +82 -0
- package/src/collision/epa/structs.ts +227 -0
- package/src/collision/gjk/GjkModule.ts +864 -0
- package/src/collision/gjk/PenetrationDepthModule.ts +493 -0
- package/src/collision/gjk/SupportPoints.ts +50 -0
- package/src/collision/imp/MinkowskiDifference.ts +36 -0
- package/src/collision/imp/computeExploredDistanceLowerUpperBound.ts +40 -0
- package/src/collision/imp/finalizeImpResult.ts +69 -0
- package/src/collision/imp/findContactImp.ts +196 -0
- package/src/collision/imp/imp.ts +28 -0
- package/src/collision/imp/incrementalMinimumDistanceExploreDirection.ts +207 -0
- package/src/collision/mpr/findPortal.ts +152 -0
- package/src/collision/mpr/mpr.ts +29 -0
- package/src/collision/mpr/updatePortal.ts +52 -0
- package/src/constraints/BaseConstraint.ts +50 -0
- package/src/constraints/ConstraintOptions.ts +22 -0
- package/src/constraints/ConstraintSolver.ts +119 -0
- package/src/constraints/DistanceConstraint.ts +229 -0
- package/src/constraints/FixedConstraint.ts +203 -0
- package/src/constraints/HingeConstraint.ts +460 -0
- package/src/constraints/PointConstraint.ts +108 -0
- package/src/constraints/components/AngleComponent.ts +226 -0
- package/src/constraints/components/AxisComponent.ts +263 -0
- package/src/constraints/components/HingeComponent.ts +215 -0
- package/src/constraints/components/Motor.ts +36 -0
- package/src/constraints/components/PointConstraintComponent.ts +179 -0
- package/src/constraints/components/RotationEulerComponent.ts +139 -0
- package/src/constraints/components/Spring.ts +30 -0
- package/src/constraints/components/SpringComponent.ts +71 -0
- package/src/constraints/types.ts +6 -0
- package/src/helpers.ts +147 -0
- package/src/index.ts +50 -0
- package/src/math/BasicTransform.ts +19 -0
- package/src/math/NumberValue.ts +13 -0
- package/src/math/isometry.ts +64 -0
- package/src/math/mat3.ts +529 -0
- package/src/math/mat4.ts +588 -0
- package/src/math/quat.ts +193 -0
- package/src/math/scalar.ts +81 -0
- package/src/math/tensor.ts +17 -0
- package/src/math/vec3.ts +589 -0
- package/src/math/vec4.ts +10 -0
- package/src/physics/Body.ts +581 -0
- package/src/physics/CollisionFilter.ts +52 -0
- package/src/physics/SleepModule.ts +163 -0
- package/src/physics/broadphase/BodyPairsModule.ts +363 -0
- package/src/physics/broadphase/BvhModule.ts +237 -0
- package/src/physics/broadphase/BvhTree.ts +803 -0
- package/src/physics/broadphase/ConstraintPairsModule.ts +385 -0
- package/src/physics/broadphase/TriangleMeshBvhTree.ts +379 -0
- package/src/physics/manifold/ContactManifold.ts +227 -0
- package/src/physics/manifold/ContactManifoldModule.ts +623 -0
- package/src/physics/manifold/Face.ts +119 -0
- package/src/physics/manifold/ManifoldCache.ts +116 -0
- package/src/physics/manifold/clipping/clipPolyVsEdge.ts +131 -0
- package/src/physics/manifold/clipping/clipPolyVsPlane.ts +73 -0
- package/src/physics/manifold/clipping/clipPolyVsPoly.ts +72 -0
- package/src/physics/narrowphase/CollideBodiesModule.ts +755 -0
- package/src/physics/solver/ContactConstraintModule.ts +659 -0
- package/src/physics/solver/ManifoldConstraint.ts +420 -0
- package/src/physics/solver/estimateCollisionResponse.ts +146 -0
- package/src/shape/Aabb.ts +400 -0
- package/src/shape/Box.ts +231 -0
- package/src/shape/Capsule.ts +332 -0
- package/src/shape/CompoundShape.ts +288 -0
- package/src/shape/Convex.ts +130 -0
- package/src/shape/ConvexHull.ts +423 -0
- package/src/shape/Cylinder.ts +313 -0
- package/src/shape/HeightMap.ts +511 -0
- package/src/shape/Line.ts +14 -0
- package/src/shape/Plane.ts +116 -0
- package/src/shape/Ray.ts +81 -0
- package/src/shape/Segment.ts +25 -0
- package/src/shape/Shape.ts +77 -0
- package/src/shape/Sphere.ts +181 -0
- package/src/shape/TransformedShape.ts +51 -0
- package/src/shape/Triangle.ts +122 -0
- package/src/shape/TriangleMesh.ts +186 -0
- package/src/types.ts +1 -0
- package/src/world.ts +1335 -0
- package/tests/BodyPairsModule.test.ts +71 -0
- package/tests/BvhTree.test.ts +406 -0
- package/tests/test.md +642 -0
- package/tests/vec3.test.ts +12 -0
- package/tsconfig.json +20 -0
- package/vite.config.js +40 -0
|
@@ -0,0 +1,755 @@
|
|
|
1
|
+
import { destroyAllInstancesInPool } from "../../helpers";
|
|
2
|
+
import { degreesToRadians, squared } from "../../math/scalar";
|
|
3
|
+
import { Vec3 } from "../../math/vec3";
|
|
4
|
+
import { Body, BodyType } from "../Body";
|
|
5
|
+
import {
|
|
6
|
+
ActiveEdgeMode,
|
|
7
|
+
CollectFacesMode,
|
|
8
|
+
CollisionCollector,
|
|
9
|
+
CollisionResult,
|
|
10
|
+
CollisionSettings,
|
|
11
|
+
} from "../../collision/collide/collide";
|
|
12
|
+
import { CollideShapesModule } from "../../collision/CollideShapesModule";
|
|
13
|
+
import { ContactConstraintModule } from "../../physics/solver/ContactConstraintModule";
|
|
14
|
+
import { ContactManifold, ContactManifoldPool, createContactPairKey } from "../manifold/ContactManifold";
|
|
15
|
+
import { ContactManifoldModule } from "../manifold/ContactManifoldModule";
|
|
16
|
+
import { SleepModule } from "../../physics/SleepModule";
|
|
17
|
+
import { Shape, ShapeType } from "../../shape/Shape";
|
|
18
|
+
import { Isometry } from "../../math/isometry";
|
|
19
|
+
import { HeightMap } from "../../shape/HeightMap";
|
|
20
|
+
import { Aabb } from "../../shape/Aabb";
|
|
21
|
+
import type { World } from "../../world";
|
|
22
|
+
import { CastCollector, CastResult, CastSettings, RayCastSettings } from "../../collision/cast/cast";
|
|
23
|
+
import { CastShapesModule } from "../../collision/CastShapesModule";
|
|
24
|
+
import { AllFlag } from "../CollisionFilter";
|
|
25
|
+
import { Quat } from "../../math/quat";
|
|
26
|
+
import { Ray } from "../../shape/Ray";
|
|
27
|
+
import { estimateCollisionResponse, EstimateCollisionResponseResult } from "../solver/estimateCollisionResponse";
|
|
28
|
+
|
|
29
|
+
const manifolds = /*@__PURE__*/ new ContactManifoldPool(32, 64);
|
|
30
|
+
|
|
31
|
+
const inverseOrientationA = /*@__PURE__*/ Quat.create();
|
|
32
|
+
|
|
33
|
+
export interface CollideBodiesSettings {
|
|
34
|
+
speculativeContactDistance: number;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const worldSpaceNormal = /*@__PURE__*/ Vec3.create();
|
|
38
|
+
const negatedWorldSpaceNormal = /*@__PURE__*/ Vec3.create();
|
|
39
|
+
const zeroVector = /*@__PURE__*/ Vec3.create({ x: 0, y: 0, z: 0 });
|
|
40
|
+
|
|
41
|
+
const centerOfMassAInWorldSpace = /*@__PURE__*/ Vec3.create();
|
|
42
|
+
const isometryWorldToB = /*@__PURE__*/ Isometry.create();
|
|
43
|
+
const projectedPointInB = /*@__PURE__*/ Vec3.create();
|
|
44
|
+
const projectedPointOnHeightMap = /*@__PURE__*/ Vec3.create();
|
|
45
|
+
|
|
46
|
+
const isometryA = /*@__PURE__*/ Isometry.create();
|
|
47
|
+
const isometryB = /*@__PURE__*/ Isometry.create();
|
|
48
|
+
const offset = /*@__PURE__*/ Vec3.create();
|
|
49
|
+
const negatedOffset = /*@__PURE__*/ Vec3.create();
|
|
50
|
+
const projectedPosition = /*@__PURE__*/ Vec3.create();
|
|
51
|
+
const centerOfMassAInB = /*@__PURE__*/ Vec3.create();
|
|
52
|
+
const linearVelocityBA = /*@__PURE__*/ Vec3.create();
|
|
53
|
+
|
|
54
|
+
class CollideBodiesCollector extends CollisionCollector {
|
|
55
|
+
numHits: number;
|
|
56
|
+
settings: CollideBodiesSettings;
|
|
57
|
+
contactManifoldModule: ContactManifoldModule;
|
|
58
|
+
bodyA: Body | null;
|
|
59
|
+
bodyB: Body | null;
|
|
60
|
+
|
|
61
|
+
constructor(contactManifoldModule: ContactManifoldModule) {
|
|
62
|
+
super();
|
|
63
|
+
this.numHits = 0;
|
|
64
|
+
this.settings = { speculativeContactDistance: 0.02 };
|
|
65
|
+
this.contactManifoldModule = contactManifoldModule;
|
|
66
|
+
this.bodyA = null;
|
|
67
|
+
this.bodyB = null;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
init(settings: CollideBodiesSettings, bodyA: Body, bodyB: Body): this {
|
|
71
|
+
this.reset();
|
|
72
|
+
this.numHits = 0;
|
|
73
|
+
this.settings = settings;
|
|
74
|
+
this.bodyA = bodyA;
|
|
75
|
+
this.bodyB = bodyB;
|
|
76
|
+
|
|
77
|
+
destroyAllInstancesInPool(manifolds.contactManifoldPool);
|
|
78
|
+
return this;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
addHit(result: CollisionResult): void {
|
|
82
|
+
this.numHits++;
|
|
83
|
+
|
|
84
|
+
const bodyA = this.bodyA!;
|
|
85
|
+
const bodyB = this.bodyB!;
|
|
86
|
+
|
|
87
|
+
// get the normal
|
|
88
|
+
worldSpaceNormal.normalizeVector(result.normalA); // TODO: or B?
|
|
89
|
+
|
|
90
|
+
// check if we can add the contact point
|
|
91
|
+
const maxDeltaCosAngle = Math.cos(degreesToRadians(5));
|
|
92
|
+
|
|
93
|
+
// iterate over all manifolds
|
|
94
|
+
let reachedEndWithoutAdding = true;
|
|
95
|
+
let newManifold: ContactManifold | null = null;
|
|
96
|
+
for (const manifold of manifolds.contactManifoldPool) {
|
|
97
|
+
if (worldSpaceNormal.dot(manifold.firstWorldSpaceNormal) >= maxDeltaCosAngle) {
|
|
98
|
+
// we can add it
|
|
99
|
+
manifold.worldSpaceNormal.addVector(worldSpaceNormal);
|
|
100
|
+
manifold.penetrationDepth = Math.max(manifold.penetrationDepth, result.penetration);
|
|
101
|
+
reachedEndWithoutAdding = false;
|
|
102
|
+
newManifold = manifold;
|
|
103
|
+
break;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
if (reachedEndWithoutAdding) {
|
|
108
|
+
// TODO handle trimesh
|
|
109
|
+
|
|
110
|
+
// case: full manifolds, replace the one with the least penetration depth if possible
|
|
111
|
+
if (manifolds.contactManifoldPool.length === manifolds.contactManifoldPool.maxLength) {
|
|
112
|
+
let minPenetrationDepth = Infinity;
|
|
113
|
+
// let minPenetrationDepthId = -1;
|
|
114
|
+
let minPenetrationDepthManifold: ContactManifold | null = null;
|
|
115
|
+
|
|
116
|
+
// iterate over all manifolds
|
|
117
|
+
for (const manifold of manifolds.contactManifoldPool) {
|
|
118
|
+
if (manifold.penetrationDepth < minPenetrationDepth) {
|
|
119
|
+
minPenetrationDepth = manifold.penetrationDepth;
|
|
120
|
+
minPenetrationDepthManifold = manifold;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// get the manifold with the least penetration depth
|
|
125
|
+
if (!minPenetrationDepthManifold) {
|
|
126
|
+
throw new Error("minPenetrationDepthManifold is null");
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// case: result penetration is less than the minimum penetration depth, skip this result
|
|
130
|
+
if (result.penetration > minPenetrationDepth) {
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// case: replace the manifold with the least penetration depth
|
|
135
|
+
minPenetrationDepthManifold.destroy();
|
|
136
|
+
newManifold = manifolds.createContactManifold({
|
|
137
|
+
bodyA: bodyA,
|
|
138
|
+
bodyB: bodyB,
|
|
139
|
+
subShapeIdA: result.subShapeIdA,
|
|
140
|
+
subShapeIdB: result.subShapeIdB,
|
|
141
|
+
nextContactManifold: null,
|
|
142
|
+
|
|
143
|
+
baseTranslation: { x: 0, y: 0, z: 0 },
|
|
144
|
+
firstWorldSpaceNormal: worldSpaceNormal,
|
|
145
|
+
worldSpaceNormal: worldSpaceNormal,
|
|
146
|
+
penetrationDepth: result.penetration,
|
|
147
|
+
numContacts: 0,
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
// case: room to add a new manifold
|
|
151
|
+
else {
|
|
152
|
+
newManifold = manifolds.createContactManifold({
|
|
153
|
+
bodyA: bodyA,
|
|
154
|
+
bodyB: bodyB,
|
|
155
|
+
subShapeIdA: result.subShapeIdA,
|
|
156
|
+
subShapeIdB: result.subShapeIdB,
|
|
157
|
+
nextContactManifold: null,
|
|
158
|
+
|
|
159
|
+
baseTranslation: { x: 0, y: 0, z: 0 },
|
|
160
|
+
firstWorldSpaceNormal: worldSpaceNormal,
|
|
161
|
+
worldSpaceNormal: worldSpaceNormal,
|
|
162
|
+
penetrationDepth: result.penetration,
|
|
163
|
+
numContacts: 0,
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
if (!newManifold) {
|
|
169
|
+
throw new Error("newManifold is null");
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// add contact point
|
|
173
|
+
// get the supporting faces
|
|
174
|
+
negatedWorldSpaceNormal.negateVector(worldSpaceNormal);
|
|
175
|
+
zeroVector.zero();
|
|
176
|
+
|
|
177
|
+
if (result.faceA.numVertices === 0) {
|
|
178
|
+
bodyA!.computeSupportingFace(result.faceA, result.subShapeIdA, negatedWorldSpaceNormal, zeroVector);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
if (result.faceB.numVertices === 0) {
|
|
182
|
+
bodyB!.computeSupportingFace(result.faceB, result.subShapeIdB, worldSpaceNormal, zeroVector);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
const penetrationTolerance = 1e-3;
|
|
186
|
+
// const penetrationToleranceSquared = squared(penetrationTolerance);
|
|
187
|
+
// const speculativeContactDistanceSquared = squared(this.settings.speculativeContactDistance);
|
|
188
|
+
// const maxContactDistancedSquared = speculativeContactDistanceSquared + penetrationToleranceSquared;
|
|
189
|
+
|
|
190
|
+
result.contactPointA.addVector(result.bodyA!.computedCenterOfMassPosition);
|
|
191
|
+
result.contactPointB.addVector(result.bodyA!.computedCenterOfMassPosition);
|
|
192
|
+
// newManifold.baseTranslation.copy(bodyA.computedCenterOfMassPosition);
|
|
193
|
+
|
|
194
|
+
this.contactManifoldModule.manifoldBetweenTwoFaces(
|
|
195
|
+
result.contactPointA,
|
|
196
|
+
result.contactPointB,
|
|
197
|
+
worldSpaceNormal, // TODO: A or B?
|
|
198
|
+
// maxContactDistancedSquared,
|
|
199
|
+
this.settings.speculativeContactDistance + 1e-3,
|
|
200
|
+
result.faceA,
|
|
201
|
+
result.faceB,
|
|
202
|
+
newManifold
|
|
203
|
+
);
|
|
204
|
+
|
|
205
|
+
// prune if more than 32 contact points
|
|
206
|
+
if (newManifold.numContacts > 32) {
|
|
207
|
+
this.contactManifoldModule.pruneContactPoints(newManifold.firstWorldSpaceNormal, newManifold);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
export class CollideBodiesModule {
|
|
213
|
+
world: World;
|
|
214
|
+
collideShapesModule: CollideShapesModule;
|
|
215
|
+
castShapesModule: CastShapesModule;
|
|
216
|
+
contactManifoldModule: ContactManifoldModule;
|
|
217
|
+
contactConstraintModule: ContactConstraintModule;
|
|
218
|
+
sleepModule: SleepModule;
|
|
219
|
+
|
|
220
|
+
collector: CollideBodiesCollector;
|
|
221
|
+
|
|
222
|
+
constructor(
|
|
223
|
+
world: World,
|
|
224
|
+
collideShapesModule: CollideShapesModule,
|
|
225
|
+
castShapesModule: CastShapesModule,
|
|
226
|
+
contactManifoldModule: ContactManifoldModule,
|
|
227
|
+
contactConstraintModule: ContactConstraintModule,
|
|
228
|
+
sleepModule: SleepModule
|
|
229
|
+
) {
|
|
230
|
+
this.world = world;
|
|
231
|
+
this.collideShapesModule = collideShapesModule;
|
|
232
|
+
this.castShapesModule = castShapesModule;
|
|
233
|
+
this.contactManifoldModule = contactManifoldModule;
|
|
234
|
+
this.contactConstraintModule = contactConstraintModule;
|
|
235
|
+
this.sleepModule = sleepModule;
|
|
236
|
+
|
|
237
|
+
this.collector = new CollideBodiesCollector(contactManifoldModule);
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* checks for collisions between two bodies. assumes bodyA is always dynamic. bodyB can be any type
|
|
242
|
+
*/
|
|
243
|
+
collideBodies(
|
|
244
|
+
// onCollide: (manifold: ContactManifold) => void,
|
|
245
|
+
bodyA: Body,
|
|
246
|
+
bodyB: Body,
|
|
247
|
+
collideShapesSettings: CollisionSettings,
|
|
248
|
+
collideBodiesSettings: CollideBodiesSettings,
|
|
249
|
+
timeStepSizeSeconds: number,
|
|
250
|
+
isWarmStartingEnabled: boolean,
|
|
251
|
+
minVelocityForElasticContact: number
|
|
252
|
+
) {
|
|
253
|
+
// TODO: pass use persistent contacts as a parameter?
|
|
254
|
+
let usePersistentContacts: boolean;
|
|
255
|
+
usePersistentContacts = true;
|
|
256
|
+
usePersistentContacts = false;
|
|
257
|
+
let pairHandled = false;
|
|
258
|
+
let constraintCreated = false;
|
|
259
|
+
|
|
260
|
+
if (usePersistentContacts) {
|
|
261
|
+
[pairHandled, constraintCreated] = this.contactManifoldModule.getContactsFromCache(
|
|
262
|
+
bodyA,
|
|
263
|
+
bodyB,
|
|
264
|
+
this.contactConstraintModule,
|
|
265
|
+
this.sleepModule,
|
|
266
|
+
isWarmStartingEnabled,
|
|
267
|
+
timeStepSizeSeconds,
|
|
268
|
+
minVelocityForElasticContact
|
|
269
|
+
);
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
// exit if pair handled by persistent contacts
|
|
273
|
+
if (pairHandled) {
|
|
274
|
+
// TODO: add bodies-in-contact for contact constraint contact baumgarte multiplier
|
|
275
|
+
return;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
linearVelocityBA.subtractVectors(bodyA.linearVelocity, bodyB.linearVelocity);
|
|
279
|
+
collideShapesSettings.activeEdgeMovementDirectionX = linearVelocityBA.x;
|
|
280
|
+
collideShapesSettings.activeEdgeMovementDirectionY = linearVelocityBA.y;
|
|
281
|
+
collideShapesSettings.activeEdgeMovementDirectionZ = linearVelocityBA.z;
|
|
282
|
+
collideShapesSettings.maxSeparation = collideBodiesSettings.speculativeContactDistance;
|
|
283
|
+
// collideShapesSettings.collectFacesMode = CollectFacesMode.CollectFaces;
|
|
284
|
+
collideShapesSettings.activeEdgeMode = ActiveEdgeMode.CollideOnlyWithActive;
|
|
285
|
+
|
|
286
|
+
offset.copy(bodyA.computedCenterOfMassPosition);
|
|
287
|
+
negatedOffset.negateVector(offset);
|
|
288
|
+
isometryA.matrix.fromQuat(bodyA.orientation);
|
|
289
|
+
isometryB.fromRotationAndTranslation(bodyB.orientation, bodyB.computedCenterOfMassPosition);
|
|
290
|
+
isometryB.matrix.postTranslated(negatedOffset);
|
|
291
|
+
|
|
292
|
+
// TODO: handle trimesh
|
|
293
|
+
this.collector.init(collideBodiesSettings, bodyA, bodyB);
|
|
294
|
+
this.collideShapesModule.collideShapes(
|
|
295
|
+
this.collector,
|
|
296
|
+
bodyA.shape!,
|
|
297
|
+
isometryA,
|
|
298
|
+
bodyB.shape!,
|
|
299
|
+
isometryB,
|
|
300
|
+
collideShapesSettings,
|
|
301
|
+
bodyA,
|
|
302
|
+
bodyB,
|
|
303
|
+
0,
|
|
304
|
+
0
|
|
305
|
+
);
|
|
306
|
+
|
|
307
|
+
if (this.collector.numHits < 1) {
|
|
308
|
+
return;
|
|
309
|
+
|
|
310
|
+
// code below was an attempt to fix tunneling through heightmaps, but it caused some problems so it's disabled for now
|
|
311
|
+
|
|
312
|
+
// case: no contact found between shape and non-heightmap, we're really done
|
|
313
|
+
if (bodyB.shape!.type !== ShapeType.heightMap) {
|
|
314
|
+
// this.world.tracker.timeEnd("compute contact manifolds");
|
|
315
|
+
return;
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
if (bodyA.shape!.type === ShapeType.triangleMesh) {
|
|
319
|
+
// this.world.tracker.timeEnd("compute contact manifolds");
|
|
320
|
+
return;
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
// case: no contact found between shape and heightmap triangles
|
|
324
|
+
// check if bodyA center of mass is above the heightmap
|
|
325
|
+
|
|
326
|
+
projectedPosition.addScaledToVector(
|
|
327
|
+
bodyA.computedCenterOfMassPosition,
|
|
328
|
+
bodyA.linearVelocity,
|
|
329
|
+
timeStepSizeSeconds
|
|
330
|
+
);
|
|
331
|
+
centerOfMassAInWorldSpace.copy(projectedPosition);
|
|
332
|
+
isometryWorldToB.matrix.fromInverseRotationAndTranslation(bodyB.orientation, bodyB.computedCenterOfMassPosition);
|
|
333
|
+
projectedPointInB.transformVectorFromMat4(centerOfMassAInWorldSpace, isometryWorldToB.matrix);
|
|
334
|
+
centerOfMassAInB.transformVectorFromMat4(bodyA.computedCenterOfMassPosition, isometryWorldToB.matrix);
|
|
335
|
+
|
|
336
|
+
const interpolatedHeight = (bodyB.shape as unknown as HeightMap).computeInterpolatedHeight(projectedPointInB);
|
|
337
|
+
|
|
338
|
+
// case: bodyA center of mass is above the heightmap surface and no contact was found, we're really done
|
|
339
|
+
if (projectedPointInB.y >= interpolatedHeight) {
|
|
340
|
+
// this.world.tracker.timeEnd("compute contact manifolds");
|
|
341
|
+
return;
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
// case: bodyA center of mass is below the heightmap surface and no contact was found, it has tunneled through the heightmap
|
|
345
|
+
|
|
346
|
+
projectedPointOnHeightMap.copy(centerOfMassAInB);
|
|
347
|
+
projectedPointOnHeightMap.y = interpolatedHeight + 1e-1;
|
|
348
|
+
isometryWorldToB.inverseTransformPoint(projectedPointOnHeightMap); // tx from b to world
|
|
349
|
+
|
|
350
|
+
// update the broadphase. TODO: does this need to happen here?
|
|
351
|
+
// this.world.broadphaseModule.moveBody(bodyA.cachedComboId);
|
|
352
|
+
bodyA.markBodyAsDirty();
|
|
353
|
+
bodyA.computedCenterOfMassPosition.copy(projectedPointOnHeightMap);
|
|
354
|
+
|
|
355
|
+
// update the isometry
|
|
356
|
+
offset.copy(bodyA.computedCenterOfMassPosition);
|
|
357
|
+
negatedOffset.negateVector(offset);
|
|
358
|
+
isometryA.matrix.fromQuat(bodyA.orientation);
|
|
359
|
+
isometryB.fromRotationAndTranslation(bodyB.orientation, bodyB.computedCenterOfMassPosition);
|
|
360
|
+
isometryB.matrix.postTranslated(negatedOffset);
|
|
361
|
+
|
|
362
|
+
// re-run the collision detection (TODO: what impact does this have on any other contacts this body has made?)
|
|
363
|
+
this.collector.init(collideBodiesSettings, bodyA, bodyB);
|
|
364
|
+
this.collideShapesModule.collideShapes(
|
|
365
|
+
this.collector,
|
|
366
|
+
bodyA.shape!,
|
|
367
|
+
isometryA,
|
|
368
|
+
bodyB.shape!,
|
|
369
|
+
isometryB,
|
|
370
|
+
collideShapesSettings,
|
|
371
|
+
bodyA,
|
|
372
|
+
bodyB,
|
|
373
|
+
0,
|
|
374
|
+
0
|
|
375
|
+
);
|
|
376
|
+
|
|
377
|
+
// if still no contact, we're really done
|
|
378
|
+
if (this.collector.numHits === 0) {
|
|
379
|
+
// this.world.tracker.timeEnd("compute contact manifolds");
|
|
380
|
+
return;
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
// if we're here, we've applied the tunneling fix, found a contact, and should fall-through to the contact processing steps
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
const pair = this.contactManifoldModule.addContactPair(bodyA, bodyB);
|
|
387
|
+
// store the current relative translation to use for next frame's contact cache evaluation
|
|
388
|
+
inverseOrientationA.conjugateQuat(bodyA.orientation); // we're able to conjugate instead of invert because it's a unit quaternion
|
|
389
|
+
pair.translationAB.subtractVectors(bodyB.computedCenterOfMassPosition, bodyA.computedCenterOfMassPosition);
|
|
390
|
+
pair.translationAB.transformVectorByQuat(pair.translationAB, inverseOrientationA);
|
|
391
|
+
// TODO: add bodies-in-contact for contact constraint contact baumgarte multiplier
|
|
392
|
+
|
|
393
|
+
// iterate over all collected manifolds
|
|
394
|
+
for (const manifold of manifolds.contactManifoldPool) {
|
|
395
|
+
manifold.worldSpaceNormal.normalize();
|
|
396
|
+
|
|
397
|
+
if (manifold.numContacts > 4) {
|
|
398
|
+
this.contactManifoldModule.pruneContactPoints(manifold.worldSpaceNormal, manifold);
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
if (manifold.numContacts < 1) {
|
|
402
|
+
throw new Error("manifold has no contacts");
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
this.contactConstraintModule.addContactConstraints(
|
|
406
|
+
bodyA,
|
|
407
|
+
bodyB,
|
|
408
|
+
manifold,
|
|
409
|
+
timeStepSizeSeconds,
|
|
410
|
+
isWarmStartingEnabled,
|
|
411
|
+
minVelocityForElasticContact
|
|
412
|
+
);
|
|
413
|
+
|
|
414
|
+
// onCollide(manifold);
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
collideShape(
|
|
419
|
+
inShape: Shape,
|
|
420
|
+
inShapeScale: number,
|
|
421
|
+
inCenterOfMassTransform: Isometry,
|
|
422
|
+
ioCollector: CollisionCollector,
|
|
423
|
+
inCollideShapeSettings: CollisionSettings,
|
|
424
|
+
inbaseTranslation?: Vec3,
|
|
425
|
+
mask: number = AllFlag
|
|
426
|
+
): void {
|
|
427
|
+
// TODO: handle other shapes
|
|
428
|
+
// TODO: handle non-static bodies
|
|
429
|
+
// iterate over all static bodies
|
|
430
|
+
|
|
431
|
+
// offset isometry A by the negated base offset
|
|
432
|
+
if (inbaseTranslation) {
|
|
433
|
+
offset.negateVector(inbaseTranslation);
|
|
434
|
+
} else {
|
|
435
|
+
offset.zero();
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
isometryA.matrix.postTranslatedMatrix(inCenterOfMassTransform.matrix, offset);
|
|
439
|
+
|
|
440
|
+
// get shapeA world bounds
|
|
441
|
+
|
|
442
|
+
boundsA.copy(inShape.computedAabb);
|
|
443
|
+
// expand the bounds by the max separation distance
|
|
444
|
+
boundsA.expand(inCollideShapeSettings ? inCollideShapeSettings.maxSeparation : 0.0);
|
|
445
|
+
// transform the bounds to world space
|
|
446
|
+
boundsA.transform(inCenterOfMassTransform);
|
|
447
|
+
|
|
448
|
+
collideShapeVisitor.initialize(
|
|
449
|
+
isometryA,
|
|
450
|
+
isometryB,
|
|
451
|
+
ioCollector,
|
|
452
|
+
this.collideShapesModule,
|
|
453
|
+
inShape,
|
|
454
|
+
offset,
|
|
455
|
+
ioCollector,
|
|
456
|
+
inCollideShapeSettings
|
|
457
|
+
);
|
|
458
|
+
const group = AllFlag; // CollisionFilter.AllFlag
|
|
459
|
+
this.world.broadphase.visitBodiesWithCollision(collideShapeVisitor, boundsA, group, mask);
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
castShape(
|
|
463
|
+
inShape: Shape,
|
|
464
|
+
inShapeScale: number,
|
|
465
|
+
inCenterOfMassTransform: Isometry,
|
|
466
|
+
inDisplacement: Vec3,
|
|
467
|
+
inShapeCastSettings: CastSettings,
|
|
468
|
+
inbaseTranslation: Vec3,
|
|
469
|
+
ioCollector: CastCollector,
|
|
470
|
+
mask: number = AllFlag
|
|
471
|
+
// mask: number = CollisionFilter.AllFlag
|
|
472
|
+
) {
|
|
473
|
+
// TODO: handle other shapes
|
|
474
|
+
// TODO: handle non-static bodies
|
|
475
|
+
// iterate over all static bodies
|
|
476
|
+
|
|
477
|
+
const castModule = this.castShapesModule;
|
|
478
|
+
|
|
479
|
+
// get shapeA world bounds
|
|
480
|
+
boundsA.copy(inShape.computedAabb);
|
|
481
|
+
|
|
482
|
+
// expand the bounds by the max separation distance
|
|
483
|
+
boundsA.expand(inShapeCastSettings.collisionTolerance);
|
|
484
|
+
|
|
485
|
+
// transform the bounds to world space
|
|
486
|
+
boundsA.transform(inCenterOfMassTransform);
|
|
487
|
+
|
|
488
|
+
// the displacement is already in world space
|
|
489
|
+
|
|
490
|
+
const visitor = castShapeVisitor;
|
|
491
|
+
visitor.initialize(
|
|
492
|
+
isometryB,
|
|
493
|
+
ioCollector,
|
|
494
|
+
castModule,
|
|
495
|
+
ioCollector,
|
|
496
|
+
inShape,
|
|
497
|
+
inCenterOfMassTransform,
|
|
498
|
+
inShapeScale,
|
|
499
|
+
inDisplacement,
|
|
500
|
+
inbaseTranslation,
|
|
501
|
+
inShapeCastSettings
|
|
502
|
+
);
|
|
503
|
+
const group = AllFlag; // CollisionFilter.AllFlag
|
|
504
|
+
this.world.broadphase.visitBodiesWithCast(visitor, boundsA, inDisplacement, group, mask);
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
castRay(
|
|
508
|
+
onHit: (result: CastRayResult) => boolean,
|
|
509
|
+
ray: Ray,
|
|
510
|
+
settings: RayCastSettings,
|
|
511
|
+
belongsToGroups: number = AllFlag,
|
|
512
|
+
collidesWithGroups: number = AllFlag
|
|
513
|
+
) {
|
|
514
|
+
if (settings.returnClosestOnly) {
|
|
515
|
+
const visitor = castRayVisitor;
|
|
516
|
+
const collector = castRayCollector;
|
|
517
|
+
visitor.init(ray, settings, this.castShapesModule, collector);
|
|
518
|
+
this.world.broadphase.raycastBodies(visitor, ray, belongsToGroups, collidesWithGroups);
|
|
519
|
+
if (collector.closestBody) {
|
|
520
|
+
raycastResult.body = collector.closestBody;
|
|
521
|
+
raycastResult.fraction = collector.closestFraction;
|
|
522
|
+
onHit(raycastResult);
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
estimateCollisionResponse(
|
|
528
|
+
result: EstimateCollisionResponseResult,
|
|
529
|
+
bodyA: Body,
|
|
530
|
+
bodyB: Body,
|
|
531
|
+
timeStepSizeSeconds: number
|
|
532
|
+
): void {
|
|
533
|
+
result.reset();
|
|
534
|
+
const cache = this.contactManifoldModule.currentManifoldCache;
|
|
535
|
+
const key = createContactPairKey(bodyA, bodyB);
|
|
536
|
+
const pair = cache.pairMap.get(key);
|
|
537
|
+
if (!pair) {
|
|
538
|
+
return;
|
|
539
|
+
}
|
|
540
|
+
// we use just the first manifold for now
|
|
541
|
+
const manifold = pair.firstContactManifold;
|
|
542
|
+
if (!manifold) {
|
|
543
|
+
return;
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
estimateCollisionResponse(result, manifold, timeStepSizeSeconds);
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
const raycastResult: CastRayResult = {
|
|
551
|
+
// @ts-ignore
|
|
552
|
+
body: null,
|
|
553
|
+
fraction: Infinity,
|
|
554
|
+
};
|
|
555
|
+
|
|
556
|
+
export interface CastRayResult {
|
|
557
|
+
body: Body;
|
|
558
|
+
fraction: number;
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
class CastRayCollector extends CastCollector {
|
|
562
|
+
closestBody: Body | null;
|
|
563
|
+
closestFraction: number;
|
|
564
|
+
|
|
565
|
+
constructor() {
|
|
566
|
+
super();
|
|
567
|
+
this.closestBody = null;
|
|
568
|
+
this.closestFraction = Infinity;
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
reset() {
|
|
572
|
+
super.reset();
|
|
573
|
+
this.closestBody = null;
|
|
574
|
+
this.closestFraction = Infinity;
|
|
575
|
+
return this;
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
addHit(result: CastResult): void {
|
|
579
|
+
if (result.fraction < this.closestFraction) {
|
|
580
|
+
this.closestFraction = result.fraction;
|
|
581
|
+
this.closestBody = result.bodyB;
|
|
582
|
+
}
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
const castRayCollector = /*@__PURE__*/ new CastRayCollector();
|
|
587
|
+
|
|
588
|
+
class CastRayBodyVisitor implements BodyVisitor {
|
|
589
|
+
shouldExit: boolean;
|
|
590
|
+
settings: RayCastSettings | null;
|
|
591
|
+
ray: Ray | null;
|
|
592
|
+
castModule: CastShapesModule | null;
|
|
593
|
+
collector: CastRayCollector | null;
|
|
594
|
+
|
|
595
|
+
constructor() {
|
|
596
|
+
this.shouldExit = false;
|
|
597
|
+
this.ray = null;
|
|
598
|
+
this.settings = null;
|
|
599
|
+
this.castModule = null;
|
|
600
|
+
this.collector = null;
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
init(ray: Ray, settings: RayCastSettings, castModule: CastShapesModule, collector: CastRayCollector) {
|
|
604
|
+
this.shouldExit = false;
|
|
605
|
+
this.ray = ray;
|
|
606
|
+
this.settings = settings;
|
|
607
|
+
this.castModule = castModule;
|
|
608
|
+
this.collector = collector;
|
|
609
|
+
this.collector.reset();
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
visit(body: Body): void {
|
|
613
|
+
isometryB.fromRotationAndTranslation(body.orientation, body.computedCenterOfMassPosition);
|
|
614
|
+
this.castModule!.castRay(this.collector!, this.ray!, body.shape!, isometryB, 1.0, zeroVector, this.settings!, body);
|
|
615
|
+
}
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
const castRayVisitor = /*@__PURE__*/ new CastRayBodyVisitor();
|
|
619
|
+
|
|
620
|
+
class CollideShapeBodyVisitor {
|
|
621
|
+
shouldExit: boolean = false;
|
|
622
|
+
|
|
623
|
+
declare isometryA: Isometry;
|
|
624
|
+
declare isometryB: Isometry;
|
|
625
|
+
declare collector: CollisionCollector;
|
|
626
|
+
declare collisionModule: CollideShapesModule;
|
|
627
|
+
declare inShape: Shape;
|
|
628
|
+
declare inCollideShapeSettings: CollisionSettings;
|
|
629
|
+
declare offset: Vec3;
|
|
630
|
+
declare ioCollector: CollisionCollector;
|
|
631
|
+
|
|
632
|
+
initialize(
|
|
633
|
+
isometryA: Isometry,
|
|
634
|
+
isometryB: Isometry,
|
|
635
|
+
collector: CollisionCollector,
|
|
636
|
+
collisionModule: CollideShapesModule,
|
|
637
|
+
inShape: Shape,
|
|
638
|
+
offset: Vec3,
|
|
639
|
+
ioCollector: CollisionCollector,
|
|
640
|
+
inCollideShapeSettings: CollisionSettings
|
|
641
|
+
): void {
|
|
642
|
+
this.isometryA = isometryA;
|
|
643
|
+
this.isometryB = isometryB;
|
|
644
|
+
this.collector = collector;
|
|
645
|
+
this.collisionModule = collisionModule;
|
|
646
|
+
this.inShape = inShape;
|
|
647
|
+
this.inCollideShapeSettings = inCollideShapeSettings;
|
|
648
|
+
this.offset = offset;
|
|
649
|
+
this.ioCollector = ioCollector;
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
visit(body: Body) {
|
|
653
|
+
// set the isometry, offset it by the negated base offset
|
|
654
|
+
this.isometryB.fromRotationAndTranslation(body.orientation, body.computedCenterOfMassPosition);
|
|
655
|
+
this.isometryB.matrix.postTranslatedMatrix(this.isometryB.matrix, this.offset);
|
|
656
|
+
|
|
657
|
+
// Notify collector of new body
|
|
658
|
+
this.ioCollector.body2 = body;
|
|
659
|
+
|
|
660
|
+
this.collisionModule.collideShapes(
|
|
661
|
+
this.ioCollector,
|
|
662
|
+
this.inShape,
|
|
663
|
+
this.isometryA,
|
|
664
|
+
body.shape!,
|
|
665
|
+
this.isometryB,
|
|
666
|
+
this.inCollideShapeSettings,
|
|
667
|
+
null,
|
|
668
|
+
body
|
|
669
|
+
);
|
|
670
|
+
}
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
export interface BodyVisitor {
|
|
674
|
+
shouldExit: boolean;
|
|
675
|
+
visit(body: Body): void;
|
|
676
|
+
}
|
|
677
|
+
|
|
678
|
+
class CastShapeBodyVisitor implements BodyVisitor {
|
|
679
|
+
shouldExit: boolean = false;
|
|
680
|
+
|
|
681
|
+
declare isometryB: Isometry;
|
|
682
|
+
declare collector: CastCollector;
|
|
683
|
+
declare castModule: CastShapesModule;
|
|
684
|
+
declare ioCollector: CastCollector;
|
|
685
|
+
declare inShape: Shape;
|
|
686
|
+
declare inCenterOfMassTransform: Isometry;
|
|
687
|
+
declare inShapeScale: number;
|
|
688
|
+
declare inDisplacement: Vec3;
|
|
689
|
+
declare inbaseTranslation: Vec3;
|
|
690
|
+
declare inShapeCastSettings: CastSettings;
|
|
691
|
+
|
|
692
|
+
initialize(
|
|
693
|
+
isometryB: Isometry,
|
|
694
|
+
collector: CastCollector,
|
|
695
|
+
castModule: CastShapesModule,
|
|
696
|
+
ioCollector: CastCollector,
|
|
697
|
+
inShape: Shape,
|
|
698
|
+
inCenterOfMassTransform: Isometry,
|
|
699
|
+
inShapeScale: number,
|
|
700
|
+
inDisplacement: Vec3,
|
|
701
|
+
inbaseTranslation: Vec3,
|
|
702
|
+
inShapeCastSettings: CastSettings
|
|
703
|
+
): void {
|
|
704
|
+
this.isometryB = isometryB;
|
|
705
|
+
this.collector = collector;
|
|
706
|
+
this.castModule = castModule;
|
|
707
|
+
this.ioCollector = ioCollector;
|
|
708
|
+
this.inShape = inShape;
|
|
709
|
+
this.inCenterOfMassTransform = inCenterOfMassTransform;
|
|
710
|
+
this.inShapeScale = inShapeScale;
|
|
711
|
+
this.inDisplacement = inDisplacement;
|
|
712
|
+
this.inbaseTranslation = inbaseTranslation;
|
|
713
|
+
this.inShapeCastSettings = inShapeCastSettings;
|
|
714
|
+
}
|
|
715
|
+
|
|
716
|
+
visit(body: Body): void {
|
|
717
|
+
// set the isometry
|
|
718
|
+
this.isometryB.fromRotationAndTranslation(body.orientation, body.computedCenterOfMassPosition);
|
|
719
|
+
|
|
720
|
+
// Collect the transformed shape
|
|
721
|
+
// TODO: the type casting into ShapeWithSupport is not a good solution here, need to really rework the shape type system
|
|
722
|
+
// this.transformedShape.initialize(body.position, body.orientation, body.shape as ShapeWithSupport, id);
|
|
723
|
+
|
|
724
|
+
// Notify collector of new body
|
|
725
|
+
this.ioCollector.body2 = body;
|
|
726
|
+
|
|
727
|
+
this.castModule.castShapes(
|
|
728
|
+
this.ioCollector,
|
|
729
|
+
this.inShape,
|
|
730
|
+
this.inCenterOfMassTransform,
|
|
731
|
+
this.inShapeScale,
|
|
732
|
+
body.shape!,
|
|
733
|
+
this.isometryB,
|
|
734
|
+
1.0,
|
|
735
|
+
this.inDisplacement,
|
|
736
|
+
this.inbaseTranslation,
|
|
737
|
+
this.inShapeCastSettings,
|
|
738
|
+
null,
|
|
739
|
+
body
|
|
740
|
+
);
|
|
741
|
+
|
|
742
|
+
// Do narrow phase collision check
|
|
743
|
+
// this.transformedShape.castShape(inShapeCast, inShapeCastSettings, inbaseTranslation, ioCollector);
|
|
744
|
+
|
|
745
|
+
// TODO: this may not be a good translation of
|
|
746
|
+
// UpdateEarlyOutFraction(mCollector.GetEarlyOutFraction());
|
|
747
|
+
|
|
748
|
+
// Update early out fraction based on narrow phase collector
|
|
749
|
+
this.ioCollector.updateEarlyOutFraction(this.ioCollector.getEarlyOutFraction());
|
|
750
|
+
}
|
|
751
|
+
}
|
|
752
|
+
|
|
753
|
+
const boundsA = /*@__PURE__*/ Aabb.create();
|
|
754
|
+
const collideShapeVisitor = /*@__PURE__*/ new CollideShapeBodyVisitor();
|
|
755
|
+
const castShapeVisitor = /*@__PURE__*/ new CastShapeBodyVisitor();
|