@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.
Files changed (180) hide show
  1. package/dist/broadphase.d.ts +4 -0
  2. package/dist/broadphase.d.ts.map +1 -0
  3. package/dist/broadphase.js +158 -0
  4. package/dist/broadphase.js.map +1 -0
  5. package/dist/colliderCollision.d.ts +5 -0
  6. package/dist/colliderCollision.d.ts.map +1 -0
  7. package/dist/colliderCollision.js +55 -0
  8. package/dist/colliderCollision.js.map +1 -0
  9. package/dist/colliderTransform.d.ts +5 -0
  10. package/dist/colliderTransform.d.ts.map +1 -0
  11. package/dist/colliderTransform.js +424 -0
  12. package/dist/colliderTransform.js.map +1 -0
  13. package/dist/contactIntake.d.ts +5 -0
  14. package/dist/contactIntake.d.ts.map +1 -0
  15. package/dist/contactIntake.js +237 -0
  16. package/dist/contactIntake.js.map +1 -0
  17. package/dist/contacts.d.ts +4 -0
  18. package/dist/contacts.d.ts.map +1 -0
  19. package/dist/contacts.js +64 -0
  20. package/dist/contacts.js.map +1 -0
  21. package/dist/continuous.d.ts +5 -0
  22. package/dist/continuous.d.ts.map +1 -0
  23. package/dist/continuous.js +829 -0
  24. package/dist/continuous.js.map +1 -0
  25. package/dist/contract.d.ts +28 -0
  26. package/dist/contract.d.ts.map +1 -0
  27. package/dist/contract.js +28 -0
  28. package/dist/contract.js.map +1 -0
  29. package/dist/debugGeometry.d.ts +4 -0
  30. package/dist/debugGeometry.d.ts.map +1 -0
  31. package/dist/debugGeometry.js +333 -0
  32. package/dist/debugGeometry.js.map +1 -0
  33. package/dist/enablePhysics3DGuards.d.ts +4 -0
  34. package/dist/enablePhysics3DGuards.d.ts.map +1 -0
  35. package/dist/enablePhysics3DGuards.js +155 -0
  36. package/dist/enablePhysics3DGuards.js.map +1 -0
  37. package/dist/explainPhysics3DCollision.d.ts +3 -0
  38. package/dist/explainPhysics3DCollision.d.ts.map +1 -0
  39. package/dist/explainPhysics3DCollision.js +30 -0
  40. package/dist/explainPhysics3DCollision.js.map +1 -0
  41. package/dist/explainPhysics3DJoints.d.ts +3 -0
  42. package/dist/explainPhysics3DJoints.d.ts.map +1 -0
  43. package/dist/explainPhysics3DJoints.js +32 -0
  44. package/dist/explainPhysics3DJoints.js.map +1 -0
  45. package/dist/explainPhysics3DStep.d.ts +3 -0
  46. package/dist/explainPhysics3DStep.d.ts.map +1 -0
  47. package/dist/explainPhysics3DStep.js +51 -0
  48. package/dist/explainPhysics3DStep.js.map +1 -0
  49. package/dist/index.d.ts +22 -0
  50. package/dist/index.d.ts.map +1 -0
  51. package/dist/index.js +22 -0
  52. package/dist/index.js.map +1 -0
  53. package/dist/integrate.d.ts +6 -0
  54. package/dist/integrate.d.ts.map +1 -0
  55. package/dist/integrate.js +184 -0
  56. package/dist/integrate.js.map +1 -0
  57. package/dist/islands.d.ts +6 -0
  58. package/dist/islands.d.ts.map +1 -0
  59. package/dist/islands.js +333 -0
  60. package/dist/islands.js.map +1 -0
  61. package/dist/jointBreakage.d.ts +5 -0
  62. package/dist/jointBreakage.d.ts.map +1 -0
  63. package/dist/jointBreakage.js +44 -0
  64. package/dist/jointBreakage.js.map +1 -0
  65. package/dist/jointCollisionSuppression.d.ts +4 -0
  66. package/dist/jointCollisionSuppression.d.ts.map +1 -0
  67. package/dist/jointCollisionSuppression.js +40 -0
  68. package/dist/jointCollisionSuppression.js.map +1 -0
  69. package/dist/jointFactories.d.ts +9 -0
  70. package/dist/jointFactories.d.ts.map +1 -0
  71. package/dist/jointFactories.js +159 -0
  72. package/dist/jointFactories.js.map +1 -0
  73. package/dist/jointMath.d.ts +17 -0
  74. package/dist/jointMath.d.ts.map +1 -0
  75. package/dist/jointMath.js +361 -0
  76. package/dist/jointMath.js.map +1 -0
  77. package/dist/jointReaction.d.ts +8 -0
  78. package/dist/jointReaction.d.ts.map +1 -0
  79. package/dist/jointReaction.js +65 -0
  80. package/dist/jointReaction.js.map +1 -0
  81. package/dist/jointRegistry.d.ts +8 -0
  82. package/dist/jointRegistry.d.ts.map +1 -0
  83. package/dist/jointRegistry.js +144 -0
  84. package/dist/jointRegistry.js.map +1 -0
  85. package/dist/jointRows.d.ts +33 -0
  86. package/dist/jointRows.d.ts.map +1 -0
  87. package/dist/jointRows.js +352 -0
  88. package/dist/jointRows.js.map +1 -0
  89. package/dist/joints.d.ts +16 -0
  90. package/dist/joints.d.ts.map +1 -0
  91. package/dist/joints.js +1060 -0
  92. package/dist/joints.js.map +1 -0
  93. package/dist/massProperties.d.ts +13 -0
  94. package/dist/massProperties.d.ts.map +1 -0
  95. package/dist/massProperties.js +462 -0
  96. package/dist/massProperties.js.map +1 -0
  97. package/dist/material.d.ts +3 -0
  98. package/dist/material.d.ts.map +1 -0
  99. package/dist/material.js +13 -0
  100. package/dist/material.js.map +1 -0
  101. package/dist/nodeSync.d.ts +3 -0
  102. package/dist/nodeSync.d.ts.map +1 -0
  103. package/dist/nodeSync.js +16 -0
  104. package/dist/nodeSync.js.map +1 -0
  105. package/dist/ownership.d.ts +8 -0
  106. package/dist/ownership.d.ts.map +1 -0
  107. package/dist/ownership.js +26 -0
  108. package/dist/ownership.js.map +1 -0
  109. package/dist/physics3DBroadphasePublication.d.ts +5 -0
  110. package/dist/physics3DBroadphasePublication.d.ts.map +1 -0
  111. package/dist/physics3DBroadphasePublication.js +49 -0
  112. package/dist/physics3DBroadphasePublication.js.map +1 -0
  113. package/dist/physics3DSpatialIndexingGuards.d.ts +4 -0
  114. package/dist/physics3DSpatialIndexingGuards.d.ts.map +1 -0
  115. package/dist/physics3DSpatialIndexingGuards.js +11 -0
  116. package/dist/physics3DSpatialIndexingGuards.js.map +1 -0
  117. package/dist/registerBuiltInPhysics3DJointSolvers.d.ts +3 -0
  118. package/dist/registerBuiltInPhysics3DJointSolvers.d.ts.map +1 -0
  119. package/dist/registerBuiltInPhysics3DJointSolvers.js +15 -0
  120. package/dist/registerBuiltInPhysics3DJointSolvers.js.map +1 -0
  121. package/dist/solver.d.ts +8 -0
  122. package/dist/solver.d.ts.map +1 -0
  123. package/dist/solver.js +460 -0
  124. package/dist/solver.js.map +1 -0
  125. package/dist/step.d.ts +5 -0
  126. package/dist/step.d.ts.map +1 -0
  127. package/dist/step.js +302 -0
  128. package/dist/step.js.map +1 -0
  129. package/dist/stepValidation.d.ts +13 -0
  130. package/dist/stepValidation.d.ts.map +1 -0
  131. package/dist/stepValidation.js +284 -0
  132. package/dist/stepValidation.js.map +1 -0
  133. package/dist/symmetricTensor.d.ts +11 -0
  134. package/dist/symmetricTensor.d.ts.map +1 -0
  135. package/dist/symmetricTensor.js +150 -0
  136. package/dist/symmetricTensor.js.map +1 -0
  137. package/dist/world.d.ts +27 -0
  138. package/dist/world.d.ts.map +1 -0
  139. package/dist/world.js +762 -0
  140. package/dist/world.js.map +1 -0
  141. package/dist/worldQueries.d.ts +11 -0
  142. package/dist/worldQueries.d.ts.map +1 -0
  143. package/dist/worldQueries.js +409 -0
  144. package/dist/worldQueries.js.map +1 -0
  145. package/package.json +55 -0
  146. package/src/broadphase.test.ts +265 -0
  147. package/src/colliderCollision.test.ts +57 -0
  148. package/src/colliderTransform.test.ts +221 -0
  149. package/src/contactIntake.test.ts +370 -0
  150. package/src/contacts.test.ts +64 -0
  151. package/src/continuous.test.ts +679 -0
  152. package/src/debugGeometry.test.ts +288 -0
  153. package/src/enablePhysics3DGuards.test.ts +206 -0
  154. package/src/explainPhysics3DCollision.test.ts +78 -0
  155. package/src/explainPhysics3DJoints.test.ts +101 -0
  156. package/src/explainPhysics3DStep.test.ts +142 -0
  157. package/src/integrate.test.ts +279 -0
  158. package/src/islands.test.ts +384 -0
  159. package/src/jointBreakage.test.ts +143 -0
  160. package/src/jointCollisionSuppression.test.ts +94 -0
  161. package/src/jointFactories.test.ts +244 -0
  162. package/src/jointMath.test.ts +646 -0
  163. package/src/jointReaction.test.ts +241 -0
  164. package/src/jointRegistry.test.ts +229 -0
  165. package/src/jointRows.test.ts +548 -0
  166. package/src/joints.test.ts +1066 -0
  167. package/src/massProperties.test.ts +611 -0
  168. package/src/material.test.ts +40 -0
  169. package/src/nodeSync.test.ts +50 -0
  170. package/src/ownership.test.ts +61 -0
  171. package/src/physics3DBroadphasePublication.test.ts +63 -0
  172. package/src/physics3DSpatialIndexingGuards.test.ts +43 -0
  173. package/src/registerBuiltInPhysics3DJointSolvers.test.ts +51 -0
  174. package/src/solver.test.ts +567 -0
  175. package/src/step.test.ts +490 -0
  176. package/src/stepValidation.test.ts +346 -0
  177. package/src/stress.test.ts +526 -0
  178. package/src/symmetricTensor.test.ts +166 -0
  179. package/src/world.test.ts +1127 -0
  180. package/src/worldQueries.test.ts +565 -0
@@ -0,0 +1,155 @@
1
+ import { logOnce } from '@flighthq/log/contract';
2
+ import { LogLevel } from '@flighthq/types/contract';
3
+ import { setPhysics3DContactIntakeGuard } from './contactIntake';
4
+ import { explainPhysics3DCollision } from './explainPhysics3DCollision';
5
+ import { explainPhysics3DJoints } from './explainPhysics3DJoints';
6
+ import { explainPhysics3DStep } from './explainPhysics3DStep';
7
+ import { setPhysics3DJointResolutionGuard } from './islands';
8
+ import { setPhysics3DSpatialIndexingGuard } from './physics3DSpatialIndexingGuards';
9
+ import { setPhysics3DStepGuard } from './step';
10
+ export function arePhysics3DGuardsEnabled() {
11
+ return physics3DGuardsEnabled;
12
+ }
13
+ export function disablePhysics3DGuards() {
14
+ setPhysics3DStepGuard(null);
15
+ setPhysics3DContactIntakeGuard(null);
16
+ setPhysics3DJointResolutionGuard(null);
17
+ setPhysics3DSpatialIndexingGuard(null);
18
+ physics3DGuardsEnabled = false;
19
+ }
20
+ // Installs opt-in diagnostics for the ways a world can advance without simulating what its data appears
21
+ // to describe, plus the broadphase cost fallback that preserves results while defeating spatial pruning.
22
+ //
23
+ // `stepPhysics3D` declines silently on any failed precondition, which is the right behaviour — a NaN
24
+ // velocity is a state a caller reaches by writing a field, and throwing would take down a frame loop over
25
+ // something inspectable. But silence and success are indistinguishable from the callsite: a world that
26
+ // stopped simulating looks exactly like a world where nothing happens to be moving. This is the seam that
27
+ // tells them apart, and applications that omit this module shed both the message text and
28
+ // `@flighthq/log`.
29
+ // The second is worse than the first and needs its own seam: a step whose preconditions all hold still
30
+ // detects NOTHING if the 3D collision registries were never populated, because the narrow phase
31
+ // dispatches through them. That world steps, integrates, and reports success while its bodies fall
32
+ // through every floor.
33
+ // The third is a stored joint omitted from the solve because its kind has no solver or an endpoint no
34
+ // longer resolves. Deserializing ahead of registration is supported, so storing it stays silent; stepping
35
+ // while it remains inert is the moment the opt-in guard names it.
36
+ // The fourth is a body routed through a backend's overflow path. Collision remains correct, but every
37
+ // broadphase query scans that body linearly, so a mixed-scale world can retain the right contacts while
38
+ // silently shedding the pruning its index exists to provide.
39
+ export function enablePhysics3DGuards() {
40
+ setPhysics3DStepGuard(warnOnUnsteppablePhysics3DWorld);
41
+ setPhysics3DContactIntakeGuard(warnOnUndetectablePhysics3DColliders);
42
+ setPhysics3DJointResolutionGuard(warnOnUnresolvedPhysics3DJoints);
43
+ setPhysics3DSpatialIndexingGuard(warnOnPhysics3DSpatialIndexing);
44
+ physics3DGuardsEnabled = true;
45
+ }
46
+ // Reports the broadphase fallback that preserves correctness while materially changing cost. Reading the
47
+ // world's own backend keeps this diagnostic scoped to physics3d instead of taking ownership of spatial's
48
+ // process-wide caller-composed guard.
49
+ function warnOnPhysics3DSpatialIndexing(world) {
50
+ const overflowBodyIndices = [];
51
+ for (let bodyIndex = 0; bodyIndex < world.bodies.length; bodyIndex += 1) {
52
+ const index = world.bodies[bodyIndex].index;
53
+ const explanation = world.index.explainSpatialIndexing(index);
54
+ if (explanation.mode === 'overflow')
55
+ overflowBodyIndices.push(index);
56
+ }
57
+ if (overflowBodyIndices.length > 0) {
58
+ logOnce(`physics3d:spatial-overflow:${getPhysics3DGuardWorldId(world)}`, LogLevel.Warn, {
59
+ bodyIndices: overflowBodyIndices,
60
+ message: `synchronizePhysics3DBroadphase: ${overflowBodyIndices.length} ${overflowBodyIndices.length === 1 ? 'body is' : 'bodies are'} held in the spatial backend's overflow path, so broadphase queries scan ${overflowBodyIndices.length === 1 ? 'it' : 'them'} linearly — pass createBvhSpatialBackend3D() to createPhysics3DWorld(index) for a mixed-scale world, or tune createUniformGridSpatialBackend3D(cellSize) to the workload's typical body size.`,
61
+ status: 'spatial-overflow',
62
+ }, 'physics3d');
63
+ }
64
+ }
65
+ function getPhysics3DGuardWorldId(world) {
66
+ const existing = physics3DGuardWorldIds.get(world);
67
+ if (existing !== undefined)
68
+ return existing;
69
+ const created = nextPhysics3DGuardWorldId;
70
+ nextPhysics3DGuardWorldId += 1;
71
+ physics3DGuardWorldIds.set(world, created);
72
+ return created;
73
+ }
74
+ // Warns once per distinct set of undetectable collider kinds.
75
+ //
76
+ // Keyed on the kinds rather than logged per step, so a 60Hz loop says this once — and a world that later
77
+ // gains a second unsupported kind still says so.
78
+ function warnOnUndetectablePhysics3DColliders(world) {
79
+ const explanation = explainPhysics3DCollision(world);
80
+ if (explanation.status === 'ready')
81
+ return;
82
+ const kinds = explanation.unsupportedKinds;
83
+ logOnce(`physics3d:missing-support:${kinds.join(',')}`, LogLevel.Warn, {
84
+ kinds,
85
+ message: `buildPhysics3DContacts: no support function is registered for collider ${kinds.length === 1 ? 'kind' : 'kinds'} ${kinds.join(', ')}, so these generate no contacts and the bodies carrying them pass through everything — call registerBuiltInCollisionSupports3D() and registerBuiltInCollisionFaceQueries3D() from @flighthq/collision, or register your own support for a vendor kind.`,
86
+ status: explanation.status,
87
+ }, 'physics3d');
88
+ }
89
+ // Warns once per distinct world-list set of unresolved joints. Index belongs in the key: two joints of
90
+ // one kind may fail independently, and repairing the first must not suppress the second's later warning.
91
+ function warnOnUnresolvedPhysics3DJoints(world) {
92
+ const explanations = explainPhysics3DJoints(world);
93
+ const joints = [];
94
+ for (const explanation of explanations) {
95
+ if (explanation.status === 'solvable')
96
+ continue;
97
+ joints.push({ index: explanation.index, kind: explanation.kind, status: explanation.status });
98
+ }
99
+ if (joints.length === 0)
100
+ return;
101
+ const key = joints.map((joint) => `${joint.index}:${joint.kind}:${joint.status}`).join(',');
102
+ logOnce(`physics3d:unresolved-joints:${key}`, LogLevel.Warn, {
103
+ joints,
104
+ message: `buildPhysics3DSolveIslands: ${joints.length} ${joints.length === 1 ? 'joint was' : 'joints were'} omitted from the solve because its kind is unregistered or a body endpoint is missing — call explainPhysics3DJoints(world), then registerBuiltInPhysics3DJointSolvers(world) or registerPhysics3DJointSolver(world, kind, solver) for an unregistered kind, and removePhysics3DJoint(world, joint) or repair an invalid endpoint.`,
105
+ status: 'unresolved-joints',
106
+ }, 'physics3d');
107
+ }
108
+ // Warns once per distinct set of failing preconditions.
109
+ //
110
+ // EVERY failing flag is reported in one message rather than the first. The step's own condition
111
+ // short-circuits, so a world with a bad timestep and a NaN velocity would otherwise surface the timestep,
112
+ // get repaired, and reveal the next fault a frame later — one round trip per fault, which is the failure
113
+ // the explain seam was built to avoid and would be pointless to reintroduce here.
114
+ //
115
+ // Keyed on the failing set, so a loop calling this at 60Hz logs once and not once per frame, while a world
116
+ // that develops a SECOND fault after the first is repaired still says so.
117
+ function warnOnUnsteppablePhysics3DWorld(world, dt) {
118
+ const explanation = explainPhysics3DStep(world, dt);
119
+ const failing = getFailingPhysics3DPreconditions(explanation);
120
+ if (failing.length === 0)
121
+ return;
122
+ logOnce(`physics3d:${explanation.status}:${failing.join(',')}`, LogLevel.Warn, {
123
+ failing,
124
+ message: `stepPhysics3D: the world advanced nothing because ${failing.length === 1 ? 'a precondition' : 'several preconditions'} failed (${failing.join(', ')}) — call explainPhysics3DStep(world, dt) for the same flags as data, and repair the reported fields.`,
125
+ status: explanation.status,
126
+ }, 'physics3d');
127
+ }
128
+ // The names of the flags that are false, in the explanation's own field order so the key is stable for a
129
+ // given set of faults however they arose.
130
+ function getFailingPhysics3DPreconditions(explanation) {
131
+ const failing = [];
132
+ for (const flag of physics3DPreconditionFlags) {
133
+ if (!explanation[flag])
134
+ failing.push(flag);
135
+ }
136
+ return failing;
137
+ }
138
+ // Listed rather than derived by walking the object, so `status` — which is a summary and not a
139
+ // precondition — cannot be swept in, and so a flag added to the explanation is a deliberate addition here.
140
+ const physics3DPreconditionFlags = [
141
+ 'bodyStateValid',
142
+ 'colliderStateValid',
143
+ 'contactStateValid',
144
+ 'gravityValid',
145
+ 'jointStateValid',
146
+ 'solverConfigValid',
147
+ 'substepsValid',
148
+ 'timestepValid',
149
+ 'velocityIterationsValid',
150
+ 'positionIterationsValid',
151
+ ];
152
+ let physics3DGuardsEnabled = false;
153
+ let nextPhysics3DGuardWorldId = 0;
154
+ const physics3DGuardWorldIds = new WeakMap();
155
+ //# sourceMappingURL=enablePhysics3DGuards.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"enablePhysics3DGuards.js","sourceRoot":"","sources":["../src/enablePhysics3DGuards.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { Physics3DCollisionExplanation, Physics3DWorld } from '@flighthq/types/contract';
2
+ export declare function explainPhysics3DCollision(world: Readonly<Physics3DWorld>): Physics3DCollisionExplanation;
3
+ //# sourceMappingURL=explainPhysics3DCollision.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"explainPhysics3DCollision.d.ts","sourceRoot":"","sources":["../src/explainPhysics3DCollision.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,6BAA6B,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAW9F,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,QAAQ,CAAC,cAAc,CAAC,GAAG,6BAA6B,CAiBxG"}
@@ -0,0 +1,30 @@
1
+ import { getCollisionSupport3D } from '@flighthq/collision/contract';
2
+ // Reports which of a world's collider kinds the narrow phase cannot detect, as plain data.
3
+ //
4
+ // This answers a question a stepping world cannot: `stepPhysics3D` succeeds whether or not the collision
5
+ // registries were populated, and an empty contact set is the correct output for a world where nothing is
6
+ // touching AND the output for a world where nothing CAN touch. The two are indistinguishable from the
7
+ // callsite, and the second one presents as bodies sinking through the ground for no stated reason.
8
+ //
9
+ // Separately importable, and consulted rather than continuous: a shipping build that never asks links
10
+ // neither this nor the guard that phrases it.
11
+ export function explainPhysics3DCollision(world) {
12
+ const unsupported = new Set();
13
+ for (const body of world.bodies) {
14
+ for (const collider of body.colliders) {
15
+ const kind = collider.world.kind;
16
+ if (kind === 'triangle-mesh' || kind === 'heightfield')
17
+ continue;
18
+ if (getCollisionSupport3D(kind) === null)
19
+ unsupported.add(kind);
20
+ }
21
+ }
22
+ // Sorted so the value is stable for a given world however its bodies were inserted, which is what lets
23
+ // a guard key a warning on it without re-reporting the same fault under a different order.
24
+ const unsupportedKinds = [...unsupported].sort();
25
+ return {
26
+ unsupportedKinds,
27
+ status: unsupportedKinds.length > 0 ? 'missing-support' : 'ready',
28
+ };
29
+ }
30
+ //# sourceMappingURL=explainPhysics3DCollision.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"explainPhysics3DCollision.js","sourceRoot":"","sources":["../src/explainPhysics3DCollision.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AAGrE,2FAA2F;AAC3F,EAAE;AACF,yGAAyG;AACzG,yGAAyG;AACzG,sGAAsG;AACtG,mGAAmG;AACnG,EAAE;AACF,sGAAsG;AACtG,8CAA8C;AAC9C,MAAM,UAAU,yBAAyB,CAAC,KAA+B;IACvE,MAAM,WAAW,GAAG,IAAI,GAAG,EAAU,CAAC;IACtC,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;QAChC,KAAK,MAAM,QAAQ,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YACtC,MAAM,IAAI,GAAG,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC;YACjC,IAAI,IAAI,KAAK,eAAe,IAAI,IAAI,KAAK,aAAa;gBAAE,SAAS;YACjE,IAAI,qBAAqB,CAAC,IAAI,CAAC,KAAK,IAAI;gBAAE,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAClE,CAAC;IACH,CAAC;IAED,uGAAuG;IACvG,2FAA2F;IAC3F,MAAM,gBAAgB,GAAG,CAAC,GAAG,WAAW,CAAC,CAAC,IAAI,EAAE,CAAC;IACjD,OAAO;QACL,gBAAgB;QAChB,MAAM,EAAE,gBAAgB,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,OAAO;KAClE,CAAC;AACJ,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { Physics3DJointExplanation, Physics3DWorld } from '@flighthq/types/contract';
2
+ export declare function explainPhysics3DJoints(world: Readonly<Physics3DWorld>): Physics3DJointExplanation[];
3
+ //# sourceMappingURL=explainPhysics3DJoints.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"explainPhysics3DJoints.d.ts","sourceRoot":"","sources":["../src/explainPhysics3DJoints.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,yBAAyB,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAc1F,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,QAAQ,CAAC,cAAc,CAAC,GAAG,yBAAyB,EAAE,CAmBnG"}
@@ -0,0 +1,32 @@
1
+ import { findPhysics3DBody } from './world';
2
+ // Which joints the step will actually solve, and why the others are skipped.
3
+ //
4
+ // The step skips a joint in TOTAL SILENCE in two cases, and they need telling apart. An unregistered kind
5
+ // is not a fault — a scene deserialized ahead of the code that solves it is explicitly supported, and the
6
+ // joint is meant to sit inert until someone registers its solver. A joint whose body index no longer
7
+ // resolves is a fault, usually a joint outliving a `removePhysics3DBody` that missed it. Both look
8
+ // identical from outside: a constraint that holds nothing.
9
+ //
10
+ // One entry per joint, in world-list order, so `index` is a handle back into `world.joints`. Pure — it
11
+ // re-walks the world as it stands and retains nothing.
12
+ export function explainPhysics3DJoints(world) {
13
+ const explanations = [];
14
+ for (let index = 0; index < world.joints.length; index += 1) {
15
+ const joint = world.joints[index];
16
+ const solver = world.jointSolvers.get(joint.kind);
17
+ const hasSolver = solver !== undefined;
18
+ // A one-body kind never reads bodyA, so a placeholder index there is not a fault. Asking the solver
19
+ // rather than assuming two endpoints is what keeps this honest for a kind the package does not own.
20
+ const bodyAResolvable = solver?.usesBodyA === false || findPhysics3DBody(world, joint.bodyA) !== null;
21
+ const bodiesResolvable = bodyAResolvable && findPhysics3DBody(world, joint.bodyB) !== null;
22
+ explanations.push({
23
+ kind: joint.kind,
24
+ index,
25
+ hasSolver,
26
+ bodiesResolvable,
27
+ status: !hasSolver ? 'unregistered-kind' : bodiesResolvable ? 'solvable' : 'invalid-bodies',
28
+ });
29
+ }
30
+ return explanations;
31
+ }
32
+ //# sourceMappingURL=explainPhysics3DJoints.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"explainPhysics3DJoints.js","sourceRoot":"","sources":["../src/explainPhysics3DJoints.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAE5C,6EAA6E;AAC7E,EAAE;AACF,0GAA0G;AAC1G,0GAA0G;AAC1G,qGAAqG;AACrG,mGAAmG;AACnG,2DAA2D;AAC3D,EAAE;AACF,uGAAuG;AACvG,uDAAuD;AACvD,MAAM,UAAU,sBAAsB,CAAC,KAA+B;IACpE,MAAM,YAAY,GAAgC,EAAE,CAAC;IACrD,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC;QAC5D,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAClC,MAAM,MAAM,GAAG,KAAK,CAAC,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAClD,MAAM,SAAS,GAAG,MAAM,KAAK,SAAS,CAAC;QACvC,oGAAoG;QACpG,oGAAoG;QACpG,MAAM,eAAe,GAAG,MAAM,EAAE,SAAS,KAAK,KAAK,IAAI,iBAAiB,CAAC,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,KAAK,IAAI,CAAC;QACtG,MAAM,gBAAgB,GAAG,eAAe,IAAI,iBAAiB,CAAC,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,KAAK,IAAI,CAAC;QAC3F,YAAY,CAAC,IAAI,CAAC;YAChB,IAAI,EAAE,KAAK,CAAC,IAAI;YAChB,KAAK;YACL,SAAS;YACT,gBAAgB;YAChB,MAAM,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,gBAAgB;SAC5F,CAAC,CAAC;IACL,CAAC;IACD,OAAO,YAAY,CAAC;AACtB,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { Physics3DStepExplanation, Physics3DWorld } from '@flighthq/types/contract';
2
+ export declare function explainPhysics3DStep(world: Readonly<Physics3DWorld>, dt: number): Physics3DStepExplanation;
3
+ //# sourceMappingURL=explainPhysics3DStep.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"explainPhysics3DStep.d.ts","sourceRoot":"","sources":["../src/explainPhysics3DStep.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,wBAAwB,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AA4BzF,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,QAAQ,CAAC,cAAc,CAAC,EAAE,EAAE,EAAE,MAAM,GAAG,wBAAwB,CAsC1G"}
@@ -0,0 +1,51 @@
1
+ import { isPhysics3DBodyStateValid, isPhysics3DColliderStateValid, isPhysics3DContactStateValid, isPhysics3DGravityValid, isPhysics3DJointStateValid, isPhysics3DPositionIterationsValid, isPhysics3DSolverConfigValid, isPhysics3DSubstepsValid, isPhysics3DTimestepValid, isPhysics3DVelocityIterationsValid, } from './stepValidation';
2
+ // Why `stepPhysics3D(world, dt)` would advance nothing, as plain data.
3
+ //
4
+ // The step declines silently on any failed precondition, because a NaN velocity or a zero timestep is a
5
+ // state a caller reaches by writing a field and not a reason to take down a frame loop. This is the seam
6
+ // that makes that silence readable, and it is separately importable so a shipping build that never asks
7
+ // never links it.
8
+ //
9
+ // It asks the SAME predicates the step asks, in the same order, so the two cannot disagree about what
10
+ // "steppable" means. Every flag is reported rather than short-circuiting at the first false: a world with
11
+ // two faults would otherwise be repaired one frame at a time, each fix revealing the next.
12
+ //
13
+ // Pure — it reads the world as it stands and retains nothing. Calling it never changes whether the next
14
+ // step runs.
15
+ export function explainPhysics3DStep(world, dt) {
16
+ const config = world.config;
17
+ const bodyStateValid = isPhysics3DBodyStateValid(world);
18
+ const colliderStateValid = isPhysics3DColliderStateValid(world);
19
+ const contactStateValid = isPhysics3DContactStateValid(world);
20
+ const gravityValid = isPhysics3DGravityValid(world);
21
+ const jointStateValid = isPhysics3DJointStateValid(world);
22
+ const solverConfigValid = isPhysics3DSolverConfigValid(config);
23
+ const substepsValid = isPhysics3DSubstepsValid(config);
24
+ const timestepValid = isPhysics3DTimestepValid(dt);
25
+ const velocityIterationsValid = isPhysics3DVelocityIterationsValid(config);
26
+ const positionIterationsValid = isPhysics3DPositionIterationsValid(config);
27
+ const ready = bodyStateValid &&
28
+ colliderStateValid &&
29
+ contactStateValid &&
30
+ gravityValid &&
31
+ jointStateValid &&
32
+ solverConfigValid &&
33
+ substepsValid &&
34
+ timestepValid &&
35
+ velocityIterationsValid &&
36
+ positionIterationsValid;
37
+ return {
38
+ bodyStateValid,
39
+ colliderStateValid,
40
+ contactStateValid,
41
+ gravityValid,
42
+ jointStateValid,
43
+ solverConfigValid,
44
+ substepsValid,
45
+ timestepValid,
46
+ velocityIterationsValid,
47
+ positionIterationsValid,
48
+ status: ready ? 'ready' : 'invalid-step',
49
+ };
50
+ }
51
+ //# sourceMappingURL=explainPhysics3DStep.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"explainPhysics3DStep.js","sourceRoot":"","sources":["../src/explainPhysics3DStep.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,yBAAyB,EACzB,6BAA6B,EAC7B,4BAA4B,EAC5B,uBAAuB,EACvB,0BAA0B,EAC1B,kCAAkC,EAClC,4BAA4B,EAC5B,wBAAwB,EACxB,wBAAwB,EACxB,kCAAkC,GACnC,MAAM,kBAAkB,CAAC;AAE1B,uEAAuE;AACvE,EAAE;AACF,wGAAwG;AACxG,yGAAyG;AACzG,wGAAwG;AACxG,kBAAkB;AAClB,EAAE;AACF,sGAAsG;AACtG,0GAA0G;AAC1G,2FAA2F;AAC3F,EAAE;AACF,wGAAwG;AACxG,aAAa;AACb,MAAM,UAAU,oBAAoB,CAAC,KAA+B,EAAE,EAAU;IAC9E,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC;IAC5B,MAAM,cAAc,GAAG,yBAAyB,CAAC,KAAK,CAAC,CAAC;IACxD,MAAM,kBAAkB,GAAG,6BAA6B,CAAC,KAAK,CAAC,CAAC;IAChE,MAAM,iBAAiB,GAAG,4BAA4B,CAAC,KAAK,CAAC,CAAC;IAC9D,MAAM,YAAY,GAAG,uBAAuB,CAAC,KAAK,CAAC,CAAC;IACpD,MAAM,eAAe,GAAG,0BAA0B,CAAC,KAAK,CAAC,CAAC;IAC1D,MAAM,iBAAiB,GAAG,4BAA4B,CAAC,MAAM,CAAC,CAAC;IAC/D,MAAM,aAAa,GAAG,wBAAwB,CAAC,MAAM,CAAC,CAAC;IACvD,MAAM,aAAa,GAAG,wBAAwB,CAAC,EAAE,CAAC,CAAC;IACnD,MAAM,uBAAuB,GAAG,kCAAkC,CAAC,MAAM,CAAC,CAAC;IAC3E,MAAM,uBAAuB,GAAG,kCAAkC,CAAC,MAAM,CAAC,CAAC;IAE3E,MAAM,KAAK,GACT,cAAc;QACd,kBAAkB;QAClB,iBAAiB;QACjB,YAAY;QACZ,eAAe;QACf,iBAAiB;QACjB,aAAa;QACb,aAAa;QACb,uBAAuB;QACvB,uBAAuB,CAAC;IAE1B,OAAO;QACL,cAAc;QACd,kBAAkB;QAClB,iBAAiB;QACjB,YAAY;QACZ,eAAe;QACf,iBAAiB;QACjB,aAAa;QACb,aAAa;QACb,uBAAuB;QACvB,uBAAuB;QACvB,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,cAAc;KACzC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,22 @@
1
+ export { clearRigidBody3DForces, integrateRigidBody3DPose, integrateRigidBody3DVelocity, refreshRigidBody3DWorldInertia, } from './integrate';
2
+ export { createPhysics3DContact, createPhysics3DContactPoint } from './contacts';
3
+ export { explainPhysics3DCollision } from './explainPhysics3DCollision';
4
+ export { explainPhysics3DJoints } from './explainPhysics3DJoints';
5
+ export { arePhysics3DGuardsEnabled, disablePhysics3DGuards, enablePhysics3DGuards } from './enablePhysics3DGuards';
6
+ export { explainPhysics3DStep } from './explainPhysics3DStep';
7
+ export { isPhysics3DPairJointSuppressed } from './jointCollisionSuppression';
8
+ export { createPhysics3DBallAndSocketJoint, createPhysics3DConeTwistJoint, createPhysics3DDistanceJoint, createPhysics3DFixedJoint, createPhysics3DGeneric6DofJoint, createPhysics3DHingeJoint, createPhysics3DSliderJoint, } from './jointFactories';
9
+ export { addPhysics3DJoint, getPhysics3DJointSolver, invalidatePhysics3DJoint, registerPhysics3DJointSolver, removePhysics3DJoint, } from './jointRegistry';
10
+ export { physics3DBallAndSocketJointSolver, physics3DConeTwistJointSolver, physics3DDistanceJointSolver, physics3DFixedJointSolver, physics3DGeneric6DofJointSolver, physics3DHingeJointSolver, physics3DSliderJointSolver, Physics3DBallAndSocketJointKind, Physics3DConeTwistJointKind, Physics3DDistanceJointKind, Physics3DFixedJointKind, Physics3DGeneric6DofJointKind, Physics3DHingeJointKind, Physics3DSliderJointKind, } from './joints';
11
+ export { combinePhysics3DMassData, computePhysics3DBoxMassData, computePhysics3DCapsuleMassData, computePhysics3DConeMassData, computePhysics3DCylinderMassData, computePhysics3DColliderMassData, computePhysics3DConvexHullMassData, computePhysics3DSphereMassData, createPhysics3DMassData, setRigidBody3DMassData, updateRigidBody3DMassData, } from './massProperties';
12
+ export { mixPhysics3DFriction, mixPhysics3DRestitution } from './material';
13
+ export { syncPhysics3DBodyToNode3D } from './nodeSync';
14
+ export { registerBuiltInPhysics3DJointSolvers } from './registerBuiltInPhysics3DJointSolvers';
15
+ export { stepPhysics3D, stepPhysics3DInterval } from './step';
16
+ export { addPhysics3DBody, addPhysics3DCollider, applyPhysics3DForce, applyPhysics3DForceAtPoint, applyPhysics3DLinearImpulse, applyPhysics3DLinearImpulseAtPoint, applyPhysics3DTorque, createPhysics3DCollider, createPhysics3DSequentialImpulseConfig, createPhysics3DSolverConfig, createPhysics3DWorld, createRigidBody3D, findPhysics3DBody, hydratePhysics3DWorld, invalidatePhysics3DCollider, Physics3DWorldVersion, removePhysics3DBody, removePhysics3DCollider, setPhysics3DBodyBullet, setPhysics3DBodyFixedRotation, setPhysics3DBodySleepEnabled, setPhysics3DBodyTransform, setPhysics3DBodyType, wakePhysics3DBody, writeRigidBody3DWorldCenter, } from './world';
17
+ export { createPhysics3DQueryFilter, createPhysics3DQueryResult, createPhysics3DRayResult, createPhysics3DShapeCastResult, queryPhysics3DPoint, queryPhysics3DRay, queryPhysics3DRayClosest, queryPhysics3DRegion, queryPhysics3DShapeCast, } from './worldQueries';
18
+ export { createPhysics3DDebugGeometry, writePhysics3DDebugGeometry } from './debugGeometry';
19
+ export { hasActivePhysics3DBullet, integratePhysics3DContinuous, writePhysics3DRotationalCcdEnvelope, } from './continuous';
20
+ export { breakPhysics3DJoint, evaluatePhysics3DJointBreakage, isPhysics3DJointBreakable } from './jointBreakage';
21
+ export { accumulatePhysics3DJointRowReaction, clearPhysics3DJointReaction, createPhysics3DJointReaction, getPhysics3DJointReactionForce, getPhysics3DJointReactionTorque, writePhysics3DJointReaction, } from './jointReaction';
22
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js ADDED
@@ -0,0 +1,22 @@
1
+ export { clearRigidBody3DForces, integrateRigidBody3DPose, integrateRigidBody3DVelocity, refreshRigidBody3DWorldInertia, } from './integrate';
2
+ export { createPhysics3DContact, createPhysics3DContactPoint } from './contacts';
3
+ export { explainPhysics3DCollision } from './explainPhysics3DCollision';
4
+ export { explainPhysics3DJoints } from './explainPhysics3DJoints';
5
+ export { arePhysics3DGuardsEnabled, disablePhysics3DGuards, enablePhysics3DGuards } from './enablePhysics3DGuards';
6
+ export { explainPhysics3DStep } from './explainPhysics3DStep';
7
+ export { isPhysics3DPairJointSuppressed } from './jointCollisionSuppression';
8
+ export { createPhysics3DBallAndSocketJoint, createPhysics3DConeTwistJoint, createPhysics3DDistanceJoint, createPhysics3DFixedJoint, createPhysics3DGeneric6DofJoint, createPhysics3DHingeJoint, createPhysics3DSliderJoint, } from './jointFactories';
9
+ export { addPhysics3DJoint, getPhysics3DJointSolver, invalidatePhysics3DJoint, registerPhysics3DJointSolver, removePhysics3DJoint, } from './jointRegistry';
10
+ export { physics3DBallAndSocketJointSolver, physics3DConeTwistJointSolver, physics3DDistanceJointSolver, physics3DFixedJointSolver, physics3DGeneric6DofJointSolver, physics3DHingeJointSolver, physics3DSliderJointSolver, Physics3DBallAndSocketJointKind, Physics3DConeTwistJointKind, Physics3DDistanceJointKind, Physics3DFixedJointKind, Physics3DGeneric6DofJointKind, Physics3DHingeJointKind, Physics3DSliderJointKind, } from './joints';
11
+ export { combinePhysics3DMassData, computePhysics3DBoxMassData, computePhysics3DCapsuleMassData, computePhysics3DConeMassData, computePhysics3DCylinderMassData, computePhysics3DColliderMassData, computePhysics3DConvexHullMassData, computePhysics3DSphereMassData, createPhysics3DMassData, setRigidBody3DMassData, updateRigidBody3DMassData, } from './massProperties';
12
+ export { mixPhysics3DFriction, mixPhysics3DRestitution } from './material';
13
+ export { syncPhysics3DBodyToNode3D } from './nodeSync';
14
+ export { registerBuiltInPhysics3DJointSolvers } from './registerBuiltInPhysics3DJointSolvers';
15
+ export { stepPhysics3D, stepPhysics3DInterval } from './step';
16
+ export { addPhysics3DBody, addPhysics3DCollider, applyPhysics3DForce, applyPhysics3DForceAtPoint, applyPhysics3DLinearImpulse, applyPhysics3DLinearImpulseAtPoint, applyPhysics3DTorque, createPhysics3DCollider, createPhysics3DSequentialImpulseConfig, createPhysics3DSolverConfig, createPhysics3DWorld, createRigidBody3D, findPhysics3DBody, hydratePhysics3DWorld, invalidatePhysics3DCollider, Physics3DWorldVersion, removePhysics3DBody, removePhysics3DCollider, setPhysics3DBodyBullet, setPhysics3DBodyFixedRotation, setPhysics3DBodySleepEnabled, setPhysics3DBodyTransform, setPhysics3DBodyType, wakePhysics3DBody, writeRigidBody3DWorldCenter, } from './world';
17
+ export { createPhysics3DQueryFilter, createPhysics3DQueryResult, createPhysics3DRayResult, createPhysics3DShapeCastResult, queryPhysics3DPoint, queryPhysics3DRay, queryPhysics3DRayClosest, queryPhysics3DRegion, queryPhysics3DShapeCast, } from './worldQueries';
18
+ export { createPhysics3DDebugGeometry, writePhysics3DDebugGeometry } from './debugGeometry';
19
+ export { hasActivePhysics3DBullet, integratePhysics3DContinuous, writePhysics3DRotationalCcdEnvelope, } from './continuous';
20
+ export { breakPhysics3DJoint, evaluatePhysics3DJointBreakage, isPhysics3DJointBreakable } from './jointBreakage';
21
+ export { accumulatePhysics3DJointRowReaction, clearPhysics3DJointReaction, createPhysics3DJointReaction, getPhysics3DJointReactionForce, getPhysics3DJointReactionTorque, writePhysics3DJointReaction, } from './jointReaction';
22
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ import type { RigidBody3D } from '@flighthq/types/contract';
2
+ export declare function clearRigidBody3DForces(body: RigidBody3D): void;
3
+ export declare function integrateRigidBody3DPose(body: RigidBody3D, dt: number): void;
4
+ export declare function integrateRigidBody3DVelocity(body: RigidBody3D, gravityX: number, gravityY: number, gravityZ: number, dt: number): void;
5
+ export declare function refreshRigidBody3DWorldInertia(body: RigidBody3D): void;
6
+ //# sourceMappingURL=integrate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"integrate.d.ts","sourceRoot":"","sources":["../src/integrate.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAyB5D,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,WAAW,GAAG,IAAI,CAO9D;AAaD,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,WAAW,EAAE,EAAE,EAAE,MAAM,GAAG,IAAI,CA+D5E;AAYD,wBAAgB,4BAA4B,CAC1C,IAAI,EAAE,WAAW,EACjB,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,EAAE,EAAE,MAAM,GACT,IAAI,CA+DN;AAQD,wBAAgB,8BAA8B,CAAC,IAAI,EAAE,WAAW,GAAG,IAAI,CAuBtE"}
@@ -0,0 +1,184 @@
1
+ import { applySymmetricTensor, rotateSymmetricTensor, TENSOR_XX, TENSOR_XY, TENSOR_XZ, TENSOR_YY, TENSOR_YZ, TENSOR_ZZ, } from './symmetricTensor';
2
+ // Integration: turning forces into velocities and velocities into poses.
3
+ //
4
+ // The scheme is semi-implicit (symplectic) Euler — velocity is advanced first and the NEW velocity
5
+ // moves the pose. The ordering is the whole reason it is stable enough for games: explicit Euler, which
6
+ // moves the pose by the old velocity, injects energy on every step and makes an orbit spiral outward.
7
+ //
8
+ // These are exported separately rather than folded into the step because a caller assembling its own
9
+ // step wants exactly these pieces, and because each is independently testable — which matters most for
10
+ // the angular half, whose failure mode is a slow drift no single-step assertion would catch.
11
+ // Clears the force and torque accumulators. Called by the step once the forces have been integrated, so
12
+ // a caller applying a force each frame does not have it applied twice.
13
+ export function clearRigidBody3DForces(body) {
14
+ body.forceX = 0;
15
+ body.forceY = 0;
16
+ body.forceZ = 0;
17
+ body.torqueX = 0;
18
+ body.torqueY = 0;
19
+ body.torqueZ = 0;
20
+ }
21
+ // Advances a body's pose by its current velocity over `dt`.
22
+ //
23
+ // The CENTRE OF MASS takes the straight Euler step because that is where `velocity` is measured. The
24
+ // stored position is the body's authored origin, which may be offset from that centre: after rotation it
25
+ // is shifted by oldRotatedCentre - newRotatedCentre so pure angular motion cannot make the centre orbit.
26
+ //
27
+ // Orientation is advanced by the quaternion derivative `0.5 * omega * q`, where omega is the angular
28
+ // velocity as a pure quaternion. That step leaves the unit sphere — it is a tangent move on a curved
29
+ // manifold — so the result is renormalized. Skipping the renormalization does not look wrong for a step
30
+ // or a hundred; it accumulates into a quaternion whose rotation matrix is no longer orthonormal, which
31
+ // reads downstream as a body that is subtly sheared and getting worse.
32
+ export function integrateRigidBody3DPose(body, dt) {
33
+ if (body.type === 'static' || body.sleeping)
34
+ return;
35
+ body.x += body.velocityX * dt;
36
+ body.y += body.velocityY * dt;
37
+ body.z += body.velocityZ * dt;
38
+ const wX = body.angularVelocityX;
39
+ const wY = body.angularVelocityY;
40
+ const wZ = body.angularVelocityZ;
41
+ if (wX === 0 && wY === 0 && wZ === 0)
42
+ return;
43
+ const qX = body.orientationX;
44
+ const qY = body.orientationY;
45
+ const qZ = body.orientationZ;
46
+ const qW = body.orientationW;
47
+ const centerX = body.centerX;
48
+ const centerY = body.centerY;
49
+ const centerZ = body.centerZ;
50
+ const offset = centerX !== 0 || centerY !== 0 || centerZ !== 0;
51
+ let oldCenterX = 0;
52
+ let oldCenterY = 0;
53
+ let oldCenterZ = 0;
54
+ if (offset) {
55
+ const tX = 2 * (qY * centerZ - qZ * centerY);
56
+ const tY = 2 * (qZ * centerX - qX * centerZ);
57
+ const tZ = 2 * (qX * centerY - qY * centerX);
58
+ oldCenterX = centerX + qW * tX + qY * tZ - qZ * tY;
59
+ oldCenterY = centerY + qW * tY + qZ * tX - qX * tZ;
60
+ oldCenterZ = centerZ + qW * tZ + qX * tY - qY * tX;
61
+ }
62
+ const half = dt * 0.5;
63
+ const nX = qX + half * (wX * qW + wY * qZ - wZ * qY);
64
+ const nY = qY + half * (wY * qW + wZ * qX - wX * qZ);
65
+ const nZ = qZ + half * (wZ * qW + wX * qY - wY * qX);
66
+ const nW = qW + half * (-wX * qX - wY * qY - wZ * qZ);
67
+ const lengthSquared = nX * nX + nY * nY + nZ * nZ + nW * nW;
68
+ if (lengthSquared <= 0 || !Number.isFinite(lengthSquared)) {
69
+ // The only way here is a non-finite angular velocity, which a diverging simulation produces. Hold
70
+ // the previous orientation rather than writing NaN into it: a NaN pose spreads to every constraint
71
+ // the body touches within one step, and a held orientation is at least a state a caller can see.
72
+ return;
73
+ }
74
+ const scale = 1 / Math.sqrt(lengthSquared);
75
+ const nextX = nX * scale;
76
+ const nextY = nY * scale;
77
+ const nextZ = nZ * scale;
78
+ const nextW = nW * scale;
79
+ if (offset) {
80
+ const tX = 2 * (nextY * centerZ - nextZ * centerY);
81
+ const tY = 2 * (nextZ * centerX - nextX * centerZ);
82
+ const tZ = 2 * (nextX * centerY - nextY * centerX);
83
+ body.x += oldCenterX - (centerX + nextW * tX + nextY * tZ - nextZ * tY);
84
+ body.y += oldCenterY - (centerY + nextW * tY + nextZ * tX - nextX * tZ);
85
+ body.z += oldCenterZ - (centerZ + nextW * tZ + nextX * tY - nextY * tX);
86
+ }
87
+ body.orientationX = nextX;
88
+ body.orientationY = nextY;
89
+ body.orientationZ = nextZ;
90
+ body.orientationW = nextW;
91
+ }
92
+ // Advances a body's velocities by the accumulated forces, gravity, and damping over `dt`.
93
+ //
94
+ // The angular half carries the term that does not exist in 2D: Euler's equation for a rotating rigid
95
+ // body is `torque = I * alpha + omega x (I * omega)`, and that second term — the gyroscopic torque — is
96
+ // what makes a thrown object tumble rather than spin about a fixed axis. In 2D it vanishes identically,
97
+ // because omega and `I * omega` are parallel when I is a scalar. Dropping it in 3D costs nothing on a
98
+ // sphere and is visibly wrong on anything long.
99
+ //
100
+ // Damping is applied as an exponential decay rather than a subtraction, so the result does not depend
101
+ // on the step size and a large `dt` can never drive a velocity through zero into reverse.
102
+ export function integrateRigidBody3DVelocity(body, gravityX, gravityY, gravityZ, dt) {
103
+ if (body.type !== 'dynamic' || body.sleeping)
104
+ return;
105
+ body.velocityX += (body.forceX * body.inverseMass + gravityX * body.gravityScale) * dt;
106
+ body.velocityY += (body.forceY * body.inverseMass + gravityY * body.gravityScale) * dt;
107
+ body.velocityZ += (body.forceZ * body.inverseMass + gravityZ * body.gravityScale) * dt;
108
+ const wX = body.angularVelocityX;
109
+ const wY = body.angularVelocityY;
110
+ const wZ = body.angularVelocityZ;
111
+ // The gyroscopic torque, `-omega x (I * omega)`. It needs the FORWARD world inertia, which is why the
112
+ // body stores its forward local tensor: rotating that into world space is one similarity transform,
113
+ // where recovering it from the inverse would be a 3x3 inversion per body per substep.
114
+ //
115
+ // Explicit here, which is the standard game-engine treatment and is stable at ordinary timesteps. A
116
+ // body spinning fast enough that its momentum turns appreciably within one step needs an implicit
117
+ // form; the substep count is the lever for that, and is why it exists.
118
+ let torqueX = body.torqueX;
119
+ let torqueY = body.torqueY;
120
+ let torqueZ = body.torqueZ;
121
+ if (wX !== 0 || wY !== 0 || wZ !== 0) {
122
+ scratchTensor[TENSOR_XX] = body.inertiaXX;
123
+ scratchTensor[TENSOR_YY] = body.inertiaYY;
124
+ scratchTensor[TENSOR_ZZ] = body.inertiaZZ;
125
+ scratchTensor[TENSOR_XY] = body.inertiaXY;
126
+ scratchTensor[TENSOR_XZ] = body.inertiaXZ;
127
+ scratchTensor[TENSOR_YZ] = body.inertiaYZ;
128
+ rotateSymmetricTensor(scratchTensor, body.orientationX, body.orientationY, body.orientationZ, body.orientationW, scratchTensor);
129
+ // scratchVector becomes the angular momentum `L = I * omega`.
130
+ applySymmetricTensor(scratchTensor, wX, wY, wZ, scratchVector);
131
+ torqueX -= wY * scratchVector[2] - wZ * scratchVector[1];
132
+ torqueY -= wZ * scratchVector[0] - wX * scratchVector[2];
133
+ torqueZ -= wX * scratchVector[1] - wY * scratchVector[0];
134
+ }
135
+ readWorldInertia(body, scratchTensor);
136
+ applySymmetricTensor(scratchTensor, torqueX, torqueY, torqueZ, scratchVector);
137
+ body.angularVelocityX = wX + scratchVector[0] * dt;
138
+ body.angularVelocityY = wY + scratchVector[1] * dt;
139
+ body.angularVelocityZ = wZ + scratchVector[2] * dt;
140
+ if (body.linearDamping > 0) {
141
+ const damping = 1 / (1 + dt * body.linearDamping);
142
+ body.velocityX *= damping;
143
+ body.velocityY *= damping;
144
+ body.velocityZ *= damping;
145
+ }
146
+ if (body.angularDamping > 0) {
147
+ const damping = 1 / (1 + dt * body.angularDamping);
148
+ body.angularVelocityX *= damping;
149
+ body.angularVelocityY *= damping;
150
+ body.angularVelocityZ *= damping;
151
+ }
152
+ }
153
+ // Refreshes the world-space inverse inertia tensor from the body's orientation and its local tensor.
154
+ //
155
+ // Must run whenever the orientation changes — which is every substep for anything rotating, and at
156
+ // insertion and teleport for everything else. It is a pull rather than an invalidation flag because
157
+ // every rotating body needs it every substep anyway, so a flag would be checked far more often than it
158
+ // would ever be false.
159
+ export function refreshRigidBody3DWorldInertia(body) {
160
+ scratchTensor[TENSOR_XX] = body.inverseInertiaXX;
161
+ scratchTensor[TENSOR_YY] = body.inverseInertiaYY;
162
+ scratchTensor[TENSOR_ZZ] = body.inverseInertiaZZ;
163
+ scratchTensor[TENSOR_XY] = body.inverseInertiaXY;
164
+ scratchTensor[TENSOR_XZ] = body.inverseInertiaXZ;
165
+ scratchTensor[TENSOR_YZ] = body.inverseInertiaYZ;
166
+ rotateSymmetricTensor(scratchTensor, body.orientationX, body.orientationY, body.orientationZ, body.orientationW, scratchTensor);
167
+ body.inverseInertiaWorldXX = scratchTensor[TENSOR_XX];
168
+ body.inverseInertiaWorldYY = scratchTensor[TENSOR_YY];
169
+ body.inverseInertiaWorldZZ = scratchTensor[TENSOR_ZZ];
170
+ body.inverseInertiaWorldXY = scratchTensor[TENSOR_XY];
171
+ body.inverseInertiaWorldXZ = scratchTensor[TENSOR_XZ];
172
+ body.inverseInertiaWorldYZ = scratchTensor[TENSOR_YZ];
173
+ }
174
+ function readWorldInertia(body, out) {
175
+ out[TENSOR_XX] = body.inverseInertiaWorldXX;
176
+ out[TENSOR_YY] = body.inverseInertiaWorldYY;
177
+ out[TENSOR_ZZ] = body.inverseInertiaWorldZZ;
178
+ out[TENSOR_XY] = body.inverseInertiaWorldXY;
179
+ out[TENSOR_XZ] = body.inverseInertiaWorldXZ;
180
+ out[TENSOR_YZ] = body.inverseInertiaWorldYZ;
181
+ }
182
+ const scratchTensor = [0, 0, 0, 0, 0, 0];
183
+ const scratchVector = [0, 0, 0];
184
+ //# sourceMappingURL=integrate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"integrate.js","sourceRoot":"","sources":["../src/integrate.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ import type { Physics3DJointResolutionGuard, Physics3DWorld, RigidBody3D } from '@flighthq/types/contract';
2
+ export declare function buildPhysics3DSolveIslands(world: Physics3DWorld): void;
3
+ export declare function isRigidBody3DPairAwake(a: Readonly<RigidBody3D>, b: Readonly<RigidBody3D>): boolean;
4
+ export declare function setPhysics3DJointResolutionGuard(guard: Physics3DJointResolutionGuard | null): void;
5
+ export declare function updatePhysics3DSleep(world: Physics3DWorld, dt: number): void;
6
+ //# sourceMappingURL=islands.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"islands.d.ts","sourceRoot":"","sources":["../src/islands.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,6BAA6B,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAc3G,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,cAAc,GAAG,IAAI,CA0FtE;AAYD,wBAAgB,sBAAsB,CAAC,CAAC,EAAE,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC,EAAE,QAAQ,CAAC,WAAW,CAAC,GAAG,OAAO,CAElG;AAID,wBAAgB,gCAAgC,CAAC,KAAK,EAAE,6BAA6B,GAAG,IAAI,GAAG,IAAI,CAElG;AAkBD,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,cAAc,EAAE,EAAE,EAAE,MAAM,GAAG,IAAI,CA8F5E"}