@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
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
BooleanType,
|
|
3
|
-
LazyReferenceType,
|
|
4
|
-
NumberType,
|
|
5
|
-
PropertyDefinitionMap,
|
|
6
|
-
PropertyDefinitionReference,
|
|
7
|
-
} from "monomorph";
|
|
8
|
-
// unless we use require for these files, this file (BaseConstraint.ts) will be included after it is needed in the final build
|
|
9
|
-
import type { Body } from "../physics/Body";
|
|
10
|
-
import type { ConstraintPairNode } from "../physics/broadphase/ConstraintPairsModule";
|
|
11
|
-
|
|
12
|
-
export const enum ReferenceFrame {
|
|
13
|
-
local,
|
|
14
|
-
world,
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export const enum ConstraintType {
|
|
18
|
-
pointConstraint,
|
|
19
|
-
fixedConstraint,
|
|
20
|
-
distanceConstraint,
|
|
21
|
-
hingeConstraint,
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
export const baseConstraintProps = {
|
|
25
|
-
// unless we use require here, this file will be imported after it is needed
|
|
26
|
-
bodyA: LazyReferenceType((() => require('../physics/Body').Body) as () => never) as PropertyDefinitionReference<Body | null, true>,
|
|
27
|
-
bodyB: LazyReferenceType((() => require('../physics/Body').Body) as () => never) as PropertyDefinitionReference<Body | null, true>,
|
|
28
|
-
constraintPairNode: LazyReferenceType((() => require('../physics/broadphase/ConstraintPairsModule').ConstraintPairNode) as () => never) as PropertyDefinitionReference<
|
|
29
|
-
ConstraintPairNode | null,
|
|
30
|
-
true
|
|
31
|
-
>,
|
|
32
|
-
referenceFrame: NumberType(0),
|
|
33
|
-
isEnabled: BooleanType(true),
|
|
34
|
-
} as const satisfies PropertyDefinitionMap;
|
|
35
|
-
|
|
36
|
-
export interface ConstraintInterface {
|
|
37
|
-
type: ConstraintType;
|
|
38
|
-
bodyA: Body | null;
|
|
39
|
-
bodyB: Body | null;
|
|
40
|
-
constraintPairNode: ConstraintPairNode | null;
|
|
41
|
-
referenceFrame: ReferenceFrame;
|
|
42
|
-
isEnabled: boolean;
|
|
43
|
-
|
|
44
|
-
deactivate(): void;
|
|
45
|
-
initVelocityConstraint(deltaTimeSeconds: number): void;
|
|
46
|
-
warmStart(deltaTimeSeconds: number, warmStartImpulseRatio: number): void;
|
|
47
|
-
solveVelocityConstraint(deltaTimeSeconds: number): void;
|
|
48
|
-
solvePositionConstraint(deltaTimeSeconds: number): void;
|
|
49
|
-
setComponentData(): void;
|
|
50
|
-
}
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import { createClass, NumberType, PropertyDefinitionMap } from "monomorph";
|
|
2
|
-
|
|
3
|
-
const constraintOptionsProps = {
|
|
4
|
-
/**
|
|
5
|
-
* Value used to scale the amount of position error to correct per solve iteration. Expected to be in the interval [0, 1]
|
|
6
|
-
*/
|
|
7
|
-
positionBaumgarte: NumberType(0.8),
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Value used to scale the amount of velocity error to correct per solve iteration. Expected to be in the interval [0, 1]
|
|
11
|
-
*/
|
|
12
|
-
velocityBaumgarte: NumberType(1.0),
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* Value used to scale the strength of the constraint. recommend to tune in the interval of [0, 1], with 0 being no correction, 1 being full correction
|
|
16
|
-
*/
|
|
17
|
-
strength: NumberType(1.0),
|
|
18
|
-
} as const satisfies PropertyDefinitionMap;
|
|
19
|
-
|
|
20
|
-
export class ConstraintOptions extends createClass<ConstraintOptions, typeof constraintOptionsProps>(
|
|
21
|
-
constraintOptionsProps
|
|
22
|
-
) {}
|
|
@@ -1,119 +0,0 @@
|
|
|
1
|
-
import { InputType } from "monomorph";
|
|
2
|
-
import type { World } from "../world";
|
|
3
|
-
import { ConstraintInterface } from "./BaseConstraint";
|
|
4
|
-
import { DistanceConstraint } from "./DistanceConstraint";
|
|
5
|
-
import { FixedConstraint } from "./FixedConstraint";
|
|
6
|
-
import { HingeConstraint } from "./HingeConstraint";
|
|
7
|
-
import { PointConstraint } from "./PointConstraint";
|
|
8
|
-
import { ConstraintPairsModule } from "../physics/broadphase/ConstraintPairsModule";
|
|
9
|
-
import type { Constraint } from "./types";
|
|
10
|
-
|
|
11
|
-
export class ConstraintSolver {
|
|
12
|
-
// removeConstraintConnectedToBody: typeof ConstraintSolver.prototype._removeConstraintConnectedToBody;
|
|
13
|
-
|
|
14
|
-
world: World;
|
|
15
|
-
constraintPairs: ConstraintPairsModule;
|
|
16
|
-
|
|
17
|
-
fixedConstraints: typeof FixedConstraint.Pool;
|
|
18
|
-
pointConstraints: typeof PointConstraint.Pool;
|
|
19
|
-
distanceConstraints: typeof DistanceConstraint.Pool;
|
|
20
|
-
hingeConstraints: typeof HingeConstraint.Pool;
|
|
21
|
-
|
|
22
|
-
constructor(world: World, constraintPairs: ConstraintPairsModule) {
|
|
23
|
-
// this.removeConstraintConnectedToBody = this._removeConstraintConnectedToBody.bind(this);
|
|
24
|
-
this.world = world;
|
|
25
|
-
this.constraintPairs = constraintPairs;
|
|
26
|
-
this.fixedConstraints = new FixedConstraint.Pool();
|
|
27
|
-
this.pointConstraints = new PointConstraint.Pool();
|
|
28
|
-
this.distanceConstraints = new DistanceConstraint.Pool();
|
|
29
|
-
this.hingeConstraints = new HingeConstraint.Pool();
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
createFixedConstraint(params: InputType<FixedConstraint>) {
|
|
33
|
-
const constraint = /*@__PURE__*/ FixedConstraint.create(params, this.fixedConstraints);
|
|
34
|
-
this.constraintPairs.createPair(constraint);
|
|
35
|
-
constraint.bodyA?.wakeUp();
|
|
36
|
-
constraint.bodyB?.wakeUp();
|
|
37
|
-
return constraint;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
createPointConstraint(params: InputType<PointConstraint>) {
|
|
41
|
-
const constraint = /*@__PURE__*/ PointConstraint.create(params, this.pointConstraints);
|
|
42
|
-
this.constraintPairs.createPair(constraint);
|
|
43
|
-
constraint.bodyA?.wakeUp();
|
|
44
|
-
constraint.bodyB?.wakeUp();
|
|
45
|
-
return constraint;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
createDistanceConstraint(params: InputType<DistanceConstraint>) {
|
|
49
|
-
const constraint = /*@__PURE__*/ DistanceConstraint.create(params, this.distanceConstraints);
|
|
50
|
-
this.constraintPairs.createPair(constraint);
|
|
51
|
-
constraint.bodyA?.wakeUp();
|
|
52
|
-
constraint.bodyB?.wakeUp();
|
|
53
|
-
return constraint;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
createHingeConstraint(params: InputType<HingeConstraint>) {
|
|
57
|
-
const constraint = /*@__PURE__*/ HingeConstraint.create(params, this.hingeConstraints);
|
|
58
|
-
this.constraintPairs.createPair(constraint);
|
|
59
|
-
constraint.bodyA?.wakeUp();
|
|
60
|
-
constraint.bodyB?.wakeUp();
|
|
61
|
-
return constraint;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
destroyConstraint(constraint: Constraint) {
|
|
65
|
-
this.constraintPairs.destroyPair(constraint);
|
|
66
|
-
constraint.destroy();
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
*constraints(): IterableIterator<ConstraintInterface> {
|
|
70
|
-
yield* this.fixedConstraints;
|
|
71
|
-
yield* this.pointConstraints;
|
|
72
|
-
yield* this.distanceConstraints;
|
|
73
|
-
yield* this.hingeConstraints;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
initVelocityConstraints(deltaTimeSeconds: number) {
|
|
77
|
-
// iterate over all constraint allocations
|
|
78
|
-
for (const constraint of this.constraints()) {
|
|
79
|
-
if (this.world.sleepModule.isBodyPairAwake(constraint.bodyA!, constraint.bodyB!)) {
|
|
80
|
-
constraint.initVelocityConstraint(deltaTimeSeconds);
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
// TODO: should we reset warm start when waking?
|
|
86
|
-
warmStartConstraints(deltaTimeSeconds: number, warmStartImpulseRatio: number) {
|
|
87
|
-
// iterate over all constraint allocations
|
|
88
|
-
for (const constraint of this.constraints()) {
|
|
89
|
-
if (this.world.sleepModule.isBodyPairAwake(constraint.bodyA!, constraint.bodyB!)) {
|
|
90
|
-
constraint.warmStart(deltaTimeSeconds, warmStartImpulseRatio);
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
solveVelocityConstraintsStep(deltaTimeSeconds: number) {
|
|
96
|
-
// iterate over all constraint allocations
|
|
97
|
-
for (const constraint of this.constraints()) {
|
|
98
|
-
if (this.world.sleepModule.isBodyPairAwake(constraint.bodyA!, constraint.bodyB!)) {
|
|
99
|
-
constraint.solveVelocityConstraint(deltaTimeSeconds);
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
solvePositionConstraintsStep(deltaTimeSeconds: number): void {
|
|
105
|
-
// iterate over all constraint allocations
|
|
106
|
-
for (const constraint of this.constraints()) {
|
|
107
|
-
if (this.world.sleepModule.isBodyPairAwake(constraint.bodyA!, constraint.bodyB!)) {
|
|
108
|
-
constraint.solvePositionConstraint(deltaTimeSeconds);
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
solvePositionConstraints(deltaTimeSeconds: number): void {
|
|
114
|
-
// iterate as many times as there are solver position iterations, TODO: how to handle custom iterations per constraint or at least constraint type or allocation?
|
|
115
|
-
for (let i = 0; i < this.world.options.solvePositionIterations; i++) {
|
|
116
|
-
this.solvePositionConstraintsStep(deltaTimeSeconds);
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
}
|
|
@@ -1,229 +0,0 @@
|
|
|
1
|
-
import { createClass, MonomorphType, NumberType, PropertyDefinitionMap } from "monomorph";
|
|
2
|
-
import { baseConstraintProps, ConstraintInterface, ConstraintType, ReferenceFrame } from "./BaseConstraint";
|
|
3
|
-
import { Vec3 } from "../math/vec3";
|
|
4
|
-
import { Spring } from "./components/Spring";
|
|
5
|
-
import { AxisComponent } from "./components/AxisComponent";
|
|
6
|
-
import type { World } from "../world";
|
|
7
|
-
import { Mat4 } from "../math/mat4";
|
|
8
|
-
|
|
9
|
-
const transformLocalToWorld = /*@__PURE__*/ Mat4.create();
|
|
10
|
-
const worldToLocalTransformA = /*@__PURE__*/ Mat4.create();
|
|
11
|
-
const worldToLocalTransformB = /*@__PURE__*/ Mat4.create();
|
|
12
|
-
const localToWorldTransformA = /*@__PURE__*/ Mat4.create();
|
|
13
|
-
const localToWorldTransformB = /*@__PURE__*/ Mat4.create();
|
|
14
|
-
const armA = /*@__PURE__*/ Vec3.create();
|
|
15
|
-
const armB = /*@__PURE__*/ Vec3.create();
|
|
16
|
-
const vectorAB = /*@__PURE__*/ Vec3.create();
|
|
17
|
-
|
|
18
|
-
const distanceConstraintProps = {
|
|
19
|
-
...baseConstraintProps,
|
|
20
|
-
positionA: MonomorphType(Vec3, { x: 0, y: 0, z: 0 }),
|
|
21
|
-
positionB: MonomorphType(Vec3, { x: 0, y: 0, z: 0 }),
|
|
22
|
-
minDistance: NumberType(-1),
|
|
23
|
-
maxDistance: NumberType(-1),
|
|
24
|
-
spring: MonomorphType(Spring),
|
|
25
|
-
axisComponent: MonomorphType(AxisComponent),
|
|
26
|
-
localPositionA: MonomorphType(Vec3, undefined, true),
|
|
27
|
-
localPositionB: MonomorphType(Vec3, undefined, true),
|
|
28
|
-
worldPositionA: MonomorphType(Vec3, undefined, true),
|
|
29
|
-
worldPositionB: MonomorphType(Vec3, undefined, true),
|
|
30
|
-
worldNormal: MonomorphType(Vec3, undefined, true),
|
|
31
|
-
minLambda: NumberType(0, true),
|
|
32
|
-
maxLambda: NumberType(0, true),
|
|
33
|
-
} as const satisfies PropertyDefinitionMap;
|
|
34
|
-
|
|
35
|
-
export class DistanceConstraint
|
|
36
|
-
extends createClass<DistanceConstraint, typeof distanceConstraintProps>(distanceConstraintProps)
|
|
37
|
-
implements ConstraintInterface
|
|
38
|
-
{
|
|
39
|
-
type: ConstraintType.distanceConstraint = ConstraintType.distanceConstraint;
|
|
40
|
-
declare world: World;
|
|
41
|
-
|
|
42
|
-
deactivate(): void {
|
|
43
|
-
this.axisComponent.deactivate();
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
getLocalPoints(outA: Vec3, outB: Vec3): void {
|
|
47
|
-
outA.copy(this.localPositionA);
|
|
48
|
-
outB.copy(this.localPositionB);
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
getWorldPoints(outA: Vec3, outB: Vec3): void {
|
|
52
|
-
transformLocalToWorld.fromRotationTranslation(this.bodyA!.orientation, this.bodyA!.position);
|
|
53
|
-
outA.transformVectorFromMat4(this.localPositionA, transformLocalToWorld);
|
|
54
|
-
|
|
55
|
-
transformLocalToWorld.fromRotationTranslation(this.bodyB!.orientation, this.bodyB!.position);
|
|
56
|
-
outB.transformVectorFromMat4(this.localPositionB, transformLocalToWorld);
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
computeLocalPositions(): void {
|
|
60
|
-
if (this.referenceFrame === ReferenceFrame.local) {
|
|
61
|
-
this.localPositionA.copy(this.positionA);
|
|
62
|
-
this.localPositionB.copy(this.positionB);
|
|
63
|
-
} else {
|
|
64
|
-
worldToLocalTransformA.fromInverseRotationAndTranslation(
|
|
65
|
-
this.bodyA!.orientation,
|
|
66
|
-
this.bodyA!.computedCenterOfMassPosition
|
|
67
|
-
);
|
|
68
|
-
worldToLocalTransformB.fromInverseRotationAndTranslation(
|
|
69
|
-
this.bodyB!.orientation,
|
|
70
|
-
this.bodyB!.computedCenterOfMassPosition
|
|
71
|
-
);
|
|
72
|
-
this.localPositionA.transformVectorFromMat4(this.positionA, worldToLocalTransformA);
|
|
73
|
-
this.localPositionB.transformVectorFromMat4(this.positionB, worldToLocalTransformB);
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
computeWorldPositions(): void {
|
|
78
|
-
if (this.referenceFrame === ReferenceFrame.local) {
|
|
79
|
-
localToWorldTransformA.fromRotationTranslation(this.bodyA!.orientation, this.bodyA!.computedCenterOfMassPosition);
|
|
80
|
-
localToWorldTransformB.fromRotationTranslation(this.bodyB!.orientation, this.bodyB!.computedCenterOfMassPosition);
|
|
81
|
-
this.worldPositionA.transformVectorFromMat4(this.positionA, localToWorldTransformA);
|
|
82
|
-
this.worldPositionB.transformVectorFromMat4(this.positionB, localToWorldTransformB);
|
|
83
|
-
} else {
|
|
84
|
-
this.worldPositionA.copy(this.positionA);
|
|
85
|
-
this.worldPositionB.copy(this.positionB);
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
computeDistanceLimits(): void {
|
|
90
|
-
const distance = this.worldPositionA.distance(this.worldPositionB);
|
|
91
|
-
let minDistance: number;
|
|
92
|
-
let maxDistance: number;
|
|
93
|
-
|
|
94
|
-
if (this.minDistance < 0 && this.maxDistance < 0) {
|
|
95
|
-
minDistance = distance;
|
|
96
|
-
maxDistance = distance;
|
|
97
|
-
} else {
|
|
98
|
-
minDistance = this.minDistance < 0 ? Math.min(distance, this.maxDistance) : this.minDistance;
|
|
99
|
-
maxDistance = this.maxDistance < 0 ? Math.max(distance, this.minDistance) : this.maxDistance;
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
// #v-ifdef DEV
|
|
103
|
-
// assert that minDistance is less than or equal to maxDistance
|
|
104
|
-
if (minDistance > maxDistance) {
|
|
105
|
-
throw new Error(
|
|
106
|
-
"DistanceConstraint.computeDistanceLimits: minDistance must be less than or equal to maxDistance"
|
|
107
|
-
);
|
|
108
|
-
}
|
|
109
|
-
// #v-endif
|
|
110
|
-
|
|
111
|
-
this.minDistance = minDistance;
|
|
112
|
-
this.maxDistance = maxDistance;
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
warmStart(deltaTimeSeconds: number, warmStartImpulseRatio: number): void {
|
|
116
|
-
this.setComponentData();
|
|
117
|
-
this.axisComponent.warmStart(this.worldNormal, warmStartImpulseRatio);
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
initVelocityConstraint(deltaTimeSeconds: number): void {
|
|
121
|
-
this.setComponentData();
|
|
122
|
-
|
|
123
|
-
// update world positions
|
|
124
|
-
this.computeWorldPositions();
|
|
125
|
-
|
|
126
|
-
// update world normal
|
|
127
|
-
|
|
128
|
-
vectorAB.subtractVectors(this.worldPositionB, this.worldPositionA);
|
|
129
|
-
const distanceAB = vectorAB.length();
|
|
130
|
-
if (distanceAB > 0) {
|
|
131
|
-
this.worldNormal.copy(vectorAB).scale(1 / distanceAB);
|
|
132
|
-
} else {
|
|
133
|
-
// TODO: should we assert here?
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
// update moment arms
|
|
137
|
-
|
|
138
|
-
armA.subtractVectors(this.worldPositionB, this.bodyA!.computedCenterOfMassPosition);
|
|
139
|
-
armB.subtractVectors(this.worldPositionB, this.bodyB!.computedCenterOfMassPosition);
|
|
140
|
-
|
|
141
|
-
let error: number | undefined = undefined;
|
|
142
|
-
|
|
143
|
-
// case: no distance difference, push out or pull in
|
|
144
|
-
if (this.minDistance === this.maxDistance) {
|
|
145
|
-
error = distanceAB - this.minDistance;
|
|
146
|
-
this.minLambda = -Infinity;
|
|
147
|
-
this.maxLambda = +Infinity;
|
|
148
|
-
}
|
|
149
|
-
// case: below min distance, push out
|
|
150
|
-
else if (distanceAB <= this.minDistance) {
|
|
151
|
-
error = distanceAB - this.minDistance;
|
|
152
|
-
this.minLambda = 0;
|
|
153
|
-
this.maxLambda = +Infinity;
|
|
154
|
-
}
|
|
155
|
-
// case: above max distance, pull in
|
|
156
|
-
else if (distanceAB >= this.maxDistance) {
|
|
157
|
-
error = distanceAB - this.maxDistance;
|
|
158
|
-
this.minLambda = -Infinity;
|
|
159
|
-
this.maxLambda = 0;
|
|
160
|
-
}
|
|
161
|
-
// case: between min and max distance, no action
|
|
162
|
-
else {
|
|
163
|
-
this.axisComponent.deactivate();
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
if (error !== undefined) {
|
|
167
|
-
this.axisComponent.setup(deltaTimeSeconds, armA, armB, this.worldNormal, 0, error, this.spring);
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
solveVelocityConstraint(deltaTimeSeconds: number): void {
|
|
172
|
-
this.setComponentData();
|
|
173
|
-
if (!this.axisComponent.isActive()) {
|
|
174
|
-
return;
|
|
175
|
-
}
|
|
176
|
-
this.axisComponent.solveVelocity(this.worldNormal, this.minLambda, this.maxLambda);
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
solvePositionConstraint(deltaTimeSeconds: number): void {
|
|
180
|
-
this.setComponentData();
|
|
181
|
-
// only solve if no spring effect
|
|
182
|
-
if (this.spring.frequency > 0) {
|
|
183
|
-
return;
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
this.computeWorldPositions();
|
|
187
|
-
|
|
188
|
-
vectorAB.subtractVectors(this.worldPositionB, this.worldPositionA);
|
|
189
|
-
|
|
190
|
-
const distance = vectorAB.dot(this.worldNormal);
|
|
191
|
-
|
|
192
|
-
let positionError = 0;
|
|
193
|
-
if (distance < this.minDistance) {
|
|
194
|
-
positionError = distance - this.minDistance;
|
|
195
|
-
} else if (distance > this.maxDistance) {
|
|
196
|
-
positionError = distance - this.maxDistance;
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
if (positionError === 0) {
|
|
200
|
-
return;
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
this.initVelocityConstraint(deltaTimeSeconds);
|
|
204
|
-
this.axisComponent.solvePosition(this.worldNormal, positionError);
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
setComponentData(): void {
|
|
208
|
-
// @ts-ignore
|
|
209
|
-
this.world = this.bodyA!.world;
|
|
210
|
-
// @ts-ignore
|
|
211
|
-
this.axisComponent.world = this.bodyA!.world;
|
|
212
|
-
this.axisComponent.bodyA = this.bodyA!;
|
|
213
|
-
this.axisComponent.bodyB = this.bodyB!;
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
const oldCreate = DistanceConstraint.create;
|
|
218
|
-
DistanceConstraint.create = function () {
|
|
219
|
-
const constraint = oldCreate.apply(this, arguments as any);
|
|
220
|
-
constraint.setComponentData();
|
|
221
|
-
constraint.computeLocalPositions();
|
|
222
|
-
constraint.computeWorldPositions();
|
|
223
|
-
constraint.computeDistanceLimits();
|
|
224
|
-
constraint.worldNormal.fromArray([0, 1, 0]);
|
|
225
|
-
constraint.deactivate();
|
|
226
|
-
constraint.world.sleepModule.wakeBodyUp(constraint.bodyA!);
|
|
227
|
-
constraint.world.sleepModule.wakeBodyUp(constraint.bodyB!);
|
|
228
|
-
return constraint;
|
|
229
|
-
};
|
|
@@ -1,203 +0,0 @@
|
|
|
1
|
-
import { createClass, MonomorphType, PropertyDefinitionMap } from "monomorph";
|
|
2
|
-
import { baseConstraintProps, ConstraintInterface, ConstraintType, ReferenceFrame } from "./BaseConstraint";
|
|
3
|
-
import { Vec3 } from "../math/vec3";
|
|
4
|
-
import { Quat } from "../math/quat";
|
|
5
|
-
import { PointConstraintComponent } from "./components/PointConstraintComponent";
|
|
6
|
-
import { RotationEulerComponent } from "./components/RotationEulerComponent";
|
|
7
|
-
import type { World } from "../world";
|
|
8
|
-
import { Mat4 } from "../math/mat4";
|
|
9
|
-
import { Mat3 } from "../math/mat3";
|
|
10
|
-
|
|
11
|
-
const transformLocalToWorld = /*@__PURE__*/ Mat4.create();
|
|
12
|
-
const constraintRotationA = /*@__PURE__*/ Mat3.create();
|
|
13
|
-
const constraintRotationB = /*@__PURE__*/ Mat3.create();
|
|
14
|
-
const constraintQuaternionA = /*@__PURE__*/ Quat.create();
|
|
15
|
-
const constraintQuaternionB = /*@__PURE__*/ Quat.create();
|
|
16
|
-
|
|
17
|
-
const anchor = /*@__PURE__*/ Vec3.create();
|
|
18
|
-
const transformWorldToLocalA = /*@__PURE__*/ Mat4.create();
|
|
19
|
-
const transformWorldToLocalB = /*@__PURE__*/ Mat4.create();
|
|
20
|
-
const inverseRotationB = /*@__PURE__*/ Quat.create();
|
|
21
|
-
|
|
22
|
-
const fixedConstraintProps = {
|
|
23
|
-
...baseConstraintProps,
|
|
24
|
-
positionA: MonomorphType(Vec3, { x: 0, y: 0, z: 0 }),
|
|
25
|
-
positionB: MonomorphType(Vec3, { x: 0, y: 0, z: 0 }),
|
|
26
|
-
axisXA: MonomorphType(Vec3, { x: 1, y: 0, z: 0 }),
|
|
27
|
-
axisXB: MonomorphType(Vec3, { x: 1, y: 0, z: 0 }),
|
|
28
|
-
axisYA: MonomorphType(Vec3, { x: 0, y: 1, z: 0 }),
|
|
29
|
-
axisYB: MonomorphType(Vec3, { x: 0, y: 1, z: 0 }),
|
|
30
|
-
localPositionA: MonomorphType(Vec3, undefined, true),
|
|
31
|
-
localPositionB: MonomorphType(Vec3, undefined, true),
|
|
32
|
-
localAxisXA: MonomorphType(Vec3, undefined, true),
|
|
33
|
-
localAxisXB: MonomorphType(Vec3, undefined, true),
|
|
34
|
-
localAxisYA: MonomorphType(Vec3, undefined, true),
|
|
35
|
-
localAxisYB: MonomorphType(Vec3, undefined, true),
|
|
36
|
-
localAxisZA: MonomorphType(Vec3, undefined, true),
|
|
37
|
-
localAxisZB: MonomorphType(Vec3, undefined, true),
|
|
38
|
-
inverseInitialRotationAToB: MonomorphType(Quat, undefined, true),
|
|
39
|
-
translationComponent: MonomorphType(PointConstraintComponent),
|
|
40
|
-
rotationComponent: MonomorphType(RotationEulerComponent),
|
|
41
|
-
} as const satisfies PropertyDefinitionMap;
|
|
42
|
-
|
|
43
|
-
export class FixedConstraint
|
|
44
|
-
extends createClass<FixedConstraint, typeof fixedConstraintProps>(fixedConstraintProps)
|
|
45
|
-
implements ConstraintInterface
|
|
46
|
-
{
|
|
47
|
-
type: ConstraintType.fixedConstraint = ConstraintType.fixedConstraint;
|
|
48
|
-
declare world: World;
|
|
49
|
-
|
|
50
|
-
deactivate(): void {
|
|
51
|
-
this.translationComponent.deactivate();
|
|
52
|
-
this.rotationComponent.deactivate();
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
getLocalPoints(outA: Vec3, outB: Vec3): void {
|
|
56
|
-
outA.copy(this.localPositionA);
|
|
57
|
-
outB.copy(this.localPositionB);
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
getWorldPoints(outA: Vec3, outB: Vec3): void {
|
|
61
|
-
transformLocalToWorld.fromRotationTranslation(this.bodyA!.orientation, this.bodyA!.computedCenterOfMassPosition);
|
|
62
|
-
outA.transformVectorFromMat4(this.localPositionA, transformLocalToWorld);
|
|
63
|
-
|
|
64
|
-
transformLocalToWorld.fromRotationTranslation(this.bodyB!.orientation, this.bodyB!.computedCenterOfMassPosition);
|
|
65
|
-
outB.transformVectorFromMat4(this.localPositionB, transformLocalToWorld);
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
getInverseInitialRotationAToB(out: Quat): void {
|
|
69
|
-
this.localAxisXA.copy(this.axisXA);
|
|
70
|
-
this.localAxisXB.copy(this.axisXB);
|
|
71
|
-
this.localAxisYA.copy(this.axisYA);
|
|
72
|
-
this.localAxisYB.copy(this.axisYB);
|
|
73
|
-
|
|
74
|
-
if (this.localAxisXA.exactEquals(this.localAxisXB) && this.localAxisYA.exactEquals(this.localAxisYB)) {
|
|
75
|
-
this.inverseInitialRotationAToB.identity();
|
|
76
|
-
} else {
|
|
77
|
-
// normalize the local axes
|
|
78
|
-
this.localAxisXA.normalize();
|
|
79
|
-
this.localAxisXB.normalize();
|
|
80
|
-
this.localAxisYA.normalize();
|
|
81
|
-
this.localAxisYB.normalize();
|
|
82
|
-
|
|
83
|
-
this.localAxisZA.crossVectors(this.localAxisXA, this.localAxisYA);
|
|
84
|
-
this.localAxisZA.normalize();
|
|
85
|
-
constraintRotationA.setColumns(this.localAxisXA, this.localAxisYA, this.localAxisZA);
|
|
86
|
-
constraintQuaternionA.fromMat3(constraintRotationA);
|
|
87
|
-
|
|
88
|
-
this.localAxisZB.crossVectors(this.localAxisXB, this.localAxisYB);
|
|
89
|
-
this.localAxisZB.normalize();
|
|
90
|
-
constraintRotationB.setColumns(this.localAxisXB, this.localAxisYB, this.localAxisZB);
|
|
91
|
-
constraintQuaternionB.fromMat3(constraintRotationB);
|
|
92
|
-
|
|
93
|
-
constraintQuaternionA.conjugateQuat(constraintQuaternionA);
|
|
94
|
-
out.multiplyQuats(constraintQuaternionB, constraintQuaternionA);
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
computeLocalPositions(): void {
|
|
99
|
-
if (this.referenceFrame === ReferenceFrame.local) {
|
|
100
|
-
this.localPositionA.copy(this.positionA);
|
|
101
|
-
this.localPositionB.copy(this.positionB);
|
|
102
|
-
} else {
|
|
103
|
-
const inverseMassA = this.bodyA!.inverseMass;
|
|
104
|
-
const inverseMassB = this.bodyB!.inverseMass;
|
|
105
|
-
const totalInverseMass = inverseMassA + inverseMassB;
|
|
106
|
-
|
|
107
|
-
// case: at least one body is dynamic
|
|
108
|
-
if (totalInverseMass !== 0) {
|
|
109
|
-
anchor.scaleVector(this.bodyA!.computedCenterOfMassPosition, inverseMassA);
|
|
110
|
-
anchor.addScaledToVector(anchor, this.bodyB!.computedCenterOfMassPosition, inverseMassB);
|
|
111
|
-
anchor.scaleVector(anchor, 1 / totalInverseMass);
|
|
112
|
-
}
|
|
113
|
-
// case: both bodies are static
|
|
114
|
-
else {
|
|
115
|
-
anchor.copy(this.bodyA!.computedCenterOfMassPosition);
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
// store local positions
|
|
119
|
-
|
|
120
|
-
transformWorldToLocalA.fromInverseRotationAndTranslation(
|
|
121
|
-
this.bodyA!.orientation,
|
|
122
|
-
this.bodyA!.computedCenterOfMassPosition
|
|
123
|
-
);
|
|
124
|
-
transformWorldToLocalB.fromInverseRotationAndTranslation(
|
|
125
|
-
this.bodyB!.orientation,
|
|
126
|
-
this.bodyB!.computedCenterOfMassPosition
|
|
127
|
-
);
|
|
128
|
-
|
|
129
|
-
this.localPositionA.transformVectorFromMat4(anchor, transformWorldToLocalA);
|
|
130
|
-
this.localPositionB.transformVectorFromMat4(anchor, transformWorldToLocalB);
|
|
131
|
-
|
|
132
|
-
// correct the inverse initial rotation from body A to body B
|
|
133
|
-
|
|
134
|
-
inverseRotationB.conjugateQuat(this.bodyB!.orientation);
|
|
135
|
-
|
|
136
|
-
this.inverseInitialRotationAToB.multiplyQuats(inverseRotationB, this.inverseInitialRotationAToB);
|
|
137
|
-
this.inverseInitialRotationAToB.multiplyQuats(this.inverseInitialRotationAToB, this.bodyA!.orientation);
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
initVelocityConstraint(deltaTimeSeconds: number): void {
|
|
142
|
-
if (!this.isEnabled) {
|
|
143
|
-
return;
|
|
144
|
-
}
|
|
145
|
-
this.setComponentData();
|
|
146
|
-
this.translationComponent.setup(this.localPositionA, this.localPositionB);
|
|
147
|
-
this.rotationComponent.setup();
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
warmStart(deltaTimeSeconds: number, warmStartImpulseRatio: number): void {
|
|
151
|
-
if (!this.isEnabled) {
|
|
152
|
-
return;
|
|
153
|
-
}
|
|
154
|
-
this.setComponentData();
|
|
155
|
-
this.translationComponent.warmStart(warmStartImpulseRatio);
|
|
156
|
-
this.rotationComponent.warmStart(warmStartImpulseRatio);
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
solveVelocityConstraint(deltaTimeSeconds: number): void {
|
|
160
|
-
if (!this.isEnabled) {
|
|
161
|
-
return;
|
|
162
|
-
}
|
|
163
|
-
this.setComponentData();
|
|
164
|
-
this.translationComponent.solveVelocity();
|
|
165
|
-
this.rotationComponent.solveVelocity();
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
solvePositionConstraint(deltaTimeSeconds: number): void {
|
|
169
|
-
if (!this.isEnabled) {
|
|
170
|
-
return;
|
|
171
|
-
}
|
|
172
|
-
this.setComponentData();
|
|
173
|
-
this.translationComponent.setup(this.localPositionA, this.localPositionB);
|
|
174
|
-
this.translationComponent.solvePosition();
|
|
175
|
-
this.rotationComponent.setup();
|
|
176
|
-
this.rotationComponent.solvePosition(this.inverseInitialRotationAToB);
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
setComponentData(): void {
|
|
180
|
-
// @ts-ignore
|
|
181
|
-
this.world = this.bodyA!.world;
|
|
182
|
-
// @ts-ignore
|
|
183
|
-
this.translationComponent.world = this.bodyA!.world;
|
|
184
|
-
// @ts-ignore
|
|
185
|
-
this.rotationComponent.world = this.bodyA!.world;
|
|
186
|
-
this.translationComponent.bodyA = this.bodyA!;
|
|
187
|
-
this.translationComponent.bodyB = this.bodyB!;
|
|
188
|
-
this.rotationComponent.bodyA = this.bodyA!;
|
|
189
|
-
this.rotationComponent.bodyB = this.bodyB!;
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
const oldCreate = FixedConstraint.create;
|
|
194
|
-
FixedConstraint.create = function () {
|
|
195
|
-
const constraint = oldCreate.apply(this, arguments as any);
|
|
196
|
-
constraint.setComponentData();
|
|
197
|
-
constraint.getInverseInitialRotationAToB(constraint.inverseInitialRotationAToB);
|
|
198
|
-
constraint.computeLocalPositions();
|
|
199
|
-
constraint.deactivate();
|
|
200
|
-
constraint.world.sleepModule.wakeBodyUp(constraint.bodyA!);
|
|
201
|
-
constraint.world.sleepModule.wakeBodyUp(constraint.bodyB!);
|
|
202
|
-
return constraint;
|
|
203
|
-
};
|