planck-v2 2.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.

Potentially problematic release.


This version of planck-v2 might be problematic. Click here for more details.

Files changed (80) hide show
  1. package/LICENSE.txt +20 -0
  2. package/README.md +21 -0
  3. package/dist/planck-with-testbed.d.ts +4433 -0
  4. package/dist/planck-with-testbed.js +20730 -0
  5. package/dist/planck-with-testbed.js.map +1 -0
  6. package/dist/planck-with-testbed.umd.cjs +20730 -0
  7. package/dist/planck-with-testbed.umd.cjs.map +1 -0
  8. package/dist/planck.d.ts +4343 -0
  9. package/dist/planck.js +13516 -0
  10. package/dist/planck.js.map +1 -0
  11. package/dist/planck.umd.cjs +13516 -0
  12. package/dist/planck.umd.cjs.map +1 -0
  13. package/package.json +105 -0
  14. package/src/Settings.ts +238 -0
  15. package/src/__test__/Basic.test.ts +43 -0
  16. package/src/__test__/CCD.test.ts +70 -0
  17. package/src/__test__/Collision.test.ts +133 -0
  18. package/src/__test__/Math.test.ts +105 -0
  19. package/src/__test__/Pool.test.ts +48 -0
  20. package/src/__test__/World.test.ts +73 -0
  21. package/src/collision/AABB.ts +287 -0
  22. package/src/collision/BroadPhase.ts +210 -0
  23. package/src/collision/Distance.ts +962 -0
  24. package/src/collision/DynamicTree.ts +907 -0
  25. package/src/collision/Manifold.ts +420 -0
  26. package/src/collision/Raycast.ts +30 -0
  27. package/src/collision/Shape.ts +114 -0
  28. package/src/collision/TimeOfImpact.ts +502 -0
  29. package/src/collision/shape/BoxShape.ts +34 -0
  30. package/src/collision/shape/ChainShape.ts +360 -0
  31. package/src/collision/shape/CircleShape.ts +202 -0
  32. package/src/collision/shape/CollideCircle.ts +66 -0
  33. package/src/collision/shape/CollideCirclePolygon.ts +142 -0
  34. package/src/collision/shape/CollideEdgeCircle.ts +185 -0
  35. package/src/collision/shape/CollideEdgePolygon.ts +528 -0
  36. package/src/collision/shape/CollidePolygon.ts +280 -0
  37. package/src/collision/shape/EdgeShape.ts +316 -0
  38. package/src/collision/shape/PolygonShape.ts +581 -0
  39. package/src/common/Geo.ts +589 -0
  40. package/src/common/Jacobian.ts +17 -0
  41. package/src/common/Mat22.ts +221 -0
  42. package/src/common/Mat33.ts +224 -0
  43. package/src/common/Math.ts +96 -0
  44. package/src/common/Rot.ts +218 -0
  45. package/src/common/Sweep.ts +119 -0
  46. package/src/common/Transform.ts +203 -0
  47. package/src/common/Vec2.ts +624 -0
  48. package/src/common/Vec3.ts +188 -0
  49. package/src/dynamics/Body.ts +1198 -0
  50. package/src/dynamics/Contact.ts +1366 -0
  51. package/src/dynamics/Fixture.ts +506 -0
  52. package/src/dynamics/Joint.ts +226 -0
  53. package/src/dynamics/Position.ts +44 -0
  54. package/src/dynamics/Solver.ts +890 -0
  55. package/src/dynamics/Velocity.ts +18 -0
  56. package/src/dynamics/World.ts +1169 -0
  57. package/src/dynamics/joint/DistanceJoint.ts +463 -0
  58. package/src/dynamics/joint/FrictionJoint.ts +396 -0
  59. package/src/dynamics/joint/GearJoint.ts +591 -0
  60. package/src/dynamics/joint/MotorJoint.ts +430 -0
  61. package/src/dynamics/joint/MouseJoint.ts +390 -0
  62. package/src/dynamics/joint/PrismaticJoint.ts +903 -0
  63. package/src/dynamics/joint/PulleyJoint.ts +529 -0
  64. package/src/dynamics/joint/RevoluteJoint.ts +745 -0
  65. package/src/dynamics/joint/RopeJoint.ts +383 -0
  66. package/src/dynamics/joint/WeldJoint.ts +544 -0
  67. package/src/dynamics/joint/WheelJoint.ts +683 -0
  68. package/src/dynamics/joint/__test__/DistanceJoint.test.ts +66 -0
  69. package/src/index.ts +60 -0
  70. package/src/internal.ts +20 -0
  71. package/src/main.ts +3 -0
  72. package/src/serializer/__test__/Serialize.test.ts +52 -0
  73. package/src/serializer/__test__/Validator.test.ts +55 -0
  74. package/src/serializer/index.ts +257 -0
  75. package/src/serializer/schema.json +168 -0
  76. package/src/util/Pool.ts +120 -0
  77. package/src/util/Testbed.ts +157 -0
  78. package/src/util/Timer.ts +15 -0
  79. package/src/util/options.ts +28 -0
  80. package/src/util/stats.ts +26 -0
@@ -0,0 +1,420 @@
1
+ /*
2
+ * Planck.js
3
+ *
4
+ * Copyright (c) Erin Catto, Ali Shakiba
5
+ *
6
+ * This source code is licensed under the MIT license found in the
7
+ * LICENSE file in the root directory of this source tree.
8
+ */
9
+
10
+ import * as geo from "../common/Geo";
11
+ import { Vec2Value } from "../common/Vec2";
12
+ import { TransformValue } from "../common/Transform";
13
+ import { EPSILON } from "../common/Math";
14
+
15
+ /** @internal */ const math_sqrt = Math.sqrt;
16
+
17
+ /** @internal */ const pointA = geo.vec2(0, 0);
18
+ /** @internal */ const pointB = geo.vec2(0, 0);
19
+ /** @internal */ const cA = geo.vec2(0, 0);
20
+ /** @internal */ const cB = geo.vec2(0, 0);
21
+ /** @internal */ const dist = geo.vec2(0, 0);
22
+ /** @internal */ const planePoint = geo.vec2(0, 0);
23
+ /** @internal */ const clipPoint = geo.vec2(0, 0);
24
+
25
+ export enum ManifoldType {
26
+ e_unset = -1,
27
+ e_circles = 0,
28
+ e_faceA = 1,
29
+ e_faceB = 2,
30
+ }
31
+
32
+ export enum ContactFeatureType {
33
+ e_unset = -1,
34
+ e_vertex = 0,
35
+ e_face = 1,
36
+ }
37
+
38
+ /**
39
+ * This is used for determining the state of contact points.
40
+ */
41
+ export enum PointState {
42
+ /** Point does not exist */
43
+ nullState = 0,
44
+ /** Point was added in the update */
45
+ addState = 1,
46
+ /** Point persisted across the update */
47
+ persistState = 2,
48
+ /** Point was removed in the update */
49
+ removeState = 3,
50
+ }
51
+
52
+ /**
53
+ * Used for computing contact manifolds.
54
+ */
55
+ export class ClipVertex {
56
+ v = geo.vec2(0, 0);
57
+ id: ContactID = new ContactID();
58
+
59
+ set(o: ClipVertex): void {
60
+ geo.copyVec2(this.v, o.v);
61
+ this.id.set(o.id);
62
+ }
63
+ recycle() {
64
+ geo.zeroVec2(this.v);
65
+ this.id.recycle();
66
+ }
67
+ }
68
+
69
+ /**
70
+ * A manifold for two touching convex shapes. Manifolds are created in `evaluate`
71
+ * method of Contact subclasses.
72
+ *
73
+ * Supported manifold types are e_faceA or e_faceB for clip point versus plane
74
+ * with radius and e_circles point versus point with radius.
75
+ *
76
+ * We store contacts in this way so that position correction can account for
77
+ * movement, which is critical for continuous physics. All contact scenarios
78
+ * must be expressed in one of these types. This structure is stored across time
79
+ * steps, so we keep it small.
80
+ */
81
+ export class Manifold {
82
+ type: ManifoldType;
83
+
84
+ /**
85
+ * Usage depends on manifold type:
86
+ * - circles: not used
87
+ * - faceA: the normal on polygonA
88
+ * - faceB: the normal on polygonB
89
+ */
90
+ localNormal = geo.vec2(0, 0);
91
+
92
+ /**
93
+ * Usage depends on manifold type:
94
+ * - circles: the local center of circleA
95
+ * - faceA: the center of faceA
96
+ * - faceB: the center of faceB
97
+ */
98
+ localPoint = geo.vec2(0, 0);
99
+
100
+ /** The points of contact */
101
+ points: ManifoldPoint[] = [new ManifoldPoint(), new ManifoldPoint()];
102
+
103
+ /** The number of manifold points */
104
+ pointCount: number = 0;
105
+
106
+ set(that: Manifold): void {
107
+ this.type = that.type;
108
+ geo.copyVec2(this.localNormal, that.localNormal);
109
+ geo.copyVec2(this.localPoint, that.localPoint);
110
+ this.pointCount = that.pointCount;
111
+ this.points[0].set(that.points[0]);
112
+ this.points[1].set(that.points[1]);
113
+ }
114
+
115
+ recycle(): void {
116
+ this.type = ManifoldType.e_unset;
117
+ geo.zeroVec2(this.localNormal);
118
+ geo.zeroVec2(this.localPoint);
119
+ this.pointCount = 0;
120
+ this.points[0].recycle();
121
+ this.points[1].recycle();
122
+ }
123
+
124
+ /**
125
+ * Evaluate the manifold with supplied transforms. This assumes modest motion
126
+ * from the original state. This does not change the point count, impulses, etc.
127
+ * The radii must come from the shapes that generated the manifold.
128
+ */
129
+ getWorldManifold(
130
+ wm: WorldManifold | null,
131
+ xfA: TransformValue,
132
+ radiusA: number,
133
+ xfB: TransformValue,
134
+ radiusB: number,
135
+ ): WorldManifold {
136
+ if (this.pointCount == 0) {
137
+ return wm;
138
+ }
139
+
140
+ wm = wm || new WorldManifold();
141
+
142
+ wm.pointCount = this.pointCount;
143
+
144
+ const normal = wm.normal;
145
+ const points = wm.points;
146
+ const separations = wm.separations;
147
+
148
+ switch (this.type) {
149
+ case ManifoldType.e_circles: {
150
+ geo.setVec2(normal, 1.0, 0.0);
151
+ const manifoldPoint = this.points[0];
152
+ geo.transformVec2(pointA, xfA, this.localPoint);
153
+ geo.transformVec2(pointB, xfB, manifoldPoint.localPoint);
154
+ geo.subVec2(dist, pointB, pointA);
155
+ const lengthSqr = geo.lengthSqrVec2(dist);
156
+ if (lengthSqr > EPSILON * EPSILON) {
157
+ const length = math_sqrt(lengthSqr);
158
+ geo.scaleVec2(normal, 1 / length, dist);
159
+ }
160
+ geo.combine2Vec2(cA, 1, pointA, radiusA, normal);
161
+ geo.combine2Vec2(cB, 1, pointB, -radiusB, normal);
162
+ geo.combine2Vec2(points[0], 0.5, cA, 0.5, cB);
163
+ separations[0] = geo.dotSubVec2(cB, cA, normal);
164
+ break;
165
+ }
166
+
167
+ case ManifoldType.e_faceA: {
168
+ geo.rotVec2(normal, xfA.q, this.localNormal);
169
+ geo.transformVec2(planePoint, xfA, this.localPoint);
170
+
171
+ for (let i = 0; i < this.pointCount; ++i) {
172
+ const manifoldPoint = this.points[i];
173
+ geo.transformVec2(clipPoint, xfB, manifoldPoint.localPoint);
174
+ geo.combine2Vec2(cA, 1, clipPoint, radiusA - geo.dotSubVec2(clipPoint, planePoint, normal), normal);
175
+ geo.combine2Vec2(cB, 1, clipPoint, -radiusB, normal);
176
+ geo.combine2Vec2(points[i], 0.5, cA, 0.5, cB);
177
+ separations[i] = geo.dotSubVec2(cB, cA, normal);
178
+ }
179
+ break;
180
+ }
181
+
182
+ case ManifoldType.e_faceB: {
183
+ geo.rotVec2(normal, xfB.q, this.localNormal);
184
+ geo.transformVec2(planePoint, xfB, this.localPoint);
185
+
186
+ for (let i = 0; i < this.pointCount; ++i) {
187
+ const manifoldPoint = this.points[i];
188
+ geo.transformVec2(clipPoint, xfA, manifoldPoint.localPoint);
189
+ geo.combine2Vec2(cB, 1, clipPoint, radiusB - geo.dotSubVec2(clipPoint, planePoint, normal), normal);
190
+ geo.combine2Vec2(cA, 1, clipPoint, -radiusA, normal);
191
+ geo.combine2Vec2(points[i], 0.5, cA, 0.5, cB);
192
+ separations[i] = geo.dotSubVec2(cA, cB, normal);
193
+ }
194
+ // Ensure normal points from A to B.
195
+ geo.negVec2(normal);
196
+ break;
197
+ }
198
+ }
199
+
200
+ return wm;
201
+ }
202
+
203
+ static clipSegmentToLine = clipSegmentToLine;
204
+ static ClipVertex = ClipVertex;
205
+ static getPointStates = getPointStates;
206
+ static PointState = PointState;
207
+ }
208
+
209
+ /**
210
+ * A manifold point is a contact point belonging to a contact manifold. It holds
211
+ * details related to the geometry and dynamics of the contact points.
212
+ *
213
+ * This structure is stored across time steps, so we keep it small.
214
+ *
215
+ * Note: impulses are used for internal caching and may not provide reliable
216
+ * contact forces, especially for high speed collisions.
217
+ */
218
+ export class ManifoldPoint {
219
+ /**
220
+ * Usage depends on manifold type:
221
+ * - circles: the local center of circleB
222
+ * - faceA: the local center of circleB or the clip point of polygonB
223
+ * - faceB: the clip point of polygonA
224
+ */
225
+ localPoint = geo.vec2(0, 0);
226
+ /**
227
+ * The non-penetration impulse
228
+ */
229
+ normalImpulse = 0;
230
+ /**
231
+ * The friction impulse
232
+ */
233
+ tangentImpulse = 0;
234
+ /**
235
+ * Uniquely identifies a contact point between two shapes to facilitate warm starting
236
+ */
237
+ readonly id = new ContactID();
238
+
239
+ set(that: ManifoldPoint): void {
240
+ geo.copyVec2(this.localPoint, that.localPoint);
241
+ this.normalImpulse = that.normalImpulse;
242
+ this.tangentImpulse = that.tangentImpulse;
243
+ this.id.set(that.id);
244
+ }
245
+
246
+ recycle(): void {
247
+ geo.zeroVec2(this.localPoint);
248
+ this.normalImpulse = 0;
249
+ this.tangentImpulse = 0;
250
+ this.id.recycle();
251
+ }
252
+ }
253
+
254
+ /**
255
+ * Contact ids to facilitate warm starting.
256
+ *
257
+ * ContactFeature: The features that intersect to form the contact point.
258
+ */
259
+ export class ContactID {
260
+ /**
261
+ * Used to quickly compare contact ids.
262
+ */
263
+ key = -1;
264
+
265
+ /** ContactFeature index on shapeA */
266
+ indexA = -1;
267
+
268
+ /** ContactFeature index on shapeB */
269
+ indexB = -1;
270
+
271
+ /** ContactFeature type on shapeA */
272
+ typeA = ContactFeatureType.e_unset;
273
+
274
+ /** ContactFeature type on shapeB */
275
+ typeB = ContactFeatureType.e_unset;
276
+
277
+ setFeatures(indexA: number, typeA: ContactFeatureType, indexB: number, typeB: ContactFeatureType): void {
278
+ this.indexA = indexA;
279
+ this.indexB = indexB;
280
+ this.typeA = typeA;
281
+ this.typeB = typeB;
282
+ this.key = this.indexA + this.indexB * 4 + this.typeA * 16 + this.typeB * 64;
283
+ }
284
+
285
+ set(that: ContactID): void {
286
+ this.indexA = that.indexA;
287
+ this.indexB = that.indexB;
288
+ this.typeA = that.typeA;
289
+ this.typeB = that.typeB;
290
+ this.key = this.indexA + this.indexB * 4 + this.typeA * 16 + this.typeB * 64;
291
+ }
292
+
293
+ swapFeatures(): void {
294
+ const indexA = this.indexA;
295
+ const indexB = this.indexB;
296
+ const typeA = this.typeA;
297
+ const typeB = this.typeB;
298
+ this.indexA = indexB;
299
+ this.indexB = indexA;
300
+ this.typeA = typeB;
301
+ this.typeB = typeA;
302
+ this.key = this.indexA + this.indexB * 4 + this.typeA * 16 + this.typeB * 64;
303
+ }
304
+
305
+ recycle(): void {
306
+ this.indexA = 0;
307
+ this.indexB = 0;
308
+ this.typeA = ContactFeatureType.e_unset;
309
+ this.typeB = ContactFeatureType.e_unset;
310
+ this.key = -1;
311
+ }
312
+ }
313
+
314
+ /**
315
+ * This is used to compute the current state of a contact manifold.
316
+ */
317
+ export class WorldManifold {
318
+ /** World vector pointing from A to B */
319
+ normal = geo.vec2(0, 0);
320
+
321
+ /** World contact point (point of intersection) */
322
+ points = [geo.vec2(0, 0), geo.vec2(0, 0)]; // [maxManifoldPoints]
323
+
324
+ /** A negative value indicates overlap, in meters */
325
+ separations = [0, 0]; // [maxManifoldPoints]
326
+
327
+ /** The number of manifold points */
328
+ pointCount = 0;
329
+
330
+ recycle() {
331
+ geo.zeroVec2(this.normal);
332
+ geo.zeroVec2(this.points[0]);
333
+ geo.zeroVec2(this.points[1]);
334
+ this.separations[0] = 0;
335
+ this.separations[1] = 0;
336
+ this.pointCount = 0;
337
+ }
338
+ }
339
+
340
+ /**
341
+ * Compute the point states given two manifolds. The states pertain to the
342
+ * transition from manifold1 to manifold2. So state1 is either persist or remove
343
+ * while state2 is either add or persist.
344
+ */
345
+ export function getPointStates(
346
+ state1: PointState[],
347
+ state2: PointState[],
348
+ manifold1: Manifold,
349
+ manifold2: Manifold,
350
+ ): void {
351
+ // state1, state2: PointState[Settings.maxManifoldPoints]
352
+
353
+ // for (var i = 0; i < Settings.maxManifoldPoints; ++i) {
354
+ // state1[i] = PointState.nullState;
355
+ // state2[i] = PointState.nullState;
356
+ // }
357
+
358
+ // Detect persists and removes.
359
+ for (let i = 0; i < manifold1.pointCount; ++i) {
360
+ const id = manifold1.points[i].id;
361
+
362
+ state1[i] = PointState.removeState;
363
+
364
+ for (let j = 0; j < manifold2.pointCount; ++j) {
365
+ if (manifold2.points[j].id.key === id.key) {
366
+ state1[i] = PointState.persistState;
367
+ break;
368
+ }
369
+ }
370
+ }
371
+
372
+ // Detect persists and adds.
373
+ for (let i = 0; i < manifold2.pointCount; ++i) {
374
+ const id = manifold2.points[i].id;
375
+
376
+ state2[i] = PointState.addState;
377
+
378
+ for (let j = 0; j < manifold1.pointCount; ++j) {
379
+ if (manifold1.points[j].id.key === id.key) {
380
+ state2[i] = PointState.persistState;
381
+ break;
382
+ }
383
+ }
384
+ }
385
+ }
386
+
387
+ /**
388
+ * Clipping for contact manifolds. Sutherland-Hodgman clipping.
389
+ */
390
+ export function clipSegmentToLine(
391
+ vOut: ClipVertex[],
392
+ vIn: ClipVertex[],
393
+ normal: Vec2Value,
394
+ offset: number,
395
+ vertexIndexA: number,
396
+ ): number {
397
+ // Start with no output points
398
+ let numOut = 0;
399
+
400
+ // Calculate the distance of end points to the line
401
+ const distance0 = geo.dotVec2(normal, vIn[0].v) - offset;
402
+ const distance1 = geo.dotVec2(normal, vIn[1].v) - offset;
403
+
404
+ // If the points are behind the plane
405
+ if (distance0 <= 0.0) vOut[numOut++].set(vIn[0]);
406
+ if (distance1 <= 0.0) vOut[numOut++].set(vIn[1]);
407
+
408
+ // If the points are on different sides of the plane
409
+ if (distance0 * distance1 < 0.0) {
410
+ // Find intersection point of edge and plane
411
+ const interp = distance0 / (distance0 - distance1);
412
+ geo.combine2Vec2(vOut[numOut].v, 1 - interp, vIn[0].v, interp, vIn[1].v);
413
+
414
+ // VertexA is hitting edgeB.
415
+ vOut[numOut].id.setFeatures(vertexIndexA, ContactFeatureType.e_vertex, vIn[0].id.indexB, ContactFeatureType.e_face);
416
+ ++numOut;
417
+ }
418
+
419
+ return numOut;
420
+ }
@@ -0,0 +1,30 @@
1
+ /*
2
+ * Planck.js
3
+ *
4
+ * Copyright (c) Erin Catto, Ali Shakiba
5
+ *
6
+ * This source code is licensed under the MIT license found in the
7
+ * LICENSE file in the root directory of this source tree.
8
+ */
9
+
10
+ import { Vec2Value } from "../common/Vec2";
11
+
12
+ /**
13
+ * Ray-cast input data. The ray extends from `p1` to `p1 + maxFraction * (p2 - p1)`.
14
+ */
15
+ export interface RayCastInput {
16
+ p1: Vec2Value;
17
+ p2: Vec2Value;
18
+ maxFraction: number;
19
+ }
20
+
21
+ export type RayCastCallback = (subInput: RayCastInput, id: number) => number;
22
+
23
+ /**
24
+ * Ray-cast output data. The ray hits at `p1 + fraction * (p2 - p1)`,
25
+ * where `p1` and `p2` come from RayCastInput.
26
+ */
27
+ export interface RayCastOutput {
28
+ normal: Vec2Value;
29
+ fraction: number;
30
+ }
@@ -0,0 +1,114 @@
1
+ /*
2
+ * Planck.js
3
+ *
4
+ * Copyright (c) Erin Catto, Ali Shakiba
5
+ *
6
+ * This source code is licensed under the MIT license found in the
7
+ * LICENSE file in the root directory of this source tree.
8
+ */
9
+
10
+ import type { MassData } from "../dynamics/Body";
11
+ import { AABBValue } from "./AABB";
12
+ import { RayCastOutput, RayCastInput } from "./Raycast";
13
+ import { DistanceProxy } from "./Distance";
14
+ import type { TransformValue } from "../common/Transform";
15
+ import type { Vec2Value } from "../common/Vec2";
16
+ import { Style } from "../util/Testbed";
17
+
18
+ // todo make shape an interface
19
+
20
+ /**
21
+ * A shape is used for collision detection. You can create a shape however you
22
+ * like. Shapes used for simulation in World are created automatically when a
23
+ * Fixture is created. Shapes may encapsulate one or more child shapes.
24
+ */
25
+ export abstract class Shape {
26
+ /** @hidden */ m_type: ShapeType;
27
+
28
+ /**
29
+ * @hidden
30
+ * Radius of a shape. For polygonal shapes this must be b2_polygonRadius.
31
+ * There is no support for making rounded polygons.
32
+ */
33
+ m_radius: number;
34
+
35
+ /** Styling for dev-tools. */
36
+ style: Style = {};
37
+
38
+ /** @hidden @experimental Similar to userData, but used by dev-tools or runtime environment. */
39
+ appData: Record<string, any> = {};
40
+
41
+ /** @hidden */
42
+ abstract _reset(): void;
43
+
44
+ static isValid(obj: any): boolean {
45
+ if (obj === null || typeof obj === "undefined") {
46
+ return false;
47
+ }
48
+ return typeof obj.m_type === "string" && typeof obj.m_radius === "number";
49
+ }
50
+
51
+ abstract getRadius(): number;
52
+
53
+ /**
54
+ * Get the type of this shape. You can use this to down cast to the concrete
55
+ * shape.
56
+ *
57
+ * @return the shape type.
58
+ */
59
+ abstract getType(): ShapeType;
60
+
61
+ /**
62
+ * @internal @deprecated Shapes should be treated as immutable.
63
+ *
64
+ * clone the concrete shape.
65
+ */
66
+ abstract _clone(): Shape;
67
+
68
+ /**
69
+ * Get the number of child primitives.
70
+ */
71
+ abstract getChildCount(): number;
72
+
73
+ /**
74
+ * Test a point for containment in this shape. This only works for convex
75
+ * shapes.
76
+ *
77
+ * @param xf The shape world transform.
78
+ * @param p A point in world coordinates.
79
+ */
80
+ abstract testPoint(xf: TransformValue, p: Vec2Value): boolean;
81
+
82
+ /**
83
+ * Cast a ray against a child shape.
84
+ *
85
+ * @param output The ray-cast results.
86
+ * @param input The ray-cast input parameters.
87
+ * @param xf The transform to be applied to the shape.
88
+ * @param childIndex The child shape index
89
+ */
90
+ abstract rayCast(output: RayCastOutput, input: RayCastInput, xf: TransformValue, childIndex: number): boolean;
91
+
92
+ /**
93
+ * Given a transform, compute the associated axis aligned bounding box for a
94
+ * child shape.
95
+ *
96
+ * @param aabb Returns the axis aligned box.
97
+ * @param xf The world transform of the shape.
98
+ * @param childIndex The child shape
99
+ */
100
+ abstract computeAABB(aabb: AABBValue, xf: TransformValue, childIndex: number): void;
101
+
102
+ /**
103
+ * Compute the mass properties of this shape using its dimensions and density.
104
+ * The inertia tensor is computed about the local origin.
105
+ *
106
+ * @param massData Returns the mass data for this shape.
107
+ * @param density The density in kilograms per meter squared.
108
+ */
109
+ abstract computeMass(massData: MassData, density?: number): void;
110
+
111
+ abstract computeDistanceProxy(proxy: DistanceProxy, childIndex: number): void;
112
+ }
113
+
114
+ export type ShapeType = "circle" | "edge" | "polygon" | "chain";