@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.
Files changed (140) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +30 -0
  3. package/package.json +32 -0
  4. package/src/builders/ConvexHullBuilder.ts +437 -0
  5. package/src/builders/ConvexHullBuilder2d.ts +344 -0
  6. package/src/builders/ConvexHullBuilder3d.ts +1689 -0
  7. package/src/builders/HeightMapBuilder.ts +414 -0
  8. package/src/builders/TriangleMeshBuilder.ts +92 -0
  9. package/src/collision/CastShapesModule.ts +184 -0
  10. package/src/collision/CollideShapesModule.ts +152 -0
  11. package/src/collision/HeightMapCaster.ts +38 -0
  12. package/src/collision/HeightMapCollider.ts +33 -0
  13. package/src/collision/TriangleCaster.ts +249 -0
  14. package/src/collision/TriangleCollider.ts +308 -0
  15. package/src/collision/TriangleCollider2.ts +379 -0
  16. package/src/collision/activeEdge.ts +146 -0
  17. package/src/collision/cast/cast.ts +139 -0
  18. package/src/collision/cast/castCompoundVsCompound.ts +59 -0
  19. package/src/collision/cast/castCompoundVsConvex.ts +116 -0
  20. package/src/collision/cast/castConvexVsCompound.ts +123 -0
  21. package/src/collision/cast/castConvexVsConvex.ts +213 -0
  22. package/src/collision/cast/castConvexVsHeightMap.ts +73 -0
  23. package/src/collision/cast/castConvexVsTriangleMesh.ts +56 -0
  24. package/src/collision/cast/castRayVsCompound.ts +44 -0
  25. package/src/collision/cast/castRayVsConvex.ts +45 -0
  26. package/src/collision/cast/castRayVsHeightMap.ts +58 -0
  27. package/src/collision/cast/castRayVsTriangleMesh.ts +58 -0
  28. package/src/collision/closestPoints/closestPoints.ts +23 -0
  29. package/src/collision/closestPoints/computeBarycentricCoordinates2d.ts +32 -0
  30. package/src/collision/closestPoints/computeBarycentricCoordinates3d.ts +81 -0
  31. package/src/collision/closestPoints/computeClosestPointOnLine.ts +30 -0
  32. package/src/collision/closestPoints/computeClosestPointOnTetrahedron.ts +96 -0
  33. package/src/collision/closestPoints/computeClosestPointOnTriangle.ts +195 -0
  34. package/src/collision/closestPoints/isOriginOutsideOfPlane.ts +25 -0
  35. package/src/collision/closestPoints/isOriginOutsideOfTrianglePlanes.ts +72 -0
  36. package/src/collision/collide/collide.ts +146 -0
  37. package/src/collision/collide/collideCompoundVsCompound.ts +60 -0
  38. package/src/collision/collide/collideCompoundVsConvex.ts +59 -0
  39. package/src/collision/collide/collideCompoundVsHeightMap.ts +73 -0
  40. package/src/collision/collide/collideCompoundVsTriangleMesh.ts +56 -0
  41. package/src/collision/collide/collideConvexVsCompound.ts +57 -0
  42. package/src/collision/collide/collideConvexVsConvex.ts +225 -0
  43. package/src/collision/collide/collideConvexVsConvexImp.ts +236 -0
  44. package/src/collision/collide/collideConvexVsHeightMap.ts +53 -0
  45. package/src/collision/collide/collideConvexVsTriangleMesh.ts +58 -0
  46. package/src/collision/collide/collideHeightMapVsCompound.ts +69 -0
  47. package/src/collision/collide/collideHeightMapVsConvex.ts +53 -0
  48. package/src/collision/collide/collideSphereVsSphere.ts +81 -0
  49. package/src/collision/collide/collideTriangleMeshVsCompound.ts +58 -0
  50. package/src/collision/collide/collideTriangleMeshVsConvex.ts +58 -0
  51. package/src/collision/epa/EpaConvexHullBuilder.ts +397 -0
  52. package/src/collision/epa/StaticArray.ts +154 -0
  53. package/src/collision/epa/TriangleFactory.ts +32 -0
  54. package/src/collision/epa/arrays.ts +99 -0
  55. package/src/collision/epa/binaryHeap.ts +82 -0
  56. package/src/collision/epa/structs.ts +227 -0
  57. package/src/collision/gjk/GjkModule.ts +864 -0
  58. package/src/collision/gjk/PenetrationDepthModule.ts +493 -0
  59. package/src/collision/gjk/SupportPoints.ts +50 -0
  60. package/src/collision/imp/MinkowskiDifference.ts +36 -0
  61. package/src/collision/imp/computeExploredDistanceLowerUpperBound.ts +40 -0
  62. package/src/collision/imp/finalizeImpResult.ts +69 -0
  63. package/src/collision/imp/findContactImp.ts +196 -0
  64. package/src/collision/imp/imp.ts +28 -0
  65. package/src/collision/imp/incrementalMinimumDistanceExploreDirection.ts +207 -0
  66. package/src/collision/mpr/findPortal.ts +152 -0
  67. package/src/collision/mpr/mpr.ts +29 -0
  68. package/src/collision/mpr/updatePortal.ts +52 -0
  69. package/src/constraints/BaseConstraint.ts +50 -0
  70. package/src/constraints/ConstraintOptions.ts +22 -0
  71. package/src/constraints/ConstraintSolver.ts +119 -0
  72. package/src/constraints/DistanceConstraint.ts +229 -0
  73. package/src/constraints/FixedConstraint.ts +203 -0
  74. package/src/constraints/HingeConstraint.ts +460 -0
  75. package/src/constraints/PointConstraint.ts +108 -0
  76. package/src/constraints/components/AngleComponent.ts +226 -0
  77. package/src/constraints/components/AxisComponent.ts +263 -0
  78. package/src/constraints/components/HingeComponent.ts +215 -0
  79. package/src/constraints/components/Motor.ts +36 -0
  80. package/src/constraints/components/PointConstraintComponent.ts +179 -0
  81. package/src/constraints/components/RotationEulerComponent.ts +139 -0
  82. package/src/constraints/components/Spring.ts +30 -0
  83. package/src/constraints/components/SpringComponent.ts +71 -0
  84. package/src/constraints/types.ts +6 -0
  85. package/src/helpers.ts +147 -0
  86. package/src/index.ts +50 -0
  87. package/src/math/BasicTransform.ts +19 -0
  88. package/src/math/NumberValue.ts +13 -0
  89. package/src/math/isometry.ts +64 -0
  90. package/src/math/mat3.ts +529 -0
  91. package/src/math/mat4.ts +588 -0
  92. package/src/math/quat.ts +193 -0
  93. package/src/math/scalar.ts +81 -0
  94. package/src/math/tensor.ts +17 -0
  95. package/src/math/vec3.ts +589 -0
  96. package/src/math/vec4.ts +10 -0
  97. package/src/physics/Body.ts +581 -0
  98. package/src/physics/CollisionFilter.ts +52 -0
  99. package/src/physics/SleepModule.ts +163 -0
  100. package/src/physics/broadphase/BodyPairsModule.ts +363 -0
  101. package/src/physics/broadphase/BvhModule.ts +237 -0
  102. package/src/physics/broadphase/BvhTree.ts +803 -0
  103. package/src/physics/broadphase/ConstraintPairsModule.ts +385 -0
  104. package/src/physics/broadphase/TriangleMeshBvhTree.ts +379 -0
  105. package/src/physics/manifold/ContactManifold.ts +227 -0
  106. package/src/physics/manifold/ContactManifoldModule.ts +623 -0
  107. package/src/physics/manifold/Face.ts +119 -0
  108. package/src/physics/manifold/ManifoldCache.ts +116 -0
  109. package/src/physics/manifold/clipping/clipPolyVsEdge.ts +131 -0
  110. package/src/physics/manifold/clipping/clipPolyVsPlane.ts +73 -0
  111. package/src/physics/manifold/clipping/clipPolyVsPoly.ts +72 -0
  112. package/src/physics/narrowphase/CollideBodiesModule.ts +755 -0
  113. package/src/physics/solver/ContactConstraintModule.ts +659 -0
  114. package/src/physics/solver/ManifoldConstraint.ts +420 -0
  115. package/src/physics/solver/estimateCollisionResponse.ts +146 -0
  116. package/src/shape/Aabb.ts +400 -0
  117. package/src/shape/Box.ts +231 -0
  118. package/src/shape/Capsule.ts +332 -0
  119. package/src/shape/CompoundShape.ts +288 -0
  120. package/src/shape/Convex.ts +130 -0
  121. package/src/shape/ConvexHull.ts +423 -0
  122. package/src/shape/Cylinder.ts +313 -0
  123. package/src/shape/HeightMap.ts +511 -0
  124. package/src/shape/Line.ts +14 -0
  125. package/src/shape/Plane.ts +116 -0
  126. package/src/shape/Ray.ts +81 -0
  127. package/src/shape/Segment.ts +25 -0
  128. package/src/shape/Shape.ts +77 -0
  129. package/src/shape/Sphere.ts +181 -0
  130. package/src/shape/TransformedShape.ts +51 -0
  131. package/src/shape/Triangle.ts +122 -0
  132. package/src/shape/TriangleMesh.ts +186 -0
  133. package/src/types.ts +1 -0
  134. package/src/world.ts +1335 -0
  135. package/tests/BodyPairsModule.test.ts +71 -0
  136. package/tests/BvhTree.test.ts +406 -0
  137. package/tests/test.md +642 -0
  138. package/tests/vec3.test.ts +12 -0
  139. package/tsconfig.json +20 -0
  140. package/vite.config.js +40 -0
@@ -0,0 +1,344 @@
1
+ import { PoolClass } from "monomorph";
2
+ import { Vec3 } from "../math/vec3";
3
+ import { squared } from "../math/scalar";
4
+
5
+ // TODO: this may need to change, not sure if value is too large
6
+ const floatEpsilon = 1e-5;
7
+
8
+ const normal = /*@__PURE__*/ Vec3.create();
9
+ const center = /*@__PURE__*/ Vec3.create();
10
+ const tempVector = /*@__PURE__*/ Vec3.create();
11
+
12
+ const p1 = /*@__PURE__*/ Vec3.create();
13
+ const p2 = /*@__PURE__*/ Vec3.create();
14
+
15
+ const edge = /*@__PURE__*/ Vec3.create();
16
+ const point = /*@__PURE__*/ Vec3.create();
17
+
18
+ const maxComponents = /*@__PURE__*/ Vec3.create();
19
+ const currentVertex = /*@__PURE__*/ Vec3.create();
20
+ const vertexA = /*@__PURE__*/ Vec3.create();
21
+ const vertexB = /*@__PURE__*/ Vec3.create();
22
+ const vertexC = /*@__PURE__*/ Vec3.create();
23
+ const vectorAB = /*@__PURE__*/ Vec3.create();
24
+ const vectorAC = /*@__PURE__*/ Vec3.create();
25
+ const crossAB_AC = /*@__PURE__*/ Vec3.create();
26
+ const furthestPoint = /*@__PURE__*/ Vec3.create();
27
+
28
+ /// Result enum that indicates how the hull got created
29
+ export const enum ConvexHullBuilder2dResult {
30
+ Success, ///< Hull building finished successfully
31
+ MaxVerticesReached, ///< Hull building finished successfully, but the desired accuracy was not reached because the max vertices limit was reached
32
+ }
33
+
34
+ type Tuple3 = [number, number, number];
35
+
36
+ class ConvexHull2dEdge {
37
+ normal: Tuple3;
38
+ center: Tuple3;
39
+ conflictList: number[];
40
+ prevEdge?: ConvexHull2dEdge;
41
+ nextEdge?: ConvexHull2dEdge;
42
+ startIndex: number;
43
+ furthestPointDistanceSquared: number = 0;
44
+
45
+ constructor(startIndex: number) {
46
+ this.normal = [0, 0, 0];
47
+ this.center = [0, 0, 0];
48
+ this.conflictList = [];
49
+ this.startIndex = startIndex;
50
+ }
51
+
52
+ isFacing(position: Vec3): boolean {
53
+ normal.x = this.normal[0];
54
+ normal.y = this.normal[1];
55
+ normal.z = this.normal[2];
56
+
57
+ center.x = this.center[0];
58
+ center.y = this.center[1];
59
+ center.z = this.center[2];
60
+
61
+ tempVector.subtractVectors(position, center);
62
+ return normal.dot(tempVector) > 0;
63
+ }
64
+
65
+ calculateNormalAndCenter(polyhedron: PoolClass<Vec3>): void {
66
+ p1.copy(polyhedron.array[this.startIndex]);
67
+ p2.copy(polyhedron.array[this.nextEdge!.startIndex]);
68
+
69
+ // Center of edge
70
+ center.addVectors(p1, p2);
71
+ center.scale(0.5);
72
+
73
+ // Create outward pointing normal.
74
+ // We have two choices for the normal (which satisfies normal . edge = 0):
75
+ // normal1 = (-edge.y, edge.x, 0)
76
+ // normal2 = (edge.y, -edge.x, 0)
77
+ // We want (normal x edge).z > 0 so that the normal points out of the polygon. Only normal2 satisfies this condition.
78
+ edge.subtractVectors(p2, p1);
79
+ normal.x = edge.y;
80
+ normal.y = -edge.x;
81
+ normal.z = 0;
82
+
83
+ this.normal[0] = normal.x;
84
+ this.normal[1] = normal.y;
85
+ this.normal[2] = normal.z;
86
+
87
+ this.center[0] = center.x;
88
+ this.center[1] = center.y;
89
+ this.center[2] = center.z;
90
+ }
91
+ }
92
+
93
+ export class ConvexHullBuilder2d {
94
+ firstEdge?: ConvexHull2dEdge;
95
+ numEdges: number = 0;
96
+
97
+ freeEdges(): void {
98
+ this.firstEdge = undefined;
99
+ this.numEdges = 0;
100
+ }
101
+
102
+ validateEdges(): void {
103
+ if (this.firstEdge === undefined) {
104
+ if (this.numEdges !== 0) {
105
+ throw new Error("mNumEdges is not 0");
106
+ }
107
+ return;
108
+ }
109
+
110
+ let count = 0;
111
+
112
+ let edge = this.firstEdge;
113
+ do {
114
+ // Validate connectivity
115
+ if (edge.nextEdge!.prevEdge !== edge) {
116
+ throw new Error("edge->mNextEdge->mPrevEdge != edge");
117
+ }
118
+
119
+ if (edge.prevEdge!.nextEdge !== edge) {
120
+ throw new Error("edge->mPrevEdge->mNextEdge != edge");
121
+ }
122
+
123
+ ++count;
124
+ edge = edge.nextEdge!;
125
+ } while (edge !== this.firstEdge);
126
+
127
+ // Validate that count matches
128
+ if (count !== this.numEdges) {
129
+ throw new Error("count != mNumEdges");
130
+ }
131
+ }
132
+
133
+ assignPointToEdge(polyhedron: PoolClass<Vec3>, positionIndex: number, edges: ConvexHull2dEdge[]): void {
134
+ point.copy(polyhedron.array[positionIndex]);
135
+
136
+ let bestEdge: ConvexHull2dEdge | undefined = undefined;
137
+ let bestDistanceSquared = 0;
138
+
139
+ // Test against all edges
140
+ for (const edge of edges) {
141
+ // Determine distance to edge
142
+ normal.x = edge.normal[0];
143
+ normal.y = edge.normal[1];
144
+ normal.z = edge.normal[2];
145
+
146
+ center.x = edge.center[0];
147
+ center.y = edge.center[1];
148
+ center.z = edge.center[2];
149
+
150
+ tempVector.subtractVectors(point, center);
151
+ const dot = normal.dot(tempVector);
152
+ if (dot > 0.0) {
153
+ const distanceSquared = (dot * dot) / normal.squaredLength();
154
+ if (distanceSquared > bestDistanceSquared) {
155
+ bestEdge = edge;
156
+ bestDistanceSquared = distanceSquared;
157
+ }
158
+ }
159
+ }
160
+
161
+ // If this point is in front of the edge, add it to the conflict list
162
+ if (bestEdge) {
163
+ if (bestDistanceSquared > bestEdge.furthestPointDistanceSquared) {
164
+ // This point is futher away than any others, update the distance and add point as last point
165
+ bestEdge.furthestPointDistanceSquared = bestDistanceSquared;
166
+ bestEdge.conflictList.push(positionIndex);
167
+ } else {
168
+ // Not the furthest point, add it as the before last point
169
+ bestEdge.conflictList.push(bestEdge.conflictList[bestEdge.conflictList.length - 1]);
170
+ bestEdge.conflictList[bestEdge.conflictList.length - 2] = positionIndex;
171
+ }
172
+ }
173
+ }
174
+
175
+ buildConvexHull(
176
+ outEdges: number[],
177
+ index1: number,
178
+ index2: number,
179
+ index3: number,
180
+ polyhedron: PoolClass<Vec3>,
181
+ tolerance: number,
182
+ maxVertexCount: number
183
+ ): ConvexHullBuilder2dResult {
184
+ // Clear any leftovers
185
+ this.freeEdges();
186
+ outEdges.length = 0;
187
+
188
+ // Reset flag
189
+ let result: ConvexHullBuilder2dResult = ConvexHullBuilder2dResult.Success;
190
+
191
+ // Determine a suitable tolerance for detecting that points are colinear
192
+ // Formula as per: Implementing Quickhull - Dirk Gregorius.
193
+ maxComponents.zero();
194
+ for (let i = 0; i < polyhedron.length; i++) {
195
+ currentVertex.copy(polyhedron.array[i]);
196
+ maxComponents.x = Math.max(maxComponents.x, Math.abs(currentVertex.x));
197
+ maxComponents.y = Math.max(maxComponents.y, Math.abs(currentVertex.y));
198
+ // maxComponents.z = Math.max(maxComponents.z, Math.abs(currentVertex.z));
199
+ }
200
+
201
+ const colinearToleranceSquared = squared(2.0 * floatEpsilon * (maxComponents.x + maxComponents.y));
202
+
203
+ // Increase desired tolerance if accuracy doesn't allow it
204
+ const toleranceSquared = Math.max(colinearToleranceSquared, squared(tolerance));
205
+
206
+ // Start with the initial indices in counter clockwise order
207
+ vertexA.copy(polyhedron.array[index1]);
208
+ vertexB.copy(polyhedron.array[index2]);
209
+ vertexC.copy(polyhedron.array[index3]);
210
+ vectorAB.subtractVectors(vertexB, vertexA);
211
+ vectorAC.subtractVectors(vertexC, vertexA);
212
+ crossAB_AC.crossVectors(vectorAB, vectorAC);
213
+ const z = crossAB_AC.z;
214
+ if (z < 0.0) {
215
+ const tempIndex = index1;
216
+ index1 = index2;
217
+ index2 = tempIndex;
218
+ }
219
+
220
+ // Create and link edges
221
+ const e1 = new ConvexHull2dEdge(index1);
222
+ const e2 = new ConvexHull2dEdge(index2);
223
+ const e3 = new ConvexHull2dEdge(index3);
224
+ e1.nextEdge = e2;
225
+ e1.prevEdge = e3;
226
+ e2.nextEdge = e3;
227
+ e2.prevEdge = e1;
228
+ e3.nextEdge = e1;
229
+ e3.prevEdge = e2;
230
+ this.firstEdge = e1;
231
+ this.numEdges = 3;
232
+
233
+ // Build the initial conflict lists
234
+ const edges: ConvexHull2dEdge[] = [e1, e2, e3];
235
+ for (const edge of edges) {
236
+ edge.calculateNormalAndCenter(polyhedron);
237
+ }
238
+
239
+ for (let index = 0; index < polyhedron.length; ++index) {
240
+ if (index === index1 || index === index2 || index === index3) {
241
+ continue;
242
+ }
243
+
244
+ this.assignPointToEdge(polyhedron, index, edges);
245
+ }
246
+
247
+ // Add the remaining points to the hull
248
+ while (true) {
249
+ // Check if we've reached the max amount of vertices that are allowed
250
+ if (this.numEdges >= maxVertexCount) {
251
+ result = ConvexHullBuilder2dResult.MaxVerticesReached;
252
+ break;
253
+ }
254
+
255
+ // Find the edge with the furthest point on it
256
+ let edgeWithFurthestPoint: ConvexHull2dEdge | undefined = undefined;
257
+ let furthestDistanceSquared = 0.0;
258
+ let edge: ConvexHull2dEdge = this.firstEdge;
259
+
260
+ do {
261
+ if (edge.furthestPointDistanceSquared > furthestDistanceSquared) {
262
+ furthestDistanceSquared = edge.furthestPointDistanceSquared;
263
+ edgeWithFurthestPoint = edge;
264
+ }
265
+ edge = edge.nextEdge!;
266
+ } while (edge !== this.firstEdge);
267
+
268
+ // If there is none closer than our tolerance value, we're done
269
+ if (!edgeWithFurthestPoint || furthestDistanceSquared < toleranceSquared) {
270
+ break;
271
+ }
272
+
273
+ // Take the furthest point
274
+ const furthestPointIndex = edgeWithFurthestPoint.conflictList.pop()!;
275
+ furthestPoint.copy(polyhedron.array[furthestPointIndex]);
276
+
277
+ // Find the horizon of edges that need to be removed
278
+ let firstEdge = edgeWithFurthestPoint;
279
+ do {
280
+ const prev = firstEdge.prevEdge!;
281
+ if (!prev.isFacing(furthestPoint)) {
282
+ break;
283
+ }
284
+ firstEdge = prev;
285
+ } while (firstEdge !== edgeWithFurthestPoint);
286
+
287
+ let lastEdge = edgeWithFurthestPoint;
288
+ do {
289
+ const next = lastEdge.nextEdge!;
290
+ if (!next.isFacing(furthestPoint)) {
291
+ break;
292
+ }
293
+ lastEdge = next;
294
+ } while (lastEdge !== edgeWithFurthestPoint);
295
+
296
+ // Create new edges
297
+ const e1 = new ConvexHull2dEdge(firstEdge.startIndex);
298
+ const e2 = new ConvexHull2dEdge(furthestPointIndex);
299
+ e1.nextEdge = e2;
300
+ e1.prevEdge = firstEdge.prevEdge;
301
+ e2.prevEdge = e1;
302
+ e2.nextEdge = lastEdge.nextEdge;
303
+ e1.prevEdge!.nextEdge = e1;
304
+ e2.nextEdge!.prevEdge = e2;
305
+ this.firstEdge = e1; // We could delete mFirstEdge so just update it to the newly created edge
306
+ this.numEdges += 2;
307
+
308
+ // Calculate normals
309
+ const newEdges: ConvexHull2dEdge[] = [e1, e2];
310
+ for (const newEdge of newEdges) {
311
+ newEdge.calculateNormalAndCenter(polyhedron);
312
+ }
313
+
314
+ // Delete the old edges
315
+ while (true) {
316
+ const next = firstEdge.nextEdge;
317
+
318
+ // Redistribute points in conflict list
319
+ for (const index of firstEdge.conflictList) {
320
+ this.assignPointToEdge(polyhedron, index, newEdges);
321
+ }
322
+
323
+ // Delete the old edge
324
+ // delete first_edge; TODO: probably not needed in TS
325
+ --this.numEdges;
326
+
327
+ if (firstEdge === lastEdge) {
328
+ break;
329
+ }
330
+ firstEdge = next!;
331
+ }
332
+ }
333
+
334
+ // Convert the edge list to a list of indices
335
+ outEdges.length = 0;
336
+ let edge = this.firstEdge;
337
+ do {
338
+ outEdges.push(edge.startIndex);
339
+ edge = edge.nextEdge!;
340
+ } while (edge !== this.firstEdge);
341
+
342
+ return result;
343
+ }
344
+ }