@perplexdotgg/bounce 1.0.0 → 1.0.2

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.
Files changed (138) hide show
  1. package/build/bounce.d.ts +39501 -0
  2. package/build/bounce.js +17166 -0
  3. package/package.json +1 -1
  4. package/src/builders/ConvexHullBuilder.ts +0 -437
  5. package/src/builders/ConvexHullBuilder2d.ts +0 -344
  6. package/src/builders/ConvexHullBuilder3d.ts +0 -1689
  7. package/src/builders/HeightMapBuilder.ts +0 -414
  8. package/src/builders/TriangleMeshBuilder.ts +0 -92
  9. package/src/collision/CastShapesModule.ts +0 -184
  10. package/src/collision/CollideShapesModule.ts +0 -152
  11. package/src/collision/HeightMapCaster.ts +0 -38
  12. package/src/collision/HeightMapCollider.ts +0 -33
  13. package/src/collision/TriangleCaster.ts +0 -249
  14. package/src/collision/TriangleCollider.ts +0 -308
  15. package/src/collision/TriangleCollider2.ts +0 -379
  16. package/src/collision/activeEdge.ts +0 -146
  17. package/src/collision/cast/cast.ts +0 -139
  18. package/src/collision/cast/castCompoundVsCompound.ts +0 -59
  19. package/src/collision/cast/castCompoundVsConvex.ts +0 -116
  20. package/src/collision/cast/castConvexVsCompound.ts +0 -123
  21. package/src/collision/cast/castConvexVsConvex.ts +0 -213
  22. package/src/collision/cast/castConvexVsHeightMap.ts +0 -73
  23. package/src/collision/cast/castConvexVsTriangleMesh.ts +0 -56
  24. package/src/collision/cast/castRayVsCompound.ts +0 -44
  25. package/src/collision/cast/castRayVsConvex.ts +0 -45
  26. package/src/collision/cast/castRayVsHeightMap.ts +0 -58
  27. package/src/collision/cast/castRayVsTriangleMesh.ts +0 -58
  28. package/src/collision/closestPoints/closestPoints.ts +0 -23
  29. package/src/collision/closestPoints/computeBarycentricCoordinates2d.ts +0 -32
  30. package/src/collision/closestPoints/computeBarycentricCoordinates3d.ts +0 -81
  31. package/src/collision/closestPoints/computeClosestPointOnLine.ts +0 -30
  32. package/src/collision/closestPoints/computeClosestPointOnTetrahedron.ts +0 -96
  33. package/src/collision/closestPoints/computeClosestPointOnTriangle.ts +0 -195
  34. package/src/collision/closestPoints/isOriginOutsideOfPlane.ts +0 -25
  35. package/src/collision/closestPoints/isOriginOutsideOfTrianglePlanes.ts +0 -72
  36. package/src/collision/collide/collide.ts +0 -146
  37. package/src/collision/collide/collideCompoundVsCompound.ts +0 -60
  38. package/src/collision/collide/collideCompoundVsConvex.ts +0 -59
  39. package/src/collision/collide/collideCompoundVsHeightMap.ts +0 -73
  40. package/src/collision/collide/collideCompoundVsTriangleMesh.ts +0 -56
  41. package/src/collision/collide/collideConvexVsCompound.ts +0 -57
  42. package/src/collision/collide/collideConvexVsConvex.ts +0 -225
  43. package/src/collision/collide/collideConvexVsConvexImp.ts +0 -236
  44. package/src/collision/collide/collideConvexVsHeightMap.ts +0 -53
  45. package/src/collision/collide/collideConvexVsTriangleMesh.ts +0 -58
  46. package/src/collision/collide/collideHeightMapVsCompound.ts +0 -69
  47. package/src/collision/collide/collideHeightMapVsConvex.ts +0 -53
  48. package/src/collision/collide/collideSphereVsSphere.ts +0 -81
  49. package/src/collision/collide/collideTriangleMeshVsCompound.ts +0 -58
  50. package/src/collision/collide/collideTriangleMeshVsConvex.ts +0 -58
  51. package/src/collision/epa/EpaConvexHullBuilder.ts +0 -397
  52. package/src/collision/epa/StaticArray.ts +0 -154
  53. package/src/collision/epa/TriangleFactory.ts +0 -32
  54. package/src/collision/epa/arrays.ts +0 -99
  55. package/src/collision/epa/binaryHeap.ts +0 -82
  56. package/src/collision/epa/structs.ts +0 -227
  57. package/src/collision/gjk/GjkModule.ts +0 -864
  58. package/src/collision/gjk/PenetrationDepthModule.ts +0 -493
  59. package/src/collision/gjk/SupportPoints.ts +0 -50
  60. package/src/collision/imp/MinkowskiDifference.ts +0 -36
  61. package/src/collision/imp/computeExploredDistanceLowerUpperBound.ts +0 -40
  62. package/src/collision/imp/finalizeImpResult.ts +0 -69
  63. package/src/collision/imp/findContactImp.ts +0 -196
  64. package/src/collision/imp/imp.ts +0 -28
  65. package/src/collision/imp/incrementalMinimumDistanceExploreDirection.ts +0 -207
  66. package/src/collision/mpr/findPortal.ts +0 -152
  67. package/src/collision/mpr/mpr.ts +0 -29
  68. package/src/collision/mpr/updatePortal.ts +0 -52
  69. package/src/constraints/BaseConstraint.ts +0 -50
  70. package/src/constraints/ConstraintOptions.ts +0 -22
  71. package/src/constraints/ConstraintSolver.ts +0 -119
  72. package/src/constraints/DistanceConstraint.ts +0 -229
  73. package/src/constraints/FixedConstraint.ts +0 -203
  74. package/src/constraints/HingeConstraint.ts +0 -460
  75. package/src/constraints/PointConstraint.ts +0 -108
  76. package/src/constraints/components/AngleComponent.ts +0 -226
  77. package/src/constraints/components/AxisComponent.ts +0 -263
  78. package/src/constraints/components/HingeComponent.ts +0 -215
  79. package/src/constraints/components/Motor.ts +0 -36
  80. package/src/constraints/components/PointConstraintComponent.ts +0 -179
  81. package/src/constraints/components/RotationEulerComponent.ts +0 -139
  82. package/src/constraints/components/Spring.ts +0 -30
  83. package/src/constraints/components/SpringComponent.ts +0 -71
  84. package/src/constraints/types.ts +0 -6
  85. package/src/helpers.ts +0 -147
  86. package/src/index.ts +0 -50
  87. package/src/math/BasicTransform.ts +0 -19
  88. package/src/math/NumberValue.ts +0 -13
  89. package/src/math/isometry.ts +0 -64
  90. package/src/math/mat3.ts +0 -529
  91. package/src/math/mat4.ts +0 -588
  92. package/src/math/quat.ts +0 -193
  93. package/src/math/scalar.ts +0 -81
  94. package/src/math/tensor.ts +0 -17
  95. package/src/math/vec3.ts +0 -589
  96. package/src/math/vec4.ts +0 -10
  97. package/src/physics/Body.ts +0 -581
  98. package/src/physics/CollisionFilter.ts +0 -52
  99. package/src/physics/SleepModule.ts +0 -163
  100. package/src/physics/broadphase/BodyPairsModule.ts +0 -363
  101. package/src/physics/broadphase/BvhModule.ts +0 -237
  102. package/src/physics/broadphase/BvhTree.ts +0 -803
  103. package/src/physics/broadphase/ConstraintPairsModule.ts +0 -385
  104. package/src/physics/broadphase/TriangleMeshBvhTree.ts +0 -379
  105. package/src/physics/manifold/ContactManifold.ts +0 -227
  106. package/src/physics/manifold/ContactManifoldModule.ts +0 -623
  107. package/src/physics/manifold/Face.ts +0 -119
  108. package/src/physics/manifold/ManifoldCache.ts +0 -116
  109. package/src/physics/manifold/clipping/clipPolyVsEdge.ts +0 -131
  110. package/src/physics/manifold/clipping/clipPolyVsPlane.ts +0 -73
  111. package/src/physics/manifold/clipping/clipPolyVsPoly.ts +0 -72
  112. package/src/physics/narrowphase/CollideBodiesModule.ts +0 -755
  113. package/src/physics/solver/ContactConstraintModule.ts +0 -659
  114. package/src/physics/solver/ManifoldConstraint.ts +0 -420
  115. package/src/physics/solver/estimateCollisionResponse.ts +0 -146
  116. package/src/shape/Aabb.ts +0 -400
  117. package/src/shape/Box.ts +0 -231
  118. package/src/shape/Capsule.ts +0 -332
  119. package/src/shape/CompoundShape.ts +0 -288
  120. package/src/shape/Convex.ts +0 -130
  121. package/src/shape/ConvexHull.ts +0 -423
  122. package/src/shape/Cylinder.ts +0 -313
  123. package/src/shape/HeightMap.ts +0 -511
  124. package/src/shape/Line.ts +0 -14
  125. package/src/shape/Plane.ts +0 -116
  126. package/src/shape/Ray.ts +0 -81
  127. package/src/shape/Segment.ts +0 -25
  128. package/src/shape/Shape.ts +0 -77
  129. package/src/shape/Sphere.ts +0 -181
  130. package/src/shape/TransformedShape.ts +0 -51
  131. package/src/shape/Triangle.ts +0 -122
  132. package/src/shape/TriangleMesh.ts +0 -186
  133. package/src/types.ts +0 -1
  134. package/src/world.ts +0 -1335
  135. package/tests/BodyPairsModule.test.ts +0 -71
  136. package/tests/BvhTree.test.ts +0 -406
  137. package/tests/test.md +0 -642
  138. package/tests/vec3.test.ts +0 -12
@@ -1,379 +0,0 @@
1
- import {
2
- createClass,
3
- LazyReferenceListType,
4
- LazyReferenceType,
5
- MonomorphInstance,
6
- MonomorphType,
7
- NumberType,
8
- PropertyDefinitionMap,
9
- PropertyDefinitionReference,
10
- PropertyDefinitionReferenceList,
11
- ReferenceListType,
12
- WithPool,
13
- } from "monomorph";
14
- import { TriangleMesh } from "../../shape/TriangleMesh";
15
- import { Aabb } from "../../shape/Aabb";
16
- import { Vec3 } from "../../math/vec3";
17
- import { Triangle } from "../../shape/Triangle";
18
- import { Ray } from "../../shape/Ray";
19
-
20
- export interface TriangleMeshBvhTreeOptions {
21
- //
22
- }
23
-
24
- export interface TriangleMeshBvhTreeBuildParams {
25
- mesh: TriangleMesh;
26
- bvhTreeOptions: TriangleMeshBvhTreeOptions;
27
- }
28
-
29
- const bvhNodeProps = {
30
- parent: LazyReferenceType((() => TriangleMeshBvhNode) as () => never) as PropertyDefinitionReference<TriangleMeshBvhNode | null, true>,
31
- left: LazyReferenceType((() => TriangleMeshBvhNode) as () => never) as PropertyDefinitionReference<TriangleMeshBvhNode | null, true>,
32
- right: LazyReferenceType((() => TriangleMeshBvhNode) as () => never) as PropertyDefinitionReference<TriangleMeshBvhNode | null, true>,
33
- computedBounds: MonomorphType(Aabb, undefined, true),
34
- depth: NumberType(0, true),
35
- objects: LazyReferenceListType((() => Triangle) as () => never) as PropertyDefinitionReferenceList<Triangle, Triangle extends MonomorphInstance<infer P, infer I> ? P : never, Triangle extends MonomorphInstance<infer P, infer I> ? I : never>,
36
- } as const satisfies PropertyDefinitionMap;
37
-
38
- export class TriangleMeshBvhNode extends createClass<TriangleMeshBvhNode, typeof bvhNodeProps>(bvhNodeProps) {
39
- /**
40
- * if bvh node is an internal node, this will be an empty list
41
- * if bvh node is a leaf node, this will contain refs to the objects in the leaf
42
- */
43
- // objects: Triangle[] = [];
44
-
45
- isLeaf() {
46
- return this.left === null && this.right === null;
47
- }
48
-
49
- isRoot() {
50
- return this.parent === null;
51
- }
52
- }
53
-
54
- function computeBounds(out: Aabb, objects: Triangle[]) {
55
- out.copy(objects[0].computedBounds);
56
- for (let i = 1; i < objects.length; i++) {
57
- out.unionAabb(objects[i].computedBounds);
58
- }
59
- }
60
-
61
- const centroidBounds = /*@__PURE__*/ Aabb.create();
62
- const extent = /*@__PURE__*/ Vec3.create();
63
-
64
- function sortByX(a: Triangle, b: Triangle) {
65
- return a.computedBounds.centroid.x - b.computedBounds.centroid.x;
66
- }
67
-
68
- function sortByY(a: Triangle, b: Triangle) {
69
- return a.computedBounds.centroid.y - b.computedBounds.centroid.y;
70
- }
71
-
72
- function sortByZ(a: Triangle, b: Triangle) {
73
- return a.computedBounds.centroid.z - b.computedBounds.centroid.z;
74
- }
75
-
76
- const sortByAxisFunctions = {
77
- 0: sortByX,
78
- 1: sortByY,
79
- 2: sortByZ,
80
- } as const;
81
-
82
- function splitObjects(objects: Triangle[]) {
83
- if (objects.length < 2) {
84
- throw new Error("Cannot split fewer than 2 objects.");
85
- }
86
-
87
- // expand centroid bounds
88
- centroidBounds.min.fromArray([+Infinity, +Infinity, +Infinity]);
89
- centroidBounds.max.fromArray([-Infinity, -Infinity, -Infinity]);
90
-
91
- for (const obj of objects) {
92
- centroidBounds.expandToPoint(obj.computedBounds.centroid);
93
- }
94
-
95
- centroidBounds.computeExtents(extent);
96
- const axis = centroidBounds.computeLargestAxis();
97
-
98
- objects.sort(sortByAxisFunctions[axis]);
99
- let mid = Math.floor(objects.length / 2);
100
- if (mid <= 0 || mid >= objects.length) {
101
- mid = 1;
102
- }
103
-
104
- const leftObjects = objects.slice(0, mid);
105
- const rightObjects = objects.slice(mid);
106
- return [leftObjects, rightObjects] as [Triangle[], Triangle[]];
107
- }
108
-
109
- const triangleMeshBvhTreeProps = {
110
- nodes: ReferenceListType(TriangleMeshBvhNode),
111
- } as const satisfies PropertyDefinitionMap;
112
-
113
- export class TriangleMeshBvhTree extends createClass<TriangleMeshBvhTree, typeof triangleMeshBvhTreeProps>(
114
- triangleMeshBvhTreeProps
115
- ) {
116
- // TODO: init this via constructor params
117
- intersectStack: TriangleMeshBvhNode[] = [];
118
- walkStack: TriangleMeshBvhNode[] = [];
119
-
120
- build(params: TriangleMeshBvhTreeBuildParams, trianglePool: typeof Triangle.Pool) {
121
- const objects: Triangle[] = [];
122
- for (const triangle of params.mesh.triangles!) {
123
- objects.push(triangle);
124
- }
125
-
126
- const root = this.nodes.create({
127
- objects: {
128
- pool: trianglePool,
129
- },
130
- });
131
- this._buildRecursive(objects, root, null);
132
- }
133
-
134
- get root() {
135
- return this.nodes?.getAtIndex(0);
136
- }
137
-
138
- _buildRecursive(objects: Triangle[], node: TriangleMeshBvhNode, parent: TriangleMeshBvhNode | null) {
139
- node.parent = parent;
140
- node.depth = parent ? parent.depth + 1 : 0;
141
- computeBounds(node.computedBounds, objects);
142
-
143
- if (objects.length <= 2) {
144
- node.objects.length = 0;
145
- for (const object of objects) {
146
- node.objects.push(object as WithPool<Triangle>);
147
- }
148
- return;
149
- }
150
-
151
- const [leftObjects, rightObjects] = splitObjects(objects);
152
-
153
- if (leftObjects.length === 0 || rightObjects.length === 0) {
154
- node.objects.length = 0;
155
- for (const object of objects) {
156
- node.objects.push(object as WithPool<Triangle>);
157
- }
158
- return;
159
- }
160
-
161
- const left = this.nodes.create({
162
- objects: {
163
- pool: node.objects.pool,
164
- },
165
- });
166
- const right = this.nodes.create({
167
- objects: {
168
- pool: node.objects.pool,
169
- },
170
- });
171
-
172
- node.left = left;
173
- node.right = right;
174
-
175
- this._buildRecursive(leftObjects, left, node);
176
- this._buildRecursive(rightObjects, right, node);
177
- }
178
-
179
- intersectAabb(onHit: (triangle: Triangle) => boolean, aabb: Aabb) {
180
- // console.log("intersect body", body);
181
- if (!this.root) {
182
- return;
183
- }
184
-
185
- const stack = this.intersectStack;
186
- stack.length = 0;
187
- stack.push(this.root);
188
-
189
- while (stack.length > 0) {
190
- const node = stack.pop();
191
-
192
- if (!node) {
193
- continue;
194
- }
195
-
196
- // skip this node if it doesn't intersect the AABB
197
- if (!node.computedBounds.intersectsAabb(aabb)) {
198
- continue;
199
- }
200
-
201
- // if the node is not a leaf, push its children onto the stack and continue
202
- if (!node.isLeaf()) {
203
- stack.push(node.left!);
204
- stack.push(node.right!);
205
- continue;
206
- }
207
-
208
- // if the node is a leaf, check its objects
209
- for (const object of node.objects) {
210
- if (!aabb.intersectsAabb(object.computedBounds)) {
211
- continue;
212
- }
213
-
214
- if (onHit(object)) {
215
- return;
216
- }
217
- }
218
- }
219
- }
220
-
221
- walk(onNode: (node: TriangleMeshBvhNode) => boolean) {
222
- if (!this.root) {
223
- return;
224
- }
225
-
226
- const stack = this.walkStack;
227
- stack.length = 0;
228
- stack.push(this.root);
229
-
230
- while (stack.length > 0) {
231
- const node = stack.pop();
232
-
233
- if (!node) {
234
- continue;
235
- }
236
-
237
- if (onNode(node)) {
238
- return;
239
- }
240
-
241
- if (!node.isLeaf()) {
242
- stack.push(node.left!);
243
- stack.push(node.right!);
244
- }
245
- }
246
- }
247
-
248
- computeMaxDepth() {
249
- if (!this.root) {
250
- return 0;
251
- }
252
-
253
- let maxDepth = 0;
254
- this.walk(node => {
255
- if (node.depth > maxDepth) {
256
- maxDepth = node.depth;
257
- }
258
- return false;
259
- });
260
- return maxDepth;
261
- }
262
-
263
- castAabb(onHit: (triangle: Triangle) => boolean, bounds: Aabb, displacement: Vec3) {
264
- // exit if the tree is empty
265
- if (!this.root) {
266
- return;
267
- }
268
-
269
- // aabb cast is done by the following method
270
- // 1. shrink the shape aabb by its own extents down to a point
271
- // 2. expand the block aabb by the extents of the shape aabb
272
- // 3. cast the point by the displacement against the expanded block aabb (raycast vs aabb test)
273
-
274
- bounds.computeCentroid(ray.origin);
275
- ray.direction.normalizeVector(displacement);
276
- ray.length = displacement.length();
277
-
278
- bounds.computeHalfExtents(halfExtents);
279
-
280
- const stack = this.intersectStack;
281
- stack.length = 0;
282
- stack.push(this.root);
283
-
284
- while (stack.length > 0) {
285
- const node = stack.pop();
286
-
287
- if (!node) {
288
- continue;
289
- }
290
-
291
- // skip branch if the node's expanded aabb does not intersect with the shape's ray
292
- nodeBounds.copy(node.computedBounds);
293
- nodeBounds.expandByVector(halfExtents);
294
- if (ray.intersectsAabb(nodeBounds) === false) {
295
- continue;
296
- }
297
-
298
- // if the node is not a leaf, push its children onto the stack and continue
299
- if (!node.isLeaf()) {
300
- stack.push(node.left!);
301
- stack.push(node.right!);
302
- continue;
303
- }
304
-
305
- // if the node is a leaf, check its objects
306
- for (const body of node.objects) {
307
- // expand the object aabb by the shape's aabb
308
- // skip if bounds do not collide
309
- bodyBounds.copy(body.computedBounds);
310
- bodyBounds.expandByVector(halfExtents);
311
- if (ray.intersectsAabb(bodyBounds) === false) {
312
- continue;
313
- }
314
-
315
- // visit the body
316
- if (onHit(body)) {
317
- return;
318
- }
319
- }
320
- }
321
- }
322
-
323
- castRay(onHit: (triangle: Triangle) => boolean, ray: Ray) {
324
- // exit if the tree is empty
325
- if (!this.root) {
326
- return;
327
- }
328
-
329
- // aabb cast is done by the following method
330
- // 1. shrink the shape aabb by its own extents down to a point
331
- // 2. expand the block aabb by the extents of the shape aabb
332
- // 3. cast the point by the displacement against the expanded block aabb (raycast vs aabb test)
333
-
334
- const stack = this.intersectStack;
335
- stack.length = 0;
336
- stack.push(this.root);
337
-
338
- while (stack.length > 0) {
339
- const node = stack.pop();
340
-
341
- if (!node) {
342
- continue;
343
- }
344
-
345
- // skip branch if the node's expanded aabb does not intersect with the shape's ray
346
- nodeBounds.copy(node.computedBounds);
347
- if (ray.intersectsAabb(nodeBounds) === false) {
348
- continue;
349
- }
350
-
351
- // if the node is not a leaf, push its children onto the stack and continue
352
- if (!node.isLeaf()) {
353
- stack.push(node.left!);
354
- stack.push(node.right!);
355
- continue;
356
- }
357
-
358
- // if the node is a leaf, check its objects
359
- for (const body of node.objects) {
360
- // expand the object aabb by the shape's aabb
361
- // skip if bounds do not collide
362
- bodyBounds.copy(body.computedBounds);
363
- if (ray.intersectsAabb(bodyBounds) === false) {
364
- continue;
365
- }
366
-
367
- // visit the body
368
- if (onHit(body)) {
369
- return;
370
- }
371
- }
372
- }
373
- }
374
- }
375
-
376
- const ray = /*@__PURE__*/ Ray.create();
377
- const halfExtents = /*@__PURE__*/ Vec3.create();
378
- const nodeBounds = /*@__PURE__*/ Aabb.create();
379
- const bodyBounds = /*@__PURE__*/ Aabb.create();
@@ -1,227 +0,0 @@
1
- import {
2
- createClass,
3
- InputType,
4
- LazyReferenceType,
5
- MonomorphType,
6
- NumberType,
7
- PoolClass,
8
- PropertyDefinitionMap,
9
- PropertyDefinitionReference,
10
- ReferenceListType,
11
- ReferenceType,
12
- } from "monomorph";
13
- import { Body } from "../Body";
14
- import { Vec3 } from "../../math/vec3";
15
- import { Quat } from "../../math/quat";
16
- import { Mat4 } from "../../math/mat4";
17
- import { ReferenceFrame } from "../../constraints/BaseConstraint";
18
-
19
- const localToWorldTransformA = /*@__PURE__*/ Mat4.create();
20
- const point = /*@__PURE__*/ Vec3.create();
21
-
22
- const contactManifoldProps = {
23
- // meta data
24
- bodyA: LazyReferenceType((() => Body) as () => never) as PropertyDefinitionReference<Body | null, true>,
25
- bodyB: LazyReferenceType((() => Body) as () => never) as PropertyDefinitionReference<Body | null, true>,
26
- subShapeIdA: NumberType(0),
27
- subShapeIdB: NumberType(0),
28
- nextContactManifold: LazyReferenceType((() => ContactManifold) as () => never) as PropertyDefinitionReference<
29
- ContactManifold | null,
30
- true
31
- >,
32
- // geometric data
33
- baseTranslation: MonomorphType(Vec3),
34
- firstWorldSpaceNormal: MonomorphType(Vec3),
35
- worldSpaceNormal: MonomorphType(Vec3),
36
- penetrationDepth: NumberType(0.0),
37
- numContacts: NumberType(0),
38
- contactPointsA: ReferenceListType(Vec3),
39
- contactPointsB: ReferenceListType(Vec3),
40
- lambdas: ReferenceListType(Vec3),
41
- } as const satisfies PropertyDefinitionMap;
42
-
43
- export class ContactManifold extends createClass<ContactManifold, typeof contactManifoldProps>(contactManifoldProps) {
44
- get maxContacts(): number {
45
- return this.contactPointsA!.maxLength;
46
- }
47
-
48
- pushContactPoints(pointA: Vec3, pointB: Vec3): void {
49
- if (this.numContacts >= this.maxContacts) {
50
- throw new Error("contact manifold is full");
51
- }
52
-
53
- this.contactPointsA!.getAtIndex(this.numContacts)!.copy(pointA);
54
- this.contactPointsB!.getAtIndex(this.numContacts)!.copy(pointB);
55
- // this.lambdas!.getAtIndex(this.numContacts)!.copy(pointA);
56
- this.numContacts++;
57
- }
58
-
59
- get key(): string {
60
- return createContactPairKey(this.bodyA!, this.bodyB!);
61
- }
62
-
63
- copyLambda(other: ContactManifold, index: number): void {
64
- this.lambdas.getAtIndex(index)!.copy(other.lambdas.getAtIndex(index)!);
65
- }
66
-
67
- copyLambdas(other: ContactManifold): void {
68
- for (let i = 0; i < this.numContacts; i++) {
69
- this.lambdas.getAtIndex(i)!.copy(other.lambdas.getAtIndex(i)!);
70
- }
71
- }
72
-
73
- resetLambdas(): void {
74
- for (let i = 0; i < this.numContacts; i++) {
75
- this.lambdas.getAtIndex(i)!.zero();
76
- }
77
- }
78
-
79
- getContactPointA(out: Vec3, index: number): void {
80
- out.copy(this.contactPointsA.getAtIndex(index)!);
81
- }
82
-
83
- getContactPointB(out: Vec3, index: number): void {
84
- out.copy(this.contactPointsB.getAtIndex(index)!);
85
- }
86
-
87
- setContactPointA(point: Vec3, index: number): void {
88
- this.contactPointsA.getAtIndex(index)!.copy(point);
89
- }
90
-
91
- setContactPointB(point: Vec3, index: number): void {
92
- this.contactPointsB.getAtIndex(index)!.copy(point);
93
- }
94
-
95
- clear() {
96
- this.numContacts = 0;
97
- }
98
-
99
- /**
100
- * this function assumes that the contact points are stored in the local space of the corresponding body!
101
- */
102
- getWorldContactPointA(out: Vec3, index: number): void {
103
- const bodyA = this.bodyA!;
104
- localToWorldTransformA.fromRotationTranslation(bodyA.orientation, bodyA.computedCenterOfMassPosition);
105
-
106
- this.getContactPointA(out, index);
107
- out.transformVectorFromMat4(out, localToWorldTransformA);
108
- }
109
-
110
- getContactPointAInSpace(out: Vec3, index: number, space: ReferenceFrame): void {
111
- if (space === ReferenceFrame.world) {
112
- this.getWorldContactPointA(out, index);
113
- } else {
114
- this.getContactPointA(out, index);
115
- }
116
- }
117
-
118
- getCentroidA(out: Vec3): void {
119
- out.zero();
120
-
121
- for (let i = 0; i < this.numContacts; i++) {
122
- this.getContactPointA(point, i);
123
- out.addVectors(out, point);
124
- }
125
-
126
- out.scaleVector(out, 1 / this.numContacts);
127
- }
128
-
129
- getWorldCentroidA(out: Vec3): void {
130
- const bodyA = this.bodyA!;
131
- localToWorldTransformA.fromRotationTranslation(bodyA.orientation, bodyA.computedCenterOfMassPosition);
132
-
133
- this.getCentroidA(out);
134
- out.transformVectorFromMat4(out, localToWorldTransformA);
135
- }
136
-
137
- getCentroidAInSpace(out: Vec3, space: ReferenceFrame): void {
138
- if (space === ReferenceFrame.world) {
139
- this.getWorldCentroidA(out);
140
- } else {
141
- this.getCentroidA(out);
142
- }
143
- }
144
-
145
- containsBody(body: Body): boolean {
146
- return this.bodyA === body || this.bodyB === body;
147
- }
148
- }
149
-
150
- export class ContactManifoldPool {
151
- // the contact manifold pool
152
- contactManifoldPool: PoolClass<ContactManifold>;
153
- vec3Pool: PoolClass<Vec3>;
154
-
155
- numMaxManifolds: number;
156
- maxNumContacts: number;
157
-
158
- constructor(numMaxManifolds: number, numMaxContacts: number) {
159
- this.contactManifoldPool = new ContactManifold.Pool();
160
- this.vec3Pool = new Vec3.Pool();
161
-
162
- this.numMaxManifolds = numMaxManifolds;
163
- this.maxNumContacts = numMaxContacts;
164
- }
165
-
166
- createContactManifold(data: InputType<ContactManifold>): ContactManifold {
167
- data = data ?? {};
168
-
169
- if (data.contactPointsA) {
170
- data.contactPointsA.pool = this.vec3Pool;
171
- } else {
172
- data.contactPointsA = { pool: this.vec3Pool };
173
- }
174
-
175
- if (data.contactPointsB) {
176
- data.contactPointsB.pool = this.vec3Pool;
177
- } else {
178
- data.contactPointsB = { pool: this.vec3Pool };
179
- }
180
-
181
- if (data.lambdas) {
182
- data.lambdas.pool = this.vec3Pool;
183
- } else {
184
- data.lambdas = { pool: this.vec3Pool };
185
- }
186
-
187
- const manifold = ContactManifold.create(data, this.contactManifoldPool);
188
-
189
- // todo this behavior probably should change?
190
- // currently, we create all the points once the first time, and never destroy them.
191
- // they technically should be destroyed, but this is more efficient for this use case
192
- // since we will be reusing the same manifolds over and over again, so we should just
193
- // increment a numManifolds instead that is reset to 0
194
- if (manifold.contactPointsA.length >= this.maxNumContacts) {
195
- return manifold;
196
- }
197
-
198
-
199
- for (let i = 0; i < this.maxNumContacts; i++) {
200
- manifold.contactPointsA.create();
201
- manifold.contactPointsB.create();
202
- manifold.lambdas.create();
203
- }
204
-
205
- return manifold;
206
- }
207
- }
208
-
209
- const contactPairProps = {
210
- bodyA: LazyReferenceType((() => Body) as () => never) as PropertyDefinitionReference<Body | null, true>,
211
- bodyB: LazyReferenceType((() => Body) as () => never) as PropertyDefinitionReference<Body | null, true>,
212
- firstContactManifold: ReferenceType(ContactManifold),
213
- translationAB: MonomorphType(Vec3),
214
- rotationAB: MonomorphType(Quat),
215
- } as const satisfies PropertyDefinitionMap;
216
-
217
- export class ContactPair extends createClass<ContactPair, typeof contactPairProps>(contactPairProps) {
218
- get key(): string {
219
- return createContactPairKey(this.bodyA!, this.bodyB!);
220
- }
221
- }
222
-
223
- export function createContactPairKey(bodyA: Body, bodyB: Body): string {
224
- const keyA = `${bodyA.type}:${bodyA.index}`;
225
- const keyB = `${bodyB.type}:${bodyB.index}`;
226
- return keyA < keyB ? `${keyA}|${keyB}` : `${keyB}|${keyA}`;
227
- }