@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.
- package/build/bounce.d.ts +39501 -0
- package/build/bounce.js +17166 -0
- package/package.json +1 -1
- package/src/builders/ConvexHullBuilder.ts +0 -437
- package/src/builders/ConvexHullBuilder2d.ts +0 -344
- package/src/builders/ConvexHullBuilder3d.ts +0 -1689
- package/src/builders/HeightMapBuilder.ts +0 -414
- package/src/builders/TriangleMeshBuilder.ts +0 -92
- package/src/collision/CastShapesModule.ts +0 -184
- package/src/collision/CollideShapesModule.ts +0 -152
- package/src/collision/HeightMapCaster.ts +0 -38
- package/src/collision/HeightMapCollider.ts +0 -33
- package/src/collision/TriangleCaster.ts +0 -249
- package/src/collision/TriangleCollider.ts +0 -308
- package/src/collision/TriangleCollider2.ts +0 -379
- package/src/collision/activeEdge.ts +0 -146
- package/src/collision/cast/cast.ts +0 -139
- package/src/collision/cast/castCompoundVsCompound.ts +0 -59
- package/src/collision/cast/castCompoundVsConvex.ts +0 -116
- package/src/collision/cast/castConvexVsCompound.ts +0 -123
- package/src/collision/cast/castConvexVsConvex.ts +0 -213
- package/src/collision/cast/castConvexVsHeightMap.ts +0 -73
- package/src/collision/cast/castConvexVsTriangleMesh.ts +0 -56
- package/src/collision/cast/castRayVsCompound.ts +0 -44
- package/src/collision/cast/castRayVsConvex.ts +0 -45
- package/src/collision/cast/castRayVsHeightMap.ts +0 -58
- package/src/collision/cast/castRayVsTriangleMesh.ts +0 -58
- package/src/collision/closestPoints/closestPoints.ts +0 -23
- package/src/collision/closestPoints/computeBarycentricCoordinates2d.ts +0 -32
- package/src/collision/closestPoints/computeBarycentricCoordinates3d.ts +0 -81
- package/src/collision/closestPoints/computeClosestPointOnLine.ts +0 -30
- package/src/collision/closestPoints/computeClosestPointOnTetrahedron.ts +0 -96
- package/src/collision/closestPoints/computeClosestPointOnTriangle.ts +0 -195
- package/src/collision/closestPoints/isOriginOutsideOfPlane.ts +0 -25
- package/src/collision/closestPoints/isOriginOutsideOfTrianglePlanes.ts +0 -72
- package/src/collision/collide/collide.ts +0 -146
- package/src/collision/collide/collideCompoundVsCompound.ts +0 -60
- package/src/collision/collide/collideCompoundVsConvex.ts +0 -59
- package/src/collision/collide/collideCompoundVsHeightMap.ts +0 -73
- package/src/collision/collide/collideCompoundVsTriangleMesh.ts +0 -56
- package/src/collision/collide/collideConvexVsCompound.ts +0 -57
- package/src/collision/collide/collideConvexVsConvex.ts +0 -225
- package/src/collision/collide/collideConvexVsConvexImp.ts +0 -236
- package/src/collision/collide/collideConvexVsHeightMap.ts +0 -53
- package/src/collision/collide/collideConvexVsTriangleMesh.ts +0 -58
- package/src/collision/collide/collideHeightMapVsCompound.ts +0 -69
- package/src/collision/collide/collideHeightMapVsConvex.ts +0 -53
- package/src/collision/collide/collideSphereVsSphere.ts +0 -81
- package/src/collision/collide/collideTriangleMeshVsCompound.ts +0 -58
- package/src/collision/collide/collideTriangleMeshVsConvex.ts +0 -58
- package/src/collision/epa/EpaConvexHullBuilder.ts +0 -397
- package/src/collision/epa/StaticArray.ts +0 -154
- package/src/collision/epa/TriangleFactory.ts +0 -32
- package/src/collision/epa/arrays.ts +0 -99
- package/src/collision/epa/binaryHeap.ts +0 -82
- package/src/collision/epa/structs.ts +0 -227
- package/src/collision/gjk/GjkModule.ts +0 -864
- package/src/collision/gjk/PenetrationDepthModule.ts +0 -493
- package/src/collision/gjk/SupportPoints.ts +0 -50
- package/src/collision/imp/MinkowskiDifference.ts +0 -36
- package/src/collision/imp/computeExploredDistanceLowerUpperBound.ts +0 -40
- package/src/collision/imp/finalizeImpResult.ts +0 -69
- package/src/collision/imp/findContactImp.ts +0 -196
- package/src/collision/imp/imp.ts +0 -28
- package/src/collision/imp/incrementalMinimumDistanceExploreDirection.ts +0 -207
- package/src/collision/mpr/findPortal.ts +0 -152
- package/src/collision/mpr/mpr.ts +0 -29
- package/src/collision/mpr/updatePortal.ts +0 -52
- package/src/constraints/BaseConstraint.ts +0 -50
- package/src/constraints/ConstraintOptions.ts +0 -22
- package/src/constraints/ConstraintSolver.ts +0 -119
- package/src/constraints/DistanceConstraint.ts +0 -229
- package/src/constraints/FixedConstraint.ts +0 -203
- package/src/constraints/HingeConstraint.ts +0 -460
- package/src/constraints/PointConstraint.ts +0 -108
- package/src/constraints/components/AngleComponent.ts +0 -226
- package/src/constraints/components/AxisComponent.ts +0 -263
- package/src/constraints/components/HingeComponent.ts +0 -215
- package/src/constraints/components/Motor.ts +0 -36
- package/src/constraints/components/PointConstraintComponent.ts +0 -179
- package/src/constraints/components/RotationEulerComponent.ts +0 -139
- package/src/constraints/components/Spring.ts +0 -30
- package/src/constraints/components/SpringComponent.ts +0 -71
- package/src/constraints/types.ts +0 -6
- package/src/helpers.ts +0 -147
- package/src/index.ts +0 -50
- package/src/math/BasicTransform.ts +0 -19
- package/src/math/NumberValue.ts +0 -13
- package/src/math/isometry.ts +0 -64
- package/src/math/mat3.ts +0 -529
- package/src/math/mat4.ts +0 -588
- package/src/math/quat.ts +0 -193
- package/src/math/scalar.ts +0 -81
- package/src/math/tensor.ts +0 -17
- package/src/math/vec3.ts +0 -589
- package/src/math/vec4.ts +0 -10
- package/src/physics/Body.ts +0 -581
- package/src/physics/CollisionFilter.ts +0 -52
- package/src/physics/SleepModule.ts +0 -163
- package/src/physics/broadphase/BodyPairsModule.ts +0 -363
- package/src/physics/broadphase/BvhModule.ts +0 -237
- package/src/physics/broadphase/BvhTree.ts +0 -803
- package/src/physics/broadphase/ConstraintPairsModule.ts +0 -385
- package/src/physics/broadphase/TriangleMeshBvhTree.ts +0 -379
- package/src/physics/manifold/ContactManifold.ts +0 -227
- package/src/physics/manifold/ContactManifoldModule.ts +0 -623
- package/src/physics/manifold/Face.ts +0 -119
- package/src/physics/manifold/ManifoldCache.ts +0 -116
- package/src/physics/manifold/clipping/clipPolyVsEdge.ts +0 -131
- package/src/physics/manifold/clipping/clipPolyVsPlane.ts +0 -73
- package/src/physics/manifold/clipping/clipPolyVsPoly.ts +0 -72
- package/src/physics/narrowphase/CollideBodiesModule.ts +0 -755
- package/src/physics/solver/ContactConstraintModule.ts +0 -659
- package/src/physics/solver/ManifoldConstraint.ts +0 -420
- package/src/physics/solver/estimateCollisionResponse.ts +0 -146
- package/src/shape/Aabb.ts +0 -400
- package/src/shape/Box.ts +0 -231
- package/src/shape/Capsule.ts +0 -332
- package/src/shape/CompoundShape.ts +0 -288
- package/src/shape/Convex.ts +0 -130
- package/src/shape/ConvexHull.ts +0 -423
- package/src/shape/Cylinder.ts +0 -313
- package/src/shape/HeightMap.ts +0 -511
- package/src/shape/Line.ts +0 -14
- package/src/shape/Plane.ts +0 -116
- package/src/shape/Ray.ts +0 -81
- package/src/shape/Segment.ts +0 -25
- package/src/shape/Shape.ts +0 -77
- package/src/shape/Sphere.ts +0 -181
- package/src/shape/TransformedShape.ts +0 -51
- package/src/shape/Triangle.ts +0 -122
- package/src/shape/TriangleMesh.ts +0 -186
- package/src/types.ts +0 -1
- package/src/world.ts +0 -1335
package/src/shape/Capsule.ts
DELETED
|
@@ -1,332 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
createClass,
|
|
3
|
-
LazyReferenceType,
|
|
4
|
-
MonomorphType,
|
|
5
|
-
NumberType,
|
|
6
|
-
PropertyDefinitionMap,
|
|
7
|
-
PropertyDefinitionReference,
|
|
8
|
-
} from "monomorph";
|
|
9
|
-
import { Vec3 } from "../math/vec3";
|
|
10
|
-
import { Face } from "../physics/manifold/Face";
|
|
11
|
-
import { Mat4 } from "../math/mat4";
|
|
12
|
-
import { Quat } from "../math/quat";
|
|
13
|
-
import { ConvexShapeInterface, ShapeType } from "./Shape";
|
|
14
|
-
import type { World } from "../world";
|
|
15
|
-
import { Isometry } from "../math/isometry";
|
|
16
|
-
import { Mat3 } from "../math/mat3";
|
|
17
|
-
import { CollisionResult } from "../collision/collide/collide";
|
|
18
|
-
import { Aabb } from "./Aabb";
|
|
19
|
-
import { SupportMode, SupportShapeWithConvexRadius } from "./Convex";
|
|
20
|
-
import { Triangle } from "../collision/epa/structs";
|
|
21
|
-
|
|
22
|
-
/// Used by (Tapered)CapsuleShape to determine when supporting face is an edge rather than a point (unit: meter)
|
|
23
|
-
export const capsuleProjectionSlop = 0.02;
|
|
24
|
-
|
|
25
|
-
const scaledHalfHeightOfCylinder = /*@__PURE__*/ Vec3.create();
|
|
26
|
-
const tempVector = /*@__PURE__*/ Vec3.create();
|
|
27
|
-
const yAxis = /*@__PURE__*/ Vec3.create();
|
|
28
|
-
const extent = /*@__PURE__*/ Vec3.create();
|
|
29
|
-
const radiusVector = /*@__PURE__*/ Vec3.create();
|
|
30
|
-
const halfHeightOfCylinder = /*@__PURE__*/ Vec3.create();
|
|
31
|
-
const isometry = /*@__PURE__*/ Isometry.create();
|
|
32
|
-
const horizontalDirection = /*@__PURE__*/ Vec3.create();
|
|
33
|
-
const support = /*@__PURE__*/ Vec3.create();
|
|
34
|
-
const supportTop = /*@__PURE__*/ Vec3.create();
|
|
35
|
-
const negatedScaledHalfHeightOfCylinder = /*@__PURE__*/ Vec3.create();
|
|
36
|
-
const supportBottom = /*@__PURE__*/ Vec3.create();
|
|
37
|
-
|
|
38
|
-
const capsuleNoConvexProps = {
|
|
39
|
-
halfHeightOfCylinder: MonomorphType(Vec3),
|
|
40
|
-
convexRadius: NumberType(0),
|
|
41
|
-
} as const satisfies PropertyDefinitionMap;
|
|
42
|
-
|
|
43
|
-
export class CapsuleNoConvex extends createClass<CapsuleNoConvex, typeof capsuleNoConvexProps>(capsuleNoConvexProps) {
|
|
44
|
-
computeSupport(out: Vec3, direction: Vec3): void {
|
|
45
|
-
if (direction.y > 0) {
|
|
46
|
-
out.copy(this.halfHeightOfCylinder);
|
|
47
|
-
} else {
|
|
48
|
-
out.negateVector(this.halfHeightOfCylinder);
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
getConvexRadius(): number {
|
|
53
|
-
return this.convexRadius;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
computeSupportingFace(out: Face, subShapeID: number, direction: Vec3, scale: number, centerOfMassTransform: Mat4) {
|
|
57
|
-
throw new Error("Method not implemented.");
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
const capsuleWithConvexProps = {
|
|
62
|
-
halfHeightOfCylinder: MonomorphType(Vec3),
|
|
63
|
-
radius: NumberType(0),
|
|
64
|
-
} as const satisfies PropertyDefinitionMap;
|
|
65
|
-
|
|
66
|
-
export class CapsuleWithConvex extends createClass<CapsuleWithConvex, typeof capsuleWithConvexProps>(
|
|
67
|
-
capsuleWithConvexProps
|
|
68
|
-
) {
|
|
69
|
-
computeSupport(out: Vec3, direction: Vec3): void {
|
|
70
|
-
const len = direction.length();
|
|
71
|
-
|
|
72
|
-
if (len > 0) {
|
|
73
|
-
// vec3.scaleAndAdd(out, direction, direction, this.radius / len);
|
|
74
|
-
out.scaleVector(direction, this.radius / len);
|
|
75
|
-
} else {
|
|
76
|
-
out.zero();
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
if (direction.y > 0) {
|
|
80
|
-
out.addVector(this.halfHeightOfCylinder);
|
|
81
|
-
} else {
|
|
82
|
-
out.subtractVector(this.halfHeightOfCylinder);
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
getConvexRadius(): number {
|
|
87
|
-
return 0;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
computeSupportingFace(
|
|
91
|
-
out: Face,
|
|
92
|
-
subShapeID: number,
|
|
93
|
-
direction: Vec3,
|
|
94
|
-
scale: number,
|
|
95
|
-
centerOfMassTransform: Mat4
|
|
96
|
-
): void {
|
|
97
|
-
throw new Error("Method not implemented.");
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
const capsuleProps = {
|
|
102
|
-
computedCenterOfMass: MonomorphType(Vec3, undefined, true),
|
|
103
|
-
computedVolume: NumberType(0.0, true),
|
|
104
|
-
computedAabb: MonomorphType(Aabb, undefined, true),
|
|
105
|
-
radius: NumberType(0),
|
|
106
|
-
height: NumberType(0),
|
|
107
|
-
copyForDiff: LazyReferenceType((() => Capsule) as () => never) as PropertyDefinitionReference<Capsule | null, true>,
|
|
108
|
-
capsuleNoConvex: MonomorphType(CapsuleNoConvex, undefined, true),
|
|
109
|
-
capsuleWithConvex: MonomorphType(CapsuleWithConvex, undefined, true),
|
|
110
|
-
} as const satisfies PropertyDefinitionMap;
|
|
111
|
-
|
|
112
|
-
const afterConstructorCode = `
|
|
113
|
-
this.world = null;
|
|
114
|
-
`;
|
|
115
|
-
|
|
116
|
-
export class Capsule
|
|
117
|
-
extends createClass<Capsule, typeof capsuleProps>(capsuleProps, { afterConstructorCode })
|
|
118
|
-
implements ConvexShapeInterface
|
|
119
|
-
{
|
|
120
|
-
type: ShapeType.capsule = ShapeType.capsule;
|
|
121
|
-
|
|
122
|
-
declare world: World | null;
|
|
123
|
-
|
|
124
|
-
intersectsAabb(aabb: Aabb): boolean {
|
|
125
|
-
throw new Error("Method not implemented.");
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
computeSupport(out: Vec3, direction: Vec3): void {
|
|
129
|
-
throw new Error("Method not implemented.");
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
getHalfHeightOfCylinder(): number {
|
|
133
|
-
return this.height / 2;
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
computeSupportShape(mode: SupportMode, scale: number): SupportShapeWithConvexRadius {
|
|
137
|
-
// get scaled capsule
|
|
138
|
-
const absScale = Math.abs(scale);
|
|
139
|
-
|
|
140
|
-
scaledHalfHeightOfCylinder.set({ x: 0, y: scale * this.getHalfHeightOfCylinder(), z: 0 });
|
|
141
|
-
const scaledRadius = scale * this.radius;
|
|
142
|
-
|
|
143
|
-
switch (mode) {
|
|
144
|
-
case SupportMode.IncludeConvexRadius: {
|
|
145
|
-
this.capsuleWithConvex.halfHeightOfCylinder.copy(scaledHalfHeightOfCylinder);
|
|
146
|
-
this.capsuleWithConvex.radius = scaledRadius;
|
|
147
|
-
return this.capsuleWithConvex;
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
case SupportMode.ExcludeConvexRadius: {
|
|
151
|
-
this.capsuleNoConvex.halfHeightOfCylinder.copy(scaledHalfHeightOfCylinder);
|
|
152
|
-
this.capsuleNoConvex.convexRadius = scaledRadius;
|
|
153
|
-
return this.capsuleNoConvex;
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
default: {
|
|
157
|
-
throw new Error(`Invalid support mode: ${mode}`);
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
computeSurfaceNormal(out: Vec3, inLocalSurfacePosition: Vec3, subShapeId?: number): void {
|
|
163
|
-
yAxis.set({ x: 0, y: 1, z: 0 });
|
|
164
|
-
|
|
165
|
-
if (inLocalSurfacePosition.y > this.getHalfHeightOfCylinder()) {
|
|
166
|
-
tempVector.set({ x: 0, y: this.getHalfHeightOfCylinder(), z: 0 });
|
|
167
|
-
out.subtractVectors(inLocalSurfacePosition, tempVector);
|
|
168
|
-
out.normalize();
|
|
169
|
-
return;
|
|
170
|
-
} else if (inLocalSurfacePosition.y < -this.getHalfHeightOfCylinder()) {
|
|
171
|
-
tempVector.set({ x: 0, y: -this.getHalfHeightOfCylinder(), z: 0 });
|
|
172
|
-
out.subtractVectors(inLocalSurfacePosition, tempVector);
|
|
173
|
-
out.normalize();
|
|
174
|
-
return;
|
|
175
|
-
} else {
|
|
176
|
-
out.set({ x: inLocalSurfacePosition.x, y: 0, z: inLocalSurfacePosition.z });
|
|
177
|
-
out.normalizedOr(out, yAxis);
|
|
178
|
-
return;
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
computeInertiaTensor(out: Mat3, mass: number): void {
|
|
183
|
-
// assumptions:
|
|
184
|
-
// 1. capsule's center-of-mass is at origin
|
|
185
|
-
// 2. capsule is not transformed
|
|
186
|
-
// 3. capsule has uniform density = 1
|
|
187
|
-
// 4. capsule is aligned with the y-axis
|
|
188
|
-
// derivation: chapter 14 of Game Engine Gems Volume I: http://www.gameenginegems.net/geg1.php
|
|
189
|
-
const { radius, height } = this;
|
|
190
|
-
|
|
191
|
-
const heightSquared = height * height;
|
|
192
|
-
const radiusSquared = radius * radius;
|
|
193
|
-
|
|
194
|
-
// common terms
|
|
195
|
-
const commonMultiplier = mass / (4 * radius + 3 * height);
|
|
196
|
-
const commonMassTerm1 = 2 * radius * commonMultiplier;
|
|
197
|
-
const commonMassTerm2 = 3 * height * commonMultiplier;
|
|
198
|
-
const commonRadiusTerm = (4 / 5) * radiusSquared;
|
|
199
|
-
|
|
200
|
-
// axis-aligned terms
|
|
201
|
-
const xxTerm1 = (3 / 4) * radius * height + (1 / 2) * heightSquared;
|
|
202
|
-
const xxTerm2 = (1 / 4) * radiusSquared + (1 / 12) * heightSquared;
|
|
203
|
-
const yyTerm = (1 / 2) * radiusSquared;
|
|
204
|
-
|
|
205
|
-
// axis-aligned inertias
|
|
206
|
-
const xxInertia = commonMassTerm1 * (commonRadiusTerm + xxTerm1) + commonMassTerm2 * xxTerm2;
|
|
207
|
-
const yyInertia = commonMassTerm1 * commonRadiusTerm + commonMassTerm2 * yyTerm;
|
|
208
|
-
const zzInertia = xxInertia;
|
|
209
|
-
|
|
210
|
-
// set inertia tensor
|
|
211
|
-
out.fromArray([xxInertia, 0, 0, 0, yyInertia, 0, 0, 0, zzInertia]);
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
computeInverseInertiaTensor(out: Mat3, mass: number): void {
|
|
215
|
-
this.computeInertiaTensor(out, mass);
|
|
216
|
-
out.invert();
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
computeWorldBounds(out: Aabb, translation: Vec3, rotation: Quat) {
|
|
220
|
-
// TODO: apply rotation if shape's center of mass is not at the origin?
|
|
221
|
-
isometry.fromRotationAndTranslation(rotation, translation);
|
|
222
|
-
out.transformAabb(this.computedAabb, isometry);
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
collideTriangle(result: CollisionResult, triangle: Triangle, isometry: Isometry) {
|
|
226
|
-
throw new Error("Method not implemented.");
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
computeSupportingFace(out: Face, subShapeID: number, direction: Vec3, scale: number, centerOfMassTransform: Mat4) {
|
|
230
|
-
out.clear();
|
|
231
|
-
|
|
232
|
-
// Get direction in horizontal plane
|
|
233
|
-
|
|
234
|
-
horizontalDirection.copy(direction);
|
|
235
|
-
horizontalDirection.y = 0;
|
|
236
|
-
|
|
237
|
-
// check zero vector, in this case we're hitting from top/bottom so there's no supporting face
|
|
238
|
-
const horizontalDirectionLength = horizontalDirection.length();
|
|
239
|
-
if (horizontalDirectionLength === 0) {
|
|
240
|
-
return;
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
// get scaled capsule
|
|
244
|
-
scale = Math.abs(scale);
|
|
245
|
-
|
|
246
|
-
scaledHalfHeightOfCylinder.set({ x: 0, y: scale * this.getHalfHeightOfCylinder(), z: 0 });
|
|
247
|
-
const scaledRadius = scale * this.radius;
|
|
248
|
-
|
|
249
|
-
// Get support point for top and bottom sphere in the opposite of 'direction' (including convex radius)
|
|
250
|
-
|
|
251
|
-
support.scaleVector(horizontalDirection, scaledRadius / horizontalDirectionLength);
|
|
252
|
-
supportTop.subtractVectors(scaledHalfHeightOfCylinder, support);
|
|
253
|
-
negatedScaledHalfHeightOfCylinder.negateVector(scaledHalfHeightOfCylinder);
|
|
254
|
-
supportBottom.subtractVectors(negatedScaledHalfHeightOfCylinder, support);
|
|
255
|
-
|
|
256
|
-
// get projection on inDirection
|
|
257
|
-
// Note that inDirection is not normalized, so we need to divide by inDirection.Length() to get the actual projection
|
|
258
|
-
// We've multiplied both sides of the if below with inDirection.Length()
|
|
259
|
-
const projTop = supportTop.dot(direction);
|
|
260
|
-
const projBottom = supportBottom.dot(direction);
|
|
261
|
-
|
|
262
|
-
// If projection is roughly equal then return line, otherwise we return nothing as there's only 1 point
|
|
263
|
-
if (Math.abs(projTop - projBottom) < capsuleProjectionSlop * direction.length()) {
|
|
264
|
-
supportTop.transformVectorFromMat4(supportTop, centerOfMassTransform);
|
|
265
|
-
out.pushVertex(supportTop);
|
|
266
|
-
|
|
267
|
-
supportBottom.transformVectorFromMat4(supportBottom, centerOfMassTransform);
|
|
268
|
-
out.pushVertex(supportBottom);
|
|
269
|
-
// out.log("hitting side capsule face");
|
|
270
|
-
} else {
|
|
271
|
-
// out.log("hitting non-side capsule face");
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
// console.log("capsule supporting face with vertex count", out.vertexCount);
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
get isConvex(): boolean {
|
|
278
|
-
return true;
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
hasChanged() {
|
|
282
|
-
return (
|
|
283
|
-
this.copyForDiff !== null && (this.radius !== this.copyForDiff.radius || this.height !== this.copyForDiff.height)
|
|
284
|
-
);
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
commitChanges() {
|
|
288
|
-
if (this.hasChanged()) {
|
|
289
|
-
updateShape(this);
|
|
290
|
-
// this.world?.updateBodyProperties();
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
const oldCreate = Capsule.create;
|
|
296
|
-
Capsule.create = function () {
|
|
297
|
-
const shape = oldCreate.apply(this, arguments as any);
|
|
298
|
-
updateShape(shape);
|
|
299
|
-
return shape;
|
|
300
|
-
};
|
|
301
|
-
|
|
302
|
-
function updateCopyForDiff(shape: Capsule) {
|
|
303
|
-
if (shape.copyForDiff) {
|
|
304
|
-
shape.copyForDiff.copy(shape);
|
|
305
|
-
shape.copyForDiff.copyForDiff = null;
|
|
306
|
-
}
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
function updateCenterOfMass(shape: Capsule) {
|
|
310
|
-
shape.computedCenterOfMass.zero();
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
function updateVolume(shape: Capsule) {
|
|
314
|
-
shape.computedVolume =
|
|
315
|
-
(4 / 3) * Math.PI * shape.radius * shape.radius * shape.radius +
|
|
316
|
-
Math.PI * shape.radius * shape.radius * shape.height;
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
function updateLocalBounds(shape: Capsule) {
|
|
320
|
-
radiusVector.replicate(shape.radius);
|
|
321
|
-
halfHeightOfCylinder.set({ x: 0, y: shape.getHalfHeightOfCylinder(), z: 0 });
|
|
322
|
-
extent.addVectors(radiusVector, halfHeightOfCylinder);
|
|
323
|
-
shape.computedAabb.min.negateVector(extent);
|
|
324
|
-
shape.computedAabb.max.copy(extent);
|
|
325
|
-
}
|
|
326
|
-
|
|
327
|
-
function updateShape(shape: Capsule) {
|
|
328
|
-
updateCopyForDiff(shape);
|
|
329
|
-
updateCenterOfMass(shape);
|
|
330
|
-
updateVolume(shape);
|
|
331
|
-
updateLocalBounds(shape);
|
|
332
|
-
}
|
|
@@ -1,288 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
createClass,
|
|
3
|
-
LazyReferenceType,
|
|
4
|
-
MonomorphType,
|
|
5
|
-
NumberType,
|
|
6
|
-
PropertyDefinitionMap,
|
|
7
|
-
PropertyDefinitionReference,
|
|
8
|
-
ReferenceListType,
|
|
9
|
-
} from "monomorph";
|
|
10
|
-
import { ConvexShape, ConvexShapeInterface, Shape, ShapeCollectionInterface, ShapeType } from "./Shape";
|
|
11
|
-
import type { World } from "../world";
|
|
12
|
-
import { Aabb } from "./Aabb";
|
|
13
|
-
import { BasicTransform } from "../math/BasicTransform";
|
|
14
|
-
import { Vec3 } from "../math/vec3";
|
|
15
|
-
import { Sphere } from "./Sphere";
|
|
16
|
-
import { Box } from "./Box";
|
|
17
|
-
import { Mat4 } from "../math/mat4";
|
|
18
|
-
import { Face } from "../physics/manifold/Face";
|
|
19
|
-
import { Mat3 } from "../math/mat3";
|
|
20
|
-
import { Isometry } from "../math/isometry";
|
|
21
|
-
import { Quat } from "../math/quat";
|
|
22
|
-
import { TransformedShape } from "./TransformedShape";
|
|
23
|
-
import ConvexHull from "./ConvexHull";
|
|
24
|
-
import { Cylinder } from "./Cylinder";
|
|
25
|
-
import { Capsule } from "./Capsule";
|
|
26
|
-
|
|
27
|
-
const cumulativeInertia = /*@__PURE__*/ Mat3.create();
|
|
28
|
-
const inertia = /*@__PURE__*/ Mat3.create();
|
|
29
|
-
const rotationMatrix = /*@__PURE__*/ Mat3.create();
|
|
30
|
-
const tempMatrixA = /*@__PURE__*/ Mat3.create();
|
|
31
|
-
const tempMatrixB = /*@__PURE__*/ Mat3.create();
|
|
32
|
-
const tempMatrixC = /*@__PURE__*/ Mat3.create();
|
|
33
|
-
|
|
34
|
-
const innerBounds = /*@__PURE__*/ Aabb.create();
|
|
35
|
-
const isometry = /*@__PURE__*/ Isometry.create();
|
|
36
|
-
|
|
37
|
-
const centerOfMass = /*@__PURE__*/ Vec3.create();
|
|
38
|
-
const transformedCenterOfMass = /*@__PURE__*/ Vec3.create();
|
|
39
|
-
|
|
40
|
-
const transformSubshapeToCompound = /*@__PURE__*/ Isometry.create();
|
|
41
|
-
const subShapeDirection = /*@__PURE__*/ Vec3.create();
|
|
42
|
-
const subShapeToWorld = /*@__PURE__*/ Isometry.create();
|
|
43
|
-
|
|
44
|
-
const compoundShapeProps = {
|
|
45
|
-
computedCenterOfMass: MonomorphType(Vec3, {}, true),
|
|
46
|
-
computedVolume: NumberType(0.0, true),
|
|
47
|
-
computedAabb: MonomorphType(Aabb, {}, true),
|
|
48
|
-
copyForDiff: LazyReferenceType((() => CompoundShape) as () => never) as PropertyDefinitionReference<
|
|
49
|
-
CompoundShape | null,
|
|
50
|
-
true
|
|
51
|
-
>,
|
|
52
|
-
shapes: ReferenceListType(TransformedShape),
|
|
53
|
-
} as const satisfies PropertyDefinitionMap;
|
|
54
|
-
|
|
55
|
-
const afterConstructorCode = `
|
|
56
|
-
this.world = null;
|
|
57
|
-
`;
|
|
58
|
-
|
|
59
|
-
const tempTransform = /*@__PURE__*/ BasicTransform.create();
|
|
60
|
-
|
|
61
|
-
export class CompoundShape
|
|
62
|
-
extends createClass<CompoundShape, typeof compoundShapeProps>(compoundShapeProps, { afterConstructorCode })
|
|
63
|
-
implements ShapeCollectionInterface
|
|
64
|
-
{
|
|
65
|
-
type: ShapeType.compoundShape = ShapeType.compoundShape;
|
|
66
|
-
|
|
67
|
-
declare world: World | null;
|
|
68
|
-
|
|
69
|
-
walkShapes(onShapeFound: (shape: ConvexShape, transform: BasicTransform) => boolean) {
|
|
70
|
-
for (const shapeObj of this.shapes) {
|
|
71
|
-
const shape = shapeObj.shape as ConvexShape;
|
|
72
|
-
const transform = shapeObj.transform as BasicTransform;
|
|
73
|
-
tempTransform.copy(transform);
|
|
74
|
-
tempTransform.position.addVector(this.computedCenterOfMass);
|
|
75
|
-
|
|
76
|
-
if (onShapeFound(shape as ConvexShape, tempTransform)) {
|
|
77
|
-
return;
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
computeNumShapes() {
|
|
83
|
-
return this.shapes.length;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
getShapeAtIndex(index: number) {
|
|
87
|
-
const shape = this.shapes.getAtIndex(index);
|
|
88
|
-
if (shape === null) {
|
|
89
|
-
throw new Error(`Shape at index ${index} not found in compound shape.`);
|
|
90
|
-
}
|
|
91
|
-
return shape;
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
computeSupportingFace(
|
|
95
|
-
out: Face,
|
|
96
|
-
subShapeID: number,
|
|
97
|
-
direction: Vec3,
|
|
98
|
-
scale: number,
|
|
99
|
-
transformCompoundToWorld: Mat4
|
|
100
|
-
): void {
|
|
101
|
-
// transform the direction from compound space to subshape space. we have the subshape's translation and rotation
|
|
102
|
-
const { shape, transform } = this.getShapeAtIndex(subShapeID) as { shape: Shape; transform: BasicTransform };
|
|
103
|
-
const translation = transform.position;
|
|
104
|
-
const rotation = transform.rotation;
|
|
105
|
-
transformSubshapeToCompound.fromRotationAndTranslation(rotation, translation);
|
|
106
|
-
transformSubshapeToCompound.matrix.multiply3x3Transposed(subShapeDirection, direction);
|
|
107
|
-
// get the subShapeToWorld transform which is just the product of the compoundToWorld and subshapeToCompound transforms
|
|
108
|
-
subShapeToWorld.matrix.multiplyMatrices(transformCompoundToWorld, transformSubshapeToCompound.matrix);
|
|
109
|
-
// TODO: account for subShapeID in case we allow recursive compound shapes
|
|
110
|
-
shape.computeSupportingFace(out, subShapeID, subShapeDirection, scale, subShapeToWorld.matrix);
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
computeInertiaTensor(out: Mat3, totalMass: number): void {
|
|
114
|
-
// init the cumulative mass and inertia
|
|
115
|
-
|
|
116
|
-
let cumulativeMass = 0;
|
|
117
|
-
cumulativeInertia.zero();
|
|
118
|
-
|
|
119
|
-
const totalVolume = this.computedVolume;
|
|
120
|
-
|
|
121
|
-
for (const shapeObj of this.shapes) {
|
|
122
|
-
const shape = shapeObj.shape as ConvexShape;
|
|
123
|
-
const transform = shapeObj.transform;
|
|
124
|
-
const translation = transform.position;
|
|
125
|
-
const rotation = transform.rotation;
|
|
126
|
-
|
|
127
|
-
const volume = shape.computedVolume;
|
|
128
|
-
const mass = (volume / totalVolume) * totalMass;
|
|
129
|
-
|
|
130
|
-
// get the shape inertia tensor
|
|
131
|
-
shape.computeInertiaTensor(inertia, mass);
|
|
132
|
-
|
|
133
|
-
// rotate the inertia tensor
|
|
134
|
-
rotationMatrix.fromQuat(rotation);
|
|
135
|
-
inertia.multiplyMat3s(rotationMatrix, inertia);
|
|
136
|
-
inertia.multiplyMat3RightTransposed(rotationMatrix);
|
|
137
|
-
|
|
138
|
-
tempMatrixA.identity();
|
|
139
|
-
tempMatrixA.multiplyByScalar(translation.dot(translation));
|
|
140
|
-
|
|
141
|
-
tempMatrixB.outerProduct(translation, translation);
|
|
142
|
-
|
|
143
|
-
tempMatrixC.subtractMatrices(tempMatrixA, tempMatrixB);
|
|
144
|
-
tempMatrixC.multiplyByScalar(mass);
|
|
145
|
-
|
|
146
|
-
inertia.addMatrix(tempMatrixC);
|
|
147
|
-
|
|
148
|
-
// accumulate the mass and inertia
|
|
149
|
-
cumulativeMass += mass;
|
|
150
|
-
cumulativeInertia.addMatrix(inertia);
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
// return the cumulative inertia tensor
|
|
154
|
-
out.copy(cumulativeInertia);
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
computeInverseInertiaTensor(out: Mat3, mass: number): void {
|
|
158
|
-
this.computeInertiaTensor(out, mass);
|
|
159
|
-
out.invert();
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
computeWorldBounds(out: Aabb, translation: Vec3, rotation: Quat): void {
|
|
163
|
-
// TODO: apply rotation if shape's center of mass is not at the origin?
|
|
164
|
-
isometry.fromRotationAndTranslation(rotation, translation);
|
|
165
|
-
out.transformAabb(this.computedAabb, isometry);
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
computeSurfaceNormal(out: Vec3, inLocalSurfacePosition: Vec3, subShapeId?: number): void {
|
|
169
|
-
if (subShapeId === undefined) {
|
|
170
|
-
throw new Error("CompoundShape.computeSurfaceNormal requires a subShapeId");
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
const { shape, transform } = this.getShapeAtIndex(subShapeId) as { shape: ConvexShape; transform: BasicTransform };
|
|
174
|
-
|
|
175
|
-
// transform the surface position from compound space to subshape space. we have the subshape's translation and rotation
|
|
176
|
-
transformCompoundToSubshape.fromInverseRotationAndTranslation(transform.rotation, transform.position);
|
|
177
|
-
subShapeSurfacePosition.transformVectorFromMat4(inLocalSurfacePosition, transformCompoundToSubshape.matrix);
|
|
178
|
-
|
|
179
|
-
// get the surface normal in subshape space
|
|
180
|
-
if (shape === undefined) {
|
|
181
|
-
throw new Error(`CompoundShape.setView: shapeId ${subShapeId} not found in world`); // TODO: handle this better
|
|
182
|
-
}
|
|
183
|
-
shape.computeSurfaceNormal(out, subShapeSurfacePosition, subShapeId);
|
|
184
|
-
|
|
185
|
-
// transform the surface normal from subshape space to compound space
|
|
186
|
-
transformCompoundToSubshape.matrix.multiply3x3Transposed(out, out);
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
hasChanged() {
|
|
190
|
-
// TODO: we don't support changes on transforms yet
|
|
191
|
-
for (const shapeObj of this.shapes) {
|
|
192
|
-
const hasChanged = (shapeObj.shape as ConvexShapeInterface).hasChanged();
|
|
193
|
-
if (hasChanged) {
|
|
194
|
-
return true;
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
return false;
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
update() {
|
|
201
|
-
updateShape(this);
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
commitChanges() {
|
|
205
|
-
if (this.hasChanged()) {
|
|
206
|
-
updateShape(this);
|
|
207
|
-
// this.world?.updateBodyProperties();
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
function updateCenterOfMass(compound: CompoundShape) {
|
|
213
|
-
// we simply average the centers of mass of the two shapes, applying the correct translation and rotation as we go
|
|
214
|
-
compound.computedCenterOfMass.zero();
|
|
215
|
-
|
|
216
|
-
for (const shapeObj of compound.shapes) {
|
|
217
|
-
const shape = shapeObj.shape as ConvexShape;
|
|
218
|
-
const transform = shapeObj.transform as BasicTransform;
|
|
219
|
-
|
|
220
|
-
const translation = transform.position;
|
|
221
|
-
const rotation = transform.rotation;
|
|
222
|
-
|
|
223
|
-
transformedCenterOfMass.applyQuatThenAddToVector(translation, rotation, shape.computedCenterOfMass);
|
|
224
|
-
// compound.computedCenterOfMass.addVectors(compound.computedCenterOfMass, transformedCenterOfMass);
|
|
225
|
-
compound.computedCenterOfMass.addVector(transformedCenterOfMass);
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
const numShapes = compound.computeNumShapes();
|
|
229
|
-
compound.computedCenterOfMass.scale(1 / numShapes);
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
const oldCreate = CompoundShape.create;
|
|
233
|
-
CompoundShape.create = function () {
|
|
234
|
-
const shape = oldCreate.apply(this, arguments as any);
|
|
235
|
-
for (const shapeObj of shape.shapes) {
|
|
236
|
-
const transform = shapeObj.transform as BasicTransform;
|
|
237
|
-
transform.rotation.normalize();
|
|
238
|
-
}
|
|
239
|
-
updateShape(shape);
|
|
240
|
-
return shape;
|
|
241
|
-
};
|
|
242
|
-
|
|
243
|
-
const transformCompoundToSubshape = /*@__PURE__*/ Isometry.create();
|
|
244
|
-
const subShapeSurfacePosition = /*@__PURE__*/ Vec3.create();
|
|
245
|
-
|
|
246
|
-
let volume = 0;
|
|
247
|
-
function addVolumeCallback(shape: Sphere | Box | ConvexHull | Cylinder | Capsule, transform: BasicTransform) {
|
|
248
|
-
volume += shape.computedVolume;
|
|
249
|
-
return false;
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
function updateVolume(shape: CompoundShape) {
|
|
253
|
-
volume = 0;
|
|
254
|
-
shape.walkShapes(addVolumeCallback);
|
|
255
|
-
shape.computedVolume = volume;
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
function updateLocalBounds(compound: CompoundShape) {
|
|
259
|
-
compound.computedAabb.min.zero();
|
|
260
|
-
compound.computedAabb.max.zero();
|
|
261
|
-
|
|
262
|
-
for (const shapeObj of compound.shapes) {
|
|
263
|
-
const shape = shapeObj.shape as ConvexShape;
|
|
264
|
-
const transform = shapeObj.transform as BasicTransform;
|
|
265
|
-
|
|
266
|
-
const translation = transform.position;
|
|
267
|
-
const rotation = transform.rotation;
|
|
268
|
-
isometry.fromRotationAndTranslation(rotation, translation);
|
|
269
|
-
innerBounds.transformAabb(shape.computedAabb, isometry);
|
|
270
|
-
compound.computedAabb.unionAabb(innerBounds);
|
|
271
|
-
}
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
function updateCopyForDiff(shape: CompoundShape) {
|
|
275
|
-
for (const shapeObj of shape.shapes) {
|
|
276
|
-
const subShape = shapeObj.shape as ConvexShape;
|
|
277
|
-
// @ts-ignore
|
|
278
|
-
subShape.copyForDiff!.copy(subShape);
|
|
279
|
-
subShape.copyForDiff!.copyForDiff = null;
|
|
280
|
-
}
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
function updateShape(shape: CompoundShape) {
|
|
284
|
-
updateCopyForDiff(shape);
|
|
285
|
-
updateCenterOfMass(shape);
|
|
286
|
-
updateVolume(shape);
|
|
287
|
-
updateLocalBounds(shape);
|
|
288
|
-
}
|