@flighthq/physics3d 0.4.0-next.1694.598ef6f
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/contacts.d.ts +4 -0
- package/dist/contacts.d.ts.map +1 -0
- package/dist/contacts.js +55 -0
- package/dist/contacts.js.map +1 -0
- package/dist/contract.d.ts +17 -0
- package/dist/contract.d.ts.map +1 -0
- package/dist/contract.js +17 -0
- package/dist/contract.js.map +1 -0
- package/dist/enablePhysics3DGuards.d.ts +4 -0
- package/dist/enablePhysics3DGuards.d.ts.map +1 -0
- package/dist/enablePhysics3DGuards.js +68 -0
- package/dist/enablePhysics3DGuards.js.map +1 -0
- package/dist/explainPhysics3DJoints.d.ts +3 -0
- package/dist/explainPhysics3DJoints.d.ts.map +1 -0
- package/dist/explainPhysics3DJoints.js +32 -0
- package/dist/explainPhysics3DJoints.js.map +1 -0
- package/dist/explainPhysics3DStep.d.ts +3 -0
- package/dist/explainPhysics3DStep.d.ts.map +1 -0
- package/dist/explainPhysics3DStep.js +48 -0
- package/dist/explainPhysics3DStep.js.map +1 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +14 -0
- package/dist/index.js.map +1 -0
- package/dist/integrate.d.ts +6 -0
- package/dist/integrate.d.ts.map +1 -0
- package/dist/integrate.js +154 -0
- package/dist/integrate.js.map +1 -0
- package/dist/islands.d.ts +5 -0
- package/dist/islands.d.ts.map +1 -0
- package/dist/islands.js +316 -0
- package/dist/islands.js.map +1 -0
- package/dist/jointCollisionSuppression.d.ts +4 -0
- package/dist/jointCollisionSuppression.d.ts.map +1 -0
- package/dist/jointCollisionSuppression.js +40 -0
- package/dist/jointCollisionSuppression.js.map +1 -0
- package/dist/jointFactories.d.ts +8 -0
- package/dist/jointFactories.d.ts.map +1 -0
- package/dist/jointFactories.js +126 -0
- package/dist/jointFactories.js.map +1 -0
- package/dist/jointMath.d.ts +17 -0
- package/dist/jointMath.d.ts.map +1 -0
- package/dist/jointMath.js +361 -0
- package/dist/jointMath.js.map +1 -0
- package/dist/jointRegistry.d.ts +8 -0
- package/dist/jointRegistry.d.ts.map +1 -0
- package/dist/jointRegistry.js +144 -0
- package/dist/jointRegistry.js.map +1 -0
- package/dist/jointRows.d.ts +32 -0
- package/dist/jointRows.d.ts.map +1 -0
- package/dist/jointRows.js +308 -0
- package/dist/jointRows.js.map +1 -0
- package/dist/joints.d.ts +14 -0
- package/dist/joints.d.ts.map +1 -0
- package/dist/joints.js +758 -0
- package/dist/joints.js.map +1 -0
- package/dist/massProperties.d.ts +8 -0
- package/dist/massProperties.d.ts.map +1 -0
- package/dist/massProperties.js +169 -0
- package/dist/massProperties.js.map +1 -0
- package/dist/ownership.d.ts +5 -0
- package/dist/ownership.d.ts.map +1 -0
- package/dist/ownership.js +16 -0
- package/dist/ownership.js.map +1 -0
- package/dist/registerBuiltInPhysics3DJointSolvers.d.ts +3 -0
- package/dist/registerBuiltInPhysics3DJointSolvers.d.ts.map +1 -0
- package/dist/registerBuiltInPhysics3DJointSolvers.js +14 -0
- package/dist/registerBuiltInPhysics3DJointSolvers.js.map +1 -0
- package/dist/solver.d.ts +8 -0
- package/dist/solver.d.ts.map +1 -0
- package/dist/solver.js +383 -0
- package/dist/solver.js.map +1 -0
- package/dist/step.d.ts +5 -0
- package/dist/step.d.ts.map +1 -0
- package/dist/step.js +250 -0
- package/dist/step.js.map +1 -0
- package/dist/stepValidation.d.ts +12 -0
- package/dist/stepValidation.d.ts.map +1 -0
- package/dist/stepValidation.js +201 -0
- package/dist/stepValidation.js.map +1 -0
- package/dist/symmetricTensor.d.ts +11 -0
- package/dist/symmetricTensor.d.ts.map +1 -0
- package/dist/symmetricTensor.js +150 -0
- package/dist/symmetricTensor.js.map +1 -0
- package/dist/world.d.ts +19 -0
- package/dist/world.d.ts.map +1 -0
- package/dist/world.js +370 -0
- package/dist/world.js.map +1 -0
- package/package.json +49 -0
- package/src/contacts.test.ts +64 -0
- package/src/enablePhysics3DGuards.test.ts +105 -0
- package/src/explainPhysics3DJoints.test.ts +101 -0
- package/src/explainPhysics3DStep.test.ts +123 -0
- package/src/integrate.test.ts +249 -0
- package/src/islands.test.ts +357 -0
- package/src/jointCollisionSuppression.test.ts +94 -0
- package/src/jointFactories.test.ts +195 -0
- package/src/jointMath.test.ts +643 -0
- package/src/jointRegistry.test.ts +229 -0
- package/src/jointRows.test.ts +484 -0
- package/src/joints.test.ts +677 -0
- package/src/massProperties.test.ts +305 -0
- package/src/ownership.test.ts +36 -0
- package/src/registerBuiltInPhysics3DJointSolvers.test.ts +48 -0
- package/src/solver.test.ts +481 -0
- package/src/step.test.ts +390 -0
- package/src/stepValidation.test.ts +244 -0
- package/src/symmetricTensor.test.ts +166 -0
- package/src/world.test.ts +512 -0
|
@@ -0,0 +1,361 @@
|
|
|
1
|
+
import { applySymmetricTensor, TENSOR_XX, TENSOR_XY, TENSOR_XZ, TENSOR_YY, TENSOR_YZ, TENSOR_ZZ, } from './symmetricTensor';
|
|
2
|
+
// The constraint arithmetic every 3D joint kind is assembled from: lever arms, effective-mass blocks,
|
|
3
|
+
// frame extraction, and the two impulse appliers.
|
|
4
|
+
//
|
|
5
|
+
// Package-internal, like `symmetricTensor`. These take and return loose numbers rather than
|
|
6
|
+
// `@flighthq/geometry`'s `Quaternion` and `Vector3`, which are `Entity` types over a `Float32Array` — both
|
|
7
|
+
// an indirection in a per-iteration loop and a precision step down from what a solver's accumulators need.
|
|
8
|
+
// That is also why the quaternion helpers here are private rather than reaching for
|
|
9
|
+
// `multiplyQuaternion`/`rotateVector3ByQuaternion`: those operate on the entity form.
|
|
10
|
+
//
|
|
11
|
+
// ONE SIGN CONVENTION HOLDS THROUGHOUT: every impulse is applied POSITIVE TO B and NEGATIVE TO A, and every
|
|
12
|
+
// relative quantity is measured B RELATIVE TO A. So a positive impulse along a direction increases the
|
|
13
|
+
// relative velocity along it, and `impulse = -mass * (velocity + bias)` drives the constraint to rest. The
|
|
14
|
+
// contact solver uses the opposite sense, because a contact normal points out of B and resolving pushes A
|
|
15
|
+
// away; mixing the two is not a small error, because the correction then adds to the violation and
|
|
16
|
+
// compounds every iteration.
|
|
17
|
+
// Applies an equal and opposite PURE angular impulse: B gains it, A loses it. No linear velocity changes,
|
|
18
|
+
// which is what makes it usable for a hinge's axis rows without disturbing the point constraint holding the
|
|
19
|
+
// same joint together.
|
|
20
|
+
export function applyPhysics3DJointAngularImpulse(bodyA, bodyB, impulseX, impulseY, impulseZ) {
|
|
21
|
+
readWorldInverseInertia(bodyA, angularImpulseTensor);
|
|
22
|
+
applySymmetricTensor(angularImpulseTensor, impulseX, impulseY, impulseZ, angularImpulseVector);
|
|
23
|
+
bodyA.angularVelocityX -= angularImpulseVector[0];
|
|
24
|
+
bodyA.angularVelocityY -= angularImpulseVector[1];
|
|
25
|
+
bodyA.angularVelocityZ -= angularImpulseVector[2];
|
|
26
|
+
readWorldInverseInertia(bodyB, angularImpulseTensor);
|
|
27
|
+
applySymmetricTensor(angularImpulseTensor, impulseX, impulseY, impulseZ, angularImpulseVector);
|
|
28
|
+
bodyB.angularVelocityX += angularImpulseVector[0];
|
|
29
|
+
bodyB.angularVelocityY += angularImpulseVector[1];
|
|
30
|
+
bodyB.angularVelocityZ += angularImpulseVector[2];
|
|
31
|
+
}
|
|
32
|
+
// Applies an equal and opposite linear impulse at the two anchors: B gains it, A loses it. Each body also
|
|
33
|
+
// picks up the torque of the impulse about its own lever arm, which is the term that lets a joint spin a
|
|
34
|
+
// body it is only pulling on.
|
|
35
|
+
//
|
|
36
|
+
// A static or fixed-rotation body's zero inverse mass and zero inverse inertia make this a no-op with no
|
|
37
|
+
// branch, which is the whole reason infinite mass is a zero inverse rather than a flag.
|
|
38
|
+
export function applyPhysics3DJointImpulse(bodyA, bodyB, rAX, rAY, rAZ, rBX, rBY, rBZ, impulseX, impulseY, impulseZ) {
|
|
39
|
+
applyBodyJointImpulse(bodyA, rAX, rAY, rAZ, -impulseX, -impulseY, -impulseZ);
|
|
40
|
+
applyBodyJointImpulse(bodyB, rBX, rBY, rBZ, impulseX, impulseY, impulseZ);
|
|
41
|
+
}
|
|
42
|
+
// Applies one scalar constraint row's impulse — the counterpart of `getPhysics3DJointRowMass`, acting
|
|
43
|
+
// through the same linear direction and the same two angular arms, so a row's mass and its impulse can
|
|
44
|
+
// never describe different constraints.
|
|
45
|
+
//
|
|
46
|
+
// The arms are given rather than derived because they are NOT always `r x direction`. A slider's
|
|
47
|
+
// perpendicular row acts through `(rA + separation) x direction` on A, since its axis is carried by A and
|
|
48
|
+
// rotates with it; using A's bare lever arm there leaks motion sideways whenever the rail body turns.
|
|
49
|
+
export function applyPhysics3DJointRowImpulse(bodyA, bodyB, directionX, directionY, directionZ, armAX, armAY, armAZ, armBX, armBY, armBZ, impulse) {
|
|
50
|
+
bodyA.velocityX -= impulse * directionX * bodyA.inverseMass;
|
|
51
|
+
bodyA.velocityY -= impulse * directionY * bodyA.inverseMass;
|
|
52
|
+
bodyA.velocityZ -= impulse * directionZ * bodyA.inverseMass;
|
|
53
|
+
readWorldInverseInertia(bodyA, rowImpulseTensor);
|
|
54
|
+
applySymmetricTensor(rowImpulseTensor, armAX * impulse, armAY * impulse, armAZ * impulse, rowImpulseVector);
|
|
55
|
+
bodyA.angularVelocityX -= rowImpulseVector[0];
|
|
56
|
+
bodyA.angularVelocityY -= rowImpulseVector[1];
|
|
57
|
+
bodyA.angularVelocityZ -= rowImpulseVector[2];
|
|
58
|
+
bodyB.velocityX += impulse * directionX * bodyB.inverseMass;
|
|
59
|
+
bodyB.velocityY += impulse * directionY * bodyB.inverseMass;
|
|
60
|
+
bodyB.velocityZ += impulse * directionZ * bodyB.inverseMass;
|
|
61
|
+
readWorldInverseInertia(bodyB, rowImpulseTensor);
|
|
62
|
+
applySymmetricTensor(rowImpulseTensor, armBX * impulse, armBY * impulse, armBZ * impulse, rowImpulseVector);
|
|
63
|
+
bodyB.angularVelocityX += rowImpulseVector[0];
|
|
64
|
+
bodyB.angularVelocityY += rowImpulseVector[1];
|
|
65
|
+
bodyB.angularVelocityZ += rowImpulseVector[2];
|
|
66
|
+
}
|
|
67
|
+
// The scalar effective mass of one constraint row, given its linear direction and the two angular arms the
|
|
68
|
+
// row acts through. Returns 0 when the pair cannot move along the row at all, so the impulse computed from
|
|
69
|
+
// it is zero rather than infinite.
|
|
70
|
+
//
|
|
71
|
+
// The linear term is scaled by the direction's own squared length, so a PURELY ANGULAR row — a hinge's
|
|
72
|
+
// motor, a twist limit — passes a zero direction and the two bodies' translational masses drop out on their
|
|
73
|
+
// own. Without that scaling the caller would have to choose between two nearly identical functions, and the
|
|
74
|
+
// one place that picked wrong would report a hinge motor as heavier than it is by the pair's whole mass.
|
|
75
|
+
export function getPhysics3DJointRowMass(bodyA, bodyB, directionX, directionY, directionZ, armAX, armAY, armAZ, armBX, armBY, armBZ) {
|
|
76
|
+
const linear = directionX * directionX + directionY * directionY + directionZ * directionZ;
|
|
77
|
+
let denominator = (bodyA.inverseMass + bodyB.inverseMass) * linear;
|
|
78
|
+
readWorldInverseInertia(bodyA, rowMassTensor);
|
|
79
|
+
applySymmetricTensor(rowMassTensor, armAX, armAY, armAZ, rowMassVector);
|
|
80
|
+
denominator += armAX * rowMassVector[0] + armAY * rowMassVector[1] + armAZ * rowMassVector[2];
|
|
81
|
+
readWorldInverseInertia(bodyB, rowMassTensor);
|
|
82
|
+
applySymmetricTensor(rowMassTensor, armBX, armBY, armBZ, rowMassVector);
|
|
83
|
+
denominator += armBX * rowMassVector[0] + armBY * rowMassVector[1] + armBZ * rowMassVector[2];
|
|
84
|
+
return denominator > 0 ? 1 / denominator : 0;
|
|
85
|
+
}
|
|
86
|
+
// The rate at which one constraint row's coordinate is changing — B relative to A, so a positive value means
|
|
87
|
+
// the row's error is growing. The third member of the row triple, and the one every solve reads before
|
|
88
|
+
// deciding an impulse.
|
|
89
|
+
export function getPhysics3DJointRowVelocity(bodyA, bodyB, directionX, directionY, directionZ, armAX, armAY, armAZ, armBX, armBY, armBZ) {
|
|
90
|
+
return ((bodyB.velocityX - bodyA.velocityX) * directionX +
|
|
91
|
+
(bodyB.velocityY - bodyA.velocityY) * directionY +
|
|
92
|
+
(bodyB.velocityZ - bodyA.velocityZ) * directionZ +
|
|
93
|
+
bodyB.angularVelocityX * armBX +
|
|
94
|
+
bodyB.angularVelocityY * armBY +
|
|
95
|
+
bodyB.angularVelocityZ * armBZ -
|
|
96
|
+
bodyA.angularVelocityX * armAX -
|
|
97
|
+
bodyA.angularVelocityY * armAY -
|
|
98
|
+
bodyA.angularVelocityZ * armAZ);
|
|
99
|
+
}
|
|
100
|
+
// Exchanges a frame-bearing joint's two local rotations, so the generic end swap the registry performs
|
|
101
|
+
// stays consistent for every kind that carries a frame. Each rotation belongs to its body and travels with
|
|
102
|
+
// it; nothing about a frame reverses sign, unlike the direction-bearing scalars a kind may also hold.
|
|
103
|
+
export function swapPhysics3DJointFrames(frames) {
|
|
104
|
+
const x = frames.localRotationAX;
|
|
105
|
+
const y = frames.localRotationAY;
|
|
106
|
+
const z = frames.localRotationAZ;
|
|
107
|
+
const w = frames.localRotationAW;
|
|
108
|
+
frames.localRotationAX = frames.localRotationBX;
|
|
109
|
+
frames.localRotationAY = frames.localRotationBY;
|
|
110
|
+
frames.localRotationAZ = frames.localRotationBZ;
|
|
111
|
+
frames.localRotationAW = frames.localRotationBW;
|
|
112
|
+
frames.localRotationBX = x;
|
|
113
|
+
frames.localRotationBY = y;
|
|
114
|
+
frames.localRotationBZ = z;
|
|
115
|
+
frames.localRotationBW = w;
|
|
116
|
+
}
|
|
117
|
+
// Rotates each body's local anchor into world space, relative to that body's CENTRE OF MASS, and writes the
|
|
118
|
+
// two lever arms onto the joint.
|
|
119
|
+
//
|
|
120
|
+
// Measured from the centre of mass rather than from the body's origin, because that is the point a body
|
|
121
|
+
// rotates about: an impulse at an anchor produces the torque of its arm about the centre, and an arm taken
|
|
122
|
+
// from the origin gives an offset body the swing of a shape it does not have. The two coincide only when a
|
|
123
|
+
// body's centre of mass sits at its origin, which is why the error survives every test built from centred
|
|
124
|
+
// primitives.
|
|
125
|
+
export function writePhysics3DJointAnchors(bodyA, bodyB, joint) {
|
|
126
|
+
rotateByQuaternion(joint.localAnchorAX - bodyA.centerX, joint.localAnchorAY - bodyA.centerY, joint.localAnchorAZ - bodyA.centerZ, bodyA.orientationX, bodyA.orientationY, bodyA.orientationZ, bodyA.orientationW, anchorVector);
|
|
127
|
+
joint.rAX = anchorVector[0];
|
|
128
|
+
joint.rAY = anchorVector[1];
|
|
129
|
+
joint.rAZ = anchorVector[2];
|
|
130
|
+
rotateByQuaternion(joint.localAnchorBX - bodyB.centerX, joint.localAnchorBY - bodyB.centerY, joint.localAnchorBZ - bodyB.centerZ, bodyB.orientationX, bodyB.orientationY, bodyB.orientationZ, bodyB.orientationW, anchorVector);
|
|
131
|
+
joint.rBX = anchorVector[0];
|
|
132
|
+
joint.rBY = anchorVector[1];
|
|
133
|
+
joint.rBZ = anchorVector[2];
|
|
134
|
+
}
|
|
135
|
+
// The velocity of B's anchor relative to A's, written into `out` as three world-space components. Each
|
|
136
|
+
// anchor's velocity is its body's linear velocity plus the rotational contribution at its lever arm — the
|
|
137
|
+
// term that makes an anchor move even when the body's centre is still.
|
|
138
|
+
export function writePhysics3DJointAnchorVelocity(bodyA, bodyB, joint, out) {
|
|
139
|
+
const anchorAX = bodyA.velocityX + (bodyA.angularVelocityY * joint.rAZ - bodyA.angularVelocityZ * joint.rAY);
|
|
140
|
+
const anchorAY = bodyA.velocityY + (bodyA.angularVelocityZ * joint.rAX - bodyA.angularVelocityX * joint.rAZ);
|
|
141
|
+
const anchorAZ = bodyA.velocityZ + (bodyA.angularVelocityX * joint.rAY - bodyA.angularVelocityY * joint.rAX);
|
|
142
|
+
out[0] = bodyB.velocityX + (bodyB.angularVelocityY * joint.rBZ - bodyB.angularVelocityZ * joint.rBY) - anchorAX;
|
|
143
|
+
out[1] = bodyB.velocityY + (bodyB.angularVelocityZ * joint.rBX - bodyB.angularVelocityX * joint.rBZ) - anchorAY;
|
|
144
|
+
out[2] = bodyB.velocityZ + (bodyB.angularVelocityX * joint.rBY - bodyB.angularVelocityY * joint.rBX) - anchorAZ;
|
|
145
|
+
}
|
|
146
|
+
// The pair's angular effective-mass block — the sum of the two world inverse inertia tensors — written into
|
|
147
|
+
// `out` in the six-component symmetric form. Invert it with `inverseSymmetricTensor` to solve a three-row
|
|
148
|
+
// angular constraint; project it onto an axis with `getPhysics3DJointRowMass` to solve a single row.
|
|
149
|
+
export function writePhysics3DJointAngularMass(bodyA, bodyB, out) {
|
|
150
|
+
out[TENSOR_XX] = bodyA.inverseInertiaWorldXX + bodyB.inverseInertiaWorldXX;
|
|
151
|
+
out[TENSOR_YY] = bodyA.inverseInertiaWorldYY + bodyB.inverseInertiaWorldYY;
|
|
152
|
+
out[TENSOR_ZZ] = bodyA.inverseInertiaWorldZZ + bodyB.inverseInertiaWorldZZ;
|
|
153
|
+
out[TENSOR_XY] = bodyA.inverseInertiaWorldXY + bodyB.inverseInertiaWorldXY;
|
|
154
|
+
out[TENSOR_XZ] = bodyA.inverseInertiaWorldXZ + bodyB.inverseInertiaWorldXZ;
|
|
155
|
+
out[TENSOR_YZ] = bodyA.inverseInertiaWorldYZ + bodyB.inverseInertiaWorldYZ;
|
|
156
|
+
}
|
|
157
|
+
// The world-space axes of one body's joint frame, written into `out` as nine numbers in COLUMN-MAJOR order:
|
|
158
|
+
// `out[0..2]` is the frame's X axis, `out[3..5]` its Y, `out[6..8]` its Z.
|
|
159
|
+
//
|
|
160
|
+
// X first is the convention every axis-bearing kind shares — a hinge spins about it, a slider translates
|
|
161
|
+
// along it, a cone-twist twists about it — so a caller that needs only the primary axis reads the first
|
|
162
|
+
// three numbers and stops.
|
|
163
|
+
export function writePhysics3DJointFrameBasis(body, localRotationX, localRotationY, localRotationZ, localRotationW, out) {
|
|
164
|
+
multiplyQuaternions(body.orientationX, body.orientationY, body.orientationZ, body.orientationW, localRotationX, localRotationY, localRotationZ, localRotationW, basisRotation);
|
|
165
|
+
const x = basisRotation[0];
|
|
166
|
+
const y = basisRotation[1];
|
|
167
|
+
const z = basisRotation[2];
|
|
168
|
+
const w = basisRotation[3];
|
|
169
|
+
const x2 = x + x;
|
|
170
|
+
const y2 = y + y;
|
|
171
|
+
const z2 = z + z;
|
|
172
|
+
const xx2 = x * x2;
|
|
173
|
+
const yy2 = y * y2;
|
|
174
|
+
const zz2 = z * z2;
|
|
175
|
+
const xy2 = x * y2;
|
|
176
|
+
const xz2 = x * z2;
|
|
177
|
+
const yz2 = y * z2;
|
|
178
|
+
const wx2 = w * x2;
|
|
179
|
+
const wy2 = w * y2;
|
|
180
|
+
const wz2 = w * z2;
|
|
181
|
+
out[0] = 1 - yy2 - zz2;
|
|
182
|
+
out[1] = xy2 + wz2;
|
|
183
|
+
out[2] = xz2 - wy2;
|
|
184
|
+
out[3] = xy2 - wz2;
|
|
185
|
+
out[4] = 1 - xx2 - zz2;
|
|
186
|
+
out[5] = yz2 + wx2;
|
|
187
|
+
out[6] = xz2 + wy2;
|
|
188
|
+
out[7] = yz2 - wx2;
|
|
189
|
+
out[8] = 1 - xx2 - yy2;
|
|
190
|
+
}
|
|
191
|
+
// One body's joint frame as a world-space unit quaternion, written into `out` as `[x, y, z, w]`. The
|
|
192
|
+
// rotation half of the frame `writePhysics3DJointFrameBasis` expands into axes; kinds that measure an angle
|
|
193
|
+
// rather than project onto an axis want this form.
|
|
194
|
+
export function writePhysics3DJointFrameRotation(body, localRotationX, localRotationY, localRotationZ, localRotationW, out) {
|
|
195
|
+
multiplyQuaternions(body.orientationX, body.orientationY, body.orientationZ, body.orientationW, localRotationX, localRotationY, localRotationZ, localRotationW, out);
|
|
196
|
+
}
|
|
197
|
+
// The 3x3 effective-mass block of a point-to-point constraint, written into `out` in the six-component
|
|
198
|
+
// symmetric form.
|
|
199
|
+
//
|
|
200
|
+
// `K = (invMassA + invMassB) * identity + skew(rA) * invInertiaA * transpose(skew(rA)) + (same for B)`, and
|
|
201
|
+
// it is symmetric by construction because each term is. Invert it with `inverseSymmetricTensor` and the
|
|
202
|
+
// three rows are solved as one coupled block; solving x, then y, then z instead lets each axis undo part of
|
|
203
|
+
// the previous correction, which presents as a loaded joint that visibly creeps.
|
|
204
|
+
export function writePhysics3DJointPointMass(bodyA, bodyB, rAX, rAY, rAZ, rBX, rBY, rBZ, out) {
|
|
205
|
+
const diagonal = bodyA.inverseMass + bodyB.inverseMass;
|
|
206
|
+
out[TENSOR_XX] = diagonal;
|
|
207
|
+
out[TENSOR_YY] = diagonal;
|
|
208
|
+
out[TENSOR_ZZ] = diagonal;
|
|
209
|
+
out[TENSOR_XY] = 0;
|
|
210
|
+
out[TENSOR_XZ] = 0;
|
|
211
|
+
out[TENSOR_YZ] = 0;
|
|
212
|
+
readWorldInverseInertia(bodyA, pointMassTensor);
|
|
213
|
+
addSkewSandwich(pointMassTensor, rAX, rAY, rAZ, out);
|
|
214
|
+
readWorldInverseInertia(bodyB, pointMassTensor);
|
|
215
|
+
addSkewSandwich(pointMassTensor, rBX, rBY, rBZ, out);
|
|
216
|
+
}
|
|
217
|
+
// The rotation taking frame A onto frame B, written into `out` as `[x, y, z, w]` and expressed IN A'S OWN
|
|
218
|
+
// FRAME rather than in world space. `conjugate(frameA) * frameB`.
|
|
219
|
+
//
|
|
220
|
+
// A's frame is the useful one for a kind that has to take the rotation apart — a cone-twist reads its twist
|
|
221
|
+
// straight off the X component here, because A's X is what twist is defined about. A kind that only needs
|
|
222
|
+
// the error as one vector wants `writePhysics3DJointRotationError` instead, which is this rotated out to
|
|
223
|
+
// world space where the inverse inertia tensors live.
|
|
224
|
+
//
|
|
225
|
+
// `w` is always non-negative on return. A unit quaternion and its negation name the same rotation, so
|
|
226
|
+
// without that fix half of all inputs would decompose as the long way round: a frame a degree from aligned
|
|
227
|
+
// would read as 359 degrees out, and every limit built on it would fire against the wrong bound.
|
|
228
|
+
export function writePhysics3DJointRelativeRotation(frameAX, frameAY, frameAZ, frameAW, frameBX, frameBY, frameBZ, frameBW, out) {
|
|
229
|
+
multiplyQuaternions(-frameAX, -frameAY, -frameAZ, frameAW, frameBX, frameBY, frameBZ, frameBW, out);
|
|
230
|
+
if (out[3] < 0) {
|
|
231
|
+
out[0] = -out[0];
|
|
232
|
+
out[1] = -out[1];
|
|
233
|
+
out[2] = -out[2];
|
|
234
|
+
out[3] = -out[3];
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
// The rotation taking frame A onto frame B, written into `out` as a world-space vector whose direction is
|
|
238
|
+
// the axis and whose magnitude is the angle in radians. Zero exactly when the two frames coincide, which is
|
|
239
|
+
// what makes it usable directly as the positional error of an angular constraint.
|
|
240
|
+
//
|
|
241
|
+
// The angle comes from `2 * atan2(|v|, w)` rather than from the small-angle shortcut `2 * v`. The shortcut
|
|
242
|
+
// is `2 * sin(angle/2) * axis`, which agrees near zero and is 10% short by a quarter turn — invisible on a
|
|
243
|
+
// locked axis, and a limit that stops progressively early as it opens up.
|
|
244
|
+
//
|
|
245
|
+
// The shorter of the two arcs is always chosen. A unit quaternion and its negation name the same rotation,
|
|
246
|
+
// so without the sign fix half of all inputs would report the long way round: a frame a degree from aligned
|
|
247
|
+
// would read as 359 degrees out and the constraint would drive it the wrong way.
|
|
248
|
+
export function writePhysics3DJointRotationError(frameAX, frameAY, frameAZ, frameAW, frameBX, frameBY, frameBZ, frameBW, out) {
|
|
249
|
+
writePhysics3DJointRelativeRotation(frameAX, frameAY, frameAZ, frameAW, frameBX, frameBY, frameBZ, frameBW, rotationErrorRelative);
|
|
250
|
+
const x = rotationErrorRelative[0];
|
|
251
|
+
const y = rotationErrorRelative[1];
|
|
252
|
+
const z = rotationErrorRelative[2];
|
|
253
|
+
const sine = Math.sqrt(x * x + y * y + z * z);
|
|
254
|
+
if (sine < QUATERNION_EPSILON) {
|
|
255
|
+
out[0] = 0;
|
|
256
|
+
out[1] = 0;
|
|
257
|
+
out[2] = 0;
|
|
258
|
+
return;
|
|
259
|
+
}
|
|
260
|
+
const scale = (2 * Math.atan2(sine, rotationErrorRelative[3])) / sine;
|
|
261
|
+
rotateByQuaternion(x * scale, y * scale, z * scale, frameAX, frameAY, frameAZ, frameAW, out);
|
|
262
|
+
}
|
|
263
|
+
// The world-space offset from A's anchor to B's, written into `out` — the positional error of a
|
|
264
|
+
// point-to-point constraint, and the vector every axis-bearing kind projects onto its frame.
|
|
265
|
+
//
|
|
266
|
+
// Built as `worldCenter + leverArm` rather than `bodyOrigin + leverArm`. The lever arm is measured from the
|
|
267
|
+
// centre of mass, so adding it to the origin lands on the anchor only when the two coincide; for a body
|
|
268
|
+
// whose centre is offset, the two anchors are each wrong by their own rotated offset and the difference
|
|
269
|
+
// does not cancel.
|
|
270
|
+
export function writePhysics3DJointSeparation(bodyA, bodyB, joint, out) {
|
|
271
|
+
writeWorldCenter(bodyA, separationCenter);
|
|
272
|
+
const anchorAX = separationCenter[0] + joint.rAX;
|
|
273
|
+
const anchorAY = separationCenter[1] + joint.rAY;
|
|
274
|
+
const anchorAZ = separationCenter[2] + joint.rAZ;
|
|
275
|
+
writeWorldCenter(bodyB, separationCenter);
|
|
276
|
+
out[0] = separationCenter[0] + joint.rBX - anchorAX;
|
|
277
|
+
out[1] = separationCenter[1] + joint.rBY - anchorAY;
|
|
278
|
+
out[2] = separationCenter[2] + joint.rBZ - anchorAZ;
|
|
279
|
+
}
|
|
280
|
+
// Adds `skew(r) * tensor * transpose(skew(r))` into an accumulating symmetric block. The rows of `skew(r)`
|
|
281
|
+
// are the three vectors below, and entry (i,j) of the product is `row_i . tensor . row_j` — six distinct
|
|
282
|
+
// entries for a symmetric result, which is why only six are computed.
|
|
283
|
+
function addSkewSandwich(tensor, rX, rY, rZ, out) {
|
|
284
|
+
applySymmetricTensor(tensor, 0, -rZ, rY, skewRow0);
|
|
285
|
+
applySymmetricTensor(tensor, rZ, 0, -rX, skewRow1);
|
|
286
|
+
applySymmetricTensor(tensor, -rY, rX, 0, skewRow2);
|
|
287
|
+
out[TENSOR_XX] += -rZ * skewRow0[1] + rY * skewRow0[2];
|
|
288
|
+
out[TENSOR_YY] += rZ * skewRow1[0] - rX * skewRow1[2];
|
|
289
|
+
out[TENSOR_ZZ] += -rY * skewRow2[0] + rX * skewRow2[1];
|
|
290
|
+
out[TENSOR_XY] += -rZ * skewRow1[1] + rY * skewRow1[2];
|
|
291
|
+
out[TENSOR_XZ] += -rZ * skewRow2[1] + rY * skewRow2[2];
|
|
292
|
+
out[TENSOR_YZ] += rZ * skewRow2[0] - rX * skewRow2[2];
|
|
293
|
+
}
|
|
294
|
+
function applyBodyJointImpulse(body, rX, rY, rZ, impulseX, impulseY, impulseZ) {
|
|
295
|
+
body.velocityX += impulseX * body.inverseMass;
|
|
296
|
+
body.velocityY += impulseY * body.inverseMass;
|
|
297
|
+
body.velocityZ += impulseZ * body.inverseMass;
|
|
298
|
+
const torqueX = rY * impulseZ - rZ * impulseY;
|
|
299
|
+
const torqueY = rZ * impulseX - rX * impulseZ;
|
|
300
|
+
const torqueZ = rX * impulseY - rY * impulseX;
|
|
301
|
+
readWorldInverseInertia(body, bodyImpulseTensor);
|
|
302
|
+
applySymmetricTensor(bodyImpulseTensor, torqueX, torqueY, torqueZ, bodyImpulseVector);
|
|
303
|
+
body.angularVelocityX += bodyImpulseVector[0];
|
|
304
|
+
body.angularVelocityY += bodyImpulseVector[1];
|
|
305
|
+
body.angularVelocityZ += bodyImpulseVector[2];
|
|
306
|
+
}
|
|
307
|
+
// `out = a * b`, the Hamilton product, in the order that composes b's rotation FIRST and then a's. Frames
|
|
308
|
+
// are built as `bodyOrientation * localRotation` for exactly that reason: the local rotation is expressed in
|
|
309
|
+
// body space and the body's orientation carries it out to the world.
|
|
310
|
+
function multiplyQuaternions(aX, aY, aZ, aW, bX, bY, bZ, bW, out) {
|
|
311
|
+
out[0] = aW * bX + aX * bW + aY * bZ - aZ * bY;
|
|
312
|
+
out[1] = aW * bY - aX * bZ + aY * bW + aZ * bX;
|
|
313
|
+
out[2] = aW * bZ + aX * bY - aY * bX + aZ * bW;
|
|
314
|
+
out[3] = aW * bW - aX * bX - aY * bY - aZ * bZ;
|
|
315
|
+
}
|
|
316
|
+
function readWorldInverseInertia(body, out) {
|
|
317
|
+
out[TENSOR_XX] = body.inverseInertiaWorldXX;
|
|
318
|
+
out[TENSOR_YY] = body.inverseInertiaWorldYY;
|
|
319
|
+
out[TENSOR_ZZ] = body.inverseInertiaWorldZZ;
|
|
320
|
+
out[TENSOR_XY] = body.inverseInertiaWorldXY;
|
|
321
|
+
out[TENSOR_XZ] = body.inverseInertiaWorldXZ;
|
|
322
|
+
out[TENSOR_YZ] = body.inverseInertiaWorldYZ;
|
|
323
|
+
}
|
|
324
|
+
// `v + 2 * q.xyz x (q.xyz x v + q.w * v)`, the standard reduction of `q * v * conjugate(q)` for a unit
|
|
325
|
+
// quaternion. Safe when `out` is one of the inputs, since every component is read into a local first.
|
|
326
|
+
function rotateByQuaternion(vX, vY, vZ, qX, qY, qZ, qW, out) {
|
|
327
|
+
const tX = qY * vZ - qZ * vY + qW * vX;
|
|
328
|
+
const tY = qZ * vX - qX * vZ + qW * vY;
|
|
329
|
+
const tZ = qX * vY - qY * vX + qW * vZ;
|
|
330
|
+
out[0] = vX + 2 * (qY * tZ - qZ * tY);
|
|
331
|
+
out[1] = vY + 2 * (qZ * tX - qX * tZ);
|
|
332
|
+
out[2] = vZ + 2 * (qX * tY - qY * tX);
|
|
333
|
+
}
|
|
334
|
+
function writeWorldCenter(body, out) {
|
|
335
|
+
rotateByQuaternion(body.centerX, body.centerY, body.centerZ, body.orientationX, body.orientationY, body.orientationZ, body.orientationW, out);
|
|
336
|
+
out[0] += body.x;
|
|
337
|
+
out[1] += body.y;
|
|
338
|
+
out[2] += body.z;
|
|
339
|
+
}
|
|
340
|
+
// Below the tolerance the rotation error is genuinely zero and the axis is undefined; returning a zero
|
|
341
|
+
// vector is correct there, where dividing by the vanishing sine would seed NaN into both bodies.
|
|
342
|
+
const QUATERNION_EPSILON = 1e-12;
|
|
343
|
+
// Per-function scratch, never shared between two functions that can be live at once. One shared pool would
|
|
344
|
+
// be smaller and would corrupt the outer call the first time one of these grew a nested use.
|
|
345
|
+
const angularImpulseTensor = [0, 0, 0, 0, 0, 0];
|
|
346
|
+
const angularImpulseVector = [0, 0, 0];
|
|
347
|
+
const anchorVector = [0, 0, 0];
|
|
348
|
+
const basisRotation = [0, 0, 0, 0];
|
|
349
|
+
const bodyImpulseTensor = [0, 0, 0, 0, 0, 0];
|
|
350
|
+
const bodyImpulseVector = [0, 0, 0];
|
|
351
|
+
const pointMassTensor = [0, 0, 0, 0, 0, 0];
|
|
352
|
+
const rotationErrorRelative = [0, 0, 0, 0];
|
|
353
|
+
const rowImpulseTensor = [0, 0, 0, 0, 0, 0];
|
|
354
|
+
const rowImpulseVector = [0, 0, 0];
|
|
355
|
+
const rowMassTensor = [0, 0, 0, 0, 0, 0];
|
|
356
|
+
const rowMassVector = [0, 0, 0];
|
|
357
|
+
const separationCenter = [0, 0, 0];
|
|
358
|
+
const skewRow0 = [0, 0, 0];
|
|
359
|
+
const skewRow1 = [0, 0, 0];
|
|
360
|
+
const skewRow2 = [0, 0, 0];
|
|
361
|
+
//# sourceMappingURL=jointMath.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jointMath.js","sourceRoot":"","sources":["../src/jointMath.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,oBAAoB,EACpB,SAAS,EACT,SAAS,EACT,SAAS,EACT,SAAS,EACT,SAAS,EACT,SAAS,GACV,MAAM,mBAAmB,CAAC;AAE3B,sGAAsG;AACtG,kDAAkD;AAClD,EAAE;AACF,4FAA4F;AAC5F,2GAA2G;AAC3G,2GAA2G;AAC3G,oFAAoF;AACpF,sFAAsF;AACtF,EAAE;AACF,4GAA4G;AAC5G,uGAAuG;AACvG,2GAA2G;AAC3G,0GAA0G;AAC1G,mGAAmG;AACnG,6BAA6B;AAE7B,0GAA0G;AAC1G,4GAA4G;AAC5G,uBAAuB;AACvB,MAAM,UAAU,iCAAiC,CAC/C,KAAkB,EAClB,KAAkB,EAClB,QAAgB,EAChB,QAAgB,EAChB,QAAgB;IAEhB,uBAAuB,CAAC,KAAK,EAAE,oBAAoB,CAAC,CAAC;IACrD,oBAAoB,CAAC,oBAAoB,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,oBAAoB,CAAC,CAAC;IAC/F,KAAK,CAAC,gBAAgB,IAAI,oBAAoB,CAAC,CAAC,CAAC,CAAC;IAClD,KAAK,CAAC,gBAAgB,IAAI,oBAAoB,CAAC,CAAC,CAAC,CAAC;IAClD,KAAK,CAAC,gBAAgB,IAAI,oBAAoB,CAAC,CAAC,CAAC,CAAC;IAElD,uBAAuB,CAAC,KAAK,EAAE,oBAAoB,CAAC,CAAC;IACrD,oBAAoB,CAAC,oBAAoB,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,oBAAoB,CAAC,CAAC;IAC/F,KAAK,CAAC,gBAAgB,IAAI,oBAAoB,CAAC,CAAC,CAAC,CAAC;IAClD,KAAK,CAAC,gBAAgB,IAAI,oBAAoB,CAAC,CAAC,CAAC,CAAC;IAClD,KAAK,CAAC,gBAAgB,IAAI,oBAAoB,CAAC,CAAC,CAAC,CAAC;AACpD,CAAC;AAED,0GAA0G;AAC1G,yGAAyG;AACzG,8BAA8B;AAC9B,EAAE;AACF,yGAAyG;AACzG,wFAAwF;AACxF,MAAM,UAAU,0BAA0B,CACxC,KAAkB,EAClB,KAAkB,EAClB,GAAW,EACX,GAAW,EACX,GAAW,EACX,GAAW,EACX,GAAW,EACX,GAAW,EACX,QAAgB,EAChB,QAAgB,EAChB,QAAgB;IAEhB,qBAAqB,CAAC,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,CAAC;IAC7E,qBAAqB,CAAC,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC;AAC5E,CAAC;AAED,sGAAsG;AACtG,uGAAuG;AACvG,wCAAwC;AACxC,EAAE;AACF,iGAAiG;AACjG,0GAA0G;AAC1G,sGAAsG;AACtG,MAAM,UAAU,6BAA6B,CAC3C,KAAkB,EAClB,KAAkB,EAClB,UAAkB,EAClB,UAAkB,EAClB,UAAkB,EAClB,KAAa,EACb,KAAa,EACb,KAAa,EACb,KAAa,EACb,KAAa,EACb,KAAa,EACb,OAAe;IAEf,KAAK,CAAC,SAAS,IAAI,OAAO,GAAG,UAAU,GAAG,KAAK,CAAC,WAAW,CAAC;IAC5D,KAAK,CAAC,SAAS,IAAI,OAAO,GAAG,UAAU,GAAG,KAAK,CAAC,WAAW,CAAC;IAC5D,KAAK,CAAC,SAAS,IAAI,OAAO,GAAG,UAAU,GAAG,KAAK,CAAC,WAAW,CAAC;IAC5D,uBAAuB,CAAC,KAAK,EAAE,gBAAgB,CAAC,CAAC;IACjD,oBAAoB,CAAC,gBAAgB,EAAE,KAAK,GAAG,OAAO,EAAE,KAAK,GAAG,OAAO,EAAE,KAAK,GAAG,OAAO,EAAE,gBAAgB,CAAC,CAAC;IAC5G,KAAK,CAAC,gBAAgB,IAAI,gBAAgB,CAAC,CAAC,CAAC,CAAC;IAC9C,KAAK,CAAC,gBAAgB,IAAI,gBAAgB,CAAC,CAAC,CAAC,CAAC;IAC9C,KAAK,CAAC,gBAAgB,IAAI,gBAAgB,CAAC,CAAC,CAAC,CAAC;IAE9C,KAAK,CAAC,SAAS,IAAI,OAAO,GAAG,UAAU,GAAG,KAAK,CAAC,WAAW,CAAC;IAC5D,KAAK,CAAC,SAAS,IAAI,OAAO,GAAG,UAAU,GAAG,KAAK,CAAC,WAAW,CAAC;IAC5D,KAAK,CAAC,SAAS,IAAI,OAAO,GAAG,UAAU,GAAG,KAAK,CAAC,WAAW,CAAC;IAC5D,uBAAuB,CAAC,KAAK,EAAE,gBAAgB,CAAC,CAAC;IACjD,oBAAoB,CAAC,gBAAgB,EAAE,KAAK,GAAG,OAAO,EAAE,KAAK,GAAG,OAAO,EAAE,KAAK,GAAG,OAAO,EAAE,gBAAgB,CAAC,CAAC;IAC5G,KAAK,CAAC,gBAAgB,IAAI,gBAAgB,CAAC,CAAC,CAAC,CAAC;IAC9C,KAAK,CAAC,gBAAgB,IAAI,gBAAgB,CAAC,CAAC,CAAC,CAAC;IAC9C,KAAK,CAAC,gBAAgB,IAAI,gBAAgB,CAAC,CAAC,CAAC,CAAC;AAChD,CAAC;AAED,2GAA2G;AAC3G,2GAA2G;AAC3G,mCAAmC;AACnC,EAAE;AACF,uGAAuG;AACvG,4GAA4G;AAC5G,4GAA4G;AAC5G,yGAAyG;AACzG,MAAM,UAAU,wBAAwB,CACtC,KAA4B,EAC5B,KAA4B,EAC5B,UAAkB,EAClB,UAAkB,EAClB,UAAkB,EAClB,KAAa,EACb,KAAa,EACb,KAAa,EACb,KAAa,EACb,KAAa,EACb,KAAa;IAEb,MAAM,MAAM,GAAG,UAAU,GAAG,UAAU,GAAG,UAAU,GAAG,UAAU,GAAG,UAAU,GAAG,UAAU,CAAC;IAC3F,IAAI,WAAW,GAAG,CAAC,KAAK,CAAC,WAAW,GAAG,KAAK,CAAC,WAAW,CAAC,GAAG,MAAM,CAAC;IAEnE,uBAAuB,CAAC,KAAK,EAAE,aAAa,CAAC,CAAC;IAC9C,oBAAoB,CAAC,aAAa,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,aAAa,CAAC,CAAC;IACxE,WAAW,IAAI,KAAK,GAAG,aAAa,CAAC,CAAC,CAAC,GAAG,KAAK,GAAG,aAAa,CAAC,CAAC,CAAC,GAAG,KAAK,GAAG,aAAa,CAAC,CAAC,CAAC,CAAC;IAE9F,uBAAuB,CAAC,KAAK,EAAE,aAAa,CAAC,CAAC;IAC9C,oBAAoB,CAAC,aAAa,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,aAAa,CAAC,CAAC;IACxE,WAAW,IAAI,KAAK,GAAG,aAAa,CAAC,CAAC,CAAC,GAAG,KAAK,GAAG,aAAa,CAAC,CAAC,CAAC,GAAG,KAAK,GAAG,aAAa,CAAC,CAAC,CAAC,CAAC;IAE9F,OAAO,WAAW,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC;AAC/C,CAAC;AAED,6GAA6G;AAC7G,uGAAuG;AACvG,uBAAuB;AACvB,MAAM,UAAU,4BAA4B,CAC1C,KAA4B,EAC5B,KAA4B,EAC5B,UAAkB,EAClB,UAAkB,EAClB,UAAkB,EAClB,KAAa,EACb,KAAa,EACb,KAAa,EACb,KAAa,EACb,KAAa,EACb,KAAa;IAEb,OAAO,CACL,CAAC,KAAK,CAAC,SAAS,GAAG,KAAK,CAAC,SAAS,CAAC,GAAG,UAAU;QAChD,CAAC,KAAK,CAAC,SAAS,GAAG,KAAK,CAAC,SAAS,CAAC,GAAG,UAAU;QAChD,CAAC,KAAK,CAAC,SAAS,GAAG,KAAK,CAAC,SAAS,CAAC,GAAG,UAAU;QAChD,KAAK,CAAC,gBAAgB,GAAG,KAAK;QAC9B,KAAK,CAAC,gBAAgB,GAAG,KAAK;QAC9B,KAAK,CAAC,gBAAgB,GAAG,KAAK;QAC9B,KAAK,CAAC,gBAAgB,GAAG,KAAK;QAC9B,KAAK,CAAC,gBAAgB,GAAG,KAAK;QAC9B,KAAK,CAAC,gBAAgB,GAAG,KAAK,CAC/B,CAAC;AACJ,CAAC;AAED,uGAAuG;AACvG,2GAA2G;AAC3G,sGAAsG;AACtG,MAAM,UAAU,wBAAwB,CAAC,MAA4B;IACnE,MAAM,CAAC,GAAG,MAAM,CAAC,eAAe,CAAC;IACjC,MAAM,CAAC,GAAG,MAAM,CAAC,eAAe,CAAC;IACjC,MAAM,CAAC,GAAG,MAAM,CAAC,eAAe,CAAC;IACjC,MAAM,CAAC,GAAG,MAAM,CAAC,eAAe,CAAC;IACjC,MAAM,CAAC,eAAe,GAAG,MAAM,CAAC,eAAe,CAAC;IAChD,MAAM,CAAC,eAAe,GAAG,MAAM,CAAC,eAAe,CAAC;IAChD,MAAM,CAAC,eAAe,GAAG,MAAM,CAAC,eAAe,CAAC;IAChD,MAAM,CAAC,eAAe,GAAG,MAAM,CAAC,eAAe,CAAC;IAChD,MAAM,CAAC,eAAe,GAAG,CAAC,CAAC;IAC3B,MAAM,CAAC,eAAe,GAAG,CAAC,CAAC;IAC3B,MAAM,CAAC,eAAe,GAAG,CAAC,CAAC;IAC3B,MAAM,CAAC,eAAe,GAAG,CAAC,CAAC;AAC7B,CAAC;AAED,4GAA4G;AAC5G,iCAAiC;AACjC,EAAE;AACF,wGAAwG;AACxG,2GAA2G;AAC3G,2GAA2G;AAC3G,0GAA0G;AAC1G,cAAc;AACd,MAAM,UAAU,0BAA0B,CACxC,KAA4B,EAC5B,KAA4B,EAC5B,KAAqB;IAErB,kBAAkB,CAChB,KAAK,CAAC,aAAa,GAAG,KAAK,CAAC,OAAO,EACnC,KAAK,CAAC,aAAa,GAAG,KAAK,CAAC,OAAO,EACnC,KAAK,CAAC,aAAa,GAAG,KAAK,CAAC,OAAO,EACnC,KAAK,CAAC,YAAY,EAClB,KAAK,CAAC,YAAY,EAClB,KAAK,CAAC,YAAY,EAClB,KAAK,CAAC,YAAY,EAClB,YAAY,CACb,CAAC;IACF,KAAK,CAAC,GAAG,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC;IAC5B,KAAK,CAAC,GAAG,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC;IAC5B,KAAK,CAAC,GAAG,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC;IAE5B,kBAAkB,CAChB,KAAK,CAAC,aAAa,GAAG,KAAK,CAAC,OAAO,EACnC,KAAK,CAAC,aAAa,GAAG,KAAK,CAAC,OAAO,EACnC,KAAK,CAAC,aAAa,GAAG,KAAK,CAAC,OAAO,EACnC,KAAK,CAAC,YAAY,EAClB,KAAK,CAAC,YAAY,EAClB,KAAK,CAAC,YAAY,EAClB,KAAK,CAAC,YAAY,EAClB,YAAY,CACb,CAAC;IACF,KAAK,CAAC,GAAG,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC;IAC5B,KAAK,CAAC,GAAG,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC;IAC5B,KAAK,CAAC,GAAG,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC;AAC9B,CAAC;AAED,uGAAuG;AACvG,0GAA0G;AAC1G,uEAAuE;AACvE,MAAM,UAAU,iCAAiC,CAC/C,KAA4B,EAC5B,KAA4B,EAC5B,KAA+B,EAC/B,GAAa;IAEb,MAAM,QAAQ,GAAG,KAAK,CAAC,SAAS,GAAG,CAAC,KAAK,CAAC,gBAAgB,GAAG,KAAK,CAAC,GAAG,GAAG,KAAK,CAAC,gBAAgB,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC;IAC7G,MAAM,QAAQ,GAAG,KAAK,CAAC,SAAS,GAAG,CAAC,KAAK,CAAC,gBAAgB,GAAG,KAAK,CAAC,GAAG,GAAG,KAAK,CAAC,gBAAgB,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC;IAC7G,MAAM,QAAQ,GAAG,KAAK,CAAC,SAAS,GAAG,CAAC,KAAK,CAAC,gBAAgB,GAAG,KAAK,CAAC,GAAG,GAAG,KAAK,CAAC,gBAAgB,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC;IAE7G,GAAG,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,SAAS,GAAG,CAAC,KAAK,CAAC,gBAAgB,GAAG,KAAK,CAAC,GAAG,GAAG,KAAK,CAAC,gBAAgB,GAAG,KAAK,CAAC,GAAG,CAAC,GAAG,QAAQ,CAAC;IAChH,GAAG,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,SAAS,GAAG,CAAC,KAAK,CAAC,gBAAgB,GAAG,KAAK,CAAC,GAAG,GAAG,KAAK,CAAC,gBAAgB,GAAG,KAAK,CAAC,GAAG,CAAC,GAAG,QAAQ,CAAC;IAChH,GAAG,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,SAAS,GAAG,CAAC,KAAK,CAAC,gBAAgB,GAAG,KAAK,CAAC,GAAG,GAAG,KAAK,CAAC,gBAAgB,GAAG,KAAK,CAAC,GAAG,CAAC,GAAG,QAAQ,CAAC;AAClH,CAAC;AAED,4GAA4G;AAC5G,0GAA0G;AAC1G,qGAAqG;AACrG,MAAM,UAAU,8BAA8B,CAC5C,KAA4B,EAC5B,KAA4B,EAC5B,GAAa;IAEb,GAAG,CAAC,SAAS,CAAC,GAAG,KAAK,CAAC,qBAAqB,GAAG,KAAK,CAAC,qBAAqB,CAAC;IAC3E,GAAG,CAAC,SAAS,CAAC,GAAG,KAAK,CAAC,qBAAqB,GAAG,KAAK,CAAC,qBAAqB,CAAC;IAC3E,GAAG,CAAC,SAAS,CAAC,GAAG,KAAK,CAAC,qBAAqB,GAAG,KAAK,CAAC,qBAAqB,CAAC;IAC3E,GAAG,CAAC,SAAS,CAAC,GAAG,KAAK,CAAC,qBAAqB,GAAG,KAAK,CAAC,qBAAqB,CAAC;IAC3E,GAAG,CAAC,SAAS,CAAC,GAAG,KAAK,CAAC,qBAAqB,GAAG,KAAK,CAAC,qBAAqB,CAAC;IAC3E,GAAG,CAAC,SAAS,CAAC,GAAG,KAAK,CAAC,qBAAqB,GAAG,KAAK,CAAC,qBAAqB,CAAC;AAC7E,CAAC;AAED,4GAA4G;AAC5G,2EAA2E;AAC3E,EAAE;AACF,yGAAyG;AACzG,wGAAwG;AACxG,2BAA2B;AAC3B,MAAM,UAAU,6BAA6B,CAC3C,IAA2B,EAC3B,cAAsB,EACtB,cAAsB,EACtB,cAAsB,EACtB,cAAsB,EACtB,GAAa;IAEb,mBAAmB,CACjB,IAAI,CAAC,YAAY,EACjB,IAAI,CAAC,YAAY,EACjB,IAAI,CAAC,YAAY,EACjB,IAAI,CAAC,YAAY,EACjB,cAAc,EACd,cAAc,EACd,cAAc,EACd,cAAc,EACd,aAAa,CACd,CAAC;IAEF,MAAM,CAAC,GAAG,aAAa,CAAC,CAAC,CAAC,CAAC;IAC3B,MAAM,CAAC,GAAG,aAAa,CAAC,CAAC,CAAC,CAAC;IAC3B,MAAM,CAAC,GAAG,aAAa,CAAC,CAAC,CAAC,CAAC;IAC3B,MAAM,CAAC,GAAG,aAAa,CAAC,CAAC,CAAC,CAAC;IAC3B,MAAM,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC;IACjB,MAAM,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC;IACjB,MAAM,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC;IACjB,MAAM,GAAG,GAAG,CAAC,GAAG,EAAE,CAAC;IACnB,MAAM,GAAG,GAAG,CAAC,GAAG,EAAE,CAAC;IACnB,MAAM,GAAG,GAAG,CAAC,GAAG,EAAE,CAAC;IACnB,MAAM,GAAG,GAAG,CAAC,GAAG,EAAE,CAAC;IACnB,MAAM,GAAG,GAAG,CAAC,GAAG,EAAE,CAAC;IACnB,MAAM,GAAG,GAAG,CAAC,GAAG,EAAE,CAAC;IACnB,MAAM,GAAG,GAAG,CAAC,GAAG,EAAE,CAAC;IACnB,MAAM,GAAG,GAAG,CAAC,GAAG,EAAE,CAAC;IACnB,MAAM,GAAG,GAAG,CAAC,GAAG,EAAE,CAAC;IAEnB,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,GAAG,GAAG,GAAG,CAAC;IACvB,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,GAAG,GAAG,CAAC;IACnB,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,GAAG,GAAG,CAAC;IACnB,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,GAAG,GAAG,CAAC;IACnB,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,GAAG,GAAG,GAAG,CAAC;IACvB,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,GAAG,GAAG,CAAC;IACnB,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,GAAG,GAAG,CAAC;IACnB,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,GAAG,GAAG,CAAC;IACnB,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,GAAG,GAAG,GAAG,CAAC;AACzB,CAAC;AAED,qGAAqG;AACrG,4GAA4G;AAC5G,mDAAmD;AACnD,MAAM,UAAU,gCAAgC,CAC9C,IAA2B,EAC3B,cAAsB,EACtB,cAAsB,EACtB,cAAsB,EACtB,cAAsB,EACtB,GAAa;IAEb,mBAAmB,CACjB,IAAI,CAAC,YAAY,EACjB,IAAI,CAAC,YAAY,EACjB,IAAI,CAAC,YAAY,EACjB,IAAI,CAAC,YAAY,EACjB,cAAc,EACd,cAAc,EACd,cAAc,EACd,cAAc,EACd,GAAG,CACJ,CAAC;AACJ,CAAC;AAED,uGAAuG;AACvG,kBAAkB;AAClB,EAAE;AACF,4GAA4G;AAC5G,wGAAwG;AACxG,4GAA4G;AAC5G,iFAAiF;AACjF,MAAM,UAAU,4BAA4B,CAC1C,KAA4B,EAC5B,KAA4B,EAC5B,GAAW,EACX,GAAW,EACX,GAAW,EACX,GAAW,EACX,GAAW,EACX,GAAW,EACX,GAAa;IAEb,MAAM,QAAQ,GAAG,KAAK,CAAC,WAAW,GAAG,KAAK,CAAC,WAAW,CAAC;IACvD,GAAG,CAAC,SAAS,CAAC,GAAG,QAAQ,CAAC;IAC1B,GAAG,CAAC,SAAS,CAAC,GAAG,QAAQ,CAAC;IAC1B,GAAG,CAAC,SAAS,CAAC,GAAG,QAAQ,CAAC;IAC1B,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;IACnB,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;IACnB,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;IAEnB,uBAAuB,CAAC,KAAK,EAAE,eAAe,CAAC,CAAC;IAChD,eAAe,CAAC,eAAe,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;IACrD,uBAAuB,CAAC,KAAK,EAAE,eAAe,CAAC,CAAC;IAChD,eAAe,CAAC,eAAe,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;AACvD,CAAC;AAED,0GAA0G;AAC1G,kEAAkE;AAClE,EAAE;AACF,4GAA4G;AAC5G,0GAA0G;AAC1G,yGAAyG;AACzG,sDAAsD;AACtD,EAAE;AACF,sGAAsG;AACtG,2GAA2G;AAC3G,iGAAiG;AACjG,MAAM,UAAU,mCAAmC,CACjD,OAAe,EACf,OAAe,EACf,OAAe,EACf,OAAe,EACf,OAAe,EACf,OAAe,EACf,OAAe,EACf,OAAe,EACf,GAAa;IAEb,mBAAmB,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,CAAC,CAAC;IACpG,IAAI,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC;QACf,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QACjB,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QACjB,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QACjB,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IACnB,CAAC;AACH,CAAC;AAED,0GAA0G;AAC1G,4GAA4G;AAC5G,kFAAkF;AAClF,EAAE;AACF,2GAA2G;AAC3G,2GAA2G;AAC3G,0EAA0E;AAC1E,EAAE;AACF,2GAA2G;AAC3G,4GAA4G;AAC5G,iFAAiF;AACjF,MAAM,UAAU,gCAAgC,CAC9C,OAAe,EACf,OAAe,EACf,OAAe,EACf,OAAe,EACf,OAAe,EACf,OAAe,EACf,OAAe,EACf,OAAe,EACf,GAAa;IAEb,mCAAmC,CACjC,OAAO,EACP,OAAO,EACP,OAAO,EACP,OAAO,EACP,OAAO,EACP,OAAO,EACP,OAAO,EACP,OAAO,EACP,qBAAqB,CACtB,CAAC;IAEF,MAAM,CAAC,GAAG,qBAAqB,CAAC,CAAC,CAAC,CAAC;IACnC,MAAM,CAAC,GAAG,qBAAqB,CAAC,CAAC,CAAC,CAAC;IACnC,MAAM,CAAC,GAAG,qBAAqB,CAAC,CAAC,CAAC,CAAC;IACnC,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;IAC9C,IAAI,IAAI,GAAG,kBAAkB,EAAE,CAAC;QAC9B,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;QACX,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;QACX,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;QACX,OAAO;IACT,CAAC;IAED,MAAM,KAAK,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,qBAAqB,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;IACtE,kBAAkB,CAAC,CAAC,GAAG,KAAK,EAAE,CAAC,GAAG,KAAK,EAAE,CAAC,GAAG,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,CAAC,CAAC;AAC/F,CAAC;AAED,gGAAgG;AAChG,6FAA6F;AAC7F,EAAE;AACF,4GAA4G;AAC5G,wGAAwG;AACxG,wGAAwG;AACxG,mBAAmB;AACnB,MAAM,UAAU,6BAA6B,CAC3C,KAA4B,EAC5B,KAA4B,EAC5B,KAA+B,EAC/B,GAAa;IAEb,gBAAgB,CAAC,KAAK,EAAE,gBAAgB,CAAC,CAAC;IAC1C,MAAM,QAAQ,GAAG,gBAAgB,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,GAAG,CAAC;IACjD,MAAM,QAAQ,GAAG,gBAAgB,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,GAAG,CAAC;IACjD,MAAM,QAAQ,GAAG,gBAAgB,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,GAAG,CAAC;IAEjD,gBAAgB,CAAC,KAAK,EAAE,gBAAgB,CAAC,CAAC;IAC1C,GAAG,CAAC,CAAC,CAAC,GAAG,gBAAgB,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,GAAG,GAAG,QAAQ,CAAC;IACpD,GAAG,CAAC,CAAC,CAAC,GAAG,gBAAgB,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,GAAG,GAAG,QAAQ,CAAC;IACpD,GAAG,CAAC,CAAC,CAAC,GAAG,gBAAgB,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,GAAG,GAAG,QAAQ,CAAC;AACtD,CAAC;AAED,2GAA2G;AAC3G,yGAAyG;AACzG,sEAAsE;AACtE,SAAS,eAAe,CAAC,MAAmC,EAAE,EAAU,EAAE,EAAU,EAAE,EAAU,EAAE,GAAa;IAC7G,oBAAoB,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,QAAQ,CAAC,CAAC;IACnD,oBAAoB,CAAC,MAAM,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,QAAQ,CAAC,CAAC;IACnD,oBAAoB,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,QAAQ,CAAC,CAAC;IAEnD,GAAG,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,GAAG,QAAQ,CAAC,CAAC,CAAC,GAAG,EAAE,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;IACvD,GAAG,CAAC,SAAS,CAAC,IAAI,EAAE,GAAG,QAAQ,CAAC,CAAC,CAAC,GAAG,EAAE,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;IACtD,GAAG,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,GAAG,QAAQ,CAAC,CAAC,CAAC,GAAG,EAAE,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;IACvD,GAAG,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,GAAG,QAAQ,CAAC,CAAC,CAAC,GAAG,EAAE,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;IACvD,GAAG,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,GAAG,QAAQ,CAAC,CAAC,CAAC,GAAG,EAAE,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;IACvD,GAAG,CAAC,SAAS,CAAC,IAAI,EAAE,GAAG,QAAQ,CAAC,CAAC,CAAC,GAAG,EAAE,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;AACxD,CAAC;AAED,SAAS,qBAAqB,CAC5B,IAAiB,EACjB,EAAU,EACV,EAAU,EACV,EAAU,EACV,QAAgB,EAChB,QAAgB,EAChB,QAAgB;IAEhB,IAAI,CAAC,SAAS,IAAI,QAAQ,GAAG,IAAI,CAAC,WAAW,CAAC;IAC9C,IAAI,CAAC,SAAS,IAAI,QAAQ,GAAG,IAAI,CAAC,WAAW,CAAC;IAC9C,IAAI,CAAC,SAAS,IAAI,QAAQ,GAAG,IAAI,CAAC,WAAW,CAAC;IAE9C,MAAM,OAAO,GAAG,EAAE,GAAG,QAAQ,GAAG,EAAE,GAAG,QAAQ,CAAC;IAC9C,MAAM,OAAO,GAAG,EAAE,GAAG,QAAQ,GAAG,EAAE,GAAG,QAAQ,CAAC;IAC9C,MAAM,OAAO,GAAG,EAAE,GAAG,QAAQ,GAAG,EAAE,GAAG,QAAQ,CAAC;IAE9C,uBAAuB,CAAC,IAAI,EAAE,iBAAiB,CAAC,CAAC;IACjD,oBAAoB,CAAC,iBAAiB,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,iBAAiB,CAAC,CAAC;IACtF,IAAI,CAAC,gBAAgB,IAAI,iBAAiB,CAAC,CAAC,CAAC,CAAC;IAC9C,IAAI,CAAC,gBAAgB,IAAI,iBAAiB,CAAC,CAAC,CAAC,CAAC;IAC9C,IAAI,CAAC,gBAAgB,IAAI,iBAAiB,CAAC,CAAC,CAAC,CAAC;AAChD,CAAC;AAED,0GAA0G;AAC1G,6GAA6G;AAC7G,qEAAqE;AACrE,SAAS,mBAAmB,CAC1B,EAAU,EACV,EAAU,EACV,EAAU,EACV,EAAU,EACV,EAAU,EACV,EAAU,EACV,EAAU,EACV,EAAU,EACV,GAAa;IAEb,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC;IAC/C,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC;IAC/C,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC;IAC/C,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC;AACjD,CAAC;AAED,SAAS,uBAAuB,CAAC,IAA2B,EAAE,GAAa;IACzE,GAAG,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC,qBAAqB,CAAC;IAC5C,GAAG,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC,qBAAqB,CAAC;IAC5C,GAAG,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC,qBAAqB,CAAC;IAC5C,GAAG,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC,qBAAqB,CAAC;IAC5C,GAAG,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC,qBAAqB,CAAC;IAC5C,GAAG,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC,qBAAqB,CAAC;AAC9C,CAAC;AAED,uGAAuG;AACvG,sGAAsG;AACtG,SAAS,kBAAkB,CACzB,EAAU,EACV,EAAU,EACV,EAAU,EACV,EAAU,EACV,EAAU,EACV,EAAU,EACV,EAAU,EACV,GAAa;IAEb,MAAM,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC;IACvC,MAAM,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC;IACvC,MAAM,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC;IAEvC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC,GAAG,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC;IACtC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC,GAAG,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC;IACtC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC,GAAG,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC;AACxC,CAAC;AAED,SAAS,gBAAgB,CAAC,IAA2B,EAAE,GAAa;IAClE,kBAAkB,CAChB,IAAI,CAAC,OAAO,EACZ,IAAI,CAAC,OAAO,EACZ,IAAI,CAAC,OAAO,EACZ,IAAI,CAAC,YAAY,EACjB,IAAI,CAAC,YAAY,EACjB,IAAI,CAAC,YAAY,EACjB,IAAI,CAAC,YAAY,EACjB,GAAG,CACJ,CAAC;IACF,GAAG,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC;IACjB,GAAG,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC;IACjB,GAAG,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC;AACnB,CAAC;AAED,uGAAuG;AACvG,iGAAiG;AACjG,MAAM,kBAAkB,GAAG,KAAK,CAAC;AACjC,2GAA2G;AAC3G,6FAA6F;AAC7F,MAAM,oBAAoB,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;AAChD,MAAM,oBAAoB,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;AACvC,MAAM,YAAY,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;AAC/B,MAAM,aAAa,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;AACnC,MAAM,iBAAiB,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;AAC7C,MAAM,iBAAiB,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;AACpC,MAAM,eAAe,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;AAC3C,MAAM,qBAAqB,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;AAC3C,MAAM,gBAAgB,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;AAC5C,MAAM,gBAAgB,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;AACnC,MAAM,aAAa,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;AACzC,MAAM,aAAa,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;AAChC,MAAM,gBAAgB,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;AACnC,MAAM,QAAQ,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;AAC3B,MAAM,QAAQ,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;AAC3B,MAAM,QAAQ,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { Physics3DJoint, Physics3DJointKind, Physics3DJointSolver, Physics3DWorld } from '@flighthq/types/contract';
|
|
2
|
+
export declare function addPhysics3DJoint<T extends Physics3DJoint>(world: Physics3DWorld, joint: T): T;
|
|
3
|
+
export declare function getPhysics3DJointSolver(world: Readonly<Physics3DWorld>, kind: Physics3DJointKind): Physics3DJointSolver | null;
|
|
4
|
+
export declare function invalidatePhysics3DJoint(world: Physics3DWorld, joint: Physics3DJoint): boolean;
|
|
5
|
+
export declare function isPhysics3DPairOrdered(a: number, b: number): boolean;
|
|
6
|
+
export declare function registerPhysics3DJointSolver(world: Physics3DWorld, kind: Physics3DJointKind, solver: Physics3DJointSolver): void;
|
|
7
|
+
export declare function removePhysics3DJoint(world: Physics3DWorld, joint: Physics3DJoint): boolean;
|
|
8
|
+
//# sourceMappingURL=jointRegistry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jointRegistry.d.ts","sourceRoot":"","sources":["../src/jointRegistry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,cAAc,EACd,kBAAkB,EAClB,oBAAoB,EACpB,cAAc,EACf,MAAM,0BAA0B,CAAC;AAalC,wBAAgB,iBAAiB,CAAC,CAAC,SAAS,cAAc,EAAE,KAAK,EAAE,cAAc,EAAE,KAAK,EAAE,CAAC,GAAG,CAAC,CAqB9F;AAKD,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,QAAQ,CAAC,cAAc,CAAC,EAC/B,IAAI,EAAE,kBAAkB,GACvB,oBAAoB,GAAG,IAAI,CAE7B;AASD,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,cAAc,EAAE,KAAK,EAAE,cAAc,GAAG,OAAO,CAa9F;AAOD,wBAAgB,sBAAsB,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO,CAEpE;AASD,wBAAgB,4BAA4B,CAC1C,KAAK,EAAE,cAAc,EACrB,IAAI,EAAE,kBAAkB,EACxB,MAAM,EAAE,oBAAoB,GAC3B,IAAI,CAcN;AAGD,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,cAAc,EAAE,KAAK,EAAE,cAAc,GAAG,OAAO,CAS1F"}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import { rebuildPhysics3DJointCollisionSuppressions } from './jointCollisionSuppression';
|
|
2
|
+
import { assertPhysics3DWorldNotStepping, physics3DJointOwners } from './ownership';
|
|
3
|
+
import { findPhysics3DBody, wakePhysics3DBody } from './world';
|
|
4
|
+
// Adds `joint` to `world` under the same canonical body ordering contacts use, exchanging its two ends when
|
|
5
|
+
// the caller supplied them the other way round.
|
|
6
|
+
//
|
|
7
|
+
// A joint is a constraint in the SAME sequential solve list as a contact, so it inherits the same
|
|
8
|
+
// obligation: each impulse lands on the velocities the previous one left, and an ordering that varied with
|
|
9
|
+
// construction history would make the result vary with it. Contacts get their order from the broadphase pair
|
|
10
|
+
// sort; joints have no broadphase, so it is enforced here, at the one place a joint enters a world.
|
|
11
|
+
export function addPhysics3DJoint(world, joint) {
|
|
12
|
+
assertPhysics3DWorldNotStepping(world);
|
|
13
|
+
if (physics3DJointOwners.has(joint) || world.joints.includes(joint)) {
|
|
14
|
+
throw new Error('Cannot add a physics joint that already belongs to a physics world');
|
|
15
|
+
}
|
|
16
|
+
// Canonicalize only when the kind can be consulted. A joint whose solver is not registered yet is
|
|
17
|
+
// explicitly supported — a scene deserialized ahead of the code that solves it — and exchanging its ends
|
|
18
|
+
// now would move the bodies, anchors, and frames while the kind's own direction-bearing fields stayed as
|
|
19
|
+
// authored: the generic half of a swap with the kind's half missing, which no later registration repairs.
|
|
20
|
+
// An unregistered joint constrains nothing, so its order does not matter until a solver exists, and
|
|
21
|
+
// `registerPhysics3DJointSolver` canonicalizes what is already in the world at that point.
|
|
22
|
+
const active = getPhysics3DJointSolver(world, joint.kind) !== null;
|
|
23
|
+
if (active)
|
|
24
|
+
canonicalizeJointEnds(world, joint);
|
|
25
|
+
world.joints.push(joint);
|
|
26
|
+
physics3DJointOwners.set(joint, world);
|
|
27
|
+
rebuildPhysics3DJointCollisionSuppressions(world);
|
|
28
|
+
// Adding an active constraint changes what both bodies may do THIS step. A sleeping pair would skip
|
|
29
|
+
// prepare and solve forever unless something unrelated happened to wake it.
|
|
30
|
+
if (active)
|
|
31
|
+
wakeJointBodies(world, joint);
|
|
32
|
+
return joint;
|
|
33
|
+
}
|
|
34
|
+
// The solver registered for `kind` on this world, or null when none is. A missing solver is an expected
|
|
35
|
+
// condition rather than an error: a scene deserialized with a joint kind the running build does not know
|
|
36
|
+
// about should import and simply not constrain, rather than refuse to load.
|
|
37
|
+
export function getPhysics3DJointSolver(world, kind) {
|
|
38
|
+
return world.jointSolvers.get(kind) ?? null;
|
|
39
|
+
}
|
|
40
|
+
// Discards solver-owned state after a stored joint's authored parameters change. Returns false when the
|
|
41
|
+
// world does not hold the joint.
|
|
42
|
+
//
|
|
43
|
+
// A cached impulse is an answer to the PREVIOUS constraint equation. Reapplying it after an anchor, frame,
|
|
44
|
+
// limit, or motor changes kicks both bodies before the new equation gets its first iteration — which reads
|
|
45
|
+
// as a joint that lurches when it is edited rather than as a stale cache. The kind clears whatever
|
|
46
|
+
// accumulators only it knows about; the common `impulse0..5` block is cleared here.
|
|
47
|
+
export function invalidatePhysics3DJoint(world, joint) {
|
|
48
|
+
assertPhysics3DWorldNotStepping(world);
|
|
49
|
+
if (physics3DJointOwners.get(joint) !== world || !world.joints.includes(joint))
|
|
50
|
+
return false;
|
|
51
|
+
getPhysics3DJointSolver(world, joint.kind)?.clearAccumulatedImpulses?.(joint);
|
|
52
|
+
joint.impulse0 = 0;
|
|
53
|
+
joint.impulse1 = 0;
|
|
54
|
+
joint.impulse2 = 0;
|
|
55
|
+
joint.impulse3 = 0;
|
|
56
|
+
joint.impulse4 = 0;
|
|
57
|
+
joint.impulse5 = 0;
|
|
58
|
+
rebuildPhysics3DJointCollisionSuppressions(world);
|
|
59
|
+
wakeJointBodies(world, joint);
|
|
60
|
+
return true;
|
|
61
|
+
}
|
|
62
|
+
// Whether the two bodies are in canonical order — `bodyA` before `bodyB` by persistent index.
|
|
63
|
+
//
|
|
64
|
+
// Ordered by INDEX rather than by anything geometric. Any order derived from coordinates flips the moment
|
|
65
|
+
// those coordinates cross, which would renumber a joint's ends mid-simulation and invalidate every
|
|
66
|
+
// accumulator keyed to them. Identity survives motion; position does not.
|
|
67
|
+
export function isPhysics3DPairOrdered(a, b) {
|
|
68
|
+
return a <= b;
|
|
69
|
+
}
|
|
70
|
+
// Registers `solver` for `kind` on this world. Last write wins, so a caller may replace a built-in with its
|
|
71
|
+
// own — collisions are avoided by the vendor-prefix convention (bare names reserved for built-ins) rather
|
|
72
|
+
// than by a guard that would make overriding impossible.
|
|
73
|
+
//
|
|
74
|
+
// Registration is per-world and explicit rather than a module-level table populated on import, so a bundle
|
|
75
|
+
// that never registers a joint never links one: six solvers are six blocks of constraint math, and a game
|
|
76
|
+
// using none of them should pay for none of them.
|
|
77
|
+
export function registerPhysics3DJointSolver(world, kind, solver) {
|
|
78
|
+
assertPhysics3DWorldNotStepping(world);
|
|
79
|
+
world.jointSolvers.set(kind, solver);
|
|
80
|
+
// Joints of this kind may already be in the world: `addPhysics3DJoint` deliberately leaves an
|
|
81
|
+
// unknown-kind joint in its authored order. This is where that deferred work happens, so the outcome no
|
|
82
|
+
// longer depends on whether the scene or the solver arrived first.
|
|
83
|
+
for (const joint of world.joints) {
|
|
84
|
+
if (joint.kind !== kind)
|
|
85
|
+
continue;
|
|
86
|
+
canonicalizeJointEnds(world, joint);
|
|
87
|
+
// Registration turns an inert descriptor into a live constraint, and re-registration may replace its
|
|
88
|
+
// equation outright. Both are the same topology change from a sleeping neighbour's point of view.
|
|
89
|
+
wakeJointBodies(world, joint);
|
|
90
|
+
}
|
|
91
|
+
rebuildPhysics3DJointCollisionSuppressions(world);
|
|
92
|
+
}
|
|
93
|
+
// Removes `joint` from `world`. Returns false when the world does not hold it.
|
|
94
|
+
export function removePhysics3DJoint(world, joint) {
|
|
95
|
+
assertPhysics3DWorldNotStepping(world);
|
|
96
|
+
const at = world.joints.indexOf(joint);
|
|
97
|
+
if (at < 0)
|
|
98
|
+
return false;
|
|
99
|
+
if (getPhysics3DJointSolver(world, joint.kind) !== null)
|
|
100
|
+
wakeJointBodies(world, joint);
|
|
101
|
+
world.joints.splice(at, 1);
|
|
102
|
+
physics3DJointOwners.delete(joint);
|
|
103
|
+
rebuildPhysics3DJointCollisionSuppressions(world);
|
|
104
|
+
return true;
|
|
105
|
+
}
|
|
106
|
+
// Exchanges `joint`'s ends when the pair is out of canonical order and the kind consents.
|
|
107
|
+
//
|
|
108
|
+
// The kind is asked only when a swap is actually pending, because `swapEnds` both vetoes AND transforms:
|
|
109
|
+
// calling it otherwise would apply a reversal to ends that never moved. What the generic half can move is
|
|
110
|
+
// only what every joint has — two body indices and two anchors. Anything a kind measures FROM bodyA TO
|
|
111
|
+
// bodyB, including its frames, reverses with them and is the kind's own to carry across.
|
|
112
|
+
function canonicalizeJointEnds(world, joint) {
|
|
113
|
+
const solver = getPhysics3DJointSolver(world, joint.kind);
|
|
114
|
+
if (solver?.usesBodyA === false)
|
|
115
|
+
return;
|
|
116
|
+
if (isPhysics3DPairOrdered(joint.bodyA, joint.bodyB))
|
|
117
|
+
return;
|
|
118
|
+
if (!(solver?.swapEnds?.(joint) ?? true))
|
|
119
|
+
return;
|
|
120
|
+
const bodyA = joint.bodyA;
|
|
121
|
+
joint.bodyA = joint.bodyB;
|
|
122
|
+
joint.bodyB = bodyA;
|
|
123
|
+
const anchorX = joint.localAnchorAX;
|
|
124
|
+
const anchorY = joint.localAnchorAY;
|
|
125
|
+
const anchorZ = joint.localAnchorAZ;
|
|
126
|
+
joint.localAnchorAX = joint.localAnchorBX;
|
|
127
|
+
joint.localAnchorAY = joint.localAnchorBY;
|
|
128
|
+
joint.localAnchorAZ = joint.localAnchorBZ;
|
|
129
|
+
joint.localAnchorBX = anchorX;
|
|
130
|
+
joint.localAnchorBY = anchorY;
|
|
131
|
+
joint.localAnchorBZ = anchorZ;
|
|
132
|
+
}
|
|
133
|
+
function wakeJointBodies(world, joint) {
|
|
134
|
+
const solver = getPhysics3DJointSolver(world, joint.kind);
|
|
135
|
+
if (solver === null)
|
|
136
|
+
return;
|
|
137
|
+
const bodyA = solver.usesBodyA === false ? null : findPhysics3DBody(world, joint.bodyA);
|
|
138
|
+
const bodyB = findPhysics3DBody(world, joint.bodyB);
|
|
139
|
+
if (bodyA !== null)
|
|
140
|
+
wakePhysics3DBody(bodyA);
|
|
141
|
+
if (bodyB !== null)
|
|
142
|
+
wakePhysics3DBody(bodyB);
|
|
143
|
+
}
|
|
144
|
+
//# sourceMappingURL=jointRegistry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jointRegistry.js","sourceRoot":"","sources":["../src/jointRegistry.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { Physics3DJoint, Physics3DJointFrames, RigidBody3D } from '@flighthq/types/contract';
|
|
2
|
+
export declare const ROW_LENGTH = 9;
|
|
3
|
+
export declare const POINT_MASS = 0;
|
|
4
|
+
export declare const POINT_BIAS = 6;
|
|
5
|
+
export declare const POINT_LENGTH = 9;
|
|
6
|
+
export declare function applyRow(bodyA: RigidBody3D, bodyB: RigidBody3D, state: readonly number[], offset: number, impulse: number): void;
|
|
7
|
+
export declare function beginJointSolve(joint: Physics3DJoint, length: number): number[];
|
|
8
|
+
export declare function clearJointSolve(joint: Physics3DJoint): void;
|
|
9
|
+
export declare function getJointSolveState(joint: Readonly<Physics3DJoint>): number[] | undefined;
|
|
10
|
+
export declare function getRowMass(bodyA: Readonly<RigidBody3D>, bodyB: Readonly<RigidBody3D>, state: readonly number[], offset: number): number;
|
|
11
|
+
export declare function getRowVelocity(bodyA: Readonly<RigidBody3D>, bodyB: Readonly<RigidBody3D>, state: readonly number[], offset: number): number;
|
|
12
|
+
export declare function prepareAngularBlock(bodyA: Readonly<RigidBody3D>, bodyB: Readonly<RigidBody3D>, state: number[], massOffset: number, biasOffset: number, dt: number): void;
|
|
13
|
+
export declare function preparePointBlock(bodyA: Readonly<RigidBody3D>, bodyB: Readonly<RigidBody3D>, joint: Physics3DJoint, state: number[], dt: number): void;
|
|
14
|
+
export declare function readFrameBases(bodyA: Readonly<RigidBody3D>, bodyB: Readonly<RigidBody3D>, frames: Physics3DJointFrames): void;
|
|
15
|
+
export declare function readFrameRotations(bodyA: Readonly<RigidBody3D>, bodyB: Readonly<RigidBody3D>, frames: Physics3DJointFrames): void;
|
|
16
|
+
export declare function readJointImpulse(joint: Readonly<Physics3DJoint>, slot: number): number;
|
|
17
|
+
export declare function solveAngularBlock(bodyA: RigidBody3D, bodyB: RigidBody3D, joint: Physics3DJoint, state: readonly number[], massOffset: number, biasOffset: number): void;
|
|
18
|
+
export declare function solveEqualityRow(bodyA: RigidBody3D, bodyB: RigidBody3D, joint: Physics3DJoint, slot: number, state: readonly number[], offset: number, mass: number, error: number, biasFactor: number): void;
|
|
19
|
+
export declare function solveLowerLimitRow(bodyA: RigidBody3D, bodyB: RigidBody3D, state: number[], offset: number, mass: number, error: number, biasFactor: number, accumulatorSlot: number): void;
|
|
20
|
+
export declare function solveMotorRow(bodyA: RigidBody3D, bodyB: RigidBody3D, state: readonly number[], offset: number, mass: number, speed: number, maxImpulse: number, previous: number): number;
|
|
21
|
+
export declare function solvePointBlock(bodyA: RigidBody3D, bodyB: RigidBody3D, joint: Physics3DJoint, state: readonly number[]): void;
|
|
22
|
+
export declare function solveUpperLimitRow(bodyA: RigidBody3D, bodyB: RigidBody3D, state: number[], offset: number, mass: number, error: number, biasFactor: number, accumulatorSlot: number): void;
|
|
23
|
+
export declare function warmStartAngularBlock(bodyA: RigidBody3D, bodyB: RigidBody3D, joint: Readonly<Physics3DJoint>): void;
|
|
24
|
+
export declare function warmStartPointBlock(bodyA: RigidBody3D, bodyB: RigidBody3D, joint: Readonly<Physics3DJoint>): void;
|
|
25
|
+
export declare function writeAngularRow(state: number[], offset: number, axisX: number, axisY: number, axisZ: number): void;
|
|
26
|
+
export declare function writeJointImpulse(joint: Physics3DJoint, slot: number, value: number): void;
|
|
27
|
+
export declare function writeRow(state: number[], offset: number, directionX: number, directionY: number, directionZ: number, armAX: number, armAY: number, armAZ: number, armBX: number, armBY: number, armBZ: number): void;
|
|
28
|
+
export declare const frameABasis: number[];
|
|
29
|
+
export declare const frameBBasis: number[];
|
|
30
|
+
export declare const frameARotation: number[];
|
|
31
|
+
export declare const frameBRotation: number[];
|
|
32
|
+
//# sourceMappingURL=jointRows.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jointRows.d.ts","sourceRoot":"","sources":["../src/jointRows.ts"],"names":[],"mappings":"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"}
|