@perplexdotgg/bounce 1.0.0 → 1.0.1

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 (134) 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
@@ -1,511 +0,0 @@
1
- import {
2
- createClass,
3
- LazyReferenceType,
4
- MonomorphType,
5
- NumberType,
6
- PropertyDefinitionMap,
7
- PropertyDefinitionReference,
8
- } from "monomorph";
9
- import { ShapeCollectionInterface, ShapeType } from "./Shape";
10
- import { Face } from "../physics/manifold/Face";
11
- import { Mat4 } from "../math/mat4";
12
- import { Mat3 } from "../math/mat3";
13
- import { Aabb } from "./Aabb";
14
- import { Vec3 } from "../math/vec3";
15
- import { Triangle } from "./Triangle";
16
- import { Isometry } from "../math/isometry";
17
- import { Quat } from "../math/quat";
18
- import { Tuple4 } from "../types";
19
- import type { World } from "../world";
20
- import { Ray } from "./Ray";
21
-
22
- export interface HeightMapVisitor {
23
- shouldVisitBlock(block: Aabb): boolean;
24
- visitTriangle(triangle: Triangle, activeEdges: number, triangleId: number): void;
25
- }
26
-
27
- class HeightMapRaycaster implements HeightMapVisitor {
28
- declare ray: Ray;
29
- declare onHit: (triangle: Triangle) => boolean;
30
-
31
- init(onHit: (triangle: Triangle) => boolean, ray: Ray): void {
32
- this.ray = ray;
33
- this.onHit = onHit;
34
- }
35
-
36
- shouldVisitBlock(block: Aabb): boolean {
37
- return this.ray.intersectsAabb(block);
38
- }
39
-
40
- visitTriangle(triangle: Triangle, activeEdges: number, triangleId: number): void {
41
- this.onHit(triangle);
42
- }
43
- }
44
-
45
- const heightMapRaycaster = /*@__PURE__*/ new HeightMapRaycaster();
46
-
47
- export function computeNumberOfLevels(numberOfSubdivisions: number): number {
48
- return Math.log2(numberOfSubdivisions) + 1;
49
- }
50
-
51
- export function computeNumberOfCells(numberOfSubdivisions: number): number {
52
- let numberOfCells = 0;
53
- let currentNumberOfSubdivisions = numberOfSubdivisions;
54
-
55
- while (currentNumberOfSubdivisions >= 1) {
56
- numberOfCells += currentNumberOfSubdivisions ** 2;
57
- currentNumberOfSubdivisions = currentNumberOfSubdivisions / 2;
58
- }
59
-
60
- return numberOfCells;
61
- }
62
-
63
- export function computeCornerIndicesInGrid(out: Tuple4<number>, x: number, z: number, stride: number): void {
64
- const bottomLeft = x * stride + z;
65
- const bottomRight = bottomLeft + 1;
66
- const topLeft = bottomLeft + stride;
67
- const topRight = topLeft + 1;
68
-
69
- out[0] = bottomLeft;
70
- out[1] = bottomRight;
71
- out[2] = topLeft;
72
- out[3] = topRight;
73
- }
74
-
75
- const triangle = /*@__PURE__*/ Triangle.create();
76
- const isometry = /*@__PURE__*/ Isometry.create();
77
- const interpolatedPoint = /*@__PURE__*/ Vec3.create();
78
- const a = /*@__PURE__*/ Vec3.create();
79
- const b = /*@__PURE__*/ Vec3.create();
80
- const c = /*@__PURE__*/ Vec3.create();
81
- const d = /*@__PURE__*/ Vec3.create();
82
- const scale = /*@__PURE__*/ Vec3.create();
83
- const blockAabb = /*@__PURE__*/ Aabb.create();
84
- const normal = /*@__PURE__*/ Vec3.create();
85
-
86
- const heightMapProps = {
87
- computedCenterOfMass: MonomorphType(Vec3, undefined, true),
88
- computedVolume: NumberType(0.0, true),
89
- computedAabb: MonomorphType(Aabb, {}, true),
90
- copyForDiff: LazyReferenceType((() => HeightMap) as () => never) as PropertyDefinitionReference<
91
- HeightMap | null,
92
- true
93
- >,
94
- subdivisionsCount: NumberType(0),
95
- scale: MonomorphType(Vec3),
96
- positionOffset: MonomorphType(Vec3),
97
- // heights: PoolReferenceType(Vec1),
98
- // minHeights: PoolReferenceType(Vec1),
99
- // maxHeights: PoolReferenceType(Vec1),
100
- // levels: PoolReferenceType(Vec1),
101
- // activeEdges: PoolReferenceType(Vec1),
102
- } as const satisfies PropertyDefinitionMap;
103
-
104
- const afterConstructorCode = `
105
- this.world = null;
106
- this.heights = [];
107
- this.minHeights = [];
108
- this.maxHeights = [];
109
- this.levels = [];
110
- this.activeEdges = [];
111
- this.stack = [];
112
- this.children = [0, 0, 0, 0];
113
- `;
114
-
115
- export class HeightMap
116
- extends createClass<HeightMap, typeof heightMapProps>(heightMapProps, { afterConstructorCode })
117
- implements ShapeCollectionInterface
118
- {
119
- type: ShapeType.heightMap = ShapeType.heightMap;
120
-
121
- declare world: World | null;
122
- declare heights: number[];
123
- declare minHeights: number[];
124
- declare maxHeights: number[];
125
- declare levels: number[];
126
- declare activeEdges: number[];
127
-
128
- /**
129
- * a stack to hold the indices of the blocks to visit during when walking the heightMap
130
- */
131
- declare stack: Array<number>;
132
-
133
- /**
134
- * a stack to hold the indices of the children of the current block when walking the heightMap
135
- */
136
- declare children: Tuple4<number>;
137
-
138
- computeSupportingFace(
139
- out: Face,
140
- subShapeID: number,
141
- direction: Vec3,
142
- scale: number,
143
- centerOfMassTransform: Mat4
144
- ): void {
145
- // get the triangle
146
-
147
- this.computeTriangle(triangle, subShapeID);
148
-
149
- // TODO: flip the triangle if scaled inside out
150
-
151
- // TODO: prescale the transform
152
-
153
- // transform to world space
154
- triangle.transform(centerOfMassTransform);
155
-
156
- // push world space triangle vertices to face
157
- out.pushVertex(triangle.a);
158
- out.pushVertex(triangle.b);
159
- out.pushVertex(triangle.c);
160
- }
161
-
162
- computeInverseInertiaTensor(out: Mat3, mass: number): void {
163
- out.zero();
164
- }
165
-
166
- computeWorldBounds(out: Aabb, translation: Vec3, rotation: Quat): void {
167
- isometry.fromRotationAndTranslation(rotation, translation);
168
- out.transformAabb(this.computedAabb, isometry);
169
- }
170
-
171
- computeInterpolatedHeight(localPosition: Vec3): number {
172
- this.computeInterpolatedLocalPoint(interpolatedPoint, localPosition);
173
- return interpolatedPoint.y;
174
- }
175
-
176
- computeInterpolatedLocalPoint(out: Vec3, localPosition: Vec3): void {
177
- // TODO: clamp the local position?
178
- const localPositionZ = localPosition.z;
179
- const localPositionX = localPosition.x;
180
-
181
- // get grid cell
182
- let columnIndex = Math.floor((localPositionZ - this.positionOffset.z) / this.scale.z);
183
- let rowIndex = Math.floor((localPositionX - this.positionOffset.x) / this.scale.x);
184
-
185
- // if either of the indices are out of bounds (< 0, or > subdivisionsCount), we return the local position as is
186
- if (
187
- columnIndex < 0 ||
188
- columnIndex >= this.subdivisionsCount ||
189
- rowIndex < 0 ||
190
- rowIndex >= this.subdivisionsCount
191
- ) {
192
- out.copy(localPosition);
193
- return;
194
- }
195
-
196
- // get the local position within the cell
197
- let normalizedZ = (localPositionZ - this.positionOffset.z) / this.scale.z - columnIndex;
198
- let normalizedX = (localPositionX - this.positionOffset.x) / this.scale.x - rowIndex;
199
-
200
- // get the quad vertices
201
-
202
- this.computeVertex(a, columnIndex + 0, rowIndex + 0); // bottom left
203
- this.computeVertex(b, columnIndex + 1, rowIndex + 0); // bottom right
204
- this.computeVertex(c, columnIndex + 0, rowIndex + 1); // top left
205
- this.computeVertex(d, columnIndex + 1, rowIndex + 1); // top right
206
-
207
- // we will use barycentric coordinates to get the height of the point
208
- let interpolatedHeight: number;
209
-
210
- // case: we project onto triangle ABC
211
- if (normalizedX + normalizedZ <= 1) {
212
- const u = normalizedZ;
213
- const v = normalizedX;
214
- const w = 1 - u - v;
215
- interpolatedHeight = a.y * w + b.y * u + c.y * v;
216
- }
217
- // case: we project onto triangle DCB
218
- else {
219
- const u = 1 - normalizedZ;
220
- const v = 1 - normalizedX;
221
- const w = 1 - u - v;
222
- interpolatedHeight = d.y * w + c.y * u + b.y * v;
223
- }
224
-
225
- // set the out point
226
- out.x = localPositionX;
227
- out.y = interpolatedHeight;
228
- out.z = localPositionZ;
229
- }
230
-
231
- castRay(onHit: (triangle: Triangle) => boolean, ray: Ray) {
232
- heightMapRaycaster.init(onHit, ray);
233
- this.walkHeightMap(heightMapRaycaster);
234
- }
235
-
236
- walkHeightMap(visitor: HeightMapVisitor): void {
237
- // get a stack to hold the indices of the blocks to visit
238
- const stack = this.stack;
239
- stack.length = 0;
240
- let stackCount = 0;
241
- let triangleId: number;
242
-
243
- const children = this.children;
244
- children.fill(0);
245
-
246
- // add the index of the root block
247
- stack[stackCount] = 0;
248
- stackCount++;
249
-
250
- // TODO: this can be cached
251
- const numberOfLevels = computeNumberOfLevels(this.subdivisionsCount);
252
-
253
- // iterate until the stack is empty
254
- while (stackCount > 0) {
255
- // visit the block at the top of the stack
256
- stackCount--;
257
-
258
- const index = stack[stackCount];
259
- const level = this.levels[index];
260
- const minHeight = this.positionOffset.y + this.minHeights[index] * this.scale.y;
261
- const maxHeight = this.positionOffset.y + this.maxHeights[index] * this.scale.y;
262
- // const currentNumberOfSubDivisions = Math.pow(2, level);
263
- const currentNumberOfSubDivisions = 1 << level;
264
-
265
- // get the scale at this level, which would be doubled for each level underneath
266
- const numberOfLevelsBelow = numberOfLevels - level - 1;
267
- // vec3.scale(scale, this.scale, Math.pow(2, numberOfLevelsBelow));
268
- scale.scaleVector(this.scale, 1 << numberOfLevelsBelow);
269
-
270
- // if at base level, row and column index are zero
271
- let rowIndex: number = 0;
272
- let columnIndex: number = 0;
273
- if (level > 0) {
274
- // get the offset of the upper level
275
- const offset = computeNumberOfCells(currentNumberOfSubDivisions / 2);
276
-
277
- const indexWithoutOffset = index - offset;
278
-
279
- // get the row and column index of the block
280
- rowIndex = Math.floor(indexWithoutOffset / currentNumberOfSubDivisions);
281
- // columnIndex = indexWithoutOffset % currentNumberOfSubDivisions;
282
- columnIndex = indexWithoutOffset & (currentNumberOfSubDivisions - 1);
283
- }
284
-
285
- // get the min x and min z position of the block
286
- const minX = this.positionOffset.x + rowIndex * scale.x;
287
- const minZ = this.positionOffset.z + columnIndex * scale.z;
288
-
289
- // get the max x and max z position of the block
290
- const maxX = minX + scale.x;
291
- const maxZ = minZ + scale.z;
292
-
293
- // create the aabb for the block
294
-
295
- blockAabb.min.fromArray([minX, minHeight, minZ]);
296
- blockAabb.max.fromArray([maxX, maxHeight, maxZ]);
297
- // expand the block aabb height by a small margin to account for flat planes
298
- blockAabb.min.y -= 0.1;
299
- blockAabb.max.y += 0.1;
300
-
301
- // case: we should not visit the block, skip
302
- if (visitor.shouldVisitBlock(blockAabb) === false) {
303
- continue;
304
- }
305
- // case: we should visit the block, get this block's children (blocks if not on last level, triangles if on last level)
306
- else {
307
- // case: on last level
308
- if (level === numberOfLevels - 1) {
309
- // console.log("visiting block", index - getNumberOfCells(currentNumberOfSubDivisions / 2));
310
-
311
- // get the 4 vertices of the quad
312
- this.computeVertex(a, columnIndex + 0, rowIndex + 0); // bottom left
313
- this.computeVertex(b, columnIndex + 1, rowIndex + 0); // bottom right
314
- this.computeVertex(c, columnIndex + 0, rowIndex + 1); // top left
315
- this.computeVertex(d, columnIndex + 1, rowIndex + 1); // top right
316
-
317
- // get the activeEdges for each triangle
318
- const firstTriangleIndex = index * 2 + 0;
319
- const secondTriangleIndex = index * 2 + 1;
320
-
321
- const activeEdges0 = this.activeEdges[firstTriangleIndex];
322
- const activeEdges1 = this.activeEdges[secondTriangleIndex];
323
-
324
- // visit the 2 triangles in the quad
325
- triangle.set({ a: a, b: b, c: c });
326
- triangleId = this.computeTriangleId(columnIndex, rowIndex, 0);
327
- // if (this.world.debug) {
328
- // console.log("visiting triangle", { columnIndex, rowIndex, triangleIndex: 0, triangleId });
329
- // }
330
- visitor.visitTriangle(triangle, activeEdges0, triangleId);
331
-
332
- triangle.set({ a: d, b: c, c: b });
333
- triangleId = this.computeTriangleId(columnIndex, rowIndex, 1);
334
- // if (this.world.debug) {
335
- // console.log("visiting triangle", { columnIndex, rowIndex, triangleIndex: 1, triangleId });
336
- // }
337
- visitor.visitTriangle(triangle, activeEdges1, triangleId);
338
- continue;
339
- }
340
-
341
- // case: not on last level
342
-
343
- // get the children of the block
344
- computeCornerIndicesInGrid(children, rowIndex * 2, columnIndex * 2, currentNumberOfSubDivisions * 2);
345
-
346
- // get the starting offset of the children
347
- const offset = computeNumberOfCells(currentNumberOfSubDivisions);
348
-
349
- // add the children to the stack
350
- stack[stackCount] = children[3] + offset;
351
- stackCount++;
352
-
353
- stack[stackCount] = children[2] + offset;
354
- stackCount++;
355
-
356
- stack[stackCount] = children[1] + offset;
357
- stackCount++;
358
-
359
- stack[stackCount] = children[0] + offset;
360
- stackCount++;
361
- }
362
- }
363
- }
364
-
365
- /**
366
- * this function visits every block and triangle of the heightMap. take care when using it on high resolution heightMaps. it is intended to generate a debug visualization of the heightMap.
367
- */
368
- createTriangulatedVerticesAndNormalsArray(): [Float64Array, Float64Array] {
369
- // performance is not a concern for this function, so we can make new allocations here
370
-
371
- const vertices: number[] = [];
372
- const normals: number[] = [];
373
-
374
- class MyVisitor implements HeightMapVisitor {
375
- shouldVisitBlock(block: Aabb): boolean {
376
- return true;
377
- }
378
-
379
- visitTriangle(triangle: Triangle, activeEdges: number, triangleId: number): void {
380
- triangle.computeNormal(normal);
381
-
382
- vertices.push(triangle.a.x, triangle.a.y, triangle.a.z);
383
- vertices.push(triangle.b.x, triangle.b.y, triangle.b.z);
384
- vertices.push(triangle.c.x, triangle.c.y, triangle.c.z);
385
-
386
- normals.push(normal.x, normal.y, normal.z);
387
- normals.push(normal.x, normal.y, normal.z);
388
- normals.push(normal.x, normal.y, normal.z);
389
- }
390
- }
391
- const visitor = new MyVisitor();
392
-
393
- this.walkHeightMap(visitor);
394
- return [new Float64Array(vertices), new Float64Array(normals)];
395
- }
396
-
397
- computeSurfaceNormal(out: Vec3, inLocalSurfacePosition: Vec3, subShapeId?: number): void {
398
- // #v-ifdef DEV
399
- // assert that we have a sub shape id
400
- if (subShapeId === undefined) {
401
- throw new Error("subShapeId is required");
402
- }
403
- // #v-endif
404
-
405
- this.computeTriangle(triangle, subShapeId);
406
- triangle.computeSurfaceNormal(out, inLocalSurfacePosition);
407
- }
408
-
409
- computeColumnCount(): number {
410
- return this.subdivisionsCount + 1;
411
- }
412
-
413
- computeRowCount(): number {
414
- return this.subdivisionsCount + 1;
415
- }
416
-
417
- computeTriangleId(columnIndex: number, rowIndex: number, triangleIndex: 0 | 1): number {
418
- return ((rowIndex * this.computeColumnCount() + columnIndex) << 1) | triangleIndex;
419
- }
420
-
421
- decodeTriangleId(triangleId: number): { columnIndex: number; rowIndex: number; triangleIndex: number } {
422
- const triangleIndex = triangleId & 1;
423
- const quadId = triangleId >> 1;
424
- const columnIndex = quadId % this.computeColumnCount();
425
- const rowIndex = Math.floor(quadId / this.computeColumnCount());
426
- return { columnIndex, rowIndex, triangleIndex };
427
- }
428
-
429
- computeTriangle(out: Triangle, triangleId: number): void {
430
- const { columnIndex, rowIndex, triangleIndex } = this.decodeTriangleId(triangleId);
431
-
432
- this.computeVertex(a, columnIndex + 0, rowIndex + 0); // bottom left
433
- this.computeVertex(b, columnIndex + 1, rowIndex + 0); // bottom right
434
- this.computeVertex(c, columnIndex + 0, rowIndex + 1); // top left
435
- this.computeVertex(d, columnIndex + 1, rowIndex + 1); // top right
436
-
437
- if (triangleIndex === 0) {
438
- out.set({ a: a, b: b, c: c });
439
- } else {
440
- out.set({ a: d, b: c, c: b });
441
- }
442
- }
443
-
444
- computeVertex(out: Vec3, columnIndex: number, rowIndex: number): void {
445
- out.z = this.positionOffset.z + columnIndex * this.scale.z;
446
- out.x = this.positionOffset.x + rowIndex * this.scale.x;
447
- out.y = this.positionOffset.y + this.heights[columnIndex + rowIndex * (this.subdivisionsCount + 1)] * this.scale.y;
448
- }
449
-
450
- hasChanged() {
451
- // TODO: we don't currently support changes for this shape
452
- return false;
453
- }
454
-
455
- commitChanges() {
456
- if (this.hasChanged()) {
457
- updateShape(this);
458
- // this.world?.updateBodyProperties();
459
- }
460
- }
461
- }
462
-
463
- function updateVolume(shape: HeightMap) {
464
- shape.computedVolume = 0.0;
465
- }
466
-
467
- export function updateLocalBounds(shape: HeightMap) {
468
- // find the min and max height
469
- let minHeight = Number.POSITIVE_INFINITY;
470
- let maxHeight = Number.NEGATIVE_INFINITY;
471
- for (let i = 0; i < shape.heights.length; i++) {
472
- const height = shape.heights[i] * shape.scale.y;
473
- minHeight = Math.min(minHeight, height);
474
- maxHeight = Math.max(maxHeight, height);
475
- }
476
-
477
- // set the local bounds
478
- shape.computedAabb.min.x = 0;
479
- // TODO: apply scale?
480
- // out.min.y = shape.scale * minHeight;
481
- shape.computedAabb.min.y = minHeight;
482
- shape.computedAabb.min.z = 0;
483
-
484
- shape.computedAabb.max.x = shape.subdivisionsCount * shape.scale.x;
485
- // TODO: apply scale?
486
- // out.max.y = shape.scale * maxHeight;
487
- shape.computedAabb.max.y = maxHeight;
488
- shape.computedAabb.max.z = shape.subdivisionsCount * shape.scale.z;
489
-
490
- // account for the position offset
491
- shape.computedAabb.min.addVector(shape.positionOffset);
492
- shape.computedAabb.max.addVector(shape.positionOffset);
493
- }
494
-
495
- function updateCopyForDiff(shape: HeightMap) {
496
- if (shape.copyForDiff) {
497
- shape.copyForDiff.copy(shape);
498
- shape.copyForDiff.copyForDiff = null;
499
- }
500
- }
501
-
502
- function updateCenterOfMass(shape: HeightMap) {
503
- shape.computedCenterOfMass.zero();
504
- }
505
-
506
- export function updateShape(shape: HeightMap) {
507
- updateCopyForDiff(shape);
508
- updateCenterOfMass(shape);
509
- updateVolume(shape);
510
- updateLocalBounds(shape);
511
- }
package/src/shape/Line.ts DELETED
@@ -1,14 +0,0 @@
1
- import { createClass, MonomorphType, PropertyDefinitionMap } from "monomorph";
2
- import { Vec3 } from "../math/vec3";
3
-
4
- const lineProps = {
5
- a: MonomorphType(Vec3),
6
- b: MonomorphType(Vec3),
7
- } as const satisfies PropertyDefinitionMap;
8
-
9
- export class Line extends createClass<Line, typeof lineProps>(lineProps) {
10
- setFromPointAndDirection(point: Vec3, direction: Vec3, length: number): void {
11
- this.a.copy(point);
12
- this.b.addScaledToVector(point, direction, length);
13
- }
14
- }
@@ -1,116 +0,0 @@
1
- import { createClass, MonomorphType, NumberType, PropertyDefinitionMap } from "monomorph";
2
- import { Vec3 } from "../math/vec3";
3
- import { Ray } from "./Ray";
4
-
5
- const cross_bn_cn = /*@__PURE__*/ Vec3.create();
6
-
7
- const planeProps = {
8
- normal: MonomorphType(Vec3),
9
- constant: NumberType(0),
10
- } as const satisfies PropertyDefinitionMap;
11
-
12
- export class Plane extends createClass<Plane, typeof planeProps>(planeProps) {
13
- toObject() {
14
- return {
15
- normal: this.normal.toObject(),
16
- constant: this.constant,
17
- };
18
- }
19
-
20
- fromPointAndNormal(point: Vec3, normal: Vec3): void {
21
- this.normal.copy(normal);
22
- this.constant = -normal.dot(point);
23
- }
24
-
25
- signedDistance(point: Vec3): number {
26
- return point.dot(this.normal) + this.constant;
27
- }
28
-
29
- offsetAlongNormal(out: Plane, inDistance: number): void {
30
- out.copy(this);
31
- out.constant -= inDistance;
32
- }
33
-
34
- offsetPlaneAlongNormal(plane: Plane, inDistance: number) {
35
- this.normal.copy(plane.normal);
36
- this.constant = plane.constant - inDistance;
37
- }
38
-
39
- toString(): string {
40
- return `Plane { normal: ${this.normal.toString()}, constant: ${this.constant} }`;
41
- }
42
-
43
- static intersectPlanes(planeA: Plane, planeB: Plane, planeC: Plane, outPoint: Vec3): boolean {
44
- // We solve the equation:
45
- // |ax, ay, az, aw| | x | | 0 |
46
- // |bx, by, bz, bw| * | y | = | 0 |
47
- // |cx, cy, cz, cw| | z | | 0 |
48
- // | 0, 0, 0, 1| | 1 | | 1 |
49
- // Where normal of plane 1 = (ax, ay, az), plane constant of 1 = aw, normal of plane 2 = (bx, by, bz) etc.
50
- // This involves inverting the matrix and multiplying it with [0, 0, 0, 1]
51
-
52
- // Fetch the normals and plane constants for the three planes
53
-
54
- cross_bn_cn.crossVectors(planeB.normal, planeC.normal);
55
-
56
- const denominator = planeA.normal.dot(cross_bn_cn);
57
- if (denominator === 0.0) {
58
- return false;
59
- }
60
-
61
- // The numerator is:
62
- // [aw*(bz*cy-by*cz)+ay*(bw*cz-bz*cw)+az*(by*cw-bw*cy)]
63
- // [aw*(bx*cz-bz*cx)+ax*(bz*cw-bw*cz)+az*(bw*cx-bx*cw)]
64
- // [aw*(by*cx-bx*cy)+ax*(bw*cy-by*cw)+ay*(bx*cw-bw*cx)]
65
-
66
- const a = planeA.normal;
67
- const b = planeB.normal;
68
- const c = planeC.normal;
69
-
70
- const ax = a.x;
71
- const ay = a.y;
72
- const az = a.z;
73
-
74
- const bx = b.x;
75
- const by = b.y;
76
- const bz = b.z;
77
-
78
- const cx = c.x;
79
- const cy = c.y;
80
- const cz = c.z;
81
-
82
- const aw = planeA.constant;
83
- const bw = planeB.constant;
84
- const cw = planeC.constant;
85
-
86
- outPoint.x = aw * (bz * cy - by * cz) + ay * (bw * cz - bz * cw) + az * (by * cw - bw * cy);
87
- outPoint.y = aw * (bx * cz - bz * cx) + ax * (bz * cw - bw * cz) + az * (bw * cx - bx * cw);
88
- outPoint.z = aw * (by * cx - bx * cy) + ax * (bw * cy - by * cw) + ay * (bx * cw - bw * cx);
89
-
90
- outPoint.scale(1 / denominator);
91
- return true;
92
- }
93
-
94
- /**
95
- * return the normalized fraction of the ray that intersects the plane in the interval [0.0, 1.0]
96
- */
97
- castRay(ray: Ray): number {
98
- const denominator = this.normal.dot(ray.direction);
99
-
100
- // case: ray is nearly parallel to the plane
101
- if (Math.abs(denominator) < 1e-6) {
102
- return 1.0;
103
- }
104
-
105
- const t = (this.constant - this.normal.dot(ray.origin)) / denominator;
106
- const fraction = t / ray.length;
107
-
108
- // case: ray does not intersect the plane
109
- if (fraction < 0.0 || fraction > 1.0) {
110
- return 1.0;
111
- }
112
-
113
- // case: ray intersects the plane
114
- return fraction;
115
- }
116
- }