@flighthq/physics3d 0.4.0-edge.1908.751021c
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/broadphase.d.ts +4 -0
- package/dist/broadphase.d.ts.map +1 -0
- package/dist/broadphase.js +158 -0
- package/dist/broadphase.js.map +1 -0
- package/dist/colliderCollision.d.ts +5 -0
- package/dist/colliderCollision.d.ts.map +1 -0
- package/dist/colliderCollision.js +55 -0
- package/dist/colliderCollision.js.map +1 -0
- package/dist/colliderTransform.d.ts +5 -0
- package/dist/colliderTransform.d.ts.map +1 -0
- package/dist/colliderTransform.js +424 -0
- package/dist/colliderTransform.js.map +1 -0
- package/dist/contactIntake.d.ts +5 -0
- package/dist/contactIntake.d.ts.map +1 -0
- package/dist/contactIntake.js +237 -0
- package/dist/contactIntake.js.map +1 -0
- package/dist/contacts.d.ts +4 -0
- package/dist/contacts.d.ts.map +1 -0
- package/dist/contacts.js +64 -0
- package/dist/contacts.js.map +1 -0
- package/dist/continuous.d.ts +5 -0
- package/dist/continuous.d.ts.map +1 -0
- package/dist/continuous.js +829 -0
- package/dist/continuous.js.map +1 -0
- package/dist/contract.d.ts +28 -0
- package/dist/contract.d.ts.map +1 -0
- package/dist/contract.js +28 -0
- package/dist/contract.js.map +1 -0
- package/dist/debugGeometry.d.ts +4 -0
- package/dist/debugGeometry.d.ts.map +1 -0
- package/dist/debugGeometry.js +333 -0
- package/dist/debugGeometry.js.map +1 -0
- package/dist/enablePhysics3DGuards.d.ts +4 -0
- package/dist/enablePhysics3DGuards.d.ts.map +1 -0
- package/dist/enablePhysics3DGuards.js +155 -0
- package/dist/enablePhysics3DGuards.js.map +1 -0
- package/dist/explainPhysics3DCollision.d.ts +3 -0
- package/dist/explainPhysics3DCollision.d.ts.map +1 -0
- package/dist/explainPhysics3DCollision.js +30 -0
- package/dist/explainPhysics3DCollision.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 +51 -0
- package/dist/explainPhysics3DStep.js.map +1 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +22 -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 +184 -0
- package/dist/integrate.js.map +1 -0
- package/dist/islands.d.ts +6 -0
- package/dist/islands.d.ts.map +1 -0
- package/dist/islands.js +333 -0
- package/dist/islands.js.map +1 -0
- package/dist/jointBreakage.d.ts +5 -0
- package/dist/jointBreakage.d.ts.map +1 -0
- package/dist/jointBreakage.js +44 -0
- package/dist/jointBreakage.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 +9 -0
- package/dist/jointFactories.d.ts.map +1 -0
- package/dist/jointFactories.js +159 -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/jointReaction.d.ts +8 -0
- package/dist/jointReaction.d.ts.map +1 -0
- package/dist/jointReaction.js +65 -0
- package/dist/jointReaction.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 +33 -0
- package/dist/jointRows.d.ts.map +1 -0
- package/dist/jointRows.js +352 -0
- package/dist/jointRows.js.map +1 -0
- package/dist/joints.d.ts +16 -0
- package/dist/joints.d.ts.map +1 -0
- package/dist/joints.js +1060 -0
- package/dist/joints.js.map +1 -0
- package/dist/massProperties.d.ts +13 -0
- package/dist/massProperties.d.ts.map +1 -0
- package/dist/massProperties.js +462 -0
- package/dist/massProperties.js.map +1 -0
- package/dist/material.d.ts +3 -0
- package/dist/material.d.ts.map +1 -0
- package/dist/material.js +13 -0
- package/dist/material.js.map +1 -0
- package/dist/nodeSync.d.ts +3 -0
- package/dist/nodeSync.d.ts.map +1 -0
- package/dist/nodeSync.js +16 -0
- package/dist/nodeSync.js.map +1 -0
- package/dist/ownership.d.ts +8 -0
- package/dist/ownership.d.ts.map +1 -0
- package/dist/ownership.js +26 -0
- package/dist/ownership.js.map +1 -0
- package/dist/physics3DBroadphasePublication.d.ts +5 -0
- package/dist/physics3DBroadphasePublication.d.ts.map +1 -0
- package/dist/physics3DBroadphasePublication.js +49 -0
- package/dist/physics3DBroadphasePublication.js.map +1 -0
- package/dist/physics3DSpatialIndexingGuards.d.ts +4 -0
- package/dist/physics3DSpatialIndexingGuards.d.ts.map +1 -0
- package/dist/physics3DSpatialIndexingGuards.js +11 -0
- package/dist/physics3DSpatialIndexingGuards.js.map +1 -0
- package/dist/registerBuiltInPhysics3DJointSolvers.d.ts +3 -0
- package/dist/registerBuiltInPhysics3DJointSolvers.d.ts.map +1 -0
- package/dist/registerBuiltInPhysics3DJointSolvers.js +15 -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 +460 -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 +302 -0
- package/dist/step.js.map +1 -0
- package/dist/stepValidation.d.ts +13 -0
- package/dist/stepValidation.d.ts.map +1 -0
- package/dist/stepValidation.js +284 -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 +27 -0
- package/dist/world.d.ts.map +1 -0
- package/dist/world.js +762 -0
- package/dist/world.js.map +1 -0
- package/dist/worldQueries.d.ts +11 -0
- package/dist/worldQueries.d.ts.map +1 -0
- package/dist/worldQueries.js +409 -0
- package/dist/worldQueries.js.map +1 -0
- package/package.json +55 -0
- package/src/broadphase.test.ts +265 -0
- package/src/colliderCollision.test.ts +57 -0
- package/src/colliderTransform.test.ts +221 -0
- package/src/contactIntake.test.ts +370 -0
- package/src/contacts.test.ts +64 -0
- package/src/continuous.test.ts +679 -0
- package/src/debugGeometry.test.ts +288 -0
- package/src/enablePhysics3DGuards.test.ts +206 -0
- package/src/explainPhysics3DCollision.test.ts +78 -0
- package/src/explainPhysics3DJoints.test.ts +101 -0
- package/src/explainPhysics3DStep.test.ts +142 -0
- package/src/integrate.test.ts +279 -0
- package/src/islands.test.ts +384 -0
- package/src/jointBreakage.test.ts +143 -0
- package/src/jointCollisionSuppression.test.ts +94 -0
- package/src/jointFactories.test.ts +244 -0
- package/src/jointMath.test.ts +646 -0
- package/src/jointReaction.test.ts +241 -0
- package/src/jointRegistry.test.ts +229 -0
- package/src/jointRows.test.ts +548 -0
- package/src/joints.test.ts +1066 -0
- package/src/massProperties.test.ts +611 -0
- package/src/material.test.ts +40 -0
- package/src/nodeSync.test.ts +50 -0
- package/src/ownership.test.ts +61 -0
- package/src/physics3DBroadphasePublication.test.ts +63 -0
- package/src/physics3DSpatialIndexingGuards.test.ts +43 -0
- package/src/registerBuiltInPhysics3DJointSolvers.test.ts +51 -0
- package/src/solver.test.ts +567 -0
- package/src/step.test.ts +490 -0
- package/src/stepValidation.test.ts +346 -0
- package/src/stress.test.ts +526 -0
- package/src/symmetricTensor.test.ts +166 -0
- package/src/world.test.ts +1127 -0
- package/src/worldQueries.test.ts +565 -0
package/dist/step.js
ADDED
|
@@ -0,0 +1,302 @@
|
|
|
1
|
+
import { buildPhysics3DContacts, refreshPhysics3DContacts } from './contactIntake';
|
|
2
|
+
import { hasActivePhysics3DBullet, integratePhysics3DContinuous } from './continuous';
|
|
3
|
+
import { clearRigidBody3DForces, integrateRigidBody3DPose, integrateRigidBody3DVelocity, refreshRigidBody3DWorldInertia, } from './integrate';
|
|
4
|
+
import { buildPhysics3DSolveIslands, updatePhysics3DSleep } from './islands';
|
|
5
|
+
import { evaluatePhysics3DJointBreakage } from './jointBreakage';
|
|
6
|
+
import { steppingPhysics3DWorlds } from './ownership';
|
|
7
|
+
import { preparePhysics3DContactConstraints, solvePhysics3DContactPositions, solvePhysics3DContactVelocities, warmStartPhysics3DContacts, } from './solver';
|
|
8
|
+
import { isPhysics3DBodyStateValid, isPhysics3DColliderStateValid, isPhysics3DContactStateValid, isPhysics3DContactValid, isPhysics3DGravityValid, isPhysics3DJointStateValid, isPhysics3DPositionIterationsValid, isPhysics3DSolverConfigValid, isPhysics3DSubstepsValid, isPhysics3DTimestepValid, isPhysics3DVelocityIterationsValid, } from './stepValidation';
|
|
9
|
+
// Installs the optional diagnostics seam consulted when a step declines its preconditions. Null by
|
|
10
|
+
// default and set only by `enablePhysics3DGuards`, so a build that never enables guards links neither the
|
|
11
|
+
// message text nor `@flighthq/log`.
|
|
12
|
+
export function setPhysics3DStepGuard(guard) {
|
|
13
|
+
physics3DStepGuard = guard;
|
|
14
|
+
}
|
|
15
|
+
// Advances the simulation by `dt` seconds. Everything the step does, it does because the caller asked:
|
|
16
|
+
// no implicit accumulation, no fixed-timestep loop hidden inside, and no allocation once the world's
|
|
17
|
+
// bodies, contacts, and joints exist.
|
|
18
|
+
//
|
|
19
|
+
// It declines SILENTLY on any failed precondition rather than throwing, because a NaN velocity or a zero
|
|
20
|
+
// timestep is a state a caller reaches by writing a field, and a throw from inside the step would take
|
|
21
|
+
// down a frame loop for something the caller can inspect and repair. `explainPhysics3DStep` is how a
|
|
22
|
+
// caller finds out which precondition failed, and it is separately importable so a shipping build that
|
|
23
|
+
// never asks never links it.
|
|
24
|
+
//
|
|
25
|
+
// Recursion IS a throw, because it is API misuse rather than data: reaching this from inside a contact
|
|
26
|
+
// hook would run a whole nested step against the arrays the outer one is midway through.
|
|
27
|
+
export function stepPhysics3D(world, dt) {
|
|
28
|
+
if (steppingPhysics3DWorlds.has(world)) {
|
|
29
|
+
throw new Error('Cannot step a physics world recursively');
|
|
30
|
+
}
|
|
31
|
+
const config = world.config;
|
|
32
|
+
if (!isPhysics3DTimestepValid(dt) ||
|
|
33
|
+
!isPhysics3DSubstepsValid(config) ||
|
|
34
|
+
!isPhysics3DVelocityIterationsValid(config) ||
|
|
35
|
+
!isPhysics3DPositionIterationsValid(config) ||
|
|
36
|
+
!isPhysics3DSolverConfigValid(config) ||
|
|
37
|
+
!isPhysics3DGravityValid(world) ||
|
|
38
|
+
!isPhysics3DBodyStateValid(world) ||
|
|
39
|
+
!isPhysics3DColliderStateValid(world) ||
|
|
40
|
+
!isPhysics3DContactStateValid(world) ||
|
|
41
|
+
!isPhysics3DJointStateValid(world)) {
|
|
42
|
+
// The one place the silent decline is observable from outside. The seam takes the world and the
|
|
43
|
+
// timestep rather than a reason, so the guard asks `explainPhysics3DStep` for ALL of them — a world
|
|
44
|
+
// with two faults reported one at a time would be repaired one frame at a time.
|
|
45
|
+
physics3DStepGuard?.(world, dt);
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
// The flag is set and cleared in exactly one place, whatever the body does or throws. It is what makes
|
|
49
|
+
// every world lifecycle and joint lifecycle helper reject a call from inside a contact hook: the hook's
|
|
50
|
+
// sole mutation surface is the contact fields its contract names.
|
|
51
|
+
steppingPhysics3DWorlds.add(world);
|
|
52
|
+
try {
|
|
53
|
+
stepValidatedPhysics3D(world, dt);
|
|
54
|
+
}
|
|
55
|
+
finally {
|
|
56
|
+
steppingPhysics3DWorlds.delete(world);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
// One sub-interval of a step: integrate velocities, solve the constraints, integrate poses, repair
|
|
60
|
+
// penetration.
|
|
61
|
+
//
|
|
62
|
+
// Exported because the solver ruling requires the step to ship as a composition of named functions rather
|
|
63
|
+
// than a monolith. A caller assembling its own loop wants exactly this piece, and a second solver would
|
|
64
|
+
// replace this while `stepPhysics3D` above it stays as it is.
|
|
65
|
+
//
|
|
66
|
+
// The substep loop is the OUTER loop, which is the whole reason this is a separate function. A solver
|
|
67
|
+
// that integrates once and then iterates cannot be turned into one that substeps without restructuring
|
|
68
|
+
// everything that reads the step, so the shape is reserved from the first release even at `substeps: 1`.
|
|
69
|
+
//
|
|
70
|
+
// The ordering is not arbitrary, and one piece of it is a trap. `refreshRigidBody3DWorldInertia` runs at
|
|
71
|
+
// the TOP, before the velocity integration reads the world tensor, and AGAIN once the poses have moved,
|
|
72
|
+
// before the position pass reads it. Integrating angular velocity against the previous sub-interval's
|
|
73
|
+
// world tensor is wrong in a way that shows only on a rotating asymmetric body — a slow, plausible
|
|
74
|
+
// precession no single-step assertion catches.
|
|
75
|
+
export function stepPhysics3DInterval(world, dt) {
|
|
76
|
+
const sequential = world.config.sequentialImpulse;
|
|
77
|
+
forEachSolveIslandBody(world, refreshRigidBody3DWorldInertia);
|
|
78
|
+
forEachSolveIslandBody(world, (body) => integrateRigidBody3DVelocity(body, world.gravityX, world.gravityY, world.gravityZ, dt));
|
|
79
|
+
preparePhysics3DContactConstraints(world);
|
|
80
|
+
forEachSolveIslandJoint(world, (joint, solver) => solver.prepare(world, joint, dt));
|
|
81
|
+
if (sequential.warmStarting) {
|
|
82
|
+
warmStartPhysics3DContacts(world);
|
|
83
|
+
// Warm starting is a per-KIND capability as well as a per-world preference. A kind that declares no
|
|
84
|
+
// `warmStart` never reapplies its accumulator, so that accumulator has to be cleared even while the
|
|
85
|
+
// world IS warm starting — an impulse that is never reapplied must be cleared, or it is neither warm
|
|
86
|
+
// nor cold, and it grows without ever acting.
|
|
87
|
+
forEachSolveIslandJoint(world, (joint, solver) => {
|
|
88
|
+
if (solver.warmStart !== undefined)
|
|
89
|
+
solver.warmStart(world, joint);
|
|
90
|
+
else
|
|
91
|
+
clearJointAccumulators(joint, solver);
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
// Contacts need no clearing here: `preparePhysics3DContactConstraints` carries an accumulator across
|
|
96
|
+
// only when the flag is set, so the constraint it just built is already cold.
|
|
97
|
+
forEachSolveIslandJoint(world, clearJointAccumulators);
|
|
98
|
+
}
|
|
99
|
+
// Joints and contacts share one iteration count and one interleaved pass. Solving them in separate
|
|
100
|
+
// passes would let each undo the other's correction — a hinge under load creeps if the contacts beneath
|
|
101
|
+
// it get a whole pass to themselves between joint iterations.
|
|
102
|
+
for (let iteration = 0; iteration < sequential.velocityIterations; iteration += 1) {
|
|
103
|
+
forEachSolveIslandJoint(world, (joint, solver) => solver.solve(world, joint, dt));
|
|
104
|
+
solvePhysics3DContactVelocities(world);
|
|
105
|
+
}
|
|
106
|
+
evaluatePhysics3DJointBreakage(world, dt);
|
|
107
|
+
forEachSolveIslandPose(world, dt);
|
|
108
|
+
for (let iteration = 0; iteration < sequential.positionIterations; iteration += 1) {
|
|
109
|
+
solvePhysics3DContactPositions(world);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
function clearJointAccumulators(joint, solver) {
|
|
113
|
+
solver.clearAccumulatedImpulses?.(joint);
|
|
114
|
+
joint.impulse0 = 0;
|
|
115
|
+
joint.impulse1 = 0;
|
|
116
|
+
joint.impulse2 = 0;
|
|
117
|
+
joint.impulse3 = 0;
|
|
118
|
+
joint.impulse4 = 0;
|
|
119
|
+
joint.impulse5 = 0;
|
|
120
|
+
}
|
|
121
|
+
// Visits every body the solve islands admit, in island-major order.
|
|
122
|
+
//
|
|
123
|
+
// The workspace holds only awake, non-static bodies, so this is also the sleeping skip — and the skip is
|
|
124
|
+
// a COST saving rather than a behavioural one, which is worth having in writing: a sleeping body's
|
|
125
|
+
// velocity is zeroed when it falls asleep and nothing can hand it more, because any awake neighbour puts
|
|
126
|
+
// it in an awake island before this point. What the skip buys is that a settled thousand-body pile costs
|
|
127
|
+
// no integration at all, which is the entire reason sleep exists.
|
|
128
|
+
function forEachSolveIslandBody(world, visit) {
|
|
129
|
+
for (let island = 0; island < world.solveIslandRoots.length; island += 1) {
|
|
130
|
+
const start = world.solveIslandBodyStarts[island];
|
|
131
|
+
const end = start + world.solveIslandBodyCounts[island];
|
|
132
|
+
for (let at = start; at < end; at += 1)
|
|
133
|
+
visit(world.bodies[world.solveIslandBodyIndices[at]]);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
// Visits every joint the solve islands admit, paired with its registered solver. The workspace already
|
|
137
|
+
// excluded unregistered kinds and sleeping islands, so the callback never has to ask again.
|
|
138
|
+
function forEachSolveIslandJoint(world, visit) {
|
|
139
|
+
for (let island = 0; island < world.solveIslandRoots.length; island += 1) {
|
|
140
|
+
const start = world.solveIslandJointStarts[island];
|
|
141
|
+
const end = start + world.solveIslandJointCounts[island];
|
|
142
|
+
for (let at = start; at < end; at += 1) {
|
|
143
|
+
const joint = world.joints[world.solveIslandJointIndices[at]];
|
|
144
|
+
const solver = world.jointSolvers.get(joint.kind);
|
|
145
|
+
if (solver !== undefined)
|
|
146
|
+
visit(joint, solver);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
// Moves every awake body by its solved velocity, then refreshes the world inertia the position pass is
|
|
151
|
+
// about to read. Two passes rather than one, because a body's pose must not move between another body's
|
|
152
|
+
// integration and its own: a single fused loop would have the second body's constraint arms measured
|
|
153
|
+
// against a world the first body had already left.
|
|
154
|
+
//
|
|
155
|
+
// Routes through the CONTINUOUS path when the world asks for it and some body is actually flagged. That
|
|
156
|
+
// path integrates in chronological order of impact instead of in one jump, which is the only way a body
|
|
157
|
+
// fast enough to cross a wall within the interval generates a contact at all. It is checked here rather
|
|
158
|
+
// than inside the continuous pass so a world with the config on and no bullets pays one scan of the body
|
|
159
|
+
// list rather than a swept broadphase.
|
|
160
|
+
function forEachSolveIslandPose(world, dt) {
|
|
161
|
+
if (world.config.continuousCollision && hasActivePhysics3DBullet(world)) {
|
|
162
|
+
integratePhysics3DContinuous(world, dt);
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
forEachSolveIslandBody(world, (body) => integrateRigidBody3DPose(body, dt));
|
|
166
|
+
forEachSolveIslandBody(world, refreshRigidBody3DWorldInertia);
|
|
167
|
+
}
|
|
168
|
+
function restoreContactHookFields(contact, friction, restitution, enabled, sensor) {
|
|
169
|
+
contact.friction = friction;
|
|
170
|
+
contact.restitution = restitution;
|
|
171
|
+
contact.enabled = enabled;
|
|
172
|
+
contact.sensor = sensor;
|
|
173
|
+
}
|
|
174
|
+
// Runs a contact hook over every resolvable contact, putting back the fields it may touch if it
|
|
175
|
+
// misbehaves.
|
|
176
|
+
//
|
|
177
|
+
// Sensors are skipped, because they produce no constraint to solve and there is nothing for a hook to
|
|
178
|
+
// adjust. A hook that throws, or that leaves a contact the step cannot use, has its four mutable fields
|
|
179
|
+
// restored before the failure propagates — otherwise a caller catching the error would resume against a
|
|
180
|
+
// world the hook half-edited.
|
|
181
|
+
function runPhysics3DContactHook(world, hook, phase) {
|
|
182
|
+
if (hook === null)
|
|
183
|
+
return;
|
|
184
|
+
for (let contactIndex = 0; contactIndex < world.contacts.length; contactIndex += 1) {
|
|
185
|
+
const contact = world.contacts[contactIndex];
|
|
186
|
+
if (contact.sensor)
|
|
187
|
+
continue;
|
|
188
|
+
const friction = contact.friction;
|
|
189
|
+
const restitution = contact.restitution;
|
|
190
|
+
const enabled = contact.enabled;
|
|
191
|
+
const sensor = contact.sensor;
|
|
192
|
+
try {
|
|
193
|
+
hook(world, contact);
|
|
194
|
+
}
|
|
195
|
+
catch (error) {
|
|
196
|
+
restoreContactHookFields(contact, friction, restitution, enabled, sensor);
|
|
197
|
+
throw error;
|
|
198
|
+
}
|
|
199
|
+
if (!isPhysics3DContactValid(contact)) {
|
|
200
|
+
restoreContactHookFields(contact, friction, restitution, enabled, sensor);
|
|
201
|
+
throw new Error(`Physics3D ${phase} hook produced invalid contact state`);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
// Expresses every cached impulse in the interval it is about to be reapplied over.
|
|
206
|
+
//
|
|
207
|
+
// An accumulated impulse has force-times-time units. Reusing one unchanged across a different interval
|
|
208
|
+
// applies the wrong force before the first iteration can correct it, which presents as a stack or a motor
|
|
209
|
+
// kicking whenever a frame changes cadence. The comparison is against the previous SUB-interval rather
|
|
210
|
+
// than the previous whole step, because a sub-interval's iterations are what built the cache — which is
|
|
211
|
+
// also why changing `substeps` between steps rescales correctly rather than silently by the wrong factor.
|
|
212
|
+
//
|
|
213
|
+
// A non-finite ratio clears the cache rather than seeding infinity from two otherwise-valid timesteps.
|
|
214
|
+
function scalePhysics3DWarmStartCaches(world, dt) {
|
|
215
|
+
const previous = world.previousTimestep;
|
|
216
|
+
if (!(previous > 0) || previous === dt)
|
|
217
|
+
return;
|
|
218
|
+
const divided = dt / previous;
|
|
219
|
+
const timestepRatio = Number.isFinite(divided) ? divided : 0;
|
|
220
|
+
for (let constraintIndex = 0; constraintIndex < world.solver.constraints.length; constraintIndex += 1) {
|
|
221
|
+
const constraint = world.solver.constraints[constraintIndex];
|
|
222
|
+
for (let i = 0; i < constraint.pointCount; i += 1) {
|
|
223
|
+
const point = constraint.points[i];
|
|
224
|
+
point.normalImpulse *= timestepRatio;
|
|
225
|
+
point.tangentImpulse0 *= timestepRatio;
|
|
226
|
+
point.tangentImpulse1 *= timestepRatio;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
for (let jointIndex = 0; jointIndex < world.joints.length; jointIndex += 1) {
|
|
230
|
+
const joint = world.joints[jointIndex];
|
|
231
|
+
joint.impulse0 *= timestepRatio;
|
|
232
|
+
joint.impulse1 *= timestepRatio;
|
|
233
|
+
joint.impulse2 *= timestepRatio;
|
|
234
|
+
joint.impulse3 *= timestepRatio;
|
|
235
|
+
joint.impulse4 *= timestepRatio;
|
|
236
|
+
joint.impulse5 *= timestepRatio;
|
|
237
|
+
world.jointSolvers.get(joint.kind)?.scaleAccumulatedImpulses?.(joint, timestepRatio);
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
// The body of one step whose preconditions already hold.
|
|
241
|
+
function stepValidatedPhysics3D(world, dt) {
|
|
242
|
+
const substepDt = dt / world.config.substeps;
|
|
243
|
+
// Break events are cleared once per STEP, not per sub-interval, so a joint that parted during the first
|
|
244
|
+
// substep is still reported after the last one. Clearing inside the substep loop would drop every break
|
|
245
|
+
// but the final sub-interval's, and would do it silently — the joint stays broken either way, so the
|
|
246
|
+
// simulation would look right and only the notification would go missing.
|
|
247
|
+
world.jointEvents.broke.length = 0;
|
|
248
|
+
// Contacts are generated FIRST, from the poses the previous step left behind. The pre-solve hook is
|
|
249
|
+
// one transaction per public step: it runs before any interval commits, so a throw cannot leave half a
|
|
250
|
+
// substepped frame behind. Later interval refreshes retain its four mutable fields.
|
|
251
|
+
buildPhysics3DContacts(world);
|
|
252
|
+
// Pre-solve runs before anything is scaled or prepared, so a hook that disables a contact for this step
|
|
253
|
+
// does so before the constraint that would have resolved it is built.
|
|
254
|
+
runPhysics3DContactHook(world, world.contactHooks.preSolve, 'pre-solve');
|
|
255
|
+
// Scale only after pre-solve succeeds. A callback may throw, and scaling first would leave the cache
|
|
256
|
+
// expressed in the new interval while `previousTimestep` still described the old one; a retry would
|
|
257
|
+
// then scale an already-scaled cache a second time.
|
|
258
|
+
scalePhysics3DWarmStartCaches(world, substepDt);
|
|
259
|
+
// Sleep TIME is advanced once per step; later refreshes pass zero merely to rebuild the constraint
|
|
260
|
+
// graph and wake a sleeper reached by a body during an earlier interval. This preserves the meaning of
|
|
261
|
+
// `timeToSleep` while making a newly connected island live in the interval that discovered it.
|
|
262
|
+
updatePhysics3DSleep(world, dt);
|
|
263
|
+
buildPhysics3DSolveIslands(world);
|
|
264
|
+
for (let substep = 0; substep < world.config.substeps; substep += 1) {
|
|
265
|
+
if (substep > 0) {
|
|
266
|
+
// A substep that only re-runs the solver against the outer step's original contact list is not a
|
|
267
|
+
// smaller timestep: bodies can cross into a collider in interval one and remain invisible through
|
|
268
|
+
// every interval after it. Refreshing here makes N substeps topologically equivalent to N calls at
|
|
269
|
+
// the sub-interval, while aggregating begin/end events across the one public call.
|
|
270
|
+
refreshPhysics3DContacts(world);
|
|
271
|
+
updatePhysics3DSleep(world, 0);
|
|
272
|
+
buildPhysics3DSolveIslands(world);
|
|
273
|
+
}
|
|
274
|
+
stepPhysics3DInterval(world, substepDt);
|
|
275
|
+
}
|
|
276
|
+
for (let bodyIndex = 0; bodyIndex < world.bodies.length; bodyIndex += 1) {
|
|
277
|
+
clearRigidBody3DForces(world.bodies[bodyIndex]);
|
|
278
|
+
}
|
|
279
|
+
// CCD contacts are appended at TOI so they cannot shift the contact indices held by constraints that
|
|
280
|
+
// were prepared earlier in the interval. Those indices have expired now, so restore the canonical
|
|
281
|
+
// identity order before publishing the committed world and invoking post-solve hooks. The active-
|
|
282
|
+
// bullet condition is the same condition that can enter the CCD path; sorting every ordinary settled
|
|
283
|
+
// contact here added an O(n log n) tax to worlds that could not possibly have appended anything.
|
|
284
|
+
if (world.config.continuousCollision && hasActivePhysics3DBullet(world)) {
|
|
285
|
+
world.contacts.sort(comparePhysics3DContactIdentity);
|
|
286
|
+
}
|
|
287
|
+
world.previousTimestep = substepDt;
|
|
288
|
+
// Post-solve observes a committed step. A hook that throws here cannot prevent pose integration, force
|
|
289
|
+
// cleanup, or the timestep agreement above, so the next call never resumes a half-finished step.
|
|
290
|
+
runPhysics3DContactHook(world, world.contactHooks.postSolve, 'post-solve');
|
|
291
|
+
}
|
|
292
|
+
function comparePhysics3DContactIdentity(left, right) {
|
|
293
|
+
if (left.bodyA !== right.bodyA)
|
|
294
|
+
return left.bodyA - right.bodyA;
|
|
295
|
+
if (left.bodyB !== right.bodyB)
|
|
296
|
+
return left.bodyB - right.bodyB;
|
|
297
|
+
if (left.colliderA !== right.colliderA)
|
|
298
|
+
return left.colliderA - right.colliderA;
|
|
299
|
+
return left.colliderB - right.colliderB;
|
|
300
|
+
}
|
|
301
|
+
let physics3DStepGuard = null;
|
|
302
|
+
//# sourceMappingURL=step.js.map
|
package/dist/step.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"step.js","sourceRoot":"","sources":["../src/step.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { Physics3DContact, Physics3DSolverConfig, Physics3DWorld } from '@flighthq/types/contract';
|
|
2
|
+
export declare function isPhysics3DBodyStateValid(world: Readonly<Physics3DWorld>): boolean;
|
|
3
|
+
export declare function isPhysics3DColliderStateValid(world: Readonly<Physics3DWorld>): boolean;
|
|
4
|
+
export declare function isPhysics3DContactStateValid(world: Readonly<Physics3DWorld>): boolean;
|
|
5
|
+
export declare function isPhysics3DContactValid(contact: Readonly<Physics3DContact>): boolean;
|
|
6
|
+
export declare function isPhysics3DGravityValid(world: Readonly<Physics3DWorld>): boolean;
|
|
7
|
+
export declare function isPhysics3DJointStateValid(world: Readonly<Physics3DWorld>): boolean;
|
|
8
|
+
export declare function isPhysics3DPositionIterationsValid(config: Readonly<Physics3DSolverConfig>): boolean;
|
|
9
|
+
export declare function isPhysics3DSolverConfigValid(config: Readonly<Physics3DSolverConfig>): boolean;
|
|
10
|
+
export declare function isPhysics3DSubstepsValid(config: Readonly<Physics3DSolverConfig>): boolean;
|
|
11
|
+
export declare function isPhysics3DTimestepValid(dt: number): boolean;
|
|
12
|
+
export declare function isPhysics3DVelocityIterationsValid(config: Readonly<Physics3DSolverConfig>): boolean;
|
|
13
|
+
//# sourceMappingURL=stepValidation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stepValidation.d.ts","sourceRoot":"","sources":["../src/stepValidation.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAEV,gBAAgB,EAEhB,qBAAqB,EACrB,cAAc,EAEf,MAAM,0BAA0B,CAAC;AAclC,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,QAAQ,CAAC,cAAc,CAAC,GAAG,OAAO,CAclF;AAQD,wBAAgB,6BAA6B,CAAC,KAAK,EAAE,QAAQ,CAAC,cAAc,CAAC,GAAG,OAAO,CAStF;AAED,wBAAgB,4BAA4B,CAAC,KAAK,EAAE,QAAQ,CAAC,cAAc,CAAC,GAAG,OAAO,CAKrF;AAID,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,QAAQ,CAAC,gBAAgB,CAAC,GAAG,OAAO,CA4CpF;AAED,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,QAAQ,CAAC,cAAc,CAAC,GAAG,OAAO,CAEhF;AAED,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,QAAQ,CAAC,cAAc,CAAC,GAAG,OAAO,CAKnF;AAED,wBAAgB,kCAAkC,CAAC,MAAM,EAAE,QAAQ,CAAC,qBAAqB,CAAC,GAAG,OAAO,CAGnG;AAKD,wBAAgB,4BAA4B,CAAC,MAAM,EAAE,QAAQ,CAAC,qBAAqB,CAAC,GAAG,OAAO,CAwB7F;AAID,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,QAAQ,CAAC,qBAAqB,CAAC,GAAG,OAAO,CAEzF;AAED,wBAAgB,wBAAwB,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAE5D;AAED,wBAAgB,kCAAkC,CAAC,MAAM,EAAE,QAAQ,CAAC,qBAAqB,CAAC,GAAG,OAAO,CAGnG"}
|
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
import { getCollisionHeightfieldValidationStatus3D, getCollisionShapeValidationStatus3D, getCollisionTriangleMeshValidationStatus3D, } from '@flighthq/collision/contract';
|
|
2
|
+
// The preconditions one explicit step needs to be meaningful, each asked as its own question.
|
|
3
|
+
//
|
|
4
|
+
// Separate predicates rather than one `canStep`, because they are the rows of `Physics3DStepExplanation`
|
|
5
|
+
// and a caller diagnosing a world that will not advance needs to know WHICH one failed. `stepPhysics3D`
|
|
6
|
+
// asks all of them and returns silently on any false; `explainPhysics3DStep` asks the same ones and
|
|
7
|
+
// reports. That is the diagnostics inversion — the step carries no messages, and the explain seam is
|
|
8
|
+
// separately importable so a shipping build that never asks never links it.
|
|
9
|
+
//
|
|
10
|
+
// A world that fails one of these is not an error to throw on: a NaN velocity, a zero timestep, or a
|
|
11
|
+
// negative iteration count is a state a caller can reach by writing a field, and a throw from inside the
|
|
12
|
+
// step would take down a frame loop for something the caller can inspect and repair.
|
|
13
|
+
export function isPhysics3DBodyStateValid(world) {
|
|
14
|
+
if (!Number.isSafeInteger(world.nextBodyIndex) || world.nextBodyIndex < 0)
|
|
15
|
+
return false;
|
|
16
|
+
for (let bodyIndex = 0; bodyIndex < world.bodies.length; bodyIndex += 1) {
|
|
17
|
+
const body = world.bodies[bodyIndex];
|
|
18
|
+
if (!isRigidBody3DStateValid(body) ||
|
|
19
|
+
!Array.isArray(body.colliders) ||
|
|
20
|
+
(body.type !== 'static' && body.colliders.some(isPhysics3DStaticSurfaceCollider)) ||
|
|
21
|
+
world.bodyByIndex.get(body.index) !== body) {
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
return true;
|
|
26
|
+
}
|
|
27
|
+
function isPhysics3DStaticSurfaceCollider(collider) {
|
|
28
|
+
return collider.local.kind === 'triangle-mesh' || collider.local.kind === 'heightfield';
|
|
29
|
+
}
|
|
30
|
+
// Validates the data that will generate NEW contacts during this step. Keeping this separate from body
|
|
31
|
+
// state is diagnostic: a NaN material is repaired at a collider, not in the body's pose or inertia.
|
|
32
|
+
export function isPhysics3DColliderStateValid(world) {
|
|
33
|
+
for (let bodyIndex = 0; bodyIndex < world.bodies.length; bodyIndex += 1) {
|
|
34
|
+
const body = world.bodies[bodyIndex];
|
|
35
|
+
if (!Array.isArray(body.colliders))
|
|
36
|
+
return false;
|
|
37
|
+
for (let colliderIndex = 0; colliderIndex < body.colliders.length; colliderIndex += 1) {
|
|
38
|
+
if (!isPhysics3DColliderValid(body.colliders[colliderIndex]))
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
return true;
|
|
43
|
+
}
|
|
44
|
+
export function isPhysics3DContactStateValid(world) {
|
|
45
|
+
for (let contactIndex = 0; contactIndex < world.contacts.length; contactIndex += 1) {
|
|
46
|
+
if (!isPhysics3DContactValid(world.contacts[contactIndex]))
|
|
47
|
+
return false;
|
|
48
|
+
}
|
|
49
|
+
return true;
|
|
50
|
+
}
|
|
51
|
+
// Also the post-hook check: a pre-solve or post-solve callback may write contact fields, and this is what
|
|
52
|
+
// says whether what it wrote is still steppable.
|
|
53
|
+
export function isPhysics3DContactValid(contact) {
|
|
54
|
+
if (!Number.isSafeInteger(contact.bodyA) ||
|
|
55
|
+
!Number.isSafeInteger(contact.bodyB) ||
|
|
56
|
+
!Number.isSafeInteger(contact.colliderA) ||
|
|
57
|
+
contact.colliderA < 0 ||
|
|
58
|
+
!Number.isSafeInteger(contact.colliderB) ||
|
|
59
|
+
contact.colliderB < 0 ||
|
|
60
|
+
!Number.isSafeInteger(contact.pointCount) ||
|
|
61
|
+
contact.pointCount < 0 ||
|
|
62
|
+
contact.pointCount > contact.points.length ||
|
|
63
|
+
!Number.isFinite(contact.normalX) ||
|
|
64
|
+
!Number.isFinite(contact.normalY) ||
|
|
65
|
+
!Number.isFinite(contact.normalZ) ||
|
|
66
|
+
!Number.isFinite(contact.friction) ||
|
|
67
|
+
contact.friction < 0 ||
|
|
68
|
+
!Number.isFinite(contact.restitution) ||
|
|
69
|
+
contact.restitution < 0 ||
|
|
70
|
+
typeof contact.enabled !== 'boolean' ||
|
|
71
|
+
typeof contact.sensor !== 'boolean' ||
|
|
72
|
+
typeof contact.touching !== 'boolean') {
|
|
73
|
+
return false;
|
|
74
|
+
}
|
|
75
|
+
for (let i = 0; i < contact.pointCount; i += 1) {
|
|
76
|
+
const point = contact.points[i];
|
|
77
|
+
if (point === undefined)
|
|
78
|
+
return false;
|
|
79
|
+
if (!Number.isFinite(point.x) ||
|
|
80
|
+
!Number.isFinite(point.y) ||
|
|
81
|
+
!Number.isFinite(point.z) ||
|
|
82
|
+
!Number.isFinite(point.depth) ||
|
|
83
|
+
!Number.isFinite(point.featureId) ||
|
|
84
|
+
!Number.isFinite(point.rAX) ||
|
|
85
|
+
!Number.isFinite(point.rAY) ||
|
|
86
|
+
!Number.isFinite(point.rAZ) ||
|
|
87
|
+
!Number.isFinite(point.rBX) ||
|
|
88
|
+
!Number.isFinite(point.rBY) ||
|
|
89
|
+
!Number.isFinite(point.rBZ)) {
|
|
90
|
+
return false;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
return true;
|
|
94
|
+
}
|
|
95
|
+
export function isPhysics3DGravityValid(world) {
|
|
96
|
+
return Number.isFinite(world.gravityX) && Number.isFinite(world.gravityY) && Number.isFinite(world.gravityZ);
|
|
97
|
+
}
|
|
98
|
+
export function isPhysics3DJointStateValid(world) {
|
|
99
|
+
for (let jointIndex = 0; jointIndex < world.joints.length; jointIndex += 1) {
|
|
100
|
+
if (!isPhysics3DJointValid(world.joints[jointIndex]))
|
|
101
|
+
return false;
|
|
102
|
+
}
|
|
103
|
+
return true;
|
|
104
|
+
}
|
|
105
|
+
export function isPhysics3DPositionIterationsValid(config) {
|
|
106
|
+
const iterations = config.sequentialImpulse.positionIterations;
|
|
107
|
+
return Number.isSafeInteger(iterations) && iterations >= 0;
|
|
108
|
+
}
|
|
109
|
+
// The solver-independent knobs plus the sequential-impulse block. Iteration counts and `substeps` are
|
|
110
|
+
// asked separately, because they are the three a caller is most likely to have tuned by hand and the
|
|
111
|
+
// explanation names each of them.
|
|
112
|
+
export function isPhysics3DSolverConfigValid(config) {
|
|
113
|
+
const sequential = config.sequentialImpulse;
|
|
114
|
+
return (typeof config.allowSleeping === 'boolean' &&
|
|
115
|
+
Number.isFinite(config.sleepLinearThreshold) &&
|
|
116
|
+
config.sleepLinearThreshold >= 0 &&
|
|
117
|
+
Number.isFinite(config.sleepAngularThreshold) &&
|
|
118
|
+
config.sleepAngularThreshold >= 0 &&
|
|
119
|
+
Number.isFinite(config.timeToSleep) &&
|
|
120
|
+
config.timeToSleep >= 0 &&
|
|
121
|
+
typeof config.continuousCollision === 'boolean' &&
|
|
122
|
+
Number.isSafeInteger(config.maxCcdSubsteps) &&
|
|
123
|
+
config.maxCcdSubsteps >= 0 &&
|
|
124
|
+
Number.isSafeInteger(config.maxCcdRotationSubsteps) &&
|
|
125
|
+
config.maxCcdRotationSubsteps >= 0 &&
|
|
126
|
+
Number.isFinite(sequential.penetrationSlop) &&
|
|
127
|
+
sequential.penetrationSlop >= 0 &&
|
|
128
|
+
Number.isFinite(sequential.positionCorrection) &&
|
|
129
|
+
sequential.positionCorrection >= 0 &&
|
|
130
|
+
sequential.positionCorrection <= 1 &&
|
|
131
|
+
Number.isFinite(sequential.restitutionThreshold) &&
|
|
132
|
+
sequential.restitutionThreshold >= 0 &&
|
|
133
|
+
typeof sequential.warmStarting === 'boolean');
|
|
134
|
+
}
|
|
135
|
+
// At least one, because `substeps` divides the timestep and the step runs the loop that many times. Zero
|
|
136
|
+
// would advance nothing while reporting a completed step, which is worse than declining to step at all.
|
|
137
|
+
export function isPhysics3DSubstepsValid(config) {
|
|
138
|
+
return Number.isSafeInteger(config.substeps) && config.substeps >= 1;
|
|
139
|
+
}
|
|
140
|
+
export function isPhysics3DTimestepValid(dt) {
|
|
141
|
+
return Number.isFinite(dt) && dt > 0;
|
|
142
|
+
}
|
|
143
|
+
export function isPhysics3DVelocityIterationsValid(config) {
|
|
144
|
+
const iterations = config.sequentialImpulse.velocityIterations;
|
|
145
|
+
return Number.isSafeInteger(iterations) && iterations >= 0;
|
|
146
|
+
}
|
|
147
|
+
function isPhysics3DJointValid(joint) {
|
|
148
|
+
if (typeof joint.kind !== 'string' ||
|
|
149
|
+
joint.kind.length === 0 ||
|
|
150
|
+
!Number.isSafeInteger(joint.bodyA) ||
|
|
151
|
+
!Number.isSafeInteger(joint.bodyB) ||
|
|
152
|
+
typeof joint.collideConnected !== 'boolean') {
|
|
153
|
+
return false;
|
|
154
|
+
}
|
|
155
|
+
// Every numeric field, whatever the kind added — a limit, a motor speed, a frame component. Walking the
|
|
156
|
+
// object rather than a fixed key list is what makes this cover a user's own joint kind, which is the
|
|
157
|
+
// point of an open registry.
|
|
158
|
+
//
|
|
159
|
+
// Except the fields where INFINITY IS THE VALUE, not a symptom. A `breakForce` of infinity is a joint
|
|
160
|
+
// that never breaks and a `maxLength` of infinity is a rope with no far stop, and both are the natural
|
|
161
|
+
// defaults — so a blanket finiteness walk declares every ordinary joint invalid and the world declines
|
|
162
|
+
// to step at all. That failure is silent by design (an invalid step is skipped, not thrown), so it
|
|
163
|
+
// presents as a motor that does not turn and contacts that never fire, with nothing pointing at the
|
|
164
|
+
// joint. Adding a field whose unset state is "no bound" means adding it here too.
|
|
165
|
+
for (const key in joint) {
|
|
166
|
+
if (UNBOUNDED_JOINT_FIELDS.has(key))
|
|
167
|
+
continue;
|
|
168
|
+
const value = joint[key];
|
|
169
|
+
if (typeof value === 'number' && !Number.isFinite(value))
|
|
170
|
+
return false;
|
|
171
|
+
}
|
|
172
|
+
return true;
|
|
173
|
+
}
|
|
174
|
+
function isRigidBody3DStateValid(body) {
|
|
175
|
+
const orientationLengthSquared = body.orientationX * body.orientationX +
|
|
176
|
+
body.orientationY * body.orientationY +
|
|
177
|
+
body.orientationZ * body.orientationZ +
|
|
178
|
+
body.orientationW * body.orientationW;
|
|
179
|
+
if (!Number.isSafeInteger(body.index) ||
|
|
180
|
+
body.index < 0 ||
|
|
181
|
+
(body.type !== 'dynamic' && body.type !== 'kinematic' && body.type !== 'static') ||
|
|
182
|
+
typeof body.fixedRotation !== 'boolean' ||
|
|
183
|
+
typeof body.bullet !== 'boolean' ||
|
|
184
|
+
typeof body.sleeping !== 'boolean' ||
|
|
185
|
+
typeof body.sleepEnabled !== 'boolean' ||
|
|
186
|
+
!Number.isFinite(body.sleepTimer) ||
|
|
187
|
+
body.sleepTimer < 0 ||
|
|
188
|
+
!Number.isFinite(body.linearDamping) ||
|
|
189
|
+
body.linearDamping < 0 ||
|
|
190
|
+
!Number.isFinite(body.angularDamping) ||
|
|
191
|
+
body.angularDamping < 0 ||
|
|
192
|
+
!Number.isFinite(body.gravityScale) ||
|
|
193
|
+
!Number.isFinite(body.mass) ||
|
|
194
|
+
body.mass < 0 ||
|
|
195
|
+
!Number.isFinite(body.inverseMass) ||
|
|
196
|
+
body.inverseMass < 0 ||
|
|
197
|
+
!Number.isFinite(orientationLengthSquared) ||
|
|
198
|
+
Math.abs(orientationLengthSquared - 1) > PHYSICS3D_QUATERNION_LENGTH_TOLERANCE) {
|
|
199
|
+
return false;
|
|
200
|
+
}
|
|
201
|
+
for (let keyIndex = 0; keyIndex < rigidBody3DFiniteKeys.length; keyIndex += 1) {
|
|
202
|
+
if (!Number.isFinite(body[rigidBody3DFiniteKeys[keyIndex]]))
|
|
203
|
+
return false;
|
|
204
|
+
}
|
|
205
|
+
return true;
|
|
206
|
+
}
|
|
207
|
+
function isPhysics3DColliderValid(collider) {
|
|
208
|
+
const material = collider.material;
|
|
209
|
+
const filter = collider.filter;
|
|
210
|
+
return (getPhysics3DColliderShapeValidationStatus(collider.local) === null &&
|
|
211
|
+
getPhysics3DColliderShapeValidationStatus(collider.world) === null &&
|
|
212
|
+
isPhysics3DColliderWorldShapeCompatible(collider) &&
|
|
213
|
+
Number.isFinite(material.density) &&
|
|
214
|
+
material.density >= 0 &&
|
|
215
|
+
Number.isFinite(material.friction) &&
|
|
216
|
+
material.friction >= 0 &&
|
|
217
|
+
Number.isFinite(material.restitution) &&
|
|
218
|
+
material.restitution >= 0 &&
|
|
219
|
+
Number.isSafeInteger(filter.categoryBits) &&
|
|
220
|
+
Number.isSafeInteger(filter.maskBits) &&
|
|
221
|
+
Number.isSafeInteger(filter.groupIndex) &&
|
|
222
|
+
typeof collider.sensor === 'boolean');
|
|
223
|
+
}
|
|
224
|
+
function getPhysics3DColliderShapeValidationStatus(shape) {
|
|
225
|
+
if (shape.kind === 'triangle-mesh')
|
|
226
|
+
return getCollisionTriangleMeshValidationStatus3D(shape);
|
|
227
|
+
if (shape.kind === 'heightfield')
|
|
228
|
+
return getCollisionHeightfieldValidationStatus3D(shape);
|
|
229
|
+
return getCollisionShapeValidationStatus3D(shape);
|
|
230
|
+
}
|
|
231
|
+
function isPhysics3DColliderWorldShapeCompatible(collider) {
|
|
232
|
+
return collider.world.kind === (collider.local.kind === 'aabb' ? 'box' : collider.local.kind);
|
|
233
|
+
}
|
|
234
|
+
// Every field that has to be a real number for the step to mean anything: the pose, the velocities, the
|
|
235
|
+
// accumulators, the centre of mass, and all three inertia tensors. The world tensor is derived and is
|
|
236
|
+
// included anyway — it is what every constraint row multiplies by, so a NaN there reaches both bodies of
|
|
237
|
+
// every contact and joint within one substep.
|
|
238
|
+
const rigidBody3DFiniteKeys = [
|
|
239
|
+
'x',
|
|
240
|
+
'y',
|
|
241
|
+
'z',
|
|
242
|
+
'orientationX',
|
|
243
|
+
'orientationY',
|
|
244
|
+
'orientationZ',
|
|
245
|
+
'orientationW',
|
|
246
|
+
'velocityX',
|
|
247
|
+
'velocityY',
|
|
248
|
+
'velocityZ',
|
|
249
|
+
'angularVelocityX',
|
|
250
|
+
'angularVelocityY',
|
|
251
|
+
'angularVelocityZ',
|
|
252
|
+
'forceX',
|
|
253
|
+
'forceY',
|
|
254
|
+
'forceZ',
|
|
255
|
+
'torqueX',
|
|
256
|
+
'torqueY',
|
|
257
|
+
'torqueZ',
|
|
258
|
+
'centerX',
|
|
259
|
+
'centerY',
|
|
260
|
+
'centerZ',
|
|
261
|
+
'inertiaXX',
|
|
262
|
+
'inertiaYY',
|
|
263
|
+
'inertiaZZ',
|
|
264
|
+
'inertiaXY',
|
|
265
|
+
'inertiaXZ',
|
|
266
|
+
'inertiaYZ',
|
|
267
|
+
'inverseInertiaXX',
|
|
268
|
+
'inverseInertiaYY',
|
|
269
|
+
'inverseInertiaZZ',
|
|
270
|
+
'inverseInertiaXY',
|
|
271
|
+
'inverseInertiaXZ',
|
|
272
|
+
'inverseInertiaYZ',
|
|
273
|
+
'inverseInertiaWorldXX',
|
|
274
|
+
'inverseInertiaWorldYY',
|
|
275
|
+
'inverseInertiaWorldZZ',
|
|
276
|
+
'inverseInertiaWorldXY',
|
|
277
|
+
'inverseInertiaWorldXZ',
|
|
278
|
+
'inverseInertiaWorldYZ',
|
|
279
|
+
];
|
|
280
|
+
// Joint fields whose infinite value is meaningful rather than corrupt: a threshold that is never reached
|
|
281
|
+
// and a bound that never stops anything.
|
|
282
|
+
const UNBOUNDED_JOINT_FIELDS = new Set(['breakForce', 'breakTorque', 'maxLength']);
|
|
283
|
+
const PHYSICS3D_QUATERNION_LENGTH_TOLERANCE = 1e-6;
|
|
284
|
+
//# sourceMappingURL=stepValidation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stepValidation.js","sourceRoot":"","sources":["../src/stepValidation.ts"],"names":[],"mappings":"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"}
|