@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,130 @@
1
+ import { createClass, MonomorphType, NumberType, PropertyDefinitionMap } from "monomorph";
2
+ import { Isometry } from "../math/isometry";
3
+ import { Vec3 } from "../math/vec3";
4
+ import { Face } from "../physics/manifold/Face";
5
+ import { Mat4 } from "../math/mat4";
6
+
7
+ export interface SupportShape {
8
+ computeSupport(out: Vec3, direction: Vec3): void;
9
+ }
10
+
11
+ export const enum SupportMode {
12
+ ExcludeConvexRadius,
13
+ IncludeConvexRadius,
14
+ }
15
+
16
+ export interface ConvexWithcomputeSupportShape {
17
+ computeSupportShape(mode: SupportMode, scale: number): SupportShapeWithConvexRadius;
18
+ }
19
+
20
+ export interface SupportShapeWithConvexRadius extends SupportShape {
21
+ getConvexRadius(): number;
22
+ }
23
+
24
+ const localDirection = /*@__PURE__*/ Vec3.create();
25
+
26
+ export class TransformedConvexObject implements SupportShape {
27
+ transform: Isometry | null;
28
+ convexShape: SupportShape | null;
29
+
30
+ constructor() {
31
+ this.transform = null;
32
+ this.convexShape = null;
33
+ }
34
+
35
+ setData(transform: Isometry, convexShape: SupportShape): void {
36
+ this.transform = transform;
37
+ this.convexShape = convexShape;
38
+ }
39
+
40
+ computeSupport(out: Vec3, direction: Vec3): void {
41
+ this.transform!.matrix.multiply3x3Transposed(localDirection, direction);
42
+ this.convexShape!.computeSupport(out, localDirection);
43
+ out.transformFromMat4(this.transform!.matrix);
44
+ }
45
+ }
46
+
47
+ const transformedConvexShapeProps = {
48
+ transform: MonomorphType(Isometry),
49
+ } as const satisfies PropertyDefinitionMap;
50
+
51
+ const direction = /*@__PURE__*/ Vec3.create();
52
+
53
+ export class TransformedConvexShape extends createClass<TransformedConvexShape, typeof transformedConvexShapeProps>(
54
+ transformedConvexShapeProps
55
+ ) {
56
+ object: SupportShape | null;
57
+
58
+ constructor() {
59
+ super();
60
+ this.object = null;
61
+ }
62
+
63
+ // Calculate the support vector for this convex shape.
64
+ computeSupport(out: Vec3, inDirection: Vec3): void {
65
+ this.transform.matrix.multiply3x3Transposed(direction, inDirection);
66
+ this.object!.computeSupport(out, direction);
67
+ out.transformByMat4(this.transform.matrix);
68
+ }
69
+ }
70
+
71
+ const convexRadiusObjectProps = {
72
+ radius: NumberType(0.0),
73
+ } as const satisfies PropertyDefinitionMap;
74
+
75
+ export class ConvexRadiusObject extends createClass<ConvexRadiusObject, typeof convexRadiusObjectProps>(
76
+ convexRadiusObjectProps
77
+ ) {
78
+ // TODO: this is an actual reference, should this be changed?
79
+ convexShape: SupportShape | null;
80
+
81
+ constructor() {
82
+ super();
83
+ this.convexShape = null;
84
+ }
85
+
86
+ setData(radius: number, convexShape: SupportShape): void {
87
+ this.radius = radius;
88
+ this.convexShape = convexShape;
89
+ }
90
+
91
+ // Calculate the support vector for this convex shape.
92
+ computeSupport(out: Vec3, inDirection: Vec3): void {
93
+ const length = inDirection.length();
94
+ this.convexShape!.computeSupport(out, inDirection);
95
+ if (length > 0.0) {
96
+ out.addScaled(inDirection, this.radius / length);
97
+ }
98
+ }
99
+ }
100
+
101
+ const vertex = /*@__PURE__*/ Vec3.create();
102
+
103
+ export class PolygonConvexSupport implements SupportShape {
104
+ declare vertices: Face;
105
+
106
+ computeSupport(out: Vec3, direction: Vec3): void {
107
+ this.vertices.getVertex(out, 0);
108
+ let bestDot = out.dot(direction);
109
+
110
+ // iterate over the vertices of the face
111
+ for (let i = 0; i < this.vertices.numVertices; i++) {
112
+ this.vertices.getVertex(vertex, i);
113
+ const dot = vertex.dot(direction);
114
+ if (dot > bestDot) {
115
+ bestDot = dot;
116
+ out.copy(vertex);
117
+ }
118
+ }
119
+ }
120
+
121
+ computeSupportingFace(
122
+ out: Face,
123
+ subShapeID: number,
124
+ direction: Vec3,
125
+ scale: number,
126
+ centerOfMassTransform: Mat4
127
+ ): void {
128
+ throw new Error("Method not implemented.");
129
+ }
130
+ }
@@ -0,0 +1,423 @@
1
+ import {
2
+ createClass,
3
+ LazyReferenceType,
4
+ MonomorphType,
5
+ NumberType,
6
+ PropertyDefinitionMap,
7
+ PropertyDefinitionReference,
8
+ ReferenceListType,
9
+ } from "monomorph";
10
+ import { Vec3 } from "../math/vec3";
11
+ import { ConvexShapeInterface, ShapeType } from "./Shape";
12
+ import { Aabb } from "./Aabb";
13
+ import { Mat3 } from "../math/mat3";
14
+ import { Plane } from "./Plane";
15
+ import { NumberValue } from "../math/NumberValue";
16
+ import { SupportMode, SupportShapeWithConvexRadius } from "./Convex";
17
+ import { Face } from "../physics/manifold/Face";
18
+ import { Mat4 } from "../math/mat4";
19
+ import { Isometry } from "../math/isometry";
20
+ import { Quat } from "../math/quat";
21
+ import type { World } from "../world";
22
+
23
+ const maxPointsInHull = 1000;
24
+ const isometry = /*@__PURE__*/ Isometry.create();
25
+ const cross_n1_n2 = /*@__PURE__*/ Vec3.create();
26
+ let newPoint = /*@__PURE__*/ Vec3.create();
27
+
28
+ const p1 = /*@__PURE__*/ Plane.create();
29
+ const p2 = /*@__PURE__*/ Plane.create();
30
+ const p3 = /*@__PURE__*/ Plane.create();
31
+
32
+ export class ConvexHullNoConvex implements SupportShapeWithConvexRadius {
33
+ shape: ConvexHull;
34
+ points: typeof ConvexHull.prototype.shapeNoConvexPoints;
35
+
36
+ constructor(shape: ConvexHull, points: typeof ConvexHull.prototype.shapeNoConvexPoints) {
37
+ this.shape = shape;
38
+ this.points = points;
39
+ }
40
+
41
+ getConvexRadius() {
42
+ return this.shape.convexRadius;
43
+ }
44
+
45
+ computeSupport(out: Vec3, direction: Vec3) {
46
+ // Find the point with the highest projection on inDirection
47
+ let bestDot = -Infinity;
48
+ let bestPointIndex = -1;
49
+
50
+ for (let i = 0; i < this.points!.length; i++) {
51
+ const point = this.points!.getAtIndex(i)!;
52
+
53
+ // Check if its support is bigger than the current max
54
+ const dot = point.dot(direction);
55
+ if (dot > bestDot) {
56
+ bestDot = dot;
57
+ bestPointIndex = i;
58
+ }
59
+ }
60
+
61
+ out.copy(this.points!.getAtIndex(bestPointIndex)!);
62
+ }
63
+
64
+ computeSupportingFace(out: Face, subShapeID: number, direction: Vec3, scale: number, centerOfMassTransform: Mat4) {
65
+ throw new Error("Method not implemented.");
66
+ }
67
+ }
68
+
69
+ export class ConvexHullWithConvex implements SupportShapeWithConvexRadius {
70
+ shape: ConvexHull;
71
+
72
+ constructor(shape: ConvexHull) {
73
+ this.shape = shape;
74
+ }
75
+
76
+ getConvexRadius() {
77
+ return 0.0;
78
+ }
79
+
80
+ computeSupport(out: Vec3, direction: Vec3) {
81
+ // Find the point with the highest projection on inDirection
82
+ let bestDot = -Infinity;
83
+ let bestPointIndex = -1;
84
+
85
+ for (let i = 0; i < this.shape.points!.length; i++) {
86
+ const point = this.shape.points!.getAtIndex(i)!;
87
+
88
+ // Check if its support is bigger than the current max
89
+ const dot = point.position.dot(direction);
90
+ if (dot > bestDot) {
91
+ bestDot = dot;
92
+ bestPointIndex = i;
93
+ }
94
+ }
95
+
96
+ out.copy(this.shape.points!.getAtIndex(bestPointIndex)!.position);
97
+ }
98
+
99
+ computeSupportingFace(out: Face, subShapeID: number, direction: Vec3, scale: number, centerOfMassTransform: Mat4) {
100
+ throw new Error("Method not implemented.");
101
+ }
102
+ }
103
+
104
+ const convexHullPointProps = {
105
+ position: MonomorphType(Vec3),
106
+ numFaces: NumberType(0),
107
+ faces: MonomorphType(Vec3),
108
+ } as const satisfies PropertyDefinitionMap;
109
+
110
+ export class ConvexHullPoint extends createClass<ConvexHullPoint, typeof convexHullPointProps>(convexHullPointProps) {
111
+ toObject() {
112
+ return {
113
+ position: this.position.toObject(),
114
+ numFaces: this.numFaces,
115
+ faces: this.faces.toObject(),
116
+ };
117
+ }
118
+ }
119
+
120
+ const convexHullFaceProps = {
121
+ firstVertex: NumberType(0),
122
+ numVertices: NumberType(0),
123
+ } as const satisfies PropertyDefinitionMap;
124
+
125
+ export class ConvexHullFace extends createClass<ConvexHullFace, typeof convexHullFaceProps>(convexHullFaceProps) {
126
+ toObject() {
127
+ return {
128
+ firstVertex: this.firstVertex,
129
+ numVertices: this.numVertices,
130
+ };
131
+ }
132
+ }
133
+
134
+ const convexHullProps = {
135
+ computedCenterOfMass: MonomorphType(Vec3, undefined, true),
136
+ computedVolume: NumberType(0.0, true),
137
+ computedAabb: MonomorphType(Aabb, undefined, true),
138
+ convexRadius: NumberType(0.0),
139
+ innerRadius: NumberType(0.0, true),
140
+ inertia: MonomorphType(Mat3, undefined, true),
141
+ points: ReferenceListType(ConvexHullPoint), // { array: Float64Array(b), itemMaxCount: b / 7, itemSize: 7 } [ConvexHullPoint], points on the convex hull surface
142
+ faces: ReferenceListType(ConvexHullFace), // { array: Float64Array(c), itemMaxCount: c / 2, itemSize: 2 } [ConvexHullFace], faces of the convex hull surface
143
+ planes: ReferenceListType(Plane), // { array: Float64Array(d), itemMaxCount: d / 4, itemSize: 4 } [Plane], planes of the convex hull surface
144
+ vertexIdx: ReferenceListType(NumberValue), // { array: Float64Array(e), itemMaxCount: e, itemSize: 1 } [Uint32], vertex indices for each of the faces
145
+ shapeNoConvexPoints: ReferenceListType(Vec3), // { array: Float64Array(f), itemMaxCount: f / 3, itemSize: 3 } [Vec3], transformed points used by ConvexHullNoConvex
146
+ translation: MonomorphType(Vec3, { x: 0, y: 0, z: 0 }),
147
+ copyForDiff: LazyReferenceType((() => ConvexHull) as () => never) as PropertyDefinitionReference<
148
+ ConvexHull | null,
149
+ true
150
+ >,
151
+ } as const satisfies PropertyDefinitionMap;
152
+
153
+ const afterConstructorCode = `
154
+ this.world = null;
155
+ this.shapeNoConvex = null;
156
+ this.shapeWithConvex = null;
157
+ this.type = ${ShapeType.convexHull};
158
+ `;
159
+
160
+ export default class ConvexHull
161
+ extends createClass<ConvexHull, typeof convexHullProps>(convexHullProps, { afterConstructorCode })
162
+ implements ConvexShapeInterface
163
+ {
164
+ declare world: World | null;
165
+ declare shapeNoConvex: ConvexHullNoConvex;
166
+ declare shapeWithConvex: ConvexHullWithConvex;
167
+ declare type: ShapeType.convexHull;
168
+
169
+ computeSupportShape(inMode: SupportMode, inScale: number): SupportShapeWithConvexRadius {
170
+ // If there's no convex radius, we don't need to shrink the hull
171
+ if (this.convexRadius === 0.0) {
172
+ // TODO: implement scale helpers logic
173
+ this.shapeWithConvex.shape = this;
174
+ return this.shapeWithConvex;
175
+ }
176
+
177
+ switch (inMode) {
178
+ case SupportMode.IncludeConvexRadius: {
179
+ if (inScale === 1.0) {
180
+ this.shapeWithConvex.shape = this;
181
+ return this.shapeWithConvex;
182
+ } else {
183
+ throw new Error("Not implemented");
184
+ }
185
+ }
186
+ case SupportMode.ExcludeConvexRadius: {
187
+ if (inScale === 1.0) {
188
+ // Create support function
189
+ const hull = this.shapeNoConvex;
190
+
191
+ // #v-ifdef DEV
192
+ // assert
193
+ if (this.points!.length > maxPointsInHull) {
194
+ throw new Error(
195
+ `Not enough space, this should have been caught during shape creation!, points: ${
196
+ this.points!.length
197
+ }, max: ${maxPointsInHull}`
198
+ );
199
+ }
200
+ // #v-endif
201
+
202
+ let numPoints = 0;
203
+
204
+ for (let i = 0; i < this.points!.length; i++) {
205
+ const point = this.points!.getAtIndex(i)!;
206
+ newPoint.zero();
207
+
208
+ if (point.numFaces === 1) {
209
+ // Simply shift back by the convex radius using our 1 plane
210
+ // plane.copyFromList(this.planes, point.faces.x);
211
+ newPoint.addScaledToVector(point.position, this.planes!.getAtIndex(point.faces.x)!.normal, -this.convexRadius);
212
+ } else {
213
+ // Get first two planes and offset inwards by convex radius
214
+ p1.offsetPlaneAlongNormal(this.planes!.getAtIndex(point.faces.x)!, -this.convexRadius);
215
+ p2.offsetPlaneAlongNormal(this.planes!.getAtIndex(point.faces.y)!, -this.convexRadius);
216
+
217
+ if (point.numFaces === 3) {
218
+ // Get third plane and offset inwards by convex radius
219
+ p3.offsetPlaneAlongNormal(this.planes!.getAtIndex(point.faces.z)!, -this.convexRadius);
220
+ } else {
221
+ // Third plane has normal perpendicular to the other two planes and goes through the vertex position
222
+ // #v-ifdef DEV
223
+ // assert
224
+ if (point.numFaces !== 2) {
225
+ throw new Error(`Invalid number of faces: ${point.numFaces}`);
226
+ }
227
+ // #v-endif
228
+ cross_n1_n2.crossVectors(p1.normal, p2.normal);
229
+ p3.fromPointAndNormal(point.position, cross_n1_n2);
230
+ }
231
+
232
+ // Find intersection point between the three planes
233
+ const intersection = Plane.intersectPlanes(p1, p2, p3, newPoint);
234
+ if (!intersection) {
235
+ // Fallback: Just push point back using the first plane
236
+ newPoint.addScaledToVector(point.position, p1.normal, -this.convexRadius);
237
+ }
238
+ }
239
+
240
+ // Add point
241
+ // new_point.pushToList(hull.points);
242
+ hull.points!.getAtIndex(numPoints)!.copy(newPoint);
243
+ numPoints++;
244
+ }
245
+
246
+ hull.points!.length = numPoints;
247
+
248
+ return hull;
249
+ } else {
250
+ throw new Error("Not implemented");
251
+ }
252
+ }
253
+ default: {
254
+ throw new Error(`Invalid support mode: ${inMode}`);
255
+ }
256
+ }
257
+ }
258
+
259
+ computeSupportingFace(
260
+ out: Face,
261
+ subShapeID: number,
262
+ direction: Vec3,
263
+ scale: number,
264
+ centerOfMassTransform: Mat4
265
+ ): void {
266
+ out.clear();
267
+
268
+ // scaling is not implemented yet
269
+ if (scale !== 1.0) {
270
+ throw new Error("scaling is not implemented yet");
271
+ }
272
+
273
+ // find the plane that has a normal as similar as possible to the search direction vector
274
+ let bestDot = +Infinity;
275
+ let bestFaceIndex = -1;
276
+ for (let i = 0; i < this.planes!.length; i++) {
277
+ const plane = this.planes!.getAtIndex(i)!;
278
+ const dot = plane.normal.dot(direction);
279
+ if (dot < bestDot) {
280
+ bestDot = dot;
281
+ bestFaceIndex = i;
282
+ }
283
+ }
284
+
285
+ // get the best face
286
+ const face = this.faces!.getAtIndex(bestFaceIndex)!;
287
+
288
+ // TODO: handle inverse scale
289
+ const maxVerticesToReturn = out.buffer!.maxLength / 2;
290
+ const deltaVtx = Math.floor((face.numVertices + maxVerticesToReturn) / maxVerticesToReturn);
291
+
292
+ // TODO: Calculate transform with scale
293
+ for (let i = 0; i < face.numVertices; i += deltaVtx) {
294
+ const index = this.vertexIdx!.getAtIndex(face.firstVertex + i)!;
295
+ const point = this.points!.getAtIndex(index.value)!;
296
+ out.pushVertex(point.position);
297
+ }
298
+
299
+ // transform the out face to world space
300
+ out.transform(centerOfMassTransform);
301
+ }
302
+
303
+ computeInertiaTensor(out: Mat3, mass: number): void {
304
+ out.multiplyMatrixByScalar(this.inertia, mass / this.computedVolume);
305
+ }
306
+
307
+ computeInverseInertiaTensor(out: Mat3, mass: number): void {
308
+ this.computeInertiaTensor(out, mass);
309
+ out.invert();
310
+ }
311
+
312
+ computeWorldBounds(out: Aabb, translation: Vec3, rotation: Quat) {
313
+ isometry.fromRotationAndTranslation(rotation, translation);
314
+ out.transformAabb(this.computedAabb, isometry);
315
+ }
316
+
317
+ createTriangulatedVerticesAndNormalsArray(): [Float32Array, Float32Array] {
318
+ const vertices = [];
319
+ const normals = [];
320
+ // loop over faces
321
+ for (let i = 0; i < this.faces!.length; i++) {
322
+ const face = this.faces!.getAtIndex(i)!;
323
+ const plane = this.planes!.getAtIndex(i)!;
324
+
325
+ for (let j = 1; j < face.numVertices - 1; j++) {
326
+ // Triangle made up of the first vertex, and every subsequent pair
327
+ const indices = [0, j, j + 1];
328
+ for (let k of indices) {
329
+ // Adjusted to use the first vertex and the current pair to form triangles
330
+ const index = this.vertexIdx!.getAtIndex(face.firstVertex + k)!;
331
+ const point = this.points!.getAtIndex(index.value)!;
332
+
333
+ // Add vertex
334
+ vertices.push(point.position.x + this.computedCenterOfMass.x);
335
+ vertices.push(point.position.y + this.computedCenterOfMass.y);
336
+ vertices.push(point.position.z + this.computedCenterOfMass.z);
337
+
338
+ // Add normal (same for all vertices of the face)
339
+ normals.push(plane.normal.x);
340
+ normals.push(plane.normal.y);
341
+ normals.push(plane.normal.z);
342
+ }
343
+ }
344
+ }
345
+
346
+ return [new Float32Array(vertices), new Float32Array(normals)];
347
+ }
348
+
349
+ computeSurfaceNormal(out: Vec3, inLocalSurfacePosition: Vec3, subShapeId?: number): void {
350
+ const first_plane = this.planes!.getAtIndex(0)!;
351
+ best_normal.set(first_plane.normal);
352
+ let best_dist = Math.abs(first_plane.signedDistance(inLocalSurfacePosition));
353
+
354
+ // Find the face that has the shortest distance to the surface point
355
+ for (let i = 1; i < this.faces!.length; ++i) {
356
+ const plane = this.planes!.getAtIndex(i)!;
357
+ const dist = Math.abs(plane.signedDistance(inLocalSurfacePosition));
358
+ if (dist < best_dist) {
359
+ best_dist = dist;
360
+ best_normal.copy(plane.normal);
361
+ }
362
+ }
363
+
364
+ out.copy(best_normal);
365
+ }
366
+
367
+ hasChanged() {
368
+ // TODO: we don't currently support changes for this shape
369
+ return false;
370
+ }
371
+
372
+ commitChanges() {
373
+ if (this.hasChanged()) {
374
+ updateShape(this);
375
+ // this.world?.updateBodyProperties();
376
+ }
377
+ }
378
+ }
379
+
380
+ const best_normal = /*@__PURE__*/ Vec3.create();
381
+
382
+ function updateVolume(shape: ConvexHull) {
383
+ // recomputing volume for this shape not supported yet
384
+ }
385
+
386
+ function updateLocalBounds(shape: ConvexHull) {
387
+ const min = shape.computedAabb.min;
388
+ const max = shape.computedAabb.max;
389
+
390
+ // Set the min and max to the first point
391
+ min.set({ x: +Infinity, y: +Infinity, z: +Infinity });
392
+ max.set({ x: -Infinity, y: -Infinity, z: -Infinity });
393
+
394
+ // Loop over the rest of the points
395
+ for (let i = 0; i < shape.points!.length; i++) {
396
+ const point = shape.points!.getAtIndex(i)!;
397
+ min.x = Math.min(min.x, point.position.x);
398
+ min.y = Math.min(min.y, point.position.y);
399
+ min.z = Math.min(min.z, point.position.z);
400
+
401
+ max.x = Math.max(max.x, point.position.x);
402
+ max.y = Math.max(max.y, point.position.y);
403
+ max.z = Math.max(max.z, point.position.z);
404
+ }
405
+ }
406
+
407
+ function updateCenterOfMass(shape: ConvexHull) {
408
+ // recomputing center of mass for this shape not supported yet
409
+ }
410
+
411
+ function updateCopyForDiff(shape: ConvexHull) {
412
+ if (shape.copyForDiff) {
413
+ shape.copyForDiff.copy(shape);
414
+ shape.copyForDiff.copyForDiff = null;
415
+ }
416
+ }
417
+
418
+ export function updateShape(shape: ConvexHull) {
419
+ updateCopyForDiff(shape);
420
+ updateCenterOfMass(shape);
421
+ updateVolume(shape);
422
+ updateLocalBounds(shape);
423
+ }