@flighthq/physics2d 0.3.0-edge.1458.0c01b63
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/dist/colliderTransform.d.ts +10 -0
- package/dist/colliderTransform.d.ts.map +1 -0
- package/dist/colliderTransform.js +137 -0
- package/dist/colliderTransform.js.map +1 -0
- package/dist/contract.d.ts +9 -0
- package/dist/contract.d.ts.map +1 -0
- package/dist/contract.js +9 -0
- package/dist/contract.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -0
- package/dist/islands.d.ts +38 -0
- package/dist/islands.d.ts.map +1 -0
- package/dist/islands.js +159 -0
- package/dist/islands.js.map +1 -0
- package/dist/jointRegistry.d.ts +6 -0
- package/dist/jointRegistry.d.ts.map +1 -0
- package/dist/jointRegistry.js +78 -0
- package/dist/jointRegistry.js.map +1 -0
- package/dist/joints.d.ts +39 -0
- package/dist/joints.d.ts.map +1 -0
- package/dist/joints.js +561 -0
- package/dist/joints.js.map +1 -0
- package/dist/massProperties.d.ts +4 -0
- package/dist/massProperties.d.ts.map +1 -0
- package/dist/massProperties.js +146 -0
- package/dist/massProperties.js.map +1 -0
- package/dist/solver.d.ts +7 -0
- package/dist/solver.d.ts.map +1 -0
- package/dist/solver.js +129 -0
- package/dist/solver.js.map +1 -0
- package/dist/step.d.ts +3 -0
- package/dist/step.d.ts.map +1 -0
- package/dist/step.js +414 -0
- package/dist/step.js.map +1 -0
- package/dist/world.d.ts +10 -0
- package/dist/world.d.ts.map +1 -0
- package/dist/world.js +133 -0
- package/dist/world.js.map +1 -0
- package/package.json +49 -0
- package/src/colliderTransform.test.ts +115 -0
- package/src/islands.test.ts +262 -0
- package/src/jointRegistry.test.ts +205 -0
- package/src/joints.test.ts +951 -0
- package/src/massProperties.test.ts +169 -0
- package/src/solver.test.ts +186 -0
- package/src/step.test.ts +745 -0
- package/src/world.test.ts +142 -0
package/dist/joints.js
ADDED
|
@@ -0,0 +1,561 @@
|
|
|
1
|
+
import { applyPhysics2DImpulse } from './solver';
|
|
2
|
+
import { findPhysics2DBody } from './world';
|
|
3
|
+
// The built-in joint kinds. Bare names are reserved for these; a user's own joint takes a vendor prefix.
|
|
4
|
+
export const Physics2DDistanceJointKind = 'Distance';
|
|
5
|
+
export const Physics2DMouseJointKind = 'Mouse';
|
|
6
|
+
export const Physics2DRevoluteJointKind = 'Revolute';
|
|
7
|
+
export const Physics2DRopeJointKind = 'Rope';
|
|
8
|
+
export const Physics2DWeldJointKind = 'Weld';
|
|
9
|
+
// Holds two anchors a fixed distance apart, rigidly or as a damped spring.
|
|
10
|
+
//
|
|
11
|
+
// One scalar constraint along the axis between the anchors. Softness enters as a modified effective mass
|
|
12
|
+
// plus a position bias rather than as a separate force: solving a spring as a constraint keeps it stable
|
|
13
|
+
// at any stiffness, where adding a spring FORCE explodes once the stiffness times the timestep exceeds
|
|
14
|
+
// what the integrator can follow.
|
|
15
|
+
export const physics2DDistanceJointSolver = {
|
|
16
|
+
warmStart(world, joint) {
|
|
17
|
+
const state = jointStateScratch.get(joint);
|
|
18
|
+
if (state === undefined)
|
|
19
|
+
return;
|
|
20
|
+
const bodyA = findPhysics2DBody(world, joint.bodyA);
|
|
21
|
+
const bodyB = findPhysics2DBody(world, joint.bodyB);
|
|
22
|
+
if (bodyA === null || bodyB === null)
|
|
23
|
+
return;
|
|
24
|
+
applyPhysics2DImpulse(bodyA, bodyB, joint.rAX, joint.rAY, joint.rBX, joint.rBY, -joint.impulse0 * state[3], -joint.impulse0 * state[4]);
|
|
25
|
+
},
|
|
26
|
+
clearAccumulatedImpulses(joint) {
|
|
27
|
+
joint.impulse0 = 0;
|
|
28
|
+
},
|
|
29
|
+
prepare(world, joint, dt) {
|
|
30
|
+
const distance = joint;
|
|
31
|
+
const bodyA = findPhysics2DBody(world, joint.bodyA);
|
|
32
|
+
const bodyB = findPhysics2DBody(world, joint.bodyB);
|
|
33
|
+
if (bodyA === null || bodyB === null)
|
|
34
|
+
return;
|
|
35
|
+
writeJointAnchors(bodyA, bodyB, joint);
|
|
36
|
+
const axisX = bodyB.x + joint.rBX - (bodyA.x + joint.rAX);
|
|
37
|
+
const axisY = bodyB.y + joint.rBY - (bodyA.y + joint.rAY);
|
|
38
|
+
const length = Math.sqrt(axisX * axisX + axisY * axisY);
|
|
39
|
+
if (length > EPSILON) {
|
|
40
|
+
axisScratch[0] = axisX / length;
|
|
41
|
+
axisScratch[1] = axisY / length;
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
// Coincident anchors leave the axis undefined. Any unit vector is as correct as another and none is
|
|
45
|
+
// wrong for one step, where dividing by the length would seed NaN into both bodies permanently.
|
|
46
|
+
axisScratch[0] = 1;
|
|
47
|
+
axisScratch[1] = 0;
|
|
48
|
+
}
|
|
49
|
+
const mass = axisEffectiveMass(bodyA, bodyB, joint, axisScratch[0], axisScratch[1]);
|
|
50
|
+
const separation = length - distance.length;
|
|
51
|
+
if (distance.stiffness > 0) {
|
|
52
|
+
const angular = 2 * Math.PI * distance.stiffness;
|
|
53
|
+
const damp = 2 * mass * distance.damping * angular;
|
|
54
|
+
const spring = mass * angular * angular;
|
|
55
|
+
const gamma = dt * (damp + dt * spring);
|
|
56
|
+
jointScratch[2] = gamma > 0 ? 1 / gamma : 0;
|
|
57
|
+
jointScratch[1] = separation * dt * spring * jointScratch[2];
|
|
58
|
+
const softMass = mass + jointScratch[2];
|
|
59
|
+
jointScratch[0] = softMass > 0 ? 1 / softMass : 0;
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
jointScratch[0] = mass > 0 ? 1 / mass : 0;
|
|
63
|
+
jointScratch[1] = separation * (BAUMGARTE / dt);
|
|
64
|
+
jointScratch[2] = 0;
|
|
65
|
+
}
|
|
66
|
+
distance.rAX = joint.rAX;
|
|
67
|
+
const distanceState = beginJointSolve(distance, 5);
|
|
68
|
+
distanceState[0] = jointScratch[0];
|
|
69
|
+
distanceState[1] = jointScratch[1];
|
|
70
|
+
distanceState[2] = jointScratch[2];
|
|
71
|
+
distanceState[3] = axisScratch[0];
|
|
72
|
+
distanceState[4] = axisScratch[1];
|
|
73
|
+
},
|
|
74
|
+
solve(world, joint) {
|
|
75
|
+
const state = jointStateScratch.get(joint);
|
|
76
|
+
if (state === undefined)
|
|
77
|
+
return;
|
|
78
|
+
const bodyA = findPhysics2DBody(world, joint.bodyA);
|
|
79
|
+
const bodyB = findPhysics2DBody(world, joint.bodyB);
|
|
80
|
+
if (bodyA === null || bodyB === null)
|
|
81
|
+
return;
|
|
82
|
+
const [effectiveMass, bias, gamma, axisX, axisY] = state;
|
|
83
|
+
const velocity = axisRelativeVelocity(bodyA, bodyB, joint, axisX, axisY);
|
|
84
|
+
const lambda = -effectiveMass * (velocity + bias + gamma * joint.impulse0);
|
|
85
|
+
joint.impulse0 += lambda;
|
|
86
|
+
applyPhysics2DImpulse(bodyA, bodyB, joint.rAX, joint.rAY, joint.rBX, joint.rBY, -lambda * axisX, -lambda * axisY);
|
|
87
|
+
},
|
|
88
|
+
};
|
|
89
|
+
// Drags one body toward a moving world-space target with bounded force.
|
|
90
|
+
//
|
|
91
|
+
// Always soft, and that is not a tuning choice: a rigid drag lets a user inject unbounded energy simply by
|
|
92
|
+
// moving the cursor faster than the simulation can follow, and the rest of the world absorbs it. The force
|
|
93
|
+
// bound is what keeps a dragged body from tunnelling through a wall it is pulled into.
|
|
94
|
+
export const physics2DMouseJointSolver = {
|
|
95
|
+
// A mouse joint drags ONE body toward a world-space target; its other end is not a body at all, and
|
|
96
|
+
// callers pass whatever index is convenient. Canonical ordering exists to fix the solve order
|
|
97
|
+
// BETWEEN two bodies, so with only one body there is nothing to order and the exchange is pure
|
|
98
|
+
// corruption: it moved the dragged body into bodyA, and this solver acts on bodyB, so the drag
|
|
99
|
+
// silently applied to the anchor instead and the dragged body never moved.
|
|
100
|
+
swapEnds() {
|
|
101
|
+
return false;
|
|
102
|
+
},
|
|
103
|
+
// No warmStart: the drag target moves between steps, so last step's impulse is aimed at a place the
|
|
104
|
+
// cursor has already left. Seeding from it fights the new target rather than helping it converge.
|
|
105
|
+
clearAccumulatedImpulses(joint) {
|
|
106
|
+
joint.impulse0 = 0;
|
|
107
|
+
joint.impulse1 = 0;
|
|
108
|
+
},
|
|
109
|
+
prepare(world, joint, dt) {
|
|
110
|
+
const mouse = joint;
|
|
111
|
+
const bodyB = findPhysics2DBody(world, joint.bodyB);
|
|
112
|
+
if (bodyB === null)
|
|
113
|
+
return;
|
|
114
|
+
const cos = Math.cos(bodyB.angle);
|
|
115
|
+
const sin = Math.sin(bodyB.angle);
|
|
116
|
+
joint.rBX = joint.localAnchorBX * cos - joint.localAnchorBY * sin;
|
|
117
|
+
joint.rBY = joint.localAnchorBX * sin + joint.localAnchorBY * cos;
|
|
118
|
+
joint.rAX = 0;
|
|
119
|
+
joint.rAY = 0;
|
|
120
|
+
const angular = 2 * Math.PI * (mouse.stiffness > 0 ? mouse.stiffness : 5);
|
|
121
|
+
const damp = 2 * mouse.damping * angular;
|
|
122
|
+
const spring = angular * angular;
|
|
123
|
+
const gamma = dt * (damp + dt * spring);
|
|
124
|
+
const inverseGamma = gamma > 0 ? 1 / gamma : 0;
|
|
125
|
+
const biasFactor = dt * spring * inverseGamma;
|
|
126
|
+
// maxForce is a force; joint.impulse0/1 accumulate an impulse. Clamping one against the other was
|
|
127
|
+
// a unit error worth a factor of 1/dt — at dt 0.01 the bound admitted a hundred times the force it
|
|
128
|
+
// named. Convert once here, where dt is in hand, rather than in solve, which does not receive it.
|
|
129
|
+
const mouseState = beginJointSolve(mouse, 5);
|
|
130
|
+
mouseState[0] = inverseGamma;
|
|
131
|
+
mouseState[1] = biasFactor;
|
|
132
|
+
mouseState[2] = dt * mouse.maxForce;
|
|
133
|
+
mouseState[3] = 0;
|
|
134
|
+
mouseState[4] = 0;
|
|
135
|
+
},
|
|
136
|
+
solve(world, joint) {
|
|
137
|
+
const mouse = joint;
|
|
138
|
+
const state = jointStateScratch.get(joint);
|
|
139
|
+
if (state === undefined)
|
|
140
|
+
return;
|
|
141
|
+
const bodyB = findPhysics2DBody(world, joint.bodyB);
|
|
142
|
+
if (bodyB === null)
|
|
143
|
+
return;
|
|
144
|
+
const [inverseGamma, biasFactor, maxImpulse] = state;
|
|
145
|
+
const anchorX = bodyB.x + joint.rBX;
|
|
146
|
+
const anchorY = bodyB.y + joint.rBY;
|
|
147
|
+
const errorX = anchorX - mouse.targetX;
|
|
148
|
+
const errorY = anchorY - mouse.targetY;
|
|
149
|
+
const velocityX = bodyB.velocityX - bodyB.angularVelocity * joint.rBY;
|
|
150
|
+
const velocityY = bodyB.velocityY + bodyB.angularVelocity * joint.rBX;
|
|
151
|
+
const mass = bodyB.inverseMass > 0 ? 1 / bodyB.inverseMass : 0;
|
|
152
|
+
let impulseX = -mass * (velocityX + biasFactor * errorX + inverseGamma * joint.impulse0);
|
|
153
|
+
let impulseY = -mass * (velocityY + biasFactor * errorY + inverseGamma * joint.impulse1);
|
|
154
|
+
const previousX = joint.impulse0;
|
|
155
|
+
const previousY = joint.impulse1;
|
|
156
|
+
joint.impulse0 += impulseX;
|
|
157
|
+
joint.impulse1 += impulseY;
|
|
158
|
+
// Clamped on the ACCUMULATED impulse, so a later iteration can correct an earlier overshoot while the
|
|
159
|
+
// total force stays inside the bound.
|
|
160
|
+
const magnitude = Math.sqrt(joint.impulse0 * joint.impulse0 + joint.impulse1 * joint.impulse1);
|
|
161
|
+
if (magnitude > maxImpulse && magnitude > 0) {
|
|
162
|
+
const scale = maxImpulse / magnitude;
|
|
163
|
+
joint.impulse0 *= scale;
|
|
164
|
+
joint.impulse1 *= scale;
|
|
165
|
+
}
|
|
166
|
+
impulseX = joint.impulse0 - previousX;
|
|
167
|
+
impulseY = joint.impulse1 - previousY;
|
|
168
|
+
bodyB.velocityX += impulseX * bodyB.inverseMass;
|
|
169
|
+
bodyB.velocityY += impulseY * bodyB.inverseMass;
|
|
170
|
+
bodyB.angularVelocity += bodyB.inverseInertia * (joint.rBX * impulseY - joint.rBY * impulseX);
|
|
171
|
+
},
|
|
172
|
+
};
|
|
173
|
+
// Pins two bodies at a point, leaving rotation free — a hinge.
|
|
174
|
+
//
|
|
175
|
+
// Two scalar constraints, one per axis of the shared point, solved as a coupled pair rather than
|
|
176
|
+
// independently: solving x then y lets each undo part of the other's correction, and a hinge under load
|
|
177
|
+
// visibly creeps.
|
|
178
|
+
export const physics2DRevoluteJointSolver = {
|
|
179
|
+
warmStart(world, joint) {
|
|
180
|
+
const bodyA = findPhysics2DBody(world, joint.bodyA);
|
|
181
|
+
const bodyB = findPhysics2DBody(world, joint.bodyB);
|
|
182
|
+
if (bodyA === null || bodyB === null)
|
|
183
|
+
return;
|
|
184
|
+
applyPhysics2DImpulse(bodyA, bodyB, joint.rAX, joint.rAY, joint.rBX, joint.rBY, -joint.impulse0, -joint.impulse1);
|
|
185
|
+
// The motor accumulator persists across steps, so it has to be REAPPLIED here like every other
|
|
186
|
+
// persisted impulse. Warm-starting only the point pair left it accumulating without ever acting:
|
|
187
|
+
// the solve clamps the running total against maxMotorTorque * dt, so once it reached that bound it
|
|
188
|
+
// stayed there and every later step added nothing. A low-torque motor would apply its first
|
|
189
|
+
// increment and then hold the same value forever, looking like a motor that had reached speed while
|
|
190
|
+
// the body never moved.
|
|
191
|
+
//
|
|
192
|
+
// Gated on the CURRENT enableMotor, not on the value being non-zero. A cached impulse is only valid
|
|
193
|
+
// while the thing that produced it is still running: `solve` skips a disabled motor, so reapplying
|
|
194
|
+
// its last impulse here would exert torque no solver ever asks for and nothing ever cancels — a
|
|
195
|
+
// disabled motor that keeps turning the joint forever. Clearing rather than merely skipping means a
|
|
196
|
+
// motor switched back on starts from rest instead of resuming a stale accumulator from whenever it
|
|
197
|
+
// was last enabled.
|
|
198
|
+
//
|
|
199
|
+
// Read plainly, because `prepare` has already established the accumulator and runs before this on
|
|
200
|
+
// every path. Defaulting again here would be a second owner for one invariant — and the version of
|
|
201
|
+
// that defense which shipped read into a LOCAL without writing the field back, so the very next read
|
|
202
|
+
// in `solve` saw the absent value again. A default that does not persist is not a fix.
|
|
203
|
+
const revolute = joint;
|
|
204
|
+
const motorImpulse = revolute.motorImpulse;
|
|
205
|
+
if (!revolute.enableMotor) {
|
|
206
|
+
revolute.motorImpulse = 0;
|
|
207
|
+
}
|
|
208
|
+
else if (motorImpulse !== 0) {
|
|
209
|
+
bodyA.angularVelocity -= bodyA.inverseInertia * motorImpulse;
|
|
210
|
+
bodyB.angularVelocity += bodyB.inverseInertia * motorImpulse;
|
|
211
|
+
}
|
|
212
|
+
},
|
|
213
|
+
clearAccumulatedImpulses(joint) {
|
|
214
|
+
joint.impulse0 = 0;
|
|
215
|
+
joint.impulse1 = 0;
|
|
216
|
+
joint.motorImpulse = 0;
|
|
217
|
+
},
|
|
218
|
+
// Swapping the ends reverses the sense of every angular quantity this solver reads. The relative
|
|
219
|
+
// angle is measured bodyA -> bodyB, so it negates; the limit interval negates AND its ends exchange
|
|
220
|
+
// (the old lower bound becomes the new upper); and the motor's target relative velocity reverses.
|
|
221
|
+
// Deriving it: the constraint is lower <= (angleB - angleA - reference) <= upper. Writing t for
|
|
222
|
+
// (angleB - angleA), that is lower + reference <= t <= upper + reference. After the swap t becomes
|
|
223
|
+
// -t, so the same physical interval requires reference' = -reference, lower' = -upper and
|
|
224
|
+
// upper' = -lower.
|
|
225
|
+
swapEnds(joint) {
|
|
226
|
+
const revolute = joint;
|
|
227
|
+
const lower = revolute.lowerAngle;
|
|
228
|
+
revolute.lowerAngle = -revolute.upperAngle;
|
|
229
|
+
revolute.upperAngle = -lower;
|
|
230
|
+
revolute.referenceAngle = -revolute.referenceAngle;
|
|
231
|
+
revolute.motorSpeed = -revolute.motorSpeed;
|
|
232
|
+
// Defaulted BEFORE the negation, not after. This runs when the joint is added, ahead of the first
|
|
233
|
+
// prepare, so the field may still be absent — and `-undefined` is NaN, which is not nullish, so a
|
|
234
|
+
// later `??` would accept the poison rather than replace it. Negating an absent accumulator has to
|
|
235
|
+
// produce zero, not NaN.
|
|
236
|
+
revolute.motorImpulse = -(revolute.motorImpulse ?? 0);
|
|
237
|
+
return true;
|
|
238
|
+
},
|
|
239
|
+
prepare(world, joint, dt) {
|
|
240
|
+
const revolute = joint;
|
|
241
|
+
const bodyA = findPhysics2DBody(world, joint.bodyA);
|
|
242
|
+
const bodyB = findPhysics2DBody(world, joint.bodyB);
|
|
243
|
+
if (bodyA === null || bodyB === null)
|
|
244
|
+
return;
|
|
245
|
+
writeJointAnchors(bodyA, bodyB, joint);
|
|
246
|
+
const errorX = bodyB.x + joint.rBX - (bodyA.x + joint.rAX);
|
|
247
|
+
const errorY = bodyB.y + joint.rBY - (bodyA.y + joint.rAY);
|
|
248
|
+
// The angular constraints share one effective mass: the pair's combined resistance to a relative
|
|
249
|
+
// spin. Zero when neither body can rotate, which disables motor and limits rather than dividing
|
|
250
|
+
// by zero.
|
|
251
|
+
const inverseInertiaSum = bodyA.inverseInertia + bodyB.inverseInertia;
|
|
252
|
+
const angularMass = inverseInertiaSum > 0 ? 1 / inverseInertiaSum : 0;
|
|
253
|
+
// The motor accumulator is revolute-specific, so the shared entry point above cannot reach it.
|
|
254
|
+
revolute.motorImpulse ??= 0;
|
|
255
|
+
const revoluteState = beginJointSolve(joint, 7);
|
|
256
|
+
revoluteState[0] = errorX * (BAUMGARTE / dt);
|
|
257
|
+
revoluteState[1] = errorY * (BAUMGARTE / dt);
|
|
258
|
+
revoluteState[2] = angularMass;
|
|
259
|
+
revoluteState[3] = 0;
|
|
260
|
+
revoluteState[4] = 0;
|
|
261
|
+
revoluteState[5] = dt * revolute.maxMotorTorque;
|
|
262
|
+
revoluteState[6] = 1 / dt;
|
|
263
|
+
},
|
|
264
|
+
solve(world, joint) {
|
|
265
|
+
const revolute = joint;
|
|
266
|
+
const state = jointStateScratch.get(joint);
|
|
267
|
+
if (state === undefined)
|
|
268
|
+
return;
|
|
269
|
+
const bodyA = findPhysics2DBody(world, joint.bodyA);
|
|
270
|
+
const bodyB = findPhysics2DBody(world, joint.bodyB);
|
|
271
|
+
if (bodyA === null || bodyB === null)
|
|
272
|
+
return;
|
|
273
|
+
const angularMass = state[2];
|
|
274
|
+
if (angularMass > 0) {
|
|
275
|
+
// Motor first: it is a soft target the limits are allowed to override, so solving it before the
|
|
276
|
+
// limits lets a limit's impulse win in the same iteration when they disagree.
|
|
277
|
+
if (revolute.enableMotor) {
|
|
278
|
+
const maxMotorImpulse = state[5];
|
|
279
|
+
const relative = bodyB.angularVelocity - bodyA.angularVelocity - revolute.motorSpeed;
|
|
280
|
+
const desired = -angularMass * relative;
|
|
281
|
+
const previous = revolute.motorImpulse;
|
|
282
|
+
// Clamped on the ACCUMULATED impulse against torque * dt, so the bound is a torque and not a
|
|
283
|
+
// per-iteration one that would scale with the iteration count.
|
|
284
|
+
const total = Math.min(Math.max(previous + desired, -maxMotorImpulse), maxMotorImpulse);
|
|
285
|
+
revolute.motorImpulse = total;
|
|
286
|
+
const applied = total - previous;
|
|
287
|
+
bodyA.angularVelocity -= bodyA.inverseInertia * applied;
|
|
288
|
+
bodyB.angularVelocity += bodyB.inverseInertia * applied;
|
|
289
|
+
}
|
|
290
|
+
if (revolute.enableLimit) {
|
|
291
|
+
const bias = state[6];
|
|
292
|
+
const angle = bodyB.angle - bodyA.angle - revolute.referenceAngle;
|
|
293
|
+
// Each end is a one-sided constraint: the non-negative clamp on the running impulse lets a
|
|
294
|
+
// limit push the angle back inside the interval and never pull it in.
|
|
295
|
+
//
|
|
296
|
+
// The bias is the SIGNED distance to the bound, C / dt, with no clamp on C — and both clamps
|
|
297
|
+
// are wrong, in opposite ways:
|
|
298
|
+
//
|
|
299
|
+
// max(C, 0) suppresses correctly but cannot correct. It zeroes the bias exactly when the
|
|
300
|
+
// angle is already outside the interval, leaving only the relative-velocity term, so a joint
|
|
301
|
+
// authored out of range and sitting still is never pushed back: it stays violated forever.
|
|
302
|
+
//
|
|
303
|
+
// min(C, 0) corrects but cannot suppress. It zeroes the bias while INSIDE the interval, and
|
|
304
|
+
// the upper end then reads a positive desired impulse against any forward rotation and brakes
|
|
305
|
+
// it to a standstill — a motor at speed 5 held the arm at exactly zero, spending its whole
|
|
306
|
+
// torque budget against a limit it was nowhere near.
|
|
307
|
+
//
|
|
308
|
+
// Signed C does both. Inside the interval it is positive, which drives the desired impulse
|
|
309
|
+
// negative and the clamp holds the accumulator at zero, so the limit contributes nothing.
|
|
310
|
+
// Outside it is negative, which drives the desired impulse positive and pushes the angle back.
|
|
311
|
+
const lowerError = angle - revolute.lowerAngle;
|
|
312
|
+
const lowerDesired = -angularMass * (bodyB.angularVelocity - bodyA.angularVelocity + lowerError * bias);
|
|
313
|
+
const lowerPrevious = state[3];
|
|
314
|
+
const lowerTotal = Math.max(lowerPrevious + lowerDesired, 0);
|
|
315
|
+
state[3] = lowerTotal;
|
|
316
|
+
const lowerApplied = lowerTotal - lowerPrevious;
|
|
317
|
+
bodyA.angularVelocity -= bodyA.inverseInertia * lowerApplied;
|
|
318
|
+
bodyB.angularVelocity += bodyB.inverseInertia * lowerApplied;
|
|
319
|
+
const upperError = revolute.upperAngle - angle;
|
|
320
|
+
const upperDesired = -angularMass * (bodyA.angularVelocity - bodyB.angularVelocity + upperError * bias);
|
|
321
|
+
const upperPrevious = state[4];
|
|
322
|
+
const upperTotal = Math.max(upperPrevious + upperDesired, 0);
|
|
323
|
+
state[4] = upperTotal;
|
|
324
|
+
const upperApplied = upperTotal - upperPrevious;
|
|
325
|
+
bodyA.angularVelocity += bodyA.inverseInertia * upperApplied;
|
|
326
|
+
bodyB.angularVelocity -= bodyB.inverseInertia * upperApplied;
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
solvePointConstraint(bodyA, bodyB, joint, state[0], state[1]);
|
|
330
|
+
},
|
|
331
|
+
};
|
|
332
|
+
// An inequality constraint that acts only at full extension. Slack within `maxLength`, caught at it.
|
|
333
|
+
//
|
|
334
|
+
// The non-negative clamp on the accumulated impulse is what makes it a rope rather than a stiff bar: a
|
|
335
|
+
// rope may pull the bodies together and may never push them apart.
|
|
336
|
+
export const physics2DRopeJointSolver = {
|
|
337
|
+
warmStart(world, joint) {
|
|
338
|
+
const state = jointStateScratch.get(joint);
|
|
339
|
+
if (state === undefined)
|
|
340
|
+
return;
|
|
341
|
+
const bodyA = findPhysics2DBody(world, joint.bodyA);
|
|
342
|
+
const bodyB = findPhysics2DBody(world, joint.bodyB);
|
|
343
|
+
if (bodyA === null || bodyB === null)
|
|
344
|
+
return;
|
|
345
|
+
applyPhysics2DImpulse(bodyA, bodyB, joint.rAX, joint.rAY, joint.rBX, joint.rBY, -joint.impulse0 * state[3], -joint.impulse0 * state[4]);
|
|
346
|
+
},
|
|
347
|
+
clearAccumulatedImpulses(joint) {
|
|
348
|
+
joint.impulse0 = 0;
|
|
349
|
+
},
|
|
350
|
+
prepare(world, joint, dt) {
|
|
351
|
+
const rope = joint;
|
|
352
|
+
const bodyA = findPhysics2DBody(world, joint.bodyA);
|
|
353
|
+
const bodyB = findPhysics2DBody(world, joint.bodyB);
|
|
354
|
+
if (bodyA === null || bodyB === null)
|
|
355
|
+
return;
|
|
356
|
+
writeJointAnchors(bodyA, bodyB, joint);
|
|
357
|
+
const axisX = bodyB.x + joint.rBX - (bodyA.x + joint.rAX);
|
|
358
|
+
const axisY = bodyB.y + joint.rBY - (bodyA.y + joint.rAY);
|
|
359
|
+
const length = Math.sqrt(axisX * axisX + axisY * axisY);
|
|
360
|
+
const unitX = length > EPSILON ? axisX / length : 1;
|
|
361
|
+
const unitY = length > EPSILON ? axisY / length : 0;
|
|
362
|
+
const mass = axisEffectiveMass(bodyA, bodyB, joint, unitX, unitY);
|
|
363
|
+
const excess = length - rope.maxLength;
|
|
364
|
+
// Slack: no constraint at all this step, which is what a rope IS. Marked by a zero effective mass so
|
|
365
|
+
// the iterations skip it without a second flag to keep in sync.
|
|
366
|
+
const active = excess > 0;
|
|
367
|
+
const ropeState = beginJointSolve(rope, 5);
|
|
368
|
+
ropeState[0] = active && mass > 0 ? 1 / mass : 0;
|
|
369
|
+
ropeState[1] = active ? excess * (BAUMGARTE / dt) : 0;
|
|
370
|
+
ropeState[2] = 0;
|
|
371
|
+
ropeState[3] = unitX;
|
|
372
|
+
ropeState[4] = unitY;
|
|
373
|
+
if (!active)
|
|
374
|
+
joint.impulse0 = 0;
|
|
375
|
+
},
|
|
376
|
+
solve(world, joint) {
|
|
377
|
+
const state = jointStateScratch.get(joint);
|
|
378
|
+
if (state === undefined || state[0] === 0)
|
|
379
|
+
return;
|
|
380
|
+
const bodyA = findPhysics2DBody(world, joint.bodyA);
|
|
381
|
+
const bodyB = findPhysics2DBody(world, joint.bodyB);
|
|
382
|
+
if (bodyA === null || bodyB === null)
|
|
383
|
+
return;
|
|
384
|
+
const [effectiveMass, bias, , axisX, axisY] = state;
|
|
385
|
+
const velocity = axisRelativeVelocity(bodyA, bodyB, joint, axisX, axisY);
|
|
386
|
+
let lambda = -effectiveMass * (velocity + bias);
|
|
387
|
+
const previous = joint.impulse0;
|
|
388
|
+
joint.impulse0 = Math.min(0, previous + lambda);
|
|
389
|
+
lambda = joint.impulse0 - previous;
|
|
390
|
+
applyPhysics2DImpulse(bodyA, bodyB, joint.rAX, joint.rAY, joint.rBX, joint.rBY, -lambda * axisX, -lambda * axisY);
|
|
391
|
+
},
|
|
392
|
+
};
|
|
393
|
+
// Pins the anchors together and locks the relative angle — rigid attachment.
|
|
394
|
+
//
|
|
395
|
+
// The point constraint plus one angular constraint. It is solved rather than exact, so it flexes under
|
|
396
|
+
// enough load; a truly rigid attachment is one body with two colliders, and the difference is that a weld
|
|
397
|
+
// can be broken at runtime.
|
|
398
|
+
// Weld holds the pair at a fixed relative angle, measured from bodyA to bodyB, so exchanging the ends
|
|
399
|
+
// reverses that measurement and the stored reference angle must be negated with them. It is the only
|
|
400
|
+
// direction-bearing field any solver reads today: revolute declares one but does not yet read it, and
|
|
401
|
+
// prismatic has no solver at all, so their transforms land with the work that makes them live.
|
|
402
|
+
export const physics2DWeldJointSolver = {
|
|
403
|
+
warmStart(world, joint) {
|
|
404
|
+
const bodyA = findPhysics2DBody(world, joint.bodyA);
|
|
405
|
+
const bodyB = findPhysics2DBody(world, joint.bodyB);
|
|
406
|
+
if (bodyA === null || bodyB === null)
|
|
407
|
+
return;
|
|
408
|
+
applyPhysics2DImpulse(bodyA, bodyB, joint.rAX, joint.rAY, joint.rBX, joint.rBY, -joint.impulse0, -joint.impulse1);
|
|
409
|
+
bodyA.angularVelocity -= bodyA.inverseInertia * joint.impulse2;
|
|
410
|
+
bodyB.angularVelocity += bodyB.inverseInertia * joint.impulse2;
|
|
411
|
+
},
|
|
412
|
+
clearAccumulatedImpulses(joint) {
|
|
413
|
+
joint.impulse0 = 0;
|
|
414
|
+
joint.impulse1 = 0;
|
|
415
|
+
joint.impulse2 = 0;
|
|
416
|
+
},
|
|
417
|
+
swapEnds(joint) {
|
|
418
|
+
const weld = joint;
|
|
419
|
+
weld.referenceAngle = -weld.referenceAngle;
|
|
420
|
+
return true;
|
|
421
|
+
},
|
|
422
|
+
prepare(world, joint, dt) {
|
|
423
|
+
const weld = joint;
|
|
424
|
+
const bodyA = findPhysics2DBody(world, joint.bodyA);
|
|
425
|
+
const bodyB = findPhysics2DBody(world, joint.bodyB);
|
|
426
|
+
if (bodyA === null || bodyB === null)
|
|
427
|
+
return;
|
|
428
|
+
writeJointAnchors(bodyA, bodyB, joint);
|
|
429
|
+
const errorX = bodyB.x + joint.rBX - (bodyA.x + joint.rAX);
|
|
430
|
+
const errorY = bodyB.y + joint.rBY - (bodyA.y + joint.rAY);
|
|
431
|
+
const angleError = bodyB.angle - bodyA.angle - weld.referenceAngle;
|
|
432
|
+
const angularMass = bodyA.inverseInertia + bodyB.inverseInertia;
|
|
433
|
+
const weldState = beginJointSolve(weld, 5);
|
|
434
|
+
weldState[0] = errorX * (BAUMGARTE / dt);
|
|
435
|
+
weldState[1] = errorY * (BAUMGARTE / dt);
|
|
436
|
+
weldState[2] = angleError * (BAUMGARTE / dt);
|
|
437
|
+
weldState[3] = angularMass > 0 ? 1 / angularMass : 0;
|
|
438
|
+
weldState[4] = 0;
|
|
439
|
+
},
|
|
440
|
+
solve(world, joint) {
|
|
441
|
+
const state = jointStateScratch.get(joint);
|
|
442
|
+
if (state === undefined)
|
|
443
|
+
return;
|
|
444
|
+
const bodyA = findPhysics2DBody(world, joint.bodyA);
|
|
445
|
+
const bodyB = findPhysics2DBody(world, joint.bodyB);
|
|
446
|
+
if (bodyA === null || bodyB === null)
|
|
447
|
+
return;
|
|
448
|
+
const angularVelocity = bodyB.angularVelocity - bodyA.angularVelocity;
|
|
449
|
+
const angularLambda = -state[3] * (angularVelocity + state[2]);
|
|
450
|
+
joint.impulse2 += angularLambda;
|
|
451
|
+
bodyA.angularVelocity -= bodyA.inverseInertia * angularLambda;
|
|
452
|
+
bodyB.angularVelocity += bodyB.inverseInertia * angularLambda;
|
|
453
|
+
solvePointConstraint(bodyA, bodyB, joint, state[0], state[1]);
|
|
454
|
+
},
|
|
455
|
+
};
|
|
456
|
+
// The shared two-axis point solve behind revolute and weld. Each axis is solved against the velocities the
|
|
457
|
+
// other just left, which is the sequential-impulse property doing its job within one constraint.
|
|
458
|
+
function solvePointConstraint(bodyA, bodyB, joint, biasX, biasY) {
|
|
459
|
+
const massX = axisEffectiveMass(bodyA, bodyB, joint, 1, 0);
|
|
460
|
+
const velocityX = axisRelativeVelocity(bodyA, bodyB, joint, 1, 0);
|
|
461
|
+
const lambdaX = massX > 0 ? -(velocityX + biasX) / massX : 0;
|
|
462
|
+
joint.impulse0 += lambdaX;
|
|
463
|
+
applyPhysics2DImpulse(bodyA, bodyB, joint.rAX, joint.rAY, joint.rBX, joint.rBY, -lambdaX, 0);
|
|
464
|
+
const massY = axisEffectiveMass(bodyA, bodyB, joint, 0, 1);
|
|
465
|
+
const velocityY = axisRelativeVelocity(bodyA, bodyB, joint, 0, 1);
|
|
466
|
+
const lambdaY = massY > 0 ? -(velocityY + biasY) / massY : 0;
|
|
467
|
+
joint.impulse1 += lambdaY;
|
|
468
|
+
applyPhysics2DImpulse(bodyA, bodyB, joint.rAX, joint.rAY, joint.rBX, joint.rBY, 0, -lambdaY);
|
|
469
|
+
}
|
|
470
|
+
// Rotates each body's local anchor into world space, relative to that body's centre of mass — the lever
|
|
471
|
+
// arm every joint impulse acts through.
|
|
472
|
+
function writeJointAnchors(bodyA, bodyB, joint) {
|
|
473
|
+
const cosA = Math.cos(bodyA.angle);
|
|
474
|
+
const sinA = Math.sin(bodyA.angle);
|
|
475
|
+
const cosB = Math.cos(bodyB.angle);
|
|
476
|
+
const sinB = Math.sin(bodyB.angle);
|
|
477
|
+
joint.rAX = (joint.localAnchorAX - bodyA.centerX) * cosA - (joint.localAnchorAY - bodyA.centerY) * sinA;
|
|
478
|
+
joint.rAY = (joint.localAnchorAX - bodyA.centerX) * sinA + (joint.localAnchorAY - bodyA.centerY) * cosA;
|
|
479
|
+
joint.rBX = (joint.localAnchorBX - bodyB.centerX) * cosB - (joint.localAnchorBY - bodyB.centerY) * sinB;
|
|
480
|
+
joint.rBY = (joint.localAnchorBX - bodyB.centerX) * sinB + (joint.localAnchorBY - bodyB.centerY) * cosB;
|
|
481
|
+
}
|
|
482
|
+
// The pair's inverse effective mass along `axis` at the joint anchors — the same quantity a contact
|
|
483
|
+
// constraint uses, over the joint's lever arms instead of a contact point's.
|
|
484
|
+
function axisEffectiveMass(bodyA, bodyB, joint, axisX, axisY) {
|
|
485
|
+
const crossA = joint.rAX * axisY - joint.rAY * axisX;
|
|
486
|
+
const crossB = joint.rBX * axisY - joint.rBY * axisX;
|
|
487
|
+
return (bodyA.inverseMass +
|
|
488
|
+
bodyB.inverseMass +
|
|
489
|
+
bodyA.inverseInertia * crossA * crossA +
|
|
490
|
+
bodyB.inverseInertia * crossB * crossB);
|
|
491
|
+
}
|
|
492
|
+
function axisRelativeVelocity(bodyA, bodyB, joint, axisX, axisY) {
|
|
493
|
+
const vax = bodyA.velocityX - bodyA.angularVelocity * joint.rAY;
|
|
494
|
+
const vay = bodyA.velocityY + bodyA.angularVelocity * joint.rAX;
|
|
495
|
+
const vbx = bodyB.velocityX - bodyB.angularVelocity * joint.rBY;
|
|
496
|
+
const vby = bodyB.velocityY + bodyB.angularVelocity * joint.rBX;
|
|
497
|
+
// B relative to A, the same sense as the positional error the bias is built from, so a positive value
|
|
498
|
+
// means the pair is separating along this axis. The contact solver measures the OPPOSITE sense, because
|
|
499
|
+
// its normal points the other way. Mixing the two is not a sign slip that shows up as a small error: the
|
|
500
|
+
// correction then adds to the violation instead of cancelling it, every iteration compounds it, and the
|
|
501
|
+
// bodies leave the world within one step.
|
|
502
|
+
return (vbx - vax) * axisX + (vby - vay) * axisY;
|
|
503
|
+
}
|
|
504
|
+
// Fills this joint's per-step state in place, allocating the array only the first time the joint is
|
|
505
|
+
// prepared. Every solver rebuilds its whole block each step, so the array is pure scratch and reusing it
|
|
506
|
+
// costs nothing — but allocating a fresh one per joint per step made the step's allocation profile scale
|
|
507
|
+
// with the joint count, which is exactly the hidden per-frame allocation the package's own charter
|
|
508
|
+
// forbids.
|
|
509
|
+
// Returns this joint's reusable per-step scratch, sized to `length`, for the caller to write into by
|
|
510
|
+
// index. It deliberately does not take the values: a `(joint, [a, b, c])` signature allocates the
|
|
511
|
+
// literal at every call site on every step, so the array the joint reuses was only ever the
|
|
512
|
+
// destination — the source was fresh garbage each frame, one array per joint per step. Handing the
|
|
513
|
+
// destination back is what makes the prepare pass allocation-free, and it matches the SDK's
|
|
514
|
+
// write-into-out convention rather than returning a new value.
|
|
515
|
+
// Entry point for one joint's step: sizes its per-step scratch and ESTABLISHES its impulse accumulators.
|
|
516
|
+
//
|
|
517
|
+
// The accumulators are established here rather than defended at each read because every read assumed the
|
|
518
|
+
// field was already a number, and a joint can reach the solver without one. The type declares them
|
|
519
|
+
// required, but a joint deserialized from a saved world satisfies that only at compile time; at runtime
|
|
520
|
+
// the fields are simply absent. The first read then computes `undefined + x`, and because an accumulator
|
|
521
|
+
// is fed back into the next iteration the NaN does not stay local — it goes out through the applied
|
|
522
|
+
// impulse into BOTH bodies' velocities, and from there into every contact they touch.
|
|
523
|
+
//
|
|
524
|
+
// This is the one place that covers the whole class. Every solver's `prepare` calls it, and `solve`
|
|
525
|
+
// returns early when the scratch is absent, so no solver can read an accumulator this has not passed
|
|
526
|
+
// over first. Kind-specific accumulators (the revolute motor) are established by their own `prepare`,
|
|
527
|
+
// which is the only code that knows they exist.
|
|
528
|
+
function beginJointSolve(joint, length) {
|
|
529
|
+
joint.impulse0 ??= 0;
|
|
530
|
+
joint.impulse1 ??= 0;
|
|
531
|
+
joint.impulse2 ??= 0;
|
|
532
|
+
let state = jointStateScratch.get(joint);
|
|
533
|
+
if (state === undefined) {
|
|
534
|
+
state = [];
|
|
535
|
+
jointStateScratch.set(joint, state);
|
|
536
|
+
}
|
|
537
|
+
state.length = length;
|
|
538
|
+
return state;
|
|
539
|
+
}
|
|
540
|
+
// Per-step solver state, keyed by joint. A Map rather than fields on the joint because the numbers each
|
|
541
|
+
// solver needs mean different things per kind, and putting a fixed block of untyped scratch on the
|
|
542
|
+
// public entity would make the header describe the solver's internals.
|
|
543
|
+
//
|
|
544
|
+
// Mutable, because a one-sided constraint accumulates its impulse ACROSS the velocity iterations of a
|
|
545
|
+
// single step: the revolute limits clamp their running totals to stay non-negative, which is what makes
|
|
546
|
+
// them limits rather than springs, and that total has to live somewhere between iterations.
|
|
547
|
+
//
|
|
548
|
+
// A WeakMap, not a Map. A module-global strong Map keyed by joint retains every joint ever prepared for
|
|
549
|
+
// the lifetime of the module: removing a joint from a world drops the world's reference but not this
|
|
550
|
+
// one, so the joint, its bodies' indices, and its state array all stay reachable forever. There is no
|
|
551
|
+
// deletion hook to forget either, because a joint can leave a world without this module being told.
|
|
552
|
+
// Keying weakly makes the retention question disappear rather than answering it — the entry goes when
|
|
553
|
+
// the joint does, at every exit path, including ones nobody has written yet.
|
|
554
|
+
const jointStateScratch = new WeakMap();
|
|
555
|
+
const axisScratch = [0, 0];
|
|
556
|
+
const jointScratch = [0, 0, 0];
|
|
557
|
+
const EPSILON = 1e-9;
|
|
558
|
+
// The fraction of a joint's positional error corrected per step. Matches the contact solver's rationale:
|
|
559
|
+
// correcting all of it at once turns a deep error into an explosion.
|
|
560
|
+
const BAUMGARTE = 0.2;
|
|
561
|
+
//# sourceMappingURL=joints.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"joints.js","sourceRoot":"","sources":["../src/joints.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { Physics2DCollider, Physics2DMassData, RigidBody2D } from '@flighthq/types/contract';
|
|
2
|
+
export declare function computePhysics2DColliderMassData(collider: Readonly<Physics2DCollider>, out: Physics2DMassData): void;
|
|
3
|
+
export declare function updateRigidBody2DMassData(body: RigidBody2D): void;
|
|
4
|
+
//# sourceMappingURL=massProperties.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"massProperties.d.ts","sourceRoot":"","sources":["../src/massProperties.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAalG,wBAAgB,gCAAgC,CAAC,QAAQ,EAAE,QAAQ,CAAC,iBAAiB,CAAC,EAAE,GAAG,EAAE,iBAAiB,GAAG,IAAI,CA0CpH;AAYD,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,WAAW,GAAG,IAAI,CAmCjE"}
|