@woosh/meep-engine 2.156.0 → 2.157.0

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 (654) hide show
  1. package/README.md +1 -3
  2. package/editor/view/ecs/components/common/AutoCanvasView.js +100 -53
  3. package/editor/view/ecs/components/common/TextController.js +59 -0
  4. package/editor/view/node-graph/NodeGraphCamera.js +90 -0
  5. package/editor/view/node-graph/NodeGraphEditorView.js +121 -22
  6. package/editor/view/node-graph/NodeGraphSelection.js +89 -0
  7. package/editor/view/node-graph/NodeGraphView.js +669 -453
  8. package/editor/view/node-graph/NodeView.js +211 -135
  9. package/editor/view/node-graph/actions/ConnectionCreateAction.js +53 -0
  10. package/editor/view/node-graph/actions/ConnectionDeleteAction.js +36 -0
  11. package/editor/view/node-graph/actions/NodeDeleteAction.js +88 -0
  12. package/editor/view/node-graph/actions/NodeParameterSetAction.js +52 -0
  13. package/editor/view/node-graph/actions/NodesMoveAction.js +41 -0
  14. package/editor/view/node-graph/actions/SelectionSetAction.js +60 -0
  15. package/editor/view/node-graph/connection_wire_geometry.js +107 -0
  16. package/package.json +1 -1
  17. package/samples/generation/SampleGenerator0.js +8 -1
  18. package/src/core/binary/reinterpret_float32_as_uint32.d.ts +7 -0
  19. package/src/core/binary/reinterpret_float32_as_uint32.d.ts.map +1 -0
  20. package/src/core/binary/reinterpret_float32_as_uint32.js +13 -0
  21. package/src/core/binary/reinterpret_uint32_as_float32.d.ts +7 -0
  22. package/src/core/binary/reinterpret_uint32_as_float32.d.ts.map +1 -0
  23. package/src/core/binary/reinterpret_uint32_as_float32.js +14 -0
  24. package/src/core/bvh2/bvh3/ebvh_build_for_geometry_incremental.d.ts.map +1 -1
  25. package/src/core/bvh2/bvh3/ebvh_build_for_geometry_incremental.js +1 -3
  26. package/src/core/bvh2/bvh3/query/bvh_query_user_data_overlaps_sphere.d.ts +12 -0
  27. package/src/core/bvh2/bvh3/query/bvh_query_user_data_overlaps_sphere.d.ts.map +1 -0
  28. package/src/core/bvh2/bvh3/query/bvh_query_user_data_overlaps_sphere.js +92 -0
  29. package/src/core/bvh8/BVH8.d.ts +127 -0
  30. package/src/core/bvh8/BVH8.d.ts.map +1 -0
  31. package/src/core/bvh8/BVH8.js +436 -0
  32. package/src/core/bvh8/NOTES.md +63 -0
  33. package/src/core/bvh8/build/BVH8Converter.d.ts +59 -0
  34. package/src/core/bvh8/build/BVH8Converter.d.ts.map +1 -0
  35. package/src/core/bvh8/build/BVH8Converter.js +588 -0
  36. package/src/core/bvh8/build/NodeProxy.d.ts +66 -0
  37. package/src/core/bvh8/build/NodeProxy.d.ts.map +1 -0
  38. package/src/core/bvh8/build/NodeProxy.js +308 -0
  39. package/src/core/bvh8/build/TriangleCluster.d.ts +29 -0
  40. package/src/core/bvh8/build/TriangleCluster.d.ts.map +1 -0
  41. package/src/core/bvh8/build/TriangleCluster.js +123 -0
  42. package/src/core/bvh8/build/aabb3_compute_merge_cost.d.ts +8 -0
  43. package/src/core/bvh8/build/aabb3_compute_merge_cost.d.ts.map +1 -0
  44. package/src/core/bvh8/build/aabb3_compute_merge_cost.js +29 -0
  45. package/src/core/bvh8/build/aabb3_from_triangle_by_index.d.ts +10 -0
  46. package/src/core/bvh8/build/aabb3_from_triangle_by_index.d.ts.map +1 -0
  47. package/src/core/bvh8/build/aabb3_from_triangle_by_index.js +18 -0
  48. package/src/core/bvh8/build/bvh8_build_for_geometry.d.ts +10 -0
  49. package/src/core/bvh8/build/bvh8_build_for_geometry.d.ts.map +1 -0
  50. package/src/core/bvh8/build/bvh8_build_for_geometry.js +303 -0
  51. package/src/core/bvh8/build/bvh8_from_proxy.d.ts +9 -0
  52. package/src/core/bvh8/build/bvh8_from_proxy.d.ts.map +1 -0
  53. package/src/core/bvh8/build/bvh8_from_proxy.js +256 -0
  54. package/src/core/bvh8/build/byte.d.ts +7 -0
  55. package/src/core/bvh8/build/byte.d.ts.map +1 -0
  56. package/src/core/bvh8/build/byte.js +10 -0
  57. package/src/core/bvh8/build/encode_bounds_e.d.ts +9 -0
  58. package/src/core/bvh8/build/encode_bounds_e.d.ts.map +1 -0
  59. package/src/core/bvh8/build/encode_bounds_e.js +12 -0
  60. package/src/core/bvh8/bvh8_convert_to_dot.d.ts +11 -0
  61. package/src/core/bvh8/bvh8_convert_to_dot.d.ts.map +1 -0
  62. package/src/core/bvh8/bvh8_convert_to_dot.js +133 -0
  63. package/src/core/bvh8/bvh8_count_primitives.d.ts +22 -0
  64. package/src/core/bvh8/bvh8_count_primitives.d.ts.map +1 -0
  65. package/src/core/bvh8/bvh8_count_primitives.js +98 -0
  66. package/src/core/bvh8/bvh8_geometry_validate.d.ts +16 -0
  67. package/src/core/bvh8/bvh8_geometry_validate.d.ts.map +1 -0
  68. package/src/core/bvh8/bvh8_geometry_validate.js +149 -0
  69. package/src/core/bvh8/bvh8_geometry_validate_indirect.d.ts +16 -0
  70. package/src/core/bvh8/bvh8_geometry_validate_indirect.d.ts.map +1 -0
  71. package/src/core/bvh8/bvh8_geometry_validate_indirect.js +177 -0
  72. package/src/core/bvh8/bvh8_get_node_bounds.d.ts +9 -0
  73. package/src/core/bvh8/bvh8_get_node_bounds.d.ts.map +1 -0
  74. package/src/core/bvh8/bvh8_get_node_bounds.js +35 -0
  75. package/src/core/bvh8/bvh8_get_node_child_bounds.d.ts +10 -0
  76. package/src/core/bvh8/bvh8_get_node_child_bounds.d.ts.map +1 -0
  77. package/src/core/bvh8/bvh8_get_node_child_bounds.js +53 -0
  78. package/src/core/bvh8/bvh8_node_child_surface_area.d.ts +9 -0
  79. package/src/core/bvh8/bvh8_node_child_surface_area.d.ts.map +1 -0
  80. package/src/core/bvh8/bvh8_node_child_surface_area.js +18 -0
  81. package/src/core/bvh8/bvh8_node_count_triangles.d.ts +8 -0
  82. package/src/core/bvh8/bvh8_node_count_triangles.d.ts.map +1 -0
  83. package/src/core/bvh8/bvh8_node_count_triangles.js +28 -0
  84. package/src/core/bvh8/bvh8_quality.d.ts +8 -0
  85. package/src/core/bvh8/bvh8_quality.d.ts.map +1 -0
  86. package/src/core/bvh8/bvh8_quality.js +73 -0
  87. package/src/core/bvh8/bvh8_validate_structure.d.ts +15 -0
  88. package/src/core/bvh8/bvh8_validate_structure.d.ts.map +1 -0
  89. package/src/core/bvh8/bvh8_validate_structure.js +87 -0
  90. package/src/core/collection/Uint32MinHeap.d.ts +56 -0
  91. package/src/core/collection/Uint32MinHeap.d.ts.map +1 -0
  92. package/src/core/collection/Uint32MinHeap.js +109 -0
  93. package/src/core/collection/list/FilteredListProjection.js +1 -1
  94. package/src/{engine/physics/island → core/collection/union-find}/union_find.d.ts +8 -5
  95. package/src/core/collection/union-find/union_find.d.ts.map +1 -0
  96. package/src/{engine/physics/island → core/collection/union-find}/union_find.js +8 -5
  97. package/src/core/dom/isImageBitmap.d.ts +7 -0
  98. package/src/core/dom/isImageBitmap.d.ts.map +1 -0
  99. package/src/core/dom/isImageBitmap.js +12 -0
  100. package/src/core/function/frameThrottle.d.ts +8 -0
  101. package/src/core/function/frameThrottle.d.ts.map +1 -0
  102. package/src/core/function/frameThrottle.js +23 -0
  103. package/src/{engine/physics/narrowphase/clip_against_axis_uv.d.ts → core/geom/2d/polygon/polygon2_clip_axis_halfplane.d.ts} +3 -3
  104. package/src/core/geom/2d/polygon/polygon2_clip_axis_halfplane.d.ts.map +1 -0
  105. package/src/{engine/physics/narrowphase/clip_against_axis_uv.js → core/geom/2d/polygon/polygon2_clip_axis_halfplane.js} +51 -51
  106. package/src/{engine/physics/narrowphase/decomposition/aabb_world_to_local.d.ts → core/geom/3d/aabb/aabb3_transform_oriented_inverse.d.ts} +9 -7
  107. package/src/core/geom/3d/aabb/aabb3_transform_oriented_inverse.d.ts.map +1 -0
  108. package/src/{engine/physics/narrowphase/decomposition/aabb_world_to_local.js → core/geom/3d/aabb/aabb3_transform_oriented_inverse.js} +9 -7
  109. package/src/core/geom/3d/aabb/compute_triangle_group_aabb3.d.ts +12 -0
  110. package/src/core/geom/3d/aabb/compute_triangle_group_aabb3.d.ts.map +1 -0
  111. package/src/core/geom/3d/aabb/compute_triangle_group_aabb3.js +46 -0
  112. package/src/core/geom/3d/box/box3_projected_half_extent.d.ts +28 -0
  113. package/src/core/geom/3d/box/box3_projected_half_extent.d.ts.map +1 -0
  114. package/src/core/geom/3d/box/box3_projected_half_extent.js +35 -0
  115. package/src/core/geom/3d/frustum/read_cluster_frustum_corners.js +1 -1
  116. package/src/core/geom/3d/frustum/read_frustum_corner.d.ts +9 -0
  117. package/src/core/geom/3d/frustum/read_frustum_corner.d.ts.map +1 -0
  118. package/src/core/geom/3d/frustum/read_frustum_corner.js +14 -0
  119. package/src/core/geom/3d/gjk/gjk.d.ts.map +1 -0
  120. package/src/{engine/physics → core/geom/3d}/gjk/gjk.js +430 -372
  121. package/src/{engine/physics → core/geom/3d}/gjk/gjk_epa_penetration.d.ts +8 -5
  122. package/src/core/geom/3d/gjk/gjk_epa_penetration.d.ts.map +1 -0
  123. package/src/{engine/physics → core/geom/3d}/gjk/gjk_epa_penetration.js +520 -544
  124. package/src/{engine/physics → core/geom/3d}/gjk/minkowski_support.d.ts +5 -4
  125. package/src/core/geom/3d/gjk/minkowski_support.d.ts.map +1 -0
  126. package/src/{engine/physics → core/geom/3d}/gjk/minkowski_support.js +71 -70
  127. package/src/{engine/physics → core/geom/3d}/gjk/mpr.d.ts +3 -3
  128. package/src/core/geom/3d/gjk/mpr.d.ts.map +1 -0
  129. package/src/{engine/physics → core/geom/3d}/gjk/mpr.js +368 -362
  130. package/src/{engine/physics/integration/quat_integrate.d.ts → core/geom/3d/quaternion/quat3_integrate.d.ts} +2 -2
  131. package/src/core/geom/3d/quaternion/quat3_integrate.d.ts.map +1 -0
  132. package/src/{engine/physics/integration/quat_integrate.js → core/geom/3d/quaternion/quat3_integrate.js} +1 -1
  133. package/src/{engine/physics/narrowphase/PosedShape.d.ts → core/geom/3d/shape/PosedShape3D.d.ts} +9 -8
  134. package/src/{engine/physics/narrowphase/PosedShape.d.ts.map → core/geom/3d/shape/PosedShape3D.d.ts.map} +1 -1
  135. package/src/{engine/physics/narrowphase/PosedShape.js → core/geom/3d/shape/PosedShape3D.js} +10 -9
  136. package/src/core/geom/3d/shape/TransformedShape3D.d.ts.map +1 -1
  137. package/src/core/geom/3d/shape/TransformedShape3D.js +15 -11
  138. package/src/core/geom/vec3/v3_quat3_apply_inverse.d.ts +1 -1
  139. package/src/core/geom/vec3/v3_quat3_apply_inverse.js +1 -1
  140. package/src/core/math/complex/complex_add.d.ts +1 -1
  141. package/src/core/math/complex/complex_add.d.ts.map +1 -1
  142. package/src/core/math/complex/complex_add.js +12 -3
  143. package/src/core/math/complex/complex_div.d.ts +1 -1
  144. package/src/core/math/complex/complex_div.d.ts.map +1 -1
  145. package/src/core/math/complex/complex_div.js +11 -4
  146. package/src/core/math/complex/complex_mul.d.ts +1 -1
  147. package/src/core/math/complex/complex_mul.d.ts.map +1 -1
  148. package/src/core/math/complex/complex_mul.js +10 -3
  149. package/src/core/math/complex/complex_sub.d.ts +1 -1
  150. package/src/core/math/complex/complex_sub.d.ts.map +1 -1
  151. package/src/core/math/complex/complex_sub.js +12 -3
  152. package/src/{engine/physics/fluid/solver/optimal_sor_omega.d.ts → core/math/linalg/sor_optimal_omega.d.ts} +4 -3
  153. package/src/core/math/linalg/sor_optimal_omega.d.ts.map +1 -0
  154. package/src/{engine/physics/fluid/solver/optimal_sor_omega.js → core/math/linalg/sor_optimal_omega.js} +4 -3
  155. package/src/core/math/lookup/ParameterLookupTable.d.ts +123 -0
  156. package/src/core/math/lookup/ParameterLookupTable.d.ts.map +1 -0
  157. package/src/core/math/lookup/ParameterLookupTable.js +495 -0
  158. package/src/core/math/lookup/ParameterLookupTableFlags.d.ts +5 -0
  159. package/src/core/math/lookup/ParameterLookupTableFlags.d.ts.map +1 -0
  160. package/src/core/math/lookup/ParameterLookupTableFlags.js +6 -0
  161. package/src/core/math/physics/kinematics/computeInterceptPoint.d.ts.map +1 -0
  162. package/src/{engine/physics → core/math/physics/kinematics}/computeInterceptPoint.js +79 -79
  163. package/src/core/math/physics/mie/ri_air.d.ts.map +1 -1
  164. package/src/core/math/physics/mie/ri_air.js +1 -3
  165. package/src/core/math/physics/mie/ri_ammonium_sulfate.d.ts.map +1 -1
  166. package/src/core/math/physics/mie/ri_ammonium_sulfate.js +1 -3
  167. package/src/core/math/physics/mie/ri_brine.d.ts.map +1 -1
  168. package/src/core/math/physics/mie/ri_brine.js +1 -3
  169. package/src/core/math/physics/mie/ri_dust.d.ts.map +1 -1
  170. package/src/core/math/physics/mie/ri_dust.js +1 -3
  171. package/src/core/math/physics/mie/ri_pollen.d.ts.map +1 -1
  172. package/src/core/math/physics/mie/ri_pollen.js +1 -3
  173. package/src/core/math/physics/mie/ri_smoke.d.ts.map +1 -1
  174. package/src/core/math/physics/mie/ri_smoke.js +1 -3
  175. package/src/core/math/physics/mie/ri_soot.d.ts.map +1 -1
  176. package/src/core/math/physics/mie/ri_soot.js +1 -3
  177. package/src/core/math/physics/mie/ri_water.d.ts.map +1 -1
  178. package/src/core/math/physics/mie/ri_water.js +1 -3
  179. package/src/core/math/random/random_pick_weighted_index.d.ts +10 -0
  180. package/src/core/math/random/random_pick_weighted_index.d.ts.map +1 -0
  181. package/src/core/math/random/random_pick_weighted_index.js +26 -0
  182. package/src/core/model/node-graph/NodeGraph.d.ts +9 -0
  183. package/src/core/model/node-graph/NodeGraph.d.ts.map +1 -1
  184. package/src/core/model/node-graph/NodeGraph.js +38 -0
  185. package/src/core/model/node-graph/visual/NodeGraphVisualData.d.ts +23 -0
  186. package/src/core/model/node-graph/visual/NodeGraphVisualData.d.ts.map +1 -1
  187. package/src/core/model/node-graph/visual/NodeGraphVisualData.js +54 -0
  188. package/src/core/path/convertPathToURL.d.ts +9 -0
  189. package/src/core/path/convertPathToURL.d.ts.map +1 -0
  190. package/src/core/path/convertPathToURL.js +107 -0
  191. package/src/core/process/worker/WorkerBuilder.js +1 -1
  192. package/src/core/process/worker/extractTransferables.js +1 -1
  193. package/src/engine/animation/curve/draw/build_tangent_editor.d.ts.map +1 -1
  194. package/src/engine/animation/curve/draw/build_tangent_editor.js +8 -1
  195. package/src/engine/animation/curve/editor/createKeyframeDraggableAspect.d.ts.map +1 -1
  196. package/src/engine/animation/curve/editor/createKeyframeDraggableAspect.js +11 -5
  197. package/src/engine/asset/Asset.d.ts.map +1 -1
  198. package/src/engine/asset/Asset.js +16 -6
  199. package/src/engine/asset/AssetManager.d.ts +61 -52
  200. package/src/engine/asset/AssetManager.d.ts.map +1 -1
  201. package/src/engine/asset/AssetManager.js +1411 -1045
  202. package/src/engine/asset/AssetRequest.d.ts +1 -1
  203. package/src/engine/asset/AssetRequest.d.ts.map +1 -1
  204. package/src/engine/asset/AssetRequest.js +1 -1
  205. package/src/engine/asset/AssetRequestScope.d.ts.map +1 -1
  206. package/src/engine/asset/AssetRequestScope.js +7 -0
  207. package/src/engine/asset/PendingAsset.d.ts +32 -1
  208. package/src/engine/asset/PendingAsset.d.ts.map +1 -1
  209. package/src/engine/asset/PendingAsset.js +108 -61
  210. package/src/engine/asset/loaders/ArrayBufferLoader.js +2 -2
  211. package/src/engine/asset/loaders/AssetLoader.d.ts.map +1 -1
  212. package/src/engine/asset/loaders/AssetLoader.js +19 -2
  213. package/src/engine/asset/loaders/GLTFAssetLoader.d.ts.map +1 -1
  214. package/src/engine/asset/loaders/GLTFAssetLoader.js +123 -114
  215. package/src/engine/asset/loaders/JavascriptAssetLoader.d.ts +1 -1
  216. package/src/engine/asset/loaders/JavascriptAssetLoader.d.ts.map +1 -1
  217. package/src/engine/asset/loaders/JavascriptAssetLoader.js +31 -47
  218. package/src/engine/asset/loaders/JsonAssetLoader.js +1 -1
  219. package/src/engine/asset/loaders/SVGAssetLoader.js +2 -2
  220. package/src/engine/asset/loaders/SoundAssetLoader.js +1 -1
  221. package/src/engine/asset/loaders/TextAssetLoader.js +2 -2
  222. package/src/{core → engine/asset/loaders}/font/FontAsset.d.ts +1 -1
  223. package/src/engine/asset/loaders/font/FontAsset.d.ts.map +1 -0
  224. package/src/{core → engine/asset/loaders}/font/FontAsset.js +21 -21
  225. package/src/{core → engine/asset/loaders}/font/FontAssetLoader.d.ts +1 -1
  226. package/src/engine/asset/loaders/font/FontAssetLoader.d.ts.map +1 -0
  227. package/src/{core → engine/asset/loaders}/font/FontAssetLoader.js +20 -20
  228. package/src/engine/asset/loaders/image/ImageRGBADataLoader.d.ts +1 -1
  229. package/src/engine/asset/loaders/image/ImageRGBADataLoader.d.ts.map +1 -1
  230. package/src/engine/asset/loaders/image/ImageRGBADataLoader.js +11 -20
  231. package/src/engine/asset/loaders/texture/TextureAssetLoader.d.ts.map +1 -1
  232. package/src/engine/asset/loaders/texture/TextureAssetLoader.js +8 -2
  233. package/src/engine/asset/preloader/AssetPreloader.js +1 -1
  234. package/src/engine/ecs/sockets/serialization/AttachmentSocketsAssetLoader.d.ts +1 -1
  235. package/src/engine/ecs/sockets/serialization/AttachmentSocketsAssetLoader.d.ts.map +1 -1
  236. package/src/engine/ecs/sockets/serialization/AttachmentSocketsAssetLoader.js +19 -22
  237. package/src/engine/graphics/FrameThrottle.d.ts +1 -7
  238. package/src/engine/graphics/FrameThrottle.d.ts.map +1 -1
  239. package/src/engine/graphics/FrameThrottle.js +2 -24
  240. package/src/{core/geom/3d/shape/util → engine/graphics/debug}/shape_to_visual_entity.d.ts +1 -1
  241. package/src/engine/graphics/debug/shape_to_visual_entity.d.ts.map +1 -0
  242. package/src/{core/geom/3d/shape/util → engine/graphics/debug}/shape_to_visual_entity.js +159 -159
  243. package/src/{core/geom/3d/tetrahedra → engine/graphics/debug}/visualize_tetrahedral_mesh.d.ts +1 -1
  244. package/src/engine/graphics/debug/visualize_tetrahedral_mesh.d.ts.map +1 -0
  245. package/src/{core/geom/3d/tetrahedra → engine/graphics/debug}/visualize_tetrahedral_mesh.js +46 -46
  246. package/src/engine/graphics/ecs/animation/animator/graph/definition/serialization/AnimationGraphDefinitionAssetLoader.d.ts +1 -1
  247. package/src/engine/graphics/ecs/animation/animator/graph/definition/serialization/AnimationGraphDefinitionAssetLoader.d.ts.map +1 -1
  248. package/src/engine/graphics/ecs/animation/animator/graph/definition/serialization/AnimationGraphDefinitionAssetLoader.js +22 -32
  249. package/src/engine/graphics/particles/particular/engine/emitter/serde/ParameterLookupTableSerializationAdapter.d.ts.map +1 -1
  250. package/src/engine/graphics/particles/particular/engine/emitter/serde/ParameterLookupTableSerializationAdapter.js +2 -76
  251. package/src/engine/graphics/particles/particular/engine/parameter/ParameterLookupTable.d.ts.map +1 -1
  252. package/src/engine/graphics/particles/particular/engine/parameter/ParameterLookupTable.js +2 -427
  253. package/src/engine/graphics/particles/particular/engine/parameter/ParameterLookupTableFlags.d.ts +1 -4
  254. package/src/engine/graphics/particles/particular/engine/parameter/ParameterLookupTableFlags.d.ts.map +1 -1
  255. package/src/engine/graphics/particles/particular/engine/parameter/ParameterLookupTableFlags.js +2 -6
  256. package/src/engine/graphics/particles/particular/engine/utils/volume/prototypeParticleVolume.js +1 -1
  257. package/src/engine/graphics/render/forward_plus/read_frustum_corner.d.ts +1 -8
  258. package/src/engine/graphics/render/forward_plus/read_frustum_corner.d.ts.map +1 -1
  259. package/src/engine/graphics/render/forward_plus/read_frustum_corner.js +2 -14
  260. package/src/engine/graphics/sh3/path_tracer/geometry/compute_triangle_group_aabb3.d.ts +1 -11
  261. package/src/engine/graphics/sh3/path_tracer/geometry/compute_triangle_group_aabb3.d.ts.map +1 -1
  262. package/src/engine/graphics/sh3/path_tracer/geometry/compute_triangle_group_aabb3.js +2 -46
  263. package/src/engine/graphics/sh3/prototypeSH3Probe.js +1 -1
  264. package/src/engine/graphics/texture/3d/scs3d_sample_linear3.d.ts +27 -0
  265. package/src/engine/graphics/texture/3d/scs3d_sample_linear3.d.ts.map +1 -0
  266. package/src/engine/graphics/texture/3d/scs3d_sample_linear3.js +81 -0
  267. package/src/engine/graphics/texture/isImageBitmap.d.ts +1 -6
  268. package/src/engine/graphics/texture/isImageBitmap.d.ts.map +1 -1
  269. package/src/engine/graphics/texture/isImageBitmap.js +2 -12
  270. package/src/{core/process/action → engine/intelligence/behavior/util}/AsynchronousDelayAction.d.ts +2 -2
  271. package/src/engine/intelligence/behavior/util/AsynchronousDelayAction.d.ts.map +1 -0
  272. package/src/{core/process/action → engine/intelligence/behavior/util}/AsynchronousDelayAction.js +55 -55
  273. package/src/engine/network/NetworkSession.d.ts +12 -1
  274. package/src/engine/network/NetworkSession.d.ts.map +1 -1
  275. package/src/engine/network/NetworkSession.js +52 -1
  276. package/src/engine/network/README.md +45 -0
  277. package/src/engine/network/convertPathToURL.d.ts +1 -8
  278. package/src/engine/network/convertPathToURL.d.ts.map +1 -1
  279. package/src/engine/network/convertPathToURL.js +2 -107
  280. package/src/engine/network/core/quantize/quantize_float.d.ts.map +1 -1
  281. package/src/engine/network/core/quantize/quantize_float.js +7 -0
  282. package/src/engine/network/core/quantize/quantize_position.d.ts.map +1 -1
  283. package/src/engine/network/core/quantize/quantize_position.js +12 -1
  284. package/src/engine/network/orchestrator/NetworkPeer.d.ts.map +1 -1
  285. package/src/engine/network/orchestrator/NetworkPeer.js +15 -1
  286. package/src/engine/network/replication/Replicator.d.ts +8 -0
  287. package/src/engine/network/replication/Replicator.d.ts.map +1 -1
  288. package/src/engine/network/replication/Replicator.js +48 -0
  289. package/src/engine/network/transport/Channel.d.ts.map +1 -1
  290. package/src/engine/network/transport/Channel.js +46 -12
  291. package/src/engine/network/transport/ReliableCommandPipeline.d.ts +16 -0
  292. package/src/engine/network/transport/ReliableCommandPipeline.d.ts.map +1 -1
  293. package/src/engine/network/transport/ReliableCommandPipeline.js +29 -0
  294. package/src/engine/network/transport/adapters/NodeUDPTransport.d.ts.map +1 -1
  295. package/src/engine/network/transport/adapters/NodeUDPTransport.js +7 -1
  296. package/src/engine/network/transport/fragments/packet_size.d.ts +5 -5
  297. package/src/engine/network/transport/fragments/packet_size.d.ts.map +1 -1
  298. package/src/engine/network/transport/fragments/packet_size.js +5 -5
  299. package/src/engine/physics/BULLET_REVIEW.md +1 -1
  300. package/src/engine/physics/JOLT_REVIEW.md +2 -2
  301. package/src/engine/physics/PLAN.md +1094 -945
  302. package/src/engine/physics/RAPIER_REVIEW.md +2 -2
  303. package/src/engine/physics/body/BodyStorage.d.ts +2 -12
  304. package/src/engine/physics/body/BodyStorage.d.ts.map +1 -1
  305. package/src/engine/physics/body/BodyStorage.js +406 -452
  306. package/src/engine/physics/body/SolverBodyState.d.ts.map +1 -1
  307. package/src/engine/physics/body/SolverBodyState.js +12 -3
  308. package/src/engine/physics/broadphase/compute_fat_world_aabb.d.ts +28 -3
  309. package/src/engine/physics/broadphase/compute_fat_world_aabb.d.ts.map +1 -1
  310. package/src/engine/physics/broadphase/compute_fat_world_aabb.js +60 -24
  311. package/src/engine/physics/broadphase/generate_pairs.d.ts +9 -5
  312. package/src/engine/physics/broadphase/generate_pairs.d.ts.map +1 -1
  313. package/src/engine/physics/broadphase/generate_pairs.js +52 -37
  314. package/src/engine/physics/ccd/linear_sweep.d.ts +15 -5
  315. package/src/engine/physics/ccd/linear_sweep.d.ts.map +1 -1
  316. package/src/engine/physics/ccd/linear_sweep.js +122 -40
  317. package/src/engine/physics/constraint/solve_constraints.d.ts.map +1 -1
  318. package/src/engine/physics/constraint/solve_constraints.js +830 -805
  319. package/src/engine/physics/contact/ManifoldStore.d.ts +91 -16
  320. package/src/engine/physics/contact/ManifoldStore.d.ts.map +1 -1
  321. package/src/engine/physics/contact/ManifoldStore.js +204 -60
  322. package/src/engine/physics/ecs/BodyKind.d.ts +7 -3
  323. package/src/engine/physics/ecs/BodyKind.d.ts.map +1 -1
  324. package/src/engine/physics/ecs/BodyKind.js +29 -25
  325. package/src/engine/physics/ecs/Collider.d.ts +7 -0
  326. package/src/engine/physics/ecs/Collider.d.ts.map +1 -1
  327. package/src/engine/physics/ecs/Collider.js +7 -0
  328. package/src/engine/physics/ecs/ColliderSerializationAdapter.js +1 -1
  329. package/src/engine/physics/ecs/PhysicsSystem.d.ts +110 -6
  330. package/src/engine/physics/ecs/PhysicsSystem.d.ts.map +1 -1
  331. package/src/engine/physics/ecs/PhysicsSystem.js +467 -45
  332. package/src/engine/physics/ecs/RigidBody.d.ts +20 -5
  333. package/src/engine/physics/ecs/RigidBody.d.ts.map +1 -1
  334. package/src/engine/physics/ecs/RigidBody.js +307 -286
  335. package/src/engine/physics/ecs/RigidBodyFlags.d.ts +6 -3
  336. package/src/engine/physics/ecs/RigidBodyFlags.d.ts.map +1 -1
  337. package/src/engine/physics/ecs/RigidBodyFlags.js +31 -28
  338. package/src/engine/physics/ecs/RigidBodySerializationAdapter.d.ts +12 -4
  339. package/src/engine/physics/ecs/RigidBodySerializationAdapter.d.ts.map +1 -1
  340. package/src/engine/physics/ecs/RigidBodySerializationAdapter.js +19 -5
  341. package/src/engine/physics/ecs/RigidBodySerializationUpgrader_0_1.d.ts +10 -0
  342. package/src/engine/physics/ecs/RigidBodySerializationUpgrader_0_1.d.ts.map +1 -0
  343. package/src/engine/physics/ecs/RigidBodySerializationUpgrader_0_1.js +37 -0
  344. package/src/engine/physics/ecs/find_non_finite_physics_state.d.ts +28 -0
  345. package/src/engine/physics/ecs/find_non_finite_physics_state.d.ts.map +1 -0
  346. package/src/engine/physics/ecs/find_non_finite_physics_state.js +76 -0
  347. package/src/engine/physics/events/ContactEventBuffer.d.ts +11 -0
  348. package/src/engine/physics/events/ContactEventBuffer.d.ts.map +1 -1
  349. package/src/engine/physics/events/ContactEventBuffer.js +40 -0
  350. package/src/engine/physics/events/diff_manifolds.d.ts +30 -13
  351. package/src/engine/physics/events/diff_manifolds.d.ts.map +1 -1
  352. package/src/engine/physics/events/diff_manifolds.js +87 -50
  353. package/src/engine/physics/fluid/FluidField.d.ts +45 -17
  354. package/src/engine/physics/fluid/FluidField.d.ts.map +1 -1
  355. package/src/engine/physics/fluid/FluidField.js +53 -23
  356. package/src/engine/physics/fluid/FluidSimulator.d.ts +141 -5
  357. package/src/engine/physics/fluid/FluidSimulator.d.ts.map +1 -1
  358. package/src/engine/physics/fluid/FluidSimulator.js +336 -43
  359. package/src/engine/physics/fluid/REVIEW_02_PLAN.md +114 -0
  360. package/src/engine/physics/fluid/ecs/FluidComponent.d.ts +4 -3
  361. package/src/engine/physics/fluid/ecs/FluidComponent.d.ts.map +1 -1
  362. package/src/engine/physics/fluid/ecs/FluidComponent.js +4 -3
  363. package/src/engine/physics/fluid/ecs/FluidSystem.d.ts +3 -3
  364. package/src/engine/physics/fluid/effector/AmbientWindFluidEffector.d.ts +41 -0
  365. package/src/engine/physics/fluid/effector/AmbientWindFluidEffector.d.ts.map +1 -0
  366. package/src/engine/physics/fluid/effector/AmbientWindFluidEffector.js +124 -0
  367. package/src/engine/physics/fluid/effector/WakeFluidEffector.d.ts +27 -8
  368. package/src/engine/physics/fluid/effector/WakeFluidEffector.d.ts.map +1 -1
  369. package/src/engine/physics/fluid/effector/WakeFluidEffector.js +67 -18
  370. package/src/engine/physics/fluid/solver/v3_grid_advect_maccormack_scalar.d.ts +42 -0
  371. package/src/engine/physics/fluid/solver/v3_grid_advect_maccormack_scalar.d.ts.map +1 -0
  372. package/src/engine/physics/fluid/solver/v3_grid_advect_maccormack_scalar.js +136 -0
  373. package/src/engine/physics/fluid/solver/v3_grid_advect_maccormack_velocity.d.ts +37 -0
  374. package/src/engine/physics/fluid/solver/v3_grid_advect_maccormack_velocity.d.ts.map +1 -0
  375. package/src/engine/physics/fluid/solver/v3_grid_advect_maccormack_velocity.js +169 -0
  376. package/src/engine/physics/fluid/solver/v3_grid_advect_sl_velocity.d.ts +36 -0
  377. package/src/engine/physics/fluid/solver/v3_grid_advect_sl_velocity.d.ts.map +1 -0
  378. package/src/engine/physics/fluid/solver/v3_grid_advect_sl_velocity.js +100 -0
  379. package/src/engine/physics/fluid/solver/v3_grid_apply_advection_forward.d.ts +6 -0
  380. package/src/engine/physics/fluid/solver/v3_grid_apply_advection_forward.d.ts.map +1 -1
  381. package/src/engine/physics/fluid/solver/v3_grid_apply_advection_forward.js +6 -0
  382. package/src/engine/physics/fluid/solver/v3_grid_apply_diffusion.d.ts +7 -2
  383. package/src/engine/physics/fluid/solver/v3_grid_apply_diffusion.d.ts.map +1 -1
  384. package/src/engine/physics/fluid/solver/v3_grid_apply_diffusion.js +17 -12
  385. package/src/engine/physics/fluid/solver/v3_grid_apply_vorticity_confinement.d.ts +42 -0
  386. package/src/engine/physics/fluid/solver/v3_grid_apply_vorticity_confinement.d.ts.map +1 -0
  387. package/src/engine/physics/fluid/solver/v3_grid_apply_vorticity_confinement.js +131 -0
  388. package/src/engine/physics/fluid/solver/v3_grid_compute_solid_neighbour_mask.d.ts +32 -22
  389. package/src/engine/physics/fluid/solver/v3_grid_compute_solid_neighbour_mask.d.ts.map +1 -1
  390. package/src/engine/physics/fluid/solver/v3_grid_compute_solid_neighbour_mask.js +43 -26
  391. package/src/engine/physics/fluid/solver/v3_grid_patch_edges_constant.d.ts +31 -0
  392. package/src/engine/physics/fluid/solver/v3_grid_patch_edges_constant.d.ts.map +1 -0
  393. package/src/engine/physics/fluid/solver/v3_grid_patch_edges_constant.js +77 -0
  394. package/src/engine/physics/fluid/solver/v3_grid_solve_pressure.d.ts +26 -19
  395. package/src/engine/physics/fluid/solver/v3_grid_solve_pressure.d.ts.map +1 -1
  396. package/src/engine/physics/fluid/solver/v3_grid_solve_pressure.js +46 -42
  397. package/src/engine/physics/fluid/solver/v3_grid_solve_pressure_pcg.d.ts +38 -10
  398. package/src/engine/physics/fluid/solver/v3_grid_solve_pressure_pcg.d.ts.map +1 -1
  399. package/src/engine/physics/fluid/solver/v3_grid_solve_pressure_pcg.js +158 -75
  400. package/src/engine/physics/fluid/solver/v3_grid_subtract_pressure_gradient.d.ts +22 -17
  401. package/src/engine/physics/fluid/solver/v3_grid_subtract_pressure_gradient.d.ts.map +1 -1
  402. package/src/engine/physics/fluid/solver/v3_grid_subtract_pressure_gradient.js +108 -96
  403. package/src/engine/physics/inertia/world_inverse_inertia.d.ts +30 -1
  404. package/src/engine/physics/inertia/world_inverse_inertia.d.ts.map +1 -1
  405. package/src/engine/physics/inertia/world_inverse_inertia.js +160 -116
  406. package/src/engine/physics/integration/integrate_position.js +97 -97
  407. package/src/engine/physics/island/IslandBuilder.d.ts +49 -8
  408. package/src/engine/physics/island/IslandBuilder.d.ts.map +1 -1
  409. package/src/engine/physics/island/IslandBuilder.js +93 -14
  410. package/src/engine/physics/narrowphase/box_box_manifold.d.ts.map +1 -1
  411. package/src/engine/physics/narrowphase/box_box_manifold.js +683 -673
  412. package/src/engine/physics/narrowphase/box_triangle_contact.d.ts.map +1 -1
  413. package/src/engine/physics/narrowphase/box_triangle_contact.js +899 -749
  414. package/src/engine/physics/narrowphase/capsule_contacts.d.ts +27 -0
  415. package/src/engine/physics/narrowphase/capsule_contacts.d.ts.map +1 -1
  416. package/src/engine/physics/narrowphase/capsule_contacts.js +624 -459
  417. package/src/engine/physics/narrowphase/capsule_triangle_contact.d.ts.map +1 -1
  418. package/src/engine/physics/narrowphase/capsule_triangle_contact.js +58 -38
  419. package/src/engine/physics/narrowphase/compute_penetration.d.ts.map +1 -1
  420. package/src/engine/physics/narrowphase/compute_penetration.js +369 -325
  421. package/src/engine/physics/narrowphase/convex_convex_manifold.d.ts +3 -1
  422. package/src/engine/physics/narrowphase/convex_convex_manifold.d.ts.map +1 -1
  423. package/src/engine/physics/narrowphase/convex_convex_manifold.js +568 -422
  424. package/src/engine/physics/narrowphase/decomposition/heightmap_enumerate_triangles.d.ts +6 -3
  425. package/src/engine/physics/narrowphase/decomposition/heightmap_enumerate_triangles.d.ts.map +1 -1
  426. package/src/engine/physics/narrowphase/decomposition/heightmap_enumerate_triangles.js +66 -10
  427. package/src/engine/physics/narrowphase/decomposition/mesh_enumerate_triangles.d.ts +4 -1
  428. package/src/engine/physics/narrowphase/decomposition/mesh_enumerate_triangles.d.ts.map +1 -1
  429. package/src/engine/physics/narrowphase/decomposition/mesh_enumerate_triangles.js +97 -94
  430. package/src/engine/physics/narrowphase/mesh_mesh_tet_manifold.js +117 -117
  431. package/src/engine/physics/narrowphase/narrowphase_step.d.ts.map +1 -1
  432. package/src/engine/physics/narrowphase/narrowphase_step.js +1738 -1739
  433. package/src/engine/physics/narrowphase/reduce_manifold_contacts.d.ts +14 -7
  434. package/src/engine/physics/narrowphase/reduce_manifold_contacts.d.ts.map +1 -1
  435. package/src/engine/physics/narrowphase/reduce_manifold_contacts.js +74 -69
  436. package/src/engine/physics/persistence/solver_caches.d.ts +20 -0
  437. package/src/engine/physics/persistence/solver_caches.d.ts.map +1 -0
  438. package/src/engine/physics/persistence/solver_caches.js +309 -0
  439. package/src/engine/physics/queries/overlap_shape.d.ts.map +1 -1
  440. package/src/engine/physics/queries/overlap_shape.js +187 -184
  441. package/src/engine/physics/queries/raycast.d.ts +3 -2
  442. package/src/engine/physics/queries/raycast.d.ts.map +1 -1
  443. package/src/engine/physics/queries/raycast.js +37 -11
  444. package/src/engine/physics/queries/shape_cast.d.ts +18 -5
  445. package/src/engine/physics/queries/shape_cast.d.ts.map +1 -1
  446. package/src/engine/physics/queries/shape_cast.js +417 -393
  447. package/src/engine/physics/solver/solve_contacts.d.ts +22 -6
  448. package/src/engine/physics/solver/solve_contacts.d.ts.map +1 -1
  449. package/src/engine/physics/solver/solve_contacts.js +1482 -1338
  450. package/src/engine/physics/vehicle/RaycastVehicle.d.ts.map +1 -1
  451. package/src/engine/physics/vehicle/RaycastVehicle.js +344 -339
  452. package/src/engine/ui/DraggableAspect.d.ts +12 -3
  453. package/src/engine/ui/DraggableAspect.d.ts.map +1 -1
  454. package/src/engine/ui/DraggableAspect.js +115 -83
  455. package/src/generation/COORDINATES.md +54 -0
  456. package/src/generation/GridTaskGroup.js +2 -2
  457. package/src/generation/REVIEW_01_ACTION_PLAN.md +628 -0
  458. package/src/generation/automata/CaveGeneratorCellularAutomata.d.ts +9 -1
  459. package/src/generation/automata/CaveGeneratorCellularAutomata.d.ts.map +1 -1
  460. package/src/generation/automata/CaveGeneratorCellularAutomata.js +79 -59
  461. package/src/generation/automata/CellularAutomata.d.ts +6 -3
  462. package/src/generation/automata/CellularAutomata.d.ts.map +1 -1
  463. package/src/generation/automata/CellularAutomata.js +22 -19
  464. package/src/generation/filtering/CellFilter.d.ts +17 -0
  465. package/src/generation/filtering/CellFilter.d.ts.map +1 -1
  466. package/src/generation/filtering/CellFilter.js +117 -77
  467. package/src/generation/filtering/CellFilterCellMatcher.d.ts.map +1 -1
  468. package/src/generation/filtering/CellFilterCellMatcher.js +2 -0
  469. package/src/generation/filtering/boolean/CellFilterLiteralBoolean.d.ts +5 -0
  470. package/src/generation/filtering/boolean/CellFilterLiteralBoolean.d.ts.map +1 -1
  471. package/src/generation/filtering/boolean/CellFilterLiteralBoolean.js +15 -0
  472. package/src/generation/filtering/core/CellFilterBinaryOperation.d.ts +0 -1
  473. package/src/generation/filtering/core/CellFilterBinaryOperation.d.ts.map +1 -1
  474. package/src/generation/filtering/core/CellFilterBinaryOperation.js +37 -50
  475. package/src/generation/filtering/core/CellFilterOperationTertiary.d.ts +0 -1
  476. package/src/generation/filtering/core/CellFilterOperationTertiary.d.ts.map +1 -1
  477. package/src/generation/filtering/core/CellFilterOperationTertiary.js +43 -59
  478. package/src/generation/filtering/core/CellFilterUnaryOperation.d.ts +0 -1
  479. package/src/generation/filtering/core/CellFilterUnaryOperation.d.ts.map +1 -1
  480. package/src/generation/filtering/core/CellFilterUnaryOperation.js +29 -33
  481. package/src/generation/filtering/numeric/CellFilterCache.d.ts +1 -0
  482. package/src/generation/filtering/numeric/CellFilterCache.d.ts.map +1 -1
  483. package/src/generation/filtering/numeric/complex/CellFilterAngleToNormal.d.ts +3 -2
  484. package/src/generation/filtering/numeric/complex/CellFilterAngleToNormal.d.ts.map +1 -1
  485. package/src/generation/filtering/numeric/complex/CellFilterAngleToNormal.js +9 -35
  486. package/src/generation/filtering/numeric/complex/CellFilterCurvature.d.ts +0 -1
  487. package/src/generation/filtering/numeric/complex/CellFilterCurvature.d.ts.map +1 -1
  488. package/src/generation/filtering/numeric/complex/CellFilterCurvature.js +19 -43
  489. package/src/generation/filtering/numeric/complex/CellFilterFXAA.d.ts +0 -1
  490. package/src/generation/filtering/numeric/complex/CellFilterFXAA.d.ts.map +1 -1
  491. package/src/generation/filtering/numeric/complex/CellFilterFXAA.js +2 -6
  492. package/src/generation/filtering/numeric/complex/CellFilterGaussianBlur.d.ts.map +1 -1
  493. package/src/generation/filtering/numeric/complex/CellFilterGaussianBlur.js +9 -12
  494. package/src/generation/filtering/numeric/complex/CellFilterSimplexNoise.d.ts.map +1 -1
  495. package/src/generation/filtering/numeric/complex/CellFilterSimplexNoise.js +2 -1
  496. package/src/generation/filtering/numeric/complex/CellFilterSobel.d.ts +0 -1
  497. package/src/generation/filtering/numeric/complex/CellFilterSobel.d.ts.map +1 -1
  498. package/src/generation/filtering/numeric/complex/CellFilterSobel.js +2 -6
  499. package/src/generation/filtering/numeric/math/CellFilterInverseLerp.d.ts +5 -4
  500. package/src/generation/filtering/numeric/math/CellFilterInverseLerp.d.ts.map +1 -1
  501. package/src/generation/filtering/numeric/math/CellFilterInverseLerp.js +5 -4
  502. package/src/generation/filtering/numeric/process/computeFilterSurfaceNormal.d.ts +17 -0
  503. package/src/generation/filtering/numeric/process/computeFilterSurfaceNormal.d.ts.map +1 -0
  504. package/src/generation/filtering/numeric/process/computeFilterSurfaceNormal.js +42 -0
  505. package/src/generation/filtering/numeric/sampling/AbstractCellFilterSampleGridLayer.d.ts.map +1 -1
  506. package/src/generation/filtering/numeric/sampling/AbstractCellFilterSampleGridLayer.js +7 -1
  507. package/src/generation/filtering/numeric/util/populateSampler2DFromCellFilter.d.ts.map +1 -1
  508. package/src/generation/filtering/numeric/util/populateSampler2DFromCellFilter.js +7 -10
  509. package/src/generation/filtering/numeric/util/sampler_from_filter.d.ts.map +1 -1
  510. package/src/generation/filtering/numeric/util/sampler_from_filter.js +2 -1
  511. package/src/generation/grid/GridData.d.ts.map +1 -1
  512. package/src/generation/grid/GridData.js +14 -1
  513. package/src/generation/grid/actions/ContinuousGridCellAction.d.ts +10 -3
  514. package/src/generation/grid/actions/ContinuousGridCellAction.d.ts.map +1 -1
  515. package/src/generation/grid/actions/ContinuousGridCellAction.js +18 -3
  516. package/src/generation/grid/actions/ContinuousGridCellActionSetTerrainHeight.d.ts +11 -1
  517. package/src/generation/grid/actions/ContinuousGridCellActionSetTerrainHeight.d.ts.map +1 -1
  518. package/src/generation/grid/actions/ContinuousGridCellActionSetTerrainHeight.js +13 -3
  519. package/src/generation/grid/actions/ContinuousGridCellActionSetTerrainObstacle.d.ts +1 -1
  520. package/src/generation/grid/actions/ContinuousGridCellActionSetTerrainObstacle.js +2 -2
  521. package/src/generation/grid/actions/ContinuousGridCellActionWriteObstacle.d.ts +1 -1
  522. package/src/generation/grid/actions/ContinuousGridCellActionWriteObstacle.d.ts.map +1 -1
  523. package/src/generation/grid/actions/ContinuousGridCellActionWriteObstacle.js +4 -6
  524. package/src/generation/grid/coords/grid_to_texel.d.ts +9 -0
  525. package/src/generation/grid/coords/grid_to_texel.d.ts.map +1 -0
  526. package/src/generation/grid/coords/grid_to_texel.js +10 -0
  527. package/src/generation/grid/coords/texel_to_grid.d.ts +9 -0
  528. package/src/generation/grid/coords/texel_to_grid.d.ts.map +1 -0
  529. package/src/generation/grid/coords/texel_to_grid.js +10 -0
  530. package/src/generation/grid/generation/GridTaskApplyActionToCells.d.ts +2 -2
  531. package/src/generation/grid/generation/GridTaskApplyActionToCells.d.ts.map +1 -1
  532. package/src/generation/grid/generation/GridTaskApplyActionToCells.js +10 -6
  533. package/src/generation/grid/generation/GridTaskDensityMarkerDistribution.d.ts.map +1 -1
  534. package/src/generation/grid/generation/GridTaskDensityMarkerDistribution.js +20 -21
  535. package/src/generation/grid/generation/GridTaskExecuteRuleTimes.d.ts +7 -0
  536. package/src/generation/grid/generation/GridTaskExecuteRuleTimes.d.ts.map +1 -1
  537. package/src/generation/grid/generation/GridTaskExecuteRuleTimes.js +18 -10
  538. package/src/generation/grid/generation/discrete/GridTaskCellularAutomata.d.ts.map +1 -1
  539. package/src/generation/grid/generation/discrete/GridTaskCellularAutomata.js +16 -7
  540. package/src/generation/grid/generation/discrete/GridTaskConnectRooms.d.ts +5 -3
  541. package/src/generation/grid/generation/discrete/GridTaskConnectRooms.d.ts.map +1 -1
  542. package/src/generation/grid/generation/discrete/GridTaskConnectRooms.js +26 -23
  543. package/src/generation/grid/generation/discrete/layer/GridTaskBuildSourceDistanceMap.d.ts.map +1 -1
  544. package/src/generation/grid/generation/discrete/layer/GridTaskBuildSourceDistanceMap.js +10 -1
  545. package/src/generation/grid/generation/grid/select/CellSupplierBestN.d.ts.map +1 -1
  546. package/src/generation/grid/generation/grid/select/CellSupplierBestN.js +4 -0
  547. package/src/generation/grid/generation/road/GridTaskGenerateRoads.d.ts +15 -8
  548. package/src/generation/grid/generation/road/GridTaskGenerateRoads.d.ts.map +1 -1
  549. package/src/generation/grid/generation/road/GridTaskGenerateRoads.js +89 -92
  550. package/src/generation/markers/GridActionRuleSet.d.ts.map +1 -1
  551. package/src/generation/markers/GridActionRuleSet.js +10 -2
  552. package/src/generation/markers/GridCellActionPlaceMarker.d.ts +11 -0
  553. package/src/generation/markers/GridCellActionPlaceMarker.d.ts.map +1 -1
  554. package/src/generation/markers/GridCellActionPlaceMarker.js +20 -3
  555. package/src/generation/markers/GridCellActionPlaceMarkerGroup.d.ts +3 -1
  556. package/src/generation/markers/GridCellActionPlaceMarkerGroup.d.ts.map +1 -1
  557. package/src/generation/markers/GridCellActionPlaceMarkerGroup.js +9 -2
  558. package/src/generation/markers/MarkerNode.d.ts +8 -3
  559. package/src/generation/markers/MarkerNode.d.ts.map +1 -1
  560. package/src/generation/markers/MarkerNode.js +12 -5
  561. package/src/generation/markers/actions/MarkerNodeActionEntityPlacement.js +1 -1
  562. package/src/generation/markers/actions/placement/MarkerNodeEntityProcessor.d.ts +1 -1
  563. package/src/generation/markers/actions/placement/MarkerNodeEntityProcessor.d.ts.map +1 -1
  564. package/src/generation/markers/actions/placement/MarkerNodeEntityProcessor.js +1 -1
  565. package/src/generation/markers/actions/placement/MarkerNodeEntityProcessorClingToTerrain.d.ts +1 -1
  566. package/src/generation/markers/actions/placement/MarkerNodeEntityProcessorClingToTerrain.d.ts.map +1 -1
  567. package/src/generation/markers/actions/placement/MarkerNodeEntityProcessorClingToTerrain.js +1 -1
  568. package/src/generation/markers/actions/placement/MarkerNodeEntityProcessorRandomRotation.d.ts +1 -1
  569. package/src/generation/markers/actions/placement/MarkerNodeEntityProcessorRandomRotation.d.ts.map +1 -1
  570. package/src/generation/markers/actions/placement/MarkerNodeEntityProcessorRandomRotation.js +2 -2
  571. package/src/generation/markers/actions/placement/MarkerNodeEntityProcessorSequence.d.ts +1 -1
  572. package/src/generation/markers/actions/placement/MarkerNodeEntityProcessorSequence.d.ts.map +1 -1
  573. package/src/generation/markers/actions/placement/MarkerNodeEntityProcessorSequence.js +2 -2
  574. package/src/generation/markers/actions/probability/MarkerNodeActionSelectWeighted.d.ts.map +1 -1
  575. package/src/generation/markers/actions/probability/MarkerNodeActionSelectWeighted.js +6 -4
  576. package/src/generation/markers/actions/probability/MarkerNodeActionWeightedElement.d.ts.map +1 -1
  577. package/src/generation/markers/actions/probability/MarkerNodeActionWeightedElement.js +1 -3
  578. package/src/generation/markers/actions/terrain/MarkerNodeActionPaintTerrain.d.ts.map +1 -1
  579. package/src/generation/markers/actions/terrain/MarkerNodeActionPaintTerrain.js +12 -11
  580. package/src/generation/markers/matcher/MarkerNodeMatcherAnd.js +2 -2
  581. package/src/generation/markers/transform/MarkerNodeTransformer.d.ts +4 -1
  582. package/src/generation/markers/transform/MarkerNodeTransformer.d.ts.map +1 -1
  583. package/src/generation/markers/transform/MarkerNodeTransformer.js +4 -1
  584. package/src/generation/markers/transform/MarkerNodeTransformerAddPositionYFromFilter.d.ts.map +1 -1
  585. package/src/generation/markers/transform/MarkerNodeTransformerAddPositionYFromFilter.js +1 -3
  586. package/src/generation/markers/transform/MarkerNodeTransformerOffsetPosition.d.ts +5 -0
  587. package/src/generation/markers/transform/MarkerNodeTransformerOffsetPosition.d.ts.map +1 -1
  588. package/src/generation/markers/transform/MarkerNodeTransformerOffsetPosition.js +15 -0
  589. package/src/generation/markers/transform/MarkerNodeTransformerRecordProperty.d.ts.map +1 -1
  590. package/src/generation/markers/transform/MarkerNodeTransformerRecordProperty.js +1 -3
  591. package/src/generation/markers/transform/MarkerNodeTransformerYRotateByFilter.d.ts.map +1 -1
  592. package/src/generation/markers/transform/MarkerNodeTransformerYRotateByFilter.js +2 -4
  593. package/src/generation/markers/transform/MarkerNodeTransformerYRotateByFilterGradient.d.ts.map +1 -1
  594. package/src/generation/markers/transform/MarkerNodeTransformerYRotateByFilterGradient.js +1 -3
  595. package/src/generation/placement/GridCellPlacementRule.d.ts.map +1 -1
  596. package/src/generation/placement/GridCellPlacementRule.js +1 -3
  597. package/src/generation/placement/action/GridCellActionWriteFilterToLayer.d.ts.map +1 -1
  598. package/src/generation/placement/action/GridCellActionWriteFilterToLayer.js +8 -10
  599. package/src/generation/placement/action/random/weighted/CellActionSelectWeightedRandom.d.ts.map +1 -1
  600. package/src/generation/placement/action/random/weighted/CellActionSelectWeightedRandom.js +6 -4
  601. package/src/generation/placement/action/random/weighted/WeightedGridCellAction.d.ts.map +1 -1
  602. package/src/generation/placement/action/random/weighted/WeightedGridCellAction.js +1 -3
  603. package/src/generation/rules/CellMatcher.d.ts +3 -1
  604. package/src/generation/rules/CellMatcher.d.ts.map +1 -1
  605. package/src/generation/rules/CellMatcher.js +3 -1
  606. package/src/generation/rules/CellMatcherFromFilter.d.ts.map +1 -1
  607. package/src/generation/rules/CellMatcherFromFilter.js +1 -3
  608. package/src/generation/rules/CellMatcherLayerBitMaskTest.d.ts.map +1 -1
  609. package/src/generation/rules/CellMatcherLayerBitMaskTest.js +6 -20
  610. package/src/generation/test_support/executeTaskTreeSync.d.ts +9 -0
  611. package/src/generation/test_support/executeTaskTreeSync.d.ts.map +1 -0
  612. package/src/generation/test_support/executeTaskTreeSync.js +78 -0
  613. package/src/generation/theme/TerrainLayerRuleAggregator.d.ts +2 -1
  614. package/src/generation/theme/TerrainLayerRuleAggregator.d.ts.map +1 -1
  615. package/src/generation/theme/TerrainLayerRuleAggregator.js +9 -6
  616. package/src/generation/theme/Theme.d.ts +1 -1
  617. package/src/generation/theme/Theme.d.ts.map +1 -1
  618. package/src/generation/theme/Theme.js +2 -2
  619. package/src/generation/theme/ThemeEngine.d.ts +3 -3
  620. package/src/generation/theme/ThemeEngine.d.ts.map +1 -1
  621. package/src/generation/theme/ThemeEngine.js +26 -16
  622. package/src/generation/theme/cell/CellProcessingRule.d.ts +3 -3
  623. package/src/generation/theme/cell/CellProcessingRule.d.ts.map +1 -1
  624. package/src/generation/theme/cell/CellProcessingRule.js +6 -10
  625. package/src/generation/theme/cell/CellProcessingRuleSet.d.ts +1 -1
  626. package/src/generation/theme/cell/CellProcessingRuleSet.d.ts.map +1 -1
  627. package/src/generation/theme/cell/CellProcessingRuleSet.js +2 -2
  628. package/src/view/common/ListView.js +1 -1
  629. package/src/view/elements/BottomLeftResizeHandleView.d.ts.map +1 -1
  630. package/src/view/elements/BottomLeftResizeHandleView.js +13 -5
  631. package/src/core/font/FontAsset.d.ts.map +0 -1
  632. package/src/core/font/FontAssetLoader.d.ts.map +0 -1
  633. package/src/core/geom/3d/shape/util/shape_to_visual_entity.d.ts.map +0 -1
  634. package/src/core/geom/3d/tetrahedra/visualize_tetrahedral_mesh.d.ts.map +0 -1
  635. package/src/core/process/action/AsynchronousDelayAction.d.ts.map +0 -1
  636. package/src/engine/physics/computeInterceptPoint.d.ts.map +0 -1
  637. package/src/engine/physics/fluid/solver/optimal_sor_omega.d.ts.map +0 -1
  638. package/src/engine/physics/gjk/gjk.d.ts.map +0 -1
  639. package/src/engine/physics/gjk/gjk_epa_penetration.d.ts.map +0 -1
  640. package/src/engine/physics/gjk/minkowski_support.d.ts.map +0 -1
  641. package/src/engine/physics/gjk/mpr.d.ts.map +0 -1
  642. package/src/engine/physics/integration/quat_integrate.d.ts.map +0 -1
  643. package/src/engine/physics/island/union_find.d.ts.map +0 -1
  644. package/src/engine/physics/narrowphase/clip_against_axis_uv.d.ts.map +0 -1
  645. package/src/engine/physics/narrowphase/decomposition/aabb_world_to_local.d.ts.map +0 -1
  646. package/src/generation/grid/generation/discrete/layer/GridTaskDistanceToMarkers.d.ts +0 -21
  647. package/src/generation/grid/generation/discrete/layer/GridTaskDistanceToMarkers.d.ts.map +0 -1
  648. package/src/generation/grid/generation/discrete/layer/GridTaskDistanceToMarkers.js +0 -68
  649. package/src/generation/grid/generation/grid/GridTaskGridAlignedNodeGenerator.d.ts +0 -10
  650. package/src/generation/grid/generation/grid/GridTaskGridAlignedNodeGenerator.d.ts.map +0 -1
  651. package/src/generation/grid/generation/grid/GridTaskGridAlignedNodeGenerator.js +0 -17
  652. /package/src/{engine/physics → core/geom/3d}/gjk/NOTES.md +0 -0
  653. /package/src/{engine/physics → core/geom/3d}/gjk/gjk.d.ts +0 -0
  654. /package/src/{engine/physics → core/math/physics/kinematics}/computeInterceptPoint.d.ts +0 -0
@@ -1,6 +1,7 @@
1
1
  import { assert } from "../../../core/assert.js";
2
2
  import { BinaryBuffer } from "../../../core/binary/BinaryBuffer.js";
3
3
  import { BVH } from "../../../core/bvh2/bvh3/BVH.js";
4
+ import { bvh_query_user_data_overlaps_aabb } from "../../../core/bvh2/bvh3/query/bvh_query_user_data_overlaps_aabb.js";
4
5
  import { returnTrue } from "../../../core/function/returnTrue.js";
5
6
  import { aabb3_transform_oriented } from "../../../core/geom/3d/aabb/aabb3_transform_oriented.js";
6
7
  import Vector3 from "../../../core/geom/Vector3.js";
@@ -11,7 +12,7 @@ import { Transform } from "../../ecs/transform/Transform.js";
11
12
  import { Interpolated } from "../../interpolation/Interpolated.js";
12
13
  import { body_id_index, BodyStorage } from "../body/BodyStorage.js";
13
14
  import { SBS_STRIDE, SolverBodyState } from "../body/SolverBodyState.js";
14
- import { compute_fat_world_aabb } from "../broadphase/compute_fat_world_aabb.js";
15
+ import { compute_world_aabb, fatten_world_aabb } from "../broadphase/compute_fat_world_aabb.js";
15
16
  import { generate_pairs } from "../broadphase/generate_pairs.js";
16
17
  import { PairList } from "../broadphase/PairList.js";
17
18
  import { ccd_resolve } from "../ccd/linear_sweep.js";
@@ -38,6 +39,7 @@ import {
38
39
  } from "../solver/solve_contacts.js";
39
40
  import { BodyKind } from "./BodyKind.js";
40
41
  import { Collider, COLLIDER_UNBOUND } from "./Collider.js";
42
+ import { find_non_finite_physics_state } from "./find_non_finite_physics_state.js";
41
43
  import { JOINT_UNALLOCATED, JOINT_WORLD } from "./Joint.js";
42
44
  import { PhysicsEvents } from "./PhysicsEvents.js";
43
45
  import { RIGID_BODY_UNALLOCATED, RigidBody } from "./RigidBody.js";
@@ -50,6 +52,13 @@ import { SleepState } from "./SleepState.js";
50
52
  */
51
53
  const scratch_angular_delta = new Float64Array(3);
52
54
 
55
+ /**
56
+ * Scratch for {@link applyImpulseAt}'s LockRot*-masked inverse-inertia
57
+ * diagonal (the same mask {@link SolverBodyState#gather} applies).
58
+ * @type {{x: number, y: number, z: number}}
59
+ */
60
+ const scratch_locked_inertia = { x: 0, y: 0, z: 0 };
61
+
53
62
  /**
54
63
  * Reusable scratch buffer for world-AABB construction so the link path is
55
64
  * allocation-free in steady state.
@@ -64,6 +73,29 @@ const scratch_world_aabb = new Float64Array(6);
64
73
  */
65
74
  const scratch_local_aabb = new Float64Array(6);
66
75
 
76
+ /**
77
+ * Candidate buffer for {@link PhysicsSystem#__wake_sleepers_overlapping_leaf}.
78
+ * Grows by doubling: a large removed support (a level floor) can overlap many
79
+ * sleeping bodies, all of which must wake.
80
+ * @type {Uint32Array}
81
+ */
82
+ let scratch_wake_candidates = new Uint32Array(64);
83
+
84
+ /**
85
+ * Scratch for a leaf's currently-stored fat AABB during the stage-2
86
+ * containment test (refit skip).
87
+ * @type {Float64Array}
88
+ */
89
+ const scratch_stored_aabb = new Float64Array(6);
90
+
91
+ /**
92
+ * Scratch boxes for {@link PhysicsSystem#__swept_proximity} — the mover's
93
+ * velocity-swept tight AABB and the sleeper's tight AABB.
94
+ * @type {Float64Array}
95
+ */
96
+ const scratch_prox_mover = new Float64Array(6);
97
+ const scratch_prox_sleeper = new Float64Array(6);
98
+
67
99
  /**
68
100
  * Rigid-body physics system.
69
101
  *
@@ -118,8 +150,10 @@ export class PhysicsSystem extends System {
118
150
  this.manifolds = new ManifoldStore();
119
151
 
120
152
  /**
121
- * Per-frame list of broadphase-overlapping pairs (canonical
122
- * `(min, max)`). Cleared at the top of each step.
153
+ * Per-frame list of broadphase-overlapping pairs, each in
154
+ * entity-canonical role order (A = the smaller entity id — see
155
+ * generate_pairs). Cleared at the top of each step; purely
156
+ * intra-step state.
123
157
  * @type {PairList}
124
158
  */
125
159
  this.pairs = new PairList();
@@ -197,6 +231,26 @@ export class PhysicsSystem extends System {
197
231
  */
198
232
  this.positionIterations = 1;
199
233
 
234
+ /**
235
+ * Contact softness frequency, Hz (Box2D-v3 soft step, hybrid form:
236
+ * the velocity rows get the hertz/ζ-derived mass + impulse-decay
237
+ * scales; penetration recovery stays in the split-impulse position
238
+ * pass). The decay term is what lets resting stacks converge
239
+ * asymptotically instead of ringing in the hard form's limit cycle
240
+ * just above the sleep threshold. Clamped per step to an eighth of
241
+ * the substep rate. `0` = hard contacts (bit-exact legacy rows).
242
+ * Pairs with a non-dynamic side use 2× this frequency (stiffer, so
243
+ * piles don't sag into the ground). @type {number}
244
+ */
245
+ this.contactHertz = 30;
246
+
247
+ /**
248
+ * Contact damping ratio ζ for the soft scales — heavily over-damped
249
+ * by design (Box2D v3 default), so contacts never oscillate.
250
+ * @type {number}
251
+ */
252
+ this.contactDampingRatio = 10;
253
+
200
254
  /**
201
255
  * Reusable contact-event payload. Listeners must copy any fields they
202
256
  * intend to retain past their own scope. Reset before each dispatch.
@@ -266,6 +320,22 @@ export class PhysicsSystem extends System {
266
320
  */
267
321
  this.__joint_free = [];
268
322
 
323
+ /**
324
+ * Live joints in CANONICAL SOLVE ORDER: ascending `(entityA,
325
+ * entityB)`, equal keys in link order. The id-indexed
326
+ * {@link __joints} registry reflects link/unlink HISTORY (slot
327
+ * reuse), which two engines holding identical joints need not
328
+ * share — the joint solver's Gauss-Seidel sweep must consume
329
+ * joints in an order derivable from state alone or the engines
330
+ * diverge. Maintained by {@link link_joint} / {@link unlink_joint};
331
+ * consumed by the substep loop. Multiple joints between the SAME
332
+ * entity pair keep their relative link order — reconstruction
333
+ * replays links in the same order, so that too is state-derived.
334
+ * @private
335
+ * @type {Joint[]}
336
+ */
337
+ this.__joints_sorted = [];
338
+
269
339
  /**
270
340
  * Velocity iterations per substep for the joint solver. Joints (and
271
341
  * especially joint chains) want a few more iterations than contacts to
@@ -491,6 +561,43 @@ export class PhysicsSystem extends System {
491
561
  bvh.release_node(node);
492
562
  }
493
563
 
564
+ /**
565
+ * Wake every sleeping dynamic body whose broadphase leaf overlaps the
566
+ * given leaf's AABB. Called BEFORE removing a NON-Dynamic body's leaf
567
+ * (unlink / collider detach): statics and kinematics join no sleep group,
568
+ * their sleepers' manifolds are dormant-frozen, and the broadphase never
569
+ * revisits sleeping bodies — so without this, a pile resting on the
570
+ * removed support would sleep in mid-air forever.
571
+ *
572
+ * Dynamic removals don't need it: a sleeping pile and its dynamic support
573
+ * slept as one island and share a sleep group, which unlink already
574
+ * dissolves by waking the group.
575
+ *
576
+ * @private
577
+ * @param {BVH} bvh tree currently holding `node`
578
+ * @param {number} node leaf about to be removed
579
+ */
580
+ __wake_sleepers_overlapping_leaf(bvh, node) {
581
+ bvh.node_get_aabb(node, scratch_world_aabb);
582
+
583
+ let n;
584
+ for (;;) {
585
+ n = bvh_query_user_data_overlaps_aabb(scratch_wake_candidates, 0, this.dynamicBvh, scratch_world_aabb);
586
+ if (n <= scratch_wake_candidates.length) break;
587
+ // TRUE count returned, overflow writes dropped — grow and re-query.
588
+ scratch_wake_candidates = new Uint32Array(Math.max(n, scratch_wake_candidates.length * 2));
589
+ }
590
+
591
+ for (let i = 0; i < n; i++) {
592
+ const body_id = scratch_wake_candidates[i];
593
+ if (!this.storage.is_valid(body_id)) continue;
594
+ const rb = this.__bodies[body_id_index(body_id)];
595
+ if (rb === undefined) continue;
596
+ if (rb.sleepState !== SleepState.Sleeping) continue;
597
+ this.__wake_body(rb);
598
+ }
599
+ }
600
+
494
601
  /**
495
602
  * Lifecycle entry: invoked when an entity gains the (RigidBody, Transform)
496
603
  * tuple. Allocates the body's slot in storage and seeds an empty collider
@@ -505,7 +612,6 @@ export class PhysicsSystem extends System {
505
612
  link(rigidBody, transform, entity) {
506
613
  const packed = this.storage.allocate(entity);
507
614
  rigidBody._bodyId = packed;
508
- rigidBody.sleepState = SleepState.Awake;
509
615
 
510
616
  const index = body_id_index(packed);
511
617
  this.storage.set_kind(index, rigidBody.kind);
@@ -515,8 +621,24 @@ export class PhysicsSystem extends System {
515
621
  this.__transforms[index] = transform;
516
622
  this.__body_collider_lists[index] = [];
517
623
 
624
+ // The component's sleep fields are AUTHORITATIVE persistent state
625
+ // (see RigidBody.sleepState): a body restored from a snapshot — or
626
+ // re-linked after an unlink — resumes exactly as drowsy or asleep
627
+ // as it was, instead of being forced awake to re-settle. That keeps
628
+ // a reconstructed world on the original's wake/sleep schedule (the
629
+ // reconstruction-determinism contract). A freshly-constructed
630
+ // component defaults to Awake, so plain spawns are unchanged.
631
+ //
632
+ // A restored sleeper arrives as a sleep-group SINGLETON (the group
633
+ // links are world-instance-tied body indices, reset here); group
634
+ // membership is re-established by the contact-state import or, for
635
+ // a body slept in isolation, is already correct.
636
+ rigidBody.sleep_group_next = -1;
637
+ rigidBody.sleep_group_prev = -1;
638
+
518
639
  // Static bodies do not need to live in the active list — they never move.
519
- if (rigidBody.kind === BodyKind.Static) {
640
+ if (rigidBody.kind === BodyKind.Static
641
+ || (rigidBody.kind === BodyKind.Dynamic && rigidBody.sleepState === SleepState.Sleeping)) {
520
642
  this.storage.mark_sleeping(index);
521
643
  }
522
644
  }
@@ -545,9 +667,17 @@ export class PhysicsSystem extends System {
545
667
  const index = body_id_index(packed);
546
668
  const list = this.__body_collider_lists[index];
547
669
  if (list !== undefined) {
670
+ // A removed static / kinematic body may have been the support
671
+ // under sleeping bodies — wake them before the leaves disappear
672
+ // (their AABBs are the query keys).
673
+ const wake_neighbours = rigidBody.kind !== BodyKind.Dynamic;
674
+ const bvh = rigidBody.kind === BodyKind.Static ? this.staticBvh : this.dynamicBvh;
548
675
  for (let i = 0; i < list.length; i++) {
549
676
  const entry = list[i];
550
677
  if (entry.bvhNode !== COLLIDER_UNBOUND) {
678
+ if (wake_neighbours) {
679
+ this.__wake_sleepers_overlapping_leaf(bvh, entry.bvhNode);
680
+ }
551
681
  this.__remove_from_broadphase(rigidBody, entry.bvhNode);
552
682
  }
553
683
  entry.collider._bvhNode = COLLIDER_UNBOUND;
@@ -559,6 +689,21 @@ export class PhysicsSystem extends System {
559
689
  this.__transforms[index] = undefined;
560
690
  this.__body_collider_lists[index] = undefined;
561
691
 
692
+ // Purge joints referencing the freed body. The solver already skips
693
+ // them via the generation-checked is_valid, but the 8-bit generation
694
+ // wraps after 256 reuse cycles of one slot (~seconds under a pooled
695
+ // spawner) — at which point a stale joint handle ALIASES an unrelated
696
+ // new body and silently reactivates against it. Removing the joint at
697
+ // the source closes the ABA window outright.
698
+ const joints = this.__joints;
699
+ for (let i = 0; i < joints.length; i++) {
700
+ const joint = joints[i];
701
+ if (joint === undefined || joint === null) continue;
702
+ if (joint._bodyIdA === packed || joint._bodyIdB === packed) {
703
+ this.unlink_joint(joint);
704
+ }
705
+ }
706
+
562
707
  this.storage.free(packed);
563
708
  rigidBody._bodyId = RIGID_BODY_UNALLOCATED;
564
709
  }
@@ -609,6 +754,12 @@ export class PhysicsSystem extends System {
609
754
  if (body_index === -1) return;
610
755
 
611
756
  const rb = this.__bodies[body_index];
757
+ // Same rule as unlink: removing a static / kinematic leaf may pull
758
+ // the support from under sleeping bodies — wake them first.
759
+ if (rb.kind !== BodyKind.Dynamic) {
760
+ const bvh = rb.kind === BodyKind.Static ? this.staticBvh : this.dynamicBvh;
761
+ this.__wake_sleepers_overlapping_leaf(bvh, collider._bvhNode);
762
+ }
612
763
  this.__remove_from_broadphase(rb, collider._bvhNode);
613
764
 
614
765
  const list = this.__body_collider_lists[body_index];
@@ -659,6 +810,11 @@ export class PhysicsSystem extends System {
659
810
  joint._bodyIdB = this.__bodies[idxB]._bodyId;
660
811
  }
661
812
 
813
+ // A (re-)linked joint starts cold: the accumulated warm-start impulse
814
+ // belongs to whatever configuration the joint solved BEFORE it was
815
+ // unlinked — replaying it against the new bodies is a phantom kick.
816
+ joint.dofImpulse.fill(0);
817
+
662
818
  // Reuse a freed slot if available so joint ids stay dense-ish.
663
819
  let id;
664
820
  if (this.__joint_free.length > 0) {
@@ -668,6 +824,20 @@ export class PhysicsSystem extends System {
668
824
  }
669
825
  joint._jointId = id;
670
826
  this.__joints[id] = joint;
827
+
828
+ // Insert at the upper bound of the joint's (entityA, entityB) key in
829
+ // the canonical solve-order list — equal keys keep link order.
830
+ const sorted = this.__joints_sorted;
831
+ let pos = sorted.length;
832
+ while (pos > 0) {
833
+ const prev = sorted[pos - 1];
834
+ if (prev.entityA < joint.entityA
835
+ || (prev.entityA === joint.entityA && prev.entityB <= joint.entityB)) {
836
+ break;
837
+ }
838
+ pos--;
839
+ }
840
+ sorted.splice(pos, 0, joint);
671
841
  }
672
842
 
673
843
  /**
@@ -681,6 +851,10 @@ export class PhysicsSystem extends System {
681
851
  this.__joints[id] = undefined;
682
852
  this.__joint_free.push(id);
683
853
  joint._jointId = JOINT_UNALLOCATED;
854
+
855
+ const sorted = this.__joints_sorted;
856
+ const pos = sorted.indexOf(joint);
857
+ if (pos !== -1) sorted.splice(pos, 1);
684
858
  }
685
859
 
686
860
  /**
@@ -754,7 +928,15 @@ export class PhysicsSystem extends System {
754
928
  const ty = rz * impulse.x - rx * impulse.z;
755
929
  const tz = rx * impulse.y - ry * impulse.x;
756
930
 
757
- world_inverse_inertia_apply(scratch_angular_delta, 0, rigidBody.inverseInertiaLocal, transform.rotation, tx, ty, tz);
931
+ // LockRot* masks the BODY-LOCAL inverse-inertia diagonal here exactly
932
+ // as the solver gather does, so a user impulse cannot spin a locked
933
+ // DOF either.
934
+ const flags = rigidBody.flags;
935
+ const ii = rigidBody.inverseInertiaLocal;
936
+ scratch_locked_inertia.x = (flags & RigidBodyFlags.LockRotX) !== 0 ? 0 : ii.x;
937
+ scratch_locked_inertia.y = (flags & RigidBodyFlags.LockRotY) !== 0 ? 0 : ii.y;
938
+ scratch_locked_inertia.z = (flags & RigidBodyFlags.LockRotZ) !== 0 ? 0 : ii.z;
939
+ world_inverse_inertia_apply(scratch_angular_delta, 0, scratch_locked_inertia, transform.rotation, tx, ty, tz);
758
940
 
759
941
  rigidBody.angularVelocity.set(
760
942
  rigidBody.angularVelocity.x + scratch_angular_delta[0],
@@ -861,6 +1043,11 @@ export class PhysicsSystem extends System {
861
1043
  * as-is; zero it via {@link setLinearVelocity} if the teleport should also
862
1044
  * stop the body.
863
1045
  *
1046
+ * Works for STATIC bodies too: their broadphase leaves (which the step
1047
+ * never refits) are re-homed to the new pose, and sleeping bodies at both
1048
+ * the old and the new location are woken — a moved support drops what
1049
+ * rested on it, and whatever the static moved into must react.
1050
+ *
864
1051
  * @param {RigidBody} rigidBody
865
1052
  * @param {Vector3|{x:number,y:number,z:number}} position world position
866
1053
  * @param {Quaternion|{x:number,y:number,z:number,w:number}} rotation world unit-quaternion rotation
@@ -875,7 +1062,29 @@ export class PhysicsSystem extends System {
875
1062
  transform.position.set(position.x, position.y, position.z);
876
1063
  transform.rotation.set(rotation.x, rotation.y, rotation.z, rotation.w);
877
1064
 
878
- this.__wake_body(rigidBody);
1065
+ if (rigidBody.kind === BodyKind.Static) {
1066
+ // The step never refits a static's leaves (stage 2 covers awake
1067
+ // bodies only), so a moved static would keep its stale broadphase
1068
+ // AABB forever: nothing collides at the new location, ghost pairs
1069
+ // at the old one. Re-home each leaf now, and wake the sleepers at
1070
+ // BOTH locations — anything resting on the support that just
1071
+ // moved away, and anything the support just moved into.
1072
+ const list = this.__body_collider_lists[idx];
1073
+ if (list !== undefined) {
1074
+ for (let i = 0; i < list.length; i++) {
1075
+ const entry = list[i];
1076
+ if (entry.bvhNode === COLLIDER_UNBOUND) continue;
1077
+ this.__wake_sleepers_overlapping_leaf(this.staticBvh, entry.bvhNode);
1078
+ this.__remove_from_broadphase(rigidBody, entry.bvhNode);
1079
+ const node = this.__insert_into_broadphase(rigidBody, entry.collider, entry.transform);
1080
+ entry.bvhNode = node;
1081
+ entry.collider._bvhNode = node;
1082
+ this.__wake_sleepers_overlapping_leaf(this.staticBvh, node);
1083
+ }
1084
+ }
1085
+ } else {
1086
+ this.__wake_body(rigidBody);
1087
+ }
879
1088
 
880
1089
  // Flag a snap on the body's Interpolated component, if any, so the
881
1090
  // interpolation producer (restore) and consumer (blend) treat this pose
@@ -913,6 +1122,12 @@ export class PhysicsSystem extends System {
913
1122
  if (rigidBody.sleepState === SleepState.Sleeping) {
914
1123
  return;
915
1124
  }
1125
+ // An unlinked (or stale) body has no storage slot — indexing with its
1126
+ // dead id would corrupt the awake-list bookkeeping of whatever body
1127
+ // now owns that index.
1128
+ if (!this.storage.is_valid(rigidBody._bodyId)) {
1129
+ return;
1130
+ }
916
1131
  rigidBody.sleepState = SleepState.Sleeping;
917
1132
  const index = body_id_index(rigidBody._bodyId);
918
1133
  this.storage.mark_sleeping(index);
@@ -936,6 +1151,9 @@ export class PhysicsSystem extends System {
936
1151
  __wake_body(rb) {
937
1152
  if (rb.kind !== BodyKind.Dynamic) return;
938
1153
  if (rb.sleepState === SleepState.Awake) return;
1154
+ // Same stale-id guard as sleep(): an unlinked body's dead id must not
1155
+ // index into (and corrupt) another body's awake-list slot.
1156
+ if (!this.storage.is_valid(rb._bodyId)) return;
939
1157
  const index = body_id_index(rb._bodyId);
940
1158
 
941
1159
  // Remember the next-in-chain before clearing the body's own pointers;
@@ -1112,30 +1330,145 @@ export class PhysicsSystem extends System {
1112
1330
  }
1113
1331
 
1114
1332
  /**
1115
- * Wake any sleeping body that appears in this step's broadphase pair list.
1116
- * A pair means the BVH AABBs overlap even if the sleeper hasn't moved,
1117
- * an awake neighbour has come into contact range and the sleeper must
1118
- * participate in narrowphase / solve.
1333
+ * Wake propagation through contact pairs. Runs BEFORE broadphase so a
1334
+ * body woken here participates in THIS frame's broadphase / narrowphase
1335
+ * / islands end to end it never simulates a step without its support
1336
+ * contacts (free-fall penetration pop).
1337
+ *
1338
+ * Reads ONLY persistent manifold state (the slots whose pair the
1339
+ * broadphase touched last frame — `prev_touched`), never the transient
1340
+ * pair list: manifold state is part of the engine's exportable contact
1341
+ * state, so a reconstructed engine wakes on exactly the original's
1342
+ * schedule.
1343
+ *
1344
+ * A sleeper wakes when:
1345
+ * - its pair holds REAL contacts (`contact_count > 0`), unless the
1346
+ * awake side is a PARKED non-Dynamic (a stationary kinematic platform
1347
+ * or a static — sleepState of either is never updated — transmits no
1348
+ * motion; the moment it gets velocity, the riders wake); or
1349
+ * - the pair has no contacts yet but the awake side's velocity-swept
1350
+ * tight AABB just REACHED the sleeper's tight AABB (false→true edge
1351
+ * of {@link __swept_proximity}) — one precautionary wake so an
1352
+ * incoming body never spends its first touching frame against a
1353
+ * non-integrating sleeper, over-embedding by v·dt. Edge-triggered on
1354
+ * a pure function of body state: pair CREATION time (the old
1355
+ * trigger) depends on broadphase fat-box history, which a
1356
+ * reconstructed engine does not share; and level-triggered proximity
1357
+ * would re-wake a pile next to a hovering body every frame. Slot
1358
+ * existence alone wakes nothing.
1119
1359
  * @private
1360
+ * @param {number} dt step size — extent of the predicate's velocity sweep
1120
1361
  */
1121
- __wake_pairs() {
1122
- const list = this.pairs;
1123
- const n = list.count;
1362
+ __wake_pairs(dt) {
1124
1363
  const bodies = this.__bodies;
1125
- for (let i = 0; i < n; i++) {
1126
- const idA = list.get_a(i);
1127
- const idB = list.get_b(i);
1128
- const idxA = body_id_index(idA);
1129
- const idxB = body_id_index(idB);
1130
- const a = bodies[idxA];
1131
- const b = bodies[idxB];
1132
- if (a !== undefined && a.sleepState === SleepState.Sleeping) {
1133
- this.__wake_body(a);
1364
+ const storage = this.storage;
1365
+ const manifolds = this.manifolds;
1366
+ const live_count = manifolds.count;
1367
+ for (let i = 0; i < live_count; i++) {
1368
+ const slot = manifolds.live_at(i);
1369
+ // "Was in last frame's broadphase": acquire set touched, the
1370
+ // end-of-step advance rolled it to prev_touched. (A dormant
1371
+ // slot can carry a stale prev_touched from its sleep frame
1372
+ // the both-asleep guard below skips it.)
1373
+ if (!manifolds.was_touched_prev(slot)) continue;
1374
+
1375
+ const idA = manifolds.bodyA(slot);
1376
+ const idB = manifolds.bodyB(slot);
1377
+ // Stale-slot guards: a body may have been unlinked since (and
1378
+ // its index reused by an unrelated body).
1379
+ if (!storage.is_valid(idA) || !storage.is_valid(idB)) continue;
1380
+ const a = bodies[body_id_index(idA)];
1381
+ const b = bodies[body_id_index(idB)];
1382
+ if (a === undefined || b === undefined) continue;
1383
+
1384
+ const aSleep = a.sleepState === SleepState.Sleeping;
1385
+ const bSleep = b.sleepState === SleepState.Sleeping;
1386
+ if (aSleep === bSleep) continue; // both awake, or a dormant pair
1387
+
1388
+ if (manifolds.contact_count(slot) > 0) {
1389
+ const mover = aSleep ? b : a;
1390
+ if (mover.kind !== BodyKind.Dynamic) {
1391
+ const lv = mover.linearVelocity;
1392
+ const av = mover.angularVelocity;
1393
+ if (lv[0] === 0 && lv[1] === 0 && lv[2] === 0
1394
+ && av[0] === 0 && av[1] === 0 && av[2] === 0) {
1395
+ continue; // parked platform / static — transmits no motion
1396
+ }
1397
+ }
1398
+ this.__wake_body(aSleep ? a : b);
1399
+ } else {
1400
+ // No contacts: pre-contact precautionary wake on the
1401
+ // proximity EDGE. The predicate needs no parked exemption —
1402
+ // a zero-velocity mover's swept box is its tight box, so it
1403
+ // only fires on actual tight-box overlap, once.
1404
+ const mover_idx = body_id_index(aSleep ? idB : idA);
1405
+ const sleeper_idx = body_id_index(aSleep ? idA : idB);
1406
+ const prox = this.__swept_proximity(mover_idx, sleeper_idx, dt);
1407
+ const had_prox = manifolds.is_prox(slot);
1408
+ manifolds.set_prox(slot, prox);
1409
+ if (prox && !had_prox) {
1410
+ this.__wake_body(aSleep ? a : b);
1411
+ }
1134
1412
  }
1135
- if (b !== undefined && b.sleepState === SleepState.Sleeping) {
1136
- this.__wake_body(b);
1413
+ }
1414
+ }
1415
+
1416
+ /**
1417
+ * Stage-0 pre-contact wake predicate: does any of `mover`'s collider
1418
+ * tight AABBs, swept directionally by the mover's linear velocity over
1419
+ * `dt`, overlap any of `sleeper`'s collider tight AABBs?
1420
+ *
1421
+ * A pure function of CURRENT body state (poses, shapes, velocity) — no
1422
+ * broadphase or pad history — so every engine holding the same bodies
1423
+ * evaluates it identically. Conservative containment: the swept box is
1424
+ * inside the mover's stage-2 fat box (pad = 2·|v|·dt + slack ⊇ v·dt)
1425
+ * and the sleeper's tight box is inside its stored leaf, so whenever
1426
+ * the predicate is true the broadphase has the pair THIS frame in any
1427
+ * engine — the manifold slot the wake stage needs is guaranteed to
1428
+ * exist on the frame the edge fires.
1429
+ *
1430
+ * Linear sweep only (matching the broadphase pad): a purely angular
1431
+ * approach is woken one frame later by its first actual contact.
1432
+ *
1433
+ * @private
1434
+ * @param {number} mover_idx body index of the awake side
1435
+ * @param {number} sleeper_idx body index of the sleeping side
1436
+ * @param {number} dt
1437
+ * @returns {boolean}
1438
+ */
1439
+ __swept_proximity(mover_idx, sleeper_idx, dt) {
1440
+ const mover_list = this.__body_collider_lists[mover_idx];
1441
+ const sleeper_list = this.__body_collider_lists[sleeper_idx];
1442
+ if (mover_list === undefined || sleeper_list === undefined) return false;
1443
+
1444
+ const lv = this.__bodies[mover_idx].linearVelocity;
1445
+ const px = lv[0] * dt;
1446
+ const py = lv[1] * dt;
1447
+ const pz = lv[2] * dt;
1448
+
1449
+ for (let i = 0; i < mover_list.length; i++) {
1450
+ const m = mover_list[i];
1451
+ if (m.bvhNode === COLLIDER_UNBOUND) continue;
1452
+ compute_world_aabb(scratch_prox_mover, 0, m.collider.shape, m.transform);
1453
+ if (px < 0) scratch_prox_mover[0] += px; else scratch_prox_mover[3] += px;
1454
+ if (py < 0) scratch_prox_mover[1] += py; else scratch_prox_mover[4] += py;
1455
+ if (pz < 0) scratch_prox_mover[2] += pz; else scratch_prox_mover[5] += pz;
1456
+
1457
+ for (let k = 0; k < sleeper_list.length; k++) {
1458
+ const s = sleeper_list[k];
1459
+ if (s.bvhNode === COLLIDER_UNBOUND) continue;
1460
+ compute_world_aabb(scratch_prox_sleeper, 0, s.collider.shape, s.transform);
1461
+ if (scratch_prox_mover[0] <= scratch_prox_sleeper[3]
1462
+ && scratch_prox_mover[3] >= scratch_prox_sleeper[0]
1463
+ && scratch_prox_mover[1] <= scratch_prox_sleeper[4]
1464
+ && scratch_prox_mover[4] >= scratch_prox_sleeper[1]
1465
+ && scratch_prox_mover[2] <= scratch_prox_sleeper[5]
1466
+ && scratch_prox_mover[5] >= scratch_prox_sleeper[2]) {
1467
+ return true;
1468
+ }
1137
1469
  }
1138
1470
  }
1471
+ return false;
1139
1472
  }
1140
1473
 
1141
1474
  /**
@@ -1168,6 +1501,23 @@ export class PhysicsSystem extends System {
1168
1501
  const aSleep = a.sleepState === SleepState.Sleeping;
1169
1502
  const bSleep = b.sleepState === SleepState.Sleeping;
1170
1503
  if (aSleep === bSleep) continue; // both awake or both asleep — leave as is
1504
+
1505
+ // The "awake" side must be capable of pulling the sleeper. A
1506
+ // static anchor's sleepState is never updated (it reads Awake
1507
+ // forever), so without this rule a body jointed to a static could
1508
+ // never sleep — perpetual mismatch wake. A kinematic driver
1509
+ // counts only while it is actually moving: a parked motor leaves
1510
+ // its chain asleep, and starting it wakes the chain (same motion
1511
+ // rule as __wake_pairs).
1512
+ const mover = aSleep ? b : a;
1513
+ if (mover.kind !== BodyKind.Dynamic) {
1514
+ const lv = mover.linearVelocity;
1515
+ const av = mover.angularVelocity;
1516
+ if (lv[0] === 0 && lv[1] === 0 && lv[2] === 0
1517
+ && av[0] === 0 && av[1] === 0 && av[2] === 0) {
1518
+ continue;
1519
+ }
1520
+ }
1171
1521
  if (aSleep) this.__wake_body(a); else this.__wake_body(b);
1172
1522
  }
1173
1523
  }
@@ -1314,6 +1664,23 @@ export class PhysicsSystem extends System {
1314
1664
  nm[1] = data[slot_off + 7];
1315
1665
  nm[2] = data[slot_off + 8];
1316
1666
  payload.depth = data[slot_off + 9];
1667
+
1668
+ // The event pair is entity-canonical (min, max); the slot's
1669
+ // stored normal points from the slot's OWN body B toward its
1670
+ // body A — an assignment that follows packed-id order, i.e.
1671
+ // slot allocation history. Mirror the normal when the
1672
+ // canonicalization swapped the pair, so the payload contract
1673
+ // ("normal points from entityB toward entityA") holds
1674
+ // identically in every engine regardless of slot history.
1675
+ const slot_idA = manifolds.bodyA(slot);
1676
+ const slot_entA = this.storage.is_valid(slot_idA)
1677
+ ? this.storage.entity_at(body_id_index(slot_idA))
1678
+ : -1;
1679
+ if (slot_entA !== entA) {
1680
+ nm[0] = -nm[0];
1681
+ nm[1] = -nm[1];
1682
+ nm[2] = -nm[2];
1683
+ }
1317
1684
  } else {
1318
1685
  pt[0] = 0;
1319
1686
  pt[1] = 0;
@@ -1447,6 +1814,17 @@ export class PhysicsSystem extends System {
1447
1814
  const joints = this.__joints;
1448
1815
  const manifolds = this.manifolds;
1449
1816
 
1817
+ // Stage 0: wake propagation — through the persistent manifolds
1818
+ // (last frame's broadphase-touched pairs), then through joints.
1819
+ // Runs before everything else so a just-woken body is part of this
1820
+ // frame's awake set end to end (forces, refit, broadphase,
1821
+ // narrowphase, islands, solve): waking later would give it one
1822
+ // unsupported step (gravity with no contacts → penetration pop).
1823
+ // Reads only manifold + body state — both part of the exportable
1824
+ // world state — never the transient pair list, so a reconstructed
1825
+ // engine wakes on the original's schedule.
1826
+ this.__wake_pairs(dt);
1827
+ this.__wake_joints();
1450
1828
 
1451
1829
  const count = storage.awake_count;
1452
1830
 
@@ -1489,14 +1867,36 @@ export class PhysicsSystem extends System {
1489
1867
 
1490
1868
  const entry = list[k];
1491
1869
 
1492
- compute_fat_world_aabb(
1493
- scratch_world_aabb, 0,
1494
- entry.collider.shape, entry.transform,
1495
- lv[0], lv[1], lv[2],
1496
- dt
1497
- );
1870
+ // Refit skip — the fat margin's whole purpose: while the
1871
+ // body's FATTENED box (tight + velocity pad) stays inside the
1872
+ // leaf's stored AABB, the stored box still covers everything
1873
+ // the body can reach this step, so the set + refit-to-root is
1874
+ // pure waste. A resting field pays only this containment test
1875
+ // per leaf per frame (at v ≈ 0 the fat box is the tight box
1876
+ // plus the constant slack, which the stored box includes).
1877
+ //
1878
+ // The containment probe MUST be the fat box, not the tight
1879
+ // one: the leaf is how the broadphase and every swept query
1880
+ // discover this body. A body whose velocity grew while its
1881
+ // tight box still sat inside the stored leaf (freshly linked
1882
+ // with a launch velocity, or accelerated by an impulse) would
1883
+ // otherwise keep a leaf covering none of the path it travels
1884
+ // this step — invisible to pair generation and to other
1885
+ // bodies' CCD sweeps for the whole step.
1886
+ compute_world_aabb(scratch_world_aabb, 0, entry.collider.shape, entry.transform);
1887
+ fatten_world_aabb(scratch_world_aabb, 0, lv[0], lv[1], lv[2], dt);
1888
+ const node = entry.bvhNode;
1889
+ this.dynamicBvh.node_get_aabb(node, scratch_stored_aabb);
1890
+ if (scratch_world_aabb[0] >= scratch_stored_aabb[0]
1891
+ && scratch_world_aabb[1] >= scratch_stored_aabb[1]
1892
+ && scratch_world_aabb[2] >= scratch_stored_aabb[2]
1893
+ && scratch_world_aabb[3] <= scratch_stored_aabb[3]
1894
+ && scratch_world_aabb[4] <= scratch_stored_aabb[4]
1895
+ && scratch_world_aabb[5] <= scratch_stored_aabb[5]) {
1896
+ continue;
1897
+ }
1498
1898
 
1499
- this.dynamicBvh.node_move_aabb(entry.bvhNode, scratch_world_aabb);
1899
+ this.dynamicBvh.node_move_aabb(node, scratch_world_aabb);
1500
1900
  }
1501
1901
  }
1502
1902
 
@@ -1514,11 +1914,6 @@ export class PhysicsSystem extends System {
1514
1914
  this,
1515
1915
  );
1516
1916
 
1517
- // Stage 4: wake propagation — through broadphase pairs, then through
1518
- // joints (a joint must not have one body awake and one asleep).
1519
- this.__wake_pairs();
1520
- this.__wake_joints();
1521
-
1522
1917
  // Stage 5: narrowphase — once per outer step. The substep loop below
1523
1918
  // re-derives each contact's penetration analytically from the moved
1524
1919
  // poses rather than re-running geometry.
@@ -1541,7 +1936,10 @@ export class PhysicsSystem extends System {
1541
1936
  // separate between substeps — the TGS stack-stability mechanism —
1542
1937
  // without re-running narrowphase. Restitution is applied once after
1543
1938
  // the loop.
1544
- const N = this.substeps;
1939
+ // Clamp the substep count: 0 (or a negative / fractional value) would
1940
+ // feed h = dt / N = Infinity into prepare_contacts and a broken loop
1941
+ // bound into the solver.
1942
+ const N = this.substeps > 1 ? this.substeps | 0 : 1;
1545
1943
  const h = dt / N;
1546
1944
  const count_after_wake = storage.awake_count;
1547
1945
 
@@ -1676,18 +2074,26 @@ export class PhysicsSystem extends System {
1676
2074
  // (a body touched by both sees one substep of Gauss-Seidel across
1677
2075
  // contacts then joints). Position correction for locked DOFs is a
1678
2076
  // SPOOK bias inside this solve, so no separate joint position pass.
1679
- if (joints.length > 0) {
2077
+ // Solved in the entity-canonical order (NOT joint-id order, which
2078
+ // encodes link/unlink history) — see __joints_sorted.
2079
+ if (this.__joints_sorted.length > 0) {
1680
2080
  // Alternate the joint sweep direction on odd substeps so the chain
1681
2081
  // is solved root→tip and tip→root across the step (symmetric
1682
2082
  // Gauss-Seidel), cancelling the one-direction propagation bias.
1683
- solve_joints(joints, this, h, this.jointIterations, (s & 1) === 1);
2083
+ solve_joints(this.__joints_sorted, this, h, this.jointIterations, (s & 1) === 1);
1684
2084
  }
1685
2085
 
1686
2086
  // Position correction writes pseudo-velocity (zeroed first so it
1687
2087
  // is a fresh per-substep correction), folded into the pose by the
1688
- // position integrate and then discarded.
2088
+ // position integrate and then discarded. SOFT contacts skip it:
2089
+ // their penetration recovery is the velocity-bias term, and the
2090
+ // relax pass below strips the momentum that bias injected
2091
+ // (Box2D-v3 substep order).
2092
+ const contacts_soft = this.contactHertz > 0;
1689
2093
  pseudoVel.fill(0, 0, pseudo_len);
1690
- solve_position(manifolds, this, this.positionIterations);
2094
+ if (!contacts_soft) {
2095
+ solve_position(manifolds, this, this.positionIterations);
2096
+ }
1691
2097
 
1692
2098
  for (let i = 0; i < count_after_wake; i++) {
1693
2099
  const idx = storage.awake_at(i);
@@ -1698,6 +2104,14 @@ export class PhysicsSystem extends System {
1698
2104
  pseudoVel[base], pseudoVel[base + 1], pseudoVel[base + 2],
1699
2105
  pseudoVel[base + 3], pseudoVel[base + 4], pseudoVel[base + 5]);
1700
2106
  }
2107
+
2108
+ // Relax pass (soft contacts only): one biasless sweep over the
2109
+ // contact rows AFTER position integration, removing the real
2110
+ // momentum the velocity-bias push injected this substep
2111
+ // (Box2D-v3 substep order: solve -> integrate -> relax).
2112
+ if (contacts_soft) {
2113
+ solve_velocity(manifolds, this, 1, false);
2114
+ }
1701
2115
  }
1702
2116
 
1703
2117
  // Stage 8: one-shot restitution, after the substep loop, keyed off
@@ -1734,9 +2148,17 @@ export class PhysicsSystem extends System {
1734
2148
  diff_manifolds(manifolds, storage, this.contactEvents);
1735
2149
  this.__dispatch_contact_events();
1736
2150
 
1737
- // Stage 11 (end-of-step): roll touched → prev_touched and evict slots
1738
- // whose pair has not been touched within the grace window.
1739
- manifolds.advance_frame();
2151
+ // Stage 11 (end-of-step): roll touched → prev_touched and the
2152
+ // had-contacts flag, evict slots whose pair has not been touched
2153
+ // within the grace window. Dormant pairs (both bodies asleep) are
2154
+ // frozen — contacts and warm-start impulses survive the nap.
2155
+ manifolds.advance_frame(storage);
2156
+
2157
+ // Dev tripwire (assert.* is compiled out of prod): no NaN / Infinity
2158
+ // may survive a step in body state or contact manifolds. NaN is
2159
+ // self-concealing downstream — it fails every depth comparison and
2160
+ // sleep threshold — so it must fail loudly here, at the step boundary.
2161
+ assert.equal(find_non_finite_physics_state(this), "", "non-finite physics state after fixedUpdate");
1740
2162
  }
1741
2163
  }
1742
2164