@woosh/meep-engine 3.21.0 → 3.23.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 (1803) hide show
  1. package/README.md +96 -213
  2. package/editor/particles/effect/ParticleEffectDocument.d.ts.map +1 -1
  3. package/editor/particles/effect/ParticleEffectDocument.js +0 -3
  4. package/editor/particles/effect/ParticleReferenceSimulation.js +1 -1
  5. package/editor/persistence/SceneMetadata.d.ts +9 -4
  6. package/editor/persistence/SceneMetadata.d.ts.map +1 -1
  7. package/editor/persistence/SceneMetadata.js +4 -3
  8. package/editor/tools/TransformToolV2.d.ts +2 -1
  9. package/editor/tools/TransformToolV2.d.ts.map +1 -1
  10. package/editor/tools/engine/Tool.d.ts +1 -1
  11. package/editor/tools/engine/Tool.d.ts.map +1 -1
  12. package/editor/tools/engine/ToolEngine.d.ts +1 -1
  13. package/editor/tools/engine/ToolEngine.d.ts.map +1 -1
  14. package/editor/view/ecs/EntityEditor.d.ts +3 -2
  15. package/editor/view/ecs/EntityEditor.d.ts.map +1 -1
  16. package/editor/view/ecs/EntityList.d.ts +7 -3
  17. package/editor/view/ecs/EntityList.d.ts.map +1 -1
  18. package/editor/view/ecs/EntityList.js +3 -2
  19. package/editor/view/ecs/components/common/NumericIntervalController.d.ts +8 -3
  20. package/editor/view/ecs/components/common/NumericIntervalController.d.ts.map +1 -1
  21. package/editor/view/ecs/components/common/NumericIntervalController.js +3 -2
  22. package/editor/view/ecs/components/common/TextController.d.ts +7 -3
  23. package/editor/view/ecs/components/common/TextController.d.ts.map +1 -1
  24. package/editor/view/ecs/components/common/TextController.js +3 -2
  25. package/editor/view/library/MeshLibraryView.d.ts.map +1 -1
  26. package/editor/view/library/MeshLibraryView.js +3 -2
  27. package/editor/view/node-graph/NodeIconView.d.ts +5 -2
  28. package/editor/view/node-graph/NodeIconView.d.ts.map +1 -1
  29. package/editor/view/node-graph/NodeIconView.js +2 -1
  30. package/editor/view/node-graph/PortView.d.ts +9 -4
  31. package/editor/view/node-graph/PortView.d.ts.map +1 -1
  32. package/editor/view/node-graph/PortView.js +4 -3
  33. package/editor/view/particles/ColorLutGradientView.d.ts +7 -3
  34. package/editor/view/particles/ColorLutGradientView.d.ts.map +1 -1
  35. package/editor/view/particles/ColorLutGradientView.js +3 -2
  36. package/editor/view/particles/ScalarLutCurveView.d.ts +9 -4
  37. package/editor/view/particles/ScalarLutCurveView.d.ts.map +1 -1
  38. package/editor/view/particles/ScalarLutCurveView.js +4 -3
  39. package/editor/view/particles/effect/ParticleEmitterInspectorView.d.ts.map +1 -1
  40. package/editor/view/particles/effect/ParticleEmitterInspectorView.js +0 -1
  41. package/editor/view/tools/ToolView.d.ts +7 -3
  42. package/editor/view/tools/ToolView.d.ts.map +1 -1
  43. package/editor/view/tools/ToolView.js +3 -2
  44. package/package.json +2 -1
  45. package/src/core/binary/allocator/OffsetAllocator.d.ts +24 -1
  46. package/src/core/binary/allocator/OffsetAllocator.d.ts.map +1 -1
  47. package/src/core/binary/allocator/OffsetAllocator.js +101 -1
  48. package/src/core/binary/type/Field.d.ts +5 -1
  49. package/src/core/binary/type/Field.d.ts.map +1 -1
  50. package/src/core/binary/type/Field.js +4 -0
  51. package/src/core/binary/type/Type.d.ts +4 -0
  52. package/src/core/binary/type/Type.d.ts.map +1 -1
  53. package/src/core/binary/type/Type.js +4 -0
  54. package/src/core/cache/Cache.d.ts +15 -7
  55. package/src/core/cache/Cache.d.ts.map +1 -1
  56. package/src/core/cache/Cache.js +7 -6
  57. package/src/core/cache/wtinylfu/CacheRegionWTinylfu.d.ts +5 -2
  58. package/src/core/cache/wtinylfu/CacheRegionWTinylfu.d.ts.map +1 -1
  59. package/src/core/cache/wtinylfu/CacheRegionWTinylfu.js +2 -1
  60. package/src/core/cache/wtinylfu/CacheWTinylfu.d.ts +20 -10
  61. package/src/core/cache/wtinylfu/CacheWTinylfu.d.ts.map +1 -1
  62. package/src/core/cache/wtinylfu/CacheWTinylfu.js +9 -8
  63. package/src/core/collection/CuckooFilter.d.ts +8 -4
  64. package/src/core/collection/CuckooFilter.d.ts.map +1 -1
  65. package/src/core/collection/CuckooFilter.js +3 -2
  66. package/src/core/collection/list/List.d.ts +0 -1
  67. package/src/core/collection/list/List.d.ts.map +1 -1
  68. package/src/core/collection/list/List.js +0 -1
  69. package/src/core/collection/map/HashMap.d.ts +12 -7
  70. package/src/core/collection/map/HashMap.d.ts.map +1 -1
  71. package/src/core/collection/map/HashMap.js +5 -5
  72. package/src/core/collection/map/ObservedMap.d.ts +1 -2
  73. package/src/core/collection/map/ObservedMap.d.ts.map +1 -1
  74. package/src/core/collection/map/ObservedMap.js +0 -1
  75. package/src/core/collection/table/RowFirstTable.d.ts +1 -0
  76. package/src/core/collection/table/RowFirstTable.d.ts.map +1 -1
  77. package/src/core/collection/table/RowFirstTable.js +4 -0
  78. package/src/core/color/Color.d.ts +1 -2
  79. package/src/core/color/Color.d.ts.map +1 -1
  80. package/src/core/color/Color.js +5 -4
  81. package/src/core/color/hsv/hsv2rgb_float.d.ts +23 -1
  82. package/src/core/color/hsv/hsv2rgb_float.d.ts.map +1 -1
  83. package/src/core/color/hsv/hsv2rgb_float.js +31 -3
  84. package/src/core/color/hsv/hsv_to_rgb.d.ts +20 -9
  85. package/src/core/color/hsv/hsv_to_rgb.d.ts.map +1 -1
  86. package/src/core/color/hsv/hsv_to_rgb.js +30 -10
  87. package/src/core/color/hsv/hsv_to_rgb_uint8.d.ts.map +1 -1
  88. package/src/core/color/hsv/hsv_to_rgb_uint8.js +10 -5
  89. package/src/core/function/FunctionCompiler.d.ts +9 -4
  90. package/src/core/function/FunctionCompiler.d.ts.map +1 -1
  91. package/src/core/function/FunctionCompiler.js +8 -6
  92. package/src/core/geom/3d/hash-grid/PointHashGrid3.d.ts +118 -0
  93. package/src/core/geom/3d/hash-grid/PointHashGrid3.d.ts.map +1 -0
  94. package/src/core/geom/3d/hash-grid/PointHashGrid3.js +283 -0
  95. package/src/core/geom/3d/quaternion/quat3_shortest_arc.d.ts +41 -0
  96. package/src/core/geom/3d/quaternion/quat3_shortest_arc.d.ts.map +1 -0
  97. package/src/core/geom/3d/quaternion/quat3_shortest_arc.js +94 -0
  98. package/src/core/geom/3d/ray/Ray3.d.ts +5 -5
  99. package/src/core/geom/3d/ray/Ray3.d.ts.map +1 -1
  100. package/src/core/geom/3d/ray/Ray3.js +3 -3
  101. package/src/core/geom/3d/shape/AbstractShape3D.d.ts +1 -0
  102. package/src/core/geom/3d/shape/AbstractShape3D.d.ts.map +1 -1
  103. package/src/core/geom/3d/shape/AbstractShape3D.js +4 -0
  104. package/src/core/geom/3d/shape/BoxShape3D.d.ts.map +1 -1
  105. package/src/core/geom/3d/shape/BoxShape3D.js +6 -17
  106. package/src/core/geom/3d/shape/CapsuleShape3D.d.ts.map +1 -1
  107. package/src/core/geom/3d/shape/CapsuleShape3D.js +3 -14
  108. package/src/core/geom/3d/shape/ConvexHullShape3D.d.ts +2 -4
  109. package/src/core/geom/3d/shape/ConvexHullShape3D.d.ts.map +1 -1
  110. package/src/core/geom/3d/shape/ConvexHullShape3D.js +0 -2
  111. package/src/core/geom/3d/shape/CylinderShape3D.d.ts.map +1 -1
  112. package/src/core/geom/3d/shape/CylinderShape3D.js +3 -21
  113. package/src/core/geom/3d/shape/PlaneShape3D.d.ts +105 -0
  114. package/src/core/geom/3d/shape/PlaneShape3D.d.ts.map +1 -0
  115. package/src/core/geom/3d/shape/PlaneShape3D.js +251 -0
  116. package/src/core/geom/3d/shape/SphereShape3D.js +3 -3
  117. package/src/core/geom/3d/shape/TransformedShape3D.d.ts +1 -2
  118. package/src/core/geom/3d/shape/TransformedShape3D.d.ts.map +1 -1
  119. package/src/core/geom/3d/shape/TransformedShape3D.js +0 -1
  120. package/src/core/geom/3d/shape/json/shape_to_type.d.ts.map +1 -1
  121. package/src/core/geom/3d/shape/json/shape_to_type.js +3 -0
  122. package/src/core/geom/3d/shape/json/type_adapters.d.ts +14 -0
  123. package/src/core/geom/3d/shape/json/type_adapters.d.ts.map +1 -1
  124. package/src/core/geom/3d/shape/json/type_adapters.js +15 -0
  125. package/src/core/geom/3d/shape/sdf/sdf3_box.d.ts +51 -0
  126. package/src/core/geom/3d/shape/sdf/sdf3_box.d.ts.map +1 -0
  127. package/src/core/geom/3d/shape/sdf/sdf3_box.js +113 -0
  128. package/src/core/geom/3d/shape/sdf/sdf3_capsule.d.ts +46 -0
  129. package/src/core/geom/3d/shape/sdf/sdf3_capsule.d.ts.map +1 -0
  130. package/src/core/geom/3d/shape/sdf/sdf3_capsule.js +82 -0
  131. package/src/core/geom/3d/shape/sdf/sdf3_cylinder.d.ts +60 -0
  132. package/src/core/geom/3d/shape/sdf/sdf3_cylinder.d.ts.map +1 -0
  133. package/src/core/geom/3d/shape/sdf/sdf3_cylinder.js +126 -0
  134. package/src/core/geom/3d/shape/sdf/sdf3_degenerate_normal.d.ts +50 -0
  135. package/src/core/geom/3d/shape/sdf/sdf3_degenerate_normal.d.ts.map +1 -0
  136. package/src/core/geom/3d/shape/sdf/sdf3_degenerate_normal.js +53 -0
  137. package/src/core/geom/3d/shape/sdf/sdf3_plane.d.ts +52 -0
  138. package/src/core/geom/3d/shape/sdf/sdf3_plane.d.ts.map +1 -0
  139. package/src/core/geom/3d/shape/sdf/sdf3_plane.js +61 -0
  140. package/src/core/geom/3d/shape/sdf/sdf3_sphere.d.ts +41 -0
  141. package/src/core/geom/3d/shape/sdf/sdf3_sphere.d.ts.map +1 -0
  142. package/src/core/geom/3d/shape/sdf/sdf3_sphere.js +71 -0
  143. package/src/core/geom/3d/topology/struct/binary/BinaryDataBlock.d.ts +6 -0
  144. package/src/core/geom/3d/topology/struct/binary/BinaryDataBlock.d.ts.map +1 -1
  145. package/src/core/geom/3d/topology/struct/binary/BinaryDataBlock.js +5 -0
  146. package/src/core/geom/3d/topology/struct/binary/BinaryTopology.d.ts +2 -0
  147. package/src/core/geom/3d/topology/struct/binary/BinaryTopology.d.ts.map +1 -1
  148. package/src/core/geom/3d/topology/struct/binary/BinaryTopology.js +5 -0
  149. package/src/core/geom/Quaternion.d.ts +1 -0
  150. package/src/core/geom/Quaternion.d.ts.map +1 -1
  151. package/src/core/geom/Quaternion.js +4 -0
  152. package/src/core/geom/Vector1.d.ts +8 -0
  153. package/src/core/geom/Vector1.d.ts.map +1 -1
  154. package/src/core/geom/Vector1.js +6 -0
  155. package/src/core/geom/Vector3.d.ts +6 -0
  156. package/src/core/geom/Vector3.d.ts.map +1 -1
  157. package/src/core/geom/Vector3.js +5 -0
  158. package/src/core/geom/Vector4.d.ts +10 -2
  159. package/src/core/geom/Vector4.d.ts.map +1 -1
  160. package/src/core/geom/Vector4.js +6 -1
  161. package/src/core/geom/packing/max-rect/MaxRectanglesPacker.d.ts +4 -4
  162. package/src/core/geom/packing/max-rect/MaxRectanglesPacker.d.ts.map +1 -1
  163. package/src/core/geom/packing/max-rect/MaxRectanglesPacker.js +1 -1
  164. package/src/core/graph/convert_graph_to_dot_string.d.ts +7 -3
  165. package/src/core/graph/convert_graph_to_dot_string.d.ts.map +1 -1
  166. package/src/core/graph/convert_graph_to_dot_string.js +3 -2
  167. package/src/core/localization/Localization.d.ts +3 -2
  168. package/src/core/localization/Localization.d.ts.map +1 -1
  169. package/src/core/localization/Localization.js +4 -0
  170. package/src/core/math/noise/create_simplex_noise_2d.js +6 -6
  171. package/src/core/model/ObservedValue.d.ts +8 -6
  172. package/src/core/model/ObservedValue.d.ts.map +1 -1
  173. package/src/core/model/ObservedValue.js +3 -1
  174. package/src/core/model/node-graph/Connection.d.ts +1 -0
  175. package/src/core/model/node-graph/Connection.d.ts.map +1 -1
  176. package/src/core/model/node-graph/Connection.js +4 -0
  177. package/src/core/model/node-graph/NodeGraph.d.ts +8 -5
  178. package/src/core/model/node-graph/NodeGraph.d.ts.map +1 -1
  179. package/src/core/model/node-graph/NodeGraph.js +3 -3
  180. package/src/core/model/node-graph/json/serializeNodeGraphToJSON.d.ts +9 -4
  181. package/src/core/model/node-graph/json/serializeNodeGraphToJSON.d.ts.map +1 -1
  182. package/src/core/model/node-graph/json/serializeNodeGraphToJSON.js +4 -3
  183. package/src/core/model/node-graph/node/NodeDescription.d.ts +12 -4
  184. package/src/core/model/node-graph/node/NodeDescription.d.ts.map +1 -1
  185. package/src/core/model/node-graph/node/NodeDescription.js +10 -3
  186. package/src/core/model/node-graph/node/NodeInstance.d.ts +5 -2
  187. package/src/core/model/node-graph/node/NodeInstance.d.ts.map +1 -1
  188. package/src/core/model/node-graph/node/NodeInstance.js +6 -0
  189. package/src/core/model/node-graph/node/NodeInstancePortReference.d.ts +5 -2
  190. package/src/core/model/node-graph/node/NodeInstancePortReference.d.ts.map +1 -1
  191. package/src/core/model/node-graph/node/NodeInstancePortReference.js +6 -0
  192. package/src/core/model/node-graph/node/NodeRegistry.d.ts +2 -1
  193. package/src/core/model/node-graph/node/NodeRegistry.d.ts.map +1 -1
  194. package/src/core/model/node-graph/node/NodeRegistry.js +4 -0
  195. package/src/core/model/node-graph/node/Port.d.ts +12 -5
  196. package/src/core/model/node-graph/node/Port.d.ts.map +1 -1
  197. package/src/core/model/node-graph/node/Port.js +9 -4
  198. package/src/core/model/node-graph/util/convert_node_graph_to_dot_string.d.ts +5 -2
  199. package/src/core/model/node-graph/util/convert_node_graph_to_dot_string.d.ts.map +1 -1
  200. package/src/core/model/node-graph/util/convert_node_graph_to_dot_string.js +2 -1
  201. package/src/core/model/node-graph/util/graph_clone_by_node_subset.d.ts +5 -2
  202. package/src/core/model/node-graph/util/graph_clone_by_node_subset.d.ts.map +1 -1
  203. package/src/core/model/node-graph/util/graph_clone_by_node_subset.js +2 -1
  204. package/src/core/model/node-graph/util/graph_collect_connections_amongst_nodes.d.ts +5 -2
  205. package/src/core/model/node-graph/util/graph_collect_connections_amongst_nodes.d.ts.map +1 -1
  206. package/src/core/model/node-graph/util/graph_collect_connections_amongst_nodes.js +2 -1
  207. package/src/core/primitives/Class.d.ts +15 -0
  208. package/src/core/primitives/Class.d.ts.map +1 -0
  209. package/src/core/primitives/Class.js +18 -0
  210. package/src/core/primitives/TypedArray.d.ts +15 -0
  211. package/src/core/primitives/TypedArray.d.ts.map +1 -0
  212. package/src/core/primitives/TypedArray.js +27 -0
  213. package/src/core/process/ConcurrencyGate.d.ts +103 -0
  214. package/src/core/process/ConcurrencyGate.d.ts.map +1 -0
  215. package/src/core/process/ConcurrencyGate.js +207 -0
  216. package/src/core/process/buildPromiseChain.d.ts +9 -4
  217. package/src/core/process/buildPromiseChain.d.ts.map +1 -1
  218. package/src/core/process/buildPromiseChain.js +4 -3
  219. package/src/core/process/executor/ConcurrentExecutor.d.ts +2 -0
  220. package/src/core/process/executor/ConcurrentExecutor.d.ts.map +1 -1
  221. package/src/core/process/executor/ConcurrentExecutor.js +5 -0
  222. package/src/core/process/task/Task.d.ts +17 -7
  223. package/src/core/process/task/Task.d.ts.map +1 -1
  224. package/src/core/process/task/Task.js +12 -6
  225. package/src/engine/Engine.d.ts +17 -7
  226. package/src/engine/Engine.d.ts.map +1 -1
  227. package/src/engine/Engine.js +9 -4
  228. package/src/engine/EngineConfiguration.d.ts +33 -9
  229. package/src/engine/EngineConfiguration.d.ts.map +1 -1
  230. package/src/engine/EngineConfiguration.js +22 -4
  231. package/src/engine/EngineHarness.d.ts +22 -10
  232. package/src/engine/EngineHarness.d.ts.map +1 -1
  233. package/src/engine/EngineHarness.js +13 -8
  234. package/src/engine/EntityCreator.d.ts +26 -11
  235. package/src/engine/EntityCreator.d.ts.map +1 -1
  236. package/src/engine/EntityCreator.js +16 -13
  237. package/src/engine/animation/EntityAnimation.d.ts +1 -1
  238. package/src/engine/animation/EntityAnimation.d.ts.map +1 -1
  239. package/src/engine/animation/curve/actionProcessorOperations/curveActions.d.ts +28 -18
  240. package/src/engine/animation/curve/actionProcessorOperations/curveActions.d.ts.map +1 -1
  241. package/src/engine/animation/curve/actionProcessorOperations/curveActions.js +9 -8
  242. package/src/engine/animation/curve/draw/build_plot_entity_from_array.d.ts +18 -8
  243. package/src/engine/animation/curve/draw/build_plot_entity_from_array.d.ts.map +1 -1
  244. package/src/engine/animation/curve/draw/build_plot_entity_from_array.js +8 -7
  245. package/src/engine/animation/curve/editor/CurveEditorView.d.ts +22 -11
  246. package/src/engine/animation/curve/editor/CurveEditorView.d.ts.map +1 -1
  247. package/src/engine/animation/curve/editor/CurveEditorView.js +7 -6
  248. package/src/engine/animation/curve/editor/DragHandler.d.ts +12 -7
  249. package/src/engine/animation/curve/editor/DragHandler.d.ts.map +1 -1
  250. package/src/engine/animation/curve/editor/DragHandler.js +4 -3
  251. package/src/engine/animation/curve/editor/KeyframeStateManager.d.ts +3 -2
  252. package/src/engine/animation/curve/editor/KeyframeStateManager.d.ts.map +1 -1
  253. package/src/engine/animation/curve/editor/canvas2dDrawWorldAxisLabels.d.ts +21 -10
  254. package/src/engine/animation/curve/editor/canvas2dDrawWorldAxisLabels.d.ts.map +1 -1
  255. package/src/engine/animation/curve/editor/canvas2dDrawWorldAxisLabels.js +10 -9
  256. package/src/engine/animation/curve/editor/canvas2dPlotCurveLine.d.ts +20 -9
  257. package/src/engine/animation/curve/editor/canvas2dPlotCurveLine.d.ts.map +1 -1
  258. package/src/engine/animation/curve/editor/canvas2dPlotCurveLine.js +9 -8
  259. package/src/engine/animation/curve/editor/canvas2dPlotCurvePoints.d.ts +15 -7
  260. package/src/engine/animation/curve/editor/canvas2dPlotCurvePoints.d.ts.map +1 -1
  261. package/src/engine/animation/curve/editor/canvas2dPlotCurvePoints.js +7 -6
  262. package/src/engine/animation/curve/editor/createKeyframeDraggableAspect.d.ts +39 -18
  263. package/src/engine/animation/curve/editor/createKeyframeDraggableAspect.d.ts.map +1 -1
  264. package/src/engine/animation/curve/editor/createKeyframeDraggableAspect.js +18 -17
  265. package/src/engine/animation/curve/editor/createPanTool.d.ts +13 -5
  266. package/src/engine/animation/curve/editor/createPanTool.d.ts.map +1 -1
  267. package/src/engine/animation/curve/editor/createPanTool.js +5 -4
  268. package/src/engine/animation/curve/editor/createSelectionBoxTool.d.ts +19 -8
  269. package/src/engine/animation/curve/editor/createSelectionBoxTool.d.ts.map +1 -1
  270. package/src/engine/animation/curve/editor/createSelectionBoxTool.js +8 -7
  271. package/src/engine/animation/keyed2/AnimationTrackPlayback.d.ts +6 -2
  272. package/src/engine/animation/keyed2/AnimationTrackPlayback.d.ts.map +1 -1
  273. package/src/engine/animation/keyed2/AnimationTrackPlayback.js +4 -0
  274. package/src/engine/animation/removeEntityGenericEffect.d.ts +13 -6
  275. package/src/engine/animation/removeEntityGenericEffect.d.ts.map +1 -1
  276. package/src/engine/animation/removeEntityGenericEffect.js +6 -5
  277. package/src/engine/animation/removeEntityWithMeshParticlesEffect.d.ts +11 -5
  278. package/src/engine/animation/removeEntityWithMeshParticlesEffect.d.ts.map +1 -1
  279. package/src/engine/animation/removeEntityWithMeshParticlesEffect.js +5 -4
  280. package/src/engine/asset/Asset.d.ts +6 -3
  281. package/src/engine/asset/Asset.d.ts.map +1 -1
  282. package/src/engine/asset/Asset.js +4 -1
  283. package/src/engine/asset/AssetManager.d.ts +52 -21
  284. package/src/engine/asset/AssetManager.d.ts.map +1 -1
  285. package/src/engine/asset/AssetManager.js +30 -12
  286. package/src/engine/asset/AssetRequest.d.ts +4 -2
  287. package/src/engine/asset/AssetRequest.d.ts.map +1 -1
  288. package/src/engine/asset/AssetRequest.js +5 -0
  289. package/src/engine/asset/AssetRequestScope.d.ts +1 -0
  290. package/src/engine/asset/AssetRequestScope.d.ts.map +1 -1
  291. package/src/engine/asset/AssetRequestScope.js +4 -0
  292. package/src/engine/asset/AssetTransformer.d.ts +7 -1
  293. package/src/engine/asset/AssetTransformer.d.ts.map +1 -1
  294. package/src/engine/asset/AssetTransformer.js +5 -0
  295. package/src/engine/asset/PendingAsset.d.ts +8 -0
  296. package/src/engine/asset/PendingAsset.d.ts.map +1 -1
  297. package/src/engine/asset/PendingAsset.js +6 -0
  298. package/src/engine/asset/loaders/ArrayBufferLoader.d.ts +6 -3
  299. package/src/engine/asset/loaders/ArrayBufferLoader.d.ts.map +1 -1
  300. package/src/engine/asset/loaders/ArrayBufferLoader.js +2 -1
  301. package/src/engine/asset/loaders/AssetLoader.d.ts +8 -2
  302. package/src/engine/asset/loaders/AssetLoader.d.ts.map +1 -1
  303. package/src/engine/asset/loaders/AssetLoader.js +5 -0
  304. package/src/engine/asset/loaders/USDSceneBundleAssetLoader.d.ts +10 -0
  305. package/src/engine/asset/loaders/USDSceneBundleAssetLoader.d.ts.map +1 -1
  306. package/src/engine/asset/loaders/image/ImageRGBADataLoader.d.ts +5 -2
  307. package/src/engine/asset/loaders/image/ImageRGBADataLoader.d.ts.map +1 -1
  308. package/src/engine/asset/loaders/image/ImageRGBADataLoader.js +2 -1
  309. package/src/engine/asset/preloader/AssetPreloader.d.ts +2 -1
  310. package/src/engine/asset/preloader/AssetPreloader.d.ts.map +1 -1
  311. package/src/engine/asset/preloader/AssetPreloader.js +4 -0
  312. package/src/engine/development/performance/MetricCollection.d.ts +11 -3
  313. package/src/engine/development/performance/MetricCollection.d.ts.map +1 -1
  314. package/src/engine/development/performance/MetricCollection.js +7 -2
  315. package/src/engine/ecs/Entity.d.ts +3 -2
  316. package/src/engine/ecs/Entity.d.ts.map +1 -1
  317. package/src/engine/ecs/Entity.js +9 -1
  318. package/src/engine/ecs/EntityComponentDataset.d.ts +8 -6
  319. package/src/engine/ecs/EntityComponentDataset.d.ts.map +1 -1
  320. package/src/engine/ecs/EntityComponentDataset.js +9 -0
  321. package/src/engine/ecs/EntityManager.d.ts +2 -1
  322. package/src/engine/ecs/EntityManager.d.ts.map +1 -1
  323. package/src/engine/ecs/EntityManager.js +5 -0
  324. package/src/engine/ecs/EntityObserver.d.ts +4 -0
  325. package/src/engine/ecs/EntityObserver.d.ts.map +1 -1
  326. package/src/engine/ecs/EntityObserver.js +4 -0
  327. package/src/engine/ecs/EntityReference.d.ts +4 -0
  328. package/src/engine/ecs/EntityReference.d.ts.map +1 -1
  329. package/src/engine/ecs/EntityReference.js +4 -0
  330. package/src/engine/ecs/System.d.ts +11 -2
  331. package/src/engine/ecs/System.d.ts.map +1 -1
  332. package/src/engine/ecs/System.js +6 -0
  333. package/src/engine/ecs/async/WorkerSystem.d.ts +10 -0
  334. package/src/engine/ecs/async/WorkerSystem.d.ts.map +1 -1
  335. package/src/engine/ecs/dynamic_actions/actions/definition/SpeakLineActionDescription.d.ts +7 -3
  336. package/src/engine/ecs/dynamic_actions/actions/definition/SpeakLineActionDescription.d.ts.map +1 -1
  337. package/src/engine/ecs/dynamic_actions/actions/definition/SpeakLineActionDescription.js +3 -2
  338. package/src/engine/ecs/dynamic_actions/actions/definition/WriteToBlackboardActionDescription.d.ts +7 -3
  339. package/src/engine/ecs/dynamic_actions/actions/definition/WriteToBlackboardActionDescription.d.ts.map +1 -1
  340. package/src/engine/ecs/dynamic_actions/actions/definition/WriteToBlackboardActionDescription.js +3 -2
  341. package/src/engine/ecs/gui/menu/radial/RadialContextMenu.d.ts +36 -17
  342. package/src/engine/ecs/gui/menu/radial/RadialContextMenu.d.ts.map +1 -1
  343. package/src/engine/ecs/gui/menu/radial/RadialContextMenu.js +17 -16
  344. package/src/engine/ecs/gui/parallax/GuiElementParallaxSystem.d.ts +7 -3
  345. package/src/engine/ecs/gui/parallax/GuiElementParallaxSystem.d.ts.map +1 -1
  346. package/src/engine/ecs/gui/parallax/GuiElementParallaxSystem.js +3 -2
  347. package/src/engine/ecs/ik/InverseKinematics.d.ts +17 -8
  348. package/src/engine/ecs/ik/InverseKinematics.d.ts.map +1 -1
  349. package/src/engine/ecs/ik/InverseKinematics.js +8 -7
  350. package/src/engine/ecs/storage/binary/BinaryClassSerializationAdapter.d.ts +9 -0
  351. package/src/engine/ecs/storage/binary/BinaryClassSerializationAdapter.d.ts.map +1 -1
  352. package/src/engine/ecs/storage/binary/BinaryClassSerializationAdapter.js +9 -0
  353. package/src/engine/ecs/storage/binary/BinaryClassUpgrader.d.ts +4 -0
  354. package/src/engine/ecs/storage/binary/BinaryClassUpgrader.d.ts.map +1 -1
  355. package/src/engine/ecs/storage/binary/BinaryClassUpgrader.js +4 -0
  356. package/src/engine/ecs/storage/binary/BinarySerializationRegistry.d.ts +10 -4
  357. package/src/engine/ecs/storage/binary/BinarySerializationRegistry.d.ts.map +1 -1
  358. package/src/engine/ecs/storage/binary/BinarySerializationRegistry.js +5 -0
  359. package/src/engine/ecs/storage/binary/collection/BinaryCollectionDeSerializer.d.ts +5 -2
  360. package/src/engine/ecs/storage/binary/collection/BinaryCollectionDeSerializer.d.ts.map +1 -1
  361. package/src/engine/ecs/storage/binary/collection/BinaryCollectionDeSerializer.js +2 -1
  362. package/src/engine/ecs/storage/binary/collection/BinaryCollectionSerializer.d.ts +7 -3
  363. package/src/engine/ecs/storage/binary/collection/BinaryCollectionSerializer.d.ts.map +1 -1
  364. package/src/engine/ecs/storage/binary/collection/BinaryCollectionSerializer.js +3 -2
  365. package/src/engine/ecs/systems/ScriptSystem.d.ts +1 -0
  366. package/src/engine/ecs/systems/ScriptSystem.d.ts.map +1 -1
  367. package/src/engine/ecs/terrain/ecs/Terrain.d.ts +7 -2
  368. package/src/engine/ecs/terrain/ecs/Terrain.d.ts.map +1 -1
  369. package/src/engine/ecs/terrain/ecs/Terrain.js +8 -0
  370. package/src/engine/ecs/terrain/ecs/cling/ClingToTerrainSerializationUpgrader_0_1.d.ts +6 -0
  371. package/src/engine/ecs/terrain/ecs/cling/ClingToTerrainSerializationUpgrader_0_1.d.ts.map +1 -1
  372. package/src/engine/ecs/terrain/ecs/layers/TerrainLayer.d.ts +3 -1
  373. package/src/engine/ecs/terrain/ecs/layers/TerrainLayer.d.ts.map +1 -1
  374. package/src/engine/ecs/terrain/ecs/layers/TerrainLayer.js +5 -0
  375. package/src/engine/ecs/terrain/ecs/layers/TerrainLayers.d.ts +3 -1
  376. package/src/engine/ecs/terrain/ecs/layers/TerrainLayers.d.ts.map +1 -1
  377. package/src/engine/ecs/terrain/ecs/layers/TerrainLayers.js +5 -0
  378. package/src/engine/ecs/terrain/ecs/splat/SplatMapping.d.ts +4 -0
  379. package/src/engine/ecs/terrain/ecs/splat/SplatMapping.d.ts.map +1 -1
  380. package/src/engine/ecs/terrain/ecs/splat/SplatMapping.js +4 -0
  381. package/src/engine/ecs/terrain/tiles/TerrainTile.d.ts +7 -2
  382. package/src/engine/ecs/terrain/tiles/TerrainTile.d.ts.map +1 -1
  383. package/src/engine/ecs/terrain/tiles/TerrainTile.js +1 -1
  384. package/src/engine/ecs/terrain/tiles/TerrainTileManager.d.ts +6 -2
  385. package/src/engine/ecs/terrain/tiles/TerrainTileManager.d.ts.map +1 -1
  386. package/src/engine/ecs/terrain/tiles/TerrainTileManager.js +6 -1
  387. package/src/engine/ecs/terrain/util/loadVisibleTerrainTiles.d.ts +9 -4
  388. package/src/engine/ecs/terrain/util/loadVisibleTerrainTiles.d.ts.map +1 -1
  389. package/src/engine/ecs/terrain/util/loadVisibleTerrainTiles.js +4 -3
  390. package/src/engine/ecs/transform/Transform64.d.ts +4 -0
  391. package/src/engine/ecs/transform/Transform64.d.ts.map +1 -1
  392. package/src/engine/ecs/transform/Transform64.js +4 -0
  393. package/src/engine/graphics/CONTEXT_LOSS_RECOVERY_PLAN.md +30 -13
  394. package/src/engine/graphics/camera/CameraShakeBehavior.d.ts +20 -10
  395. package/src/engine/graphics/camera/CameraShakeBehavior.d.ts.map +1 -1
  396. package/src/engine/graphics/camera/CameraShakeBehavior.js +9 -8
  397. package/src/engine/graphics/camera/CameraShakeTraumaBehavior.d.ts +8 -4
  398. package/src/engine/graphics/camera/CameraShakeTraumaBehavior.d.ts.map +1 -1
  399. package/src/engine/graphics/camera/CameraShakeTraumaBehavior.js +3 -2
  400. package/src/engine/graphics/camera/makeOrbitalCameraController.d.ts +11 -5
  401. package/src/engine/graphics/camera/makeOrbitalCameraController.d.ts.map +1 -1
  402. package/src/engine/graphics/camera/makeOrbitalCameraController.js +5 -4
  403. package/src/engine/graphics/canvas/canvas2d_draw_grid.d.ts +19 -9
  404. package/src/engine/graphics/canvas/canvas2d_draw_grid.d.ts.map +1 -1
  405. package/src/engine/graphics/canvas/canvas2d_draw_grid.js +9 -8
  406. package/src/engine/graphics/canvas/canvas2d_draw_label.d.ts +17 -8
  407. package/src/engine/graphics/canvas/canvas2d_draw_label.d.ts.map +1 -1
  408. package/src/engine/graphics/canvas/canvas2d_draw_label.js +8 -7
  409. package/src/engine/graphics/canvas/canvas2d_draw_linear_scale.d.ts +21 -10
  410. package/src/engine/graphics/canvas/canvas2d_draw_linear_scale.d.ts.map +1 -1
  411. package/src/engine/graphics/canvas/canvas2d_draw_linear_scale.js +10 -9
  412. package/src/engine/graphics/canvas/canvas2d_plot_data_line.d.ts +18 -8
  413. package/src/engine/graphics/canvas/canvas2d_plot_data_line.d.ts.map +1 -1
  414. package/src/engine/graphics/canvas/canvas2d_plot_data_line.js +8 -7
  415. package/src/engine/graphics/ecs/camera/Camera.d.ts +4 -0
  416. package/src/engine/graphics/ecs/camera/Camera.d.ts.map +1 -1
  417. package/src/engine/graphics/ecs/camera/Camera.js +4 -0
  418. package/src/engine/graphics/ecs/camera/filter/setup_filtered_camera_controller.d.ts +11 -5
  419. package/src/engine/graphics/ecs/camera/filter/setup_filtered_camera_controller.d.ts.map +1 -1
  420. package/src/engine/graphics/ecs/camera/filter/setup_filtered_camera_controller.js +5 -4
  421. package/src/engine/graphics/ecs/camera/topdown/TopDownCameraControllerSystem.d.ts +1 -1
  422. package/src/engine/graphics/ecs/camera/topdown/TopDownCameraControllerSystem.d.ts.map +1 -1
  423. package/src/engine/graphics/ecs/particles/ParticleEffect.d.ts +5 -5
  424. package/src/engine/graphics/ecs/particles/ParticleEffect.js +5 -5
  425. package/src/engine/graphics/ecs/trail3d/make_gradient_stroke.d.ts +19 -9
  426. package/src/engine/graphics/ecs/trail3d/make_gradient_stroke.d.ts.map +1 -1
  427. package/src/engine/graphics/ecs/trail3d/make_gradient_stroke.js +9 -8
  428. package/src/engine/graphics/particles/particular/engine/emitter/ParticleEmitter.d.ts +3 -0
  429. package/src/engine/graphics/particles/particular/engine/emitter/ParticleEmitter.d.ts.map +1 -1
  430. package/src/engine/graphics/particles/particular/engine/emitter/ParticleEmitter.js +3 -0
  431. package/src/engine/graphics/particles/particular/engine/utils/volume/AttributeValue.d.ts +9 -4
  432. package/src/engine/graphics/particles/particular/engine/utils/volume/AttributeValue.d.ts.map +1 -1
  433. package/src/engine/graphics/particles/particular/engine/utils/volume/AttributeValue.js +4 -3
  434. package/src/engine/graphics/render/frame_graph/FrameGraph.d.ts +7 -1
  435. package/src/engine/graphics/render/frame_graph/FrameGraph.d.ts.map +1 -1
  436. package/src/engine/graphics/render/frame_graph/FrameGraph.js +5 -0
  437. package/src/engine/graphics/render/frame_graph/FrameGraphNode.d.ts +4 -0
  438. package/src/engine/graphics/render/frame_graph/FrameGraphNode.d.ts.map +1 -1
  439. package/src/engine/graphics/render/frame_graph/FrameGraphNode.js +4 -0
  440. package/src/engine/graphics/render/frame_graph/FramePassBuilder.d.ts +9 -1
  441. package/src/engine/graphics/render/frame_graph/FramePassBuilder.d.ts.map +1 -1
  442. package/src/engine/graphics/render/frame_graph/FramePassBuilder.js +6 -0
  443. package/src/engine/graphics/render/frame_graph/FramePassNode.d.ts +6 -0
  444. package/src/engine/graphics/render/frame_graph/FramePassNode.d.ts.map +1 -1
  445. package/src/engine/graphics/render/frame_graph/FramePassNode.js +5 -0
  446. package/src/engine/graphics/render/frame_graph/FramePassResources.d.ts +7 -1
  447. package/src/engine/graphics/render/frame_graph/FramePassResources.d.ts.map +1 -1
  448. package/src/engine/graphics/render/frame_graph/FramePassResources.js +5 -0
  449. package/src/engine/graphics/render/frame_graph/IFrameGraphContext.d.ts +6 -2
  450. package/src/engine/graphics/render/frame_graph/IFrameGraphContext.d.ts.map +1 -1
  451. package/src/engine/graphics/render/frame_graph/IFrameGraphContext.js +4 -0
  452. package/src/engine/graphics/render/frame_graph/ResourceEntry.d.ts +13 -5
  453. package/src/engine/graphics/render/frame_graph/ResourceEntry.d.ts.map +1 -1
  454. package/src/engine/graphics/render/frame_graph/ResourceEntry.js +7 -1
  455. package/src/engine/graphics/render/frame_graph/ResourceNode.d.ts +9 -3
  456. package/src/engine/graphics/render/frame_graph/ResourceNode.d.ts.map +1 -1
  457. package/src/engine/graphics/render/frame_graph/ResourceNode.js +6 -1
  458. package/src/engine/graphics/render/frame_graph/resource/RenderResourceManager.d.ts +5 -1
  459. package/src/engine/graphics/render/frame_graph/resource/RenderResourceManager.d.ts.map +1 -1
  460. package/src/engine/graphics/render/frame_graph/resource/RenderResourceManager.js +4 -0
  461. package/src/engine/graphics/render/frame_graph/resource/ResourceDescriptor.d.ts +7 -3
  462. package/src/engine/graphics/render/frame_graph/resource/ResourceDescriptor.d.ts.map +1 -1
  463. package/src/engine/graphics/render/frame_graph/resource/ResourceDescriptor.js +6 -2
  464. package/src/engine/graphics/texture/atlas/CachingTextureAtlas.d.ts +5 -2
  465. package/src/engine/graphics/texture/atlas/CachingTextureAtlas.d.ts.map +1 -1
  466. package/src/engine/graphics/texture/atlas/CachingTextureAtlas.js +2 -1
  467. package/src/engine/graphics/texture/atlas/TextureAtlasDebugger.d.ts +9 -4
  468. package/src/engine/graphics/texture/atlas/TextureAtlasDebugger.d.ts.map +1 -1
  469. package/src/engine/graphics/texture/atlas/TextureAtlasDebugger.js +4 -3
  470. package/src/engine/graphics/texture/sampler/Sampler2D.d.ts +4 -0
  471. package/src/engine/graphics/texture/sampler/Sampler2D.d.ts.map +1 -1
  472. package/src/engine/graphics/texture/sampler/Sampler2D.js +4 -0
  473. package/src/engine/graphics/texture/sampler/debug/prototypeSamplerFiltering.js +3 -2
  474. package/src/engine/graphics3/GPUParticleEmitterSystem.d.ts +0 -5
  475. package/src/engine/graphics3/GPUParticleEmitterSystem.d.ts.map +1 -1
  476. package/src/engine/graphics3/GraphicsEngine.d.ts +6 -0
  477. package/src/engine/graphics3/GraphicsEngine.d.ts.map +1 -1
  478. package/src/engine/graphics3/GraphicsEngine.js +9 -0
  479. package/src/engine/graphics3/ParticipatingMedia.d.ts +9 -4
  480. package/src/engine/graphics3/ParticipatingMedia.d.ts.map +1 -1
  481. package/src/engine/graphics3/ParticipatingMedia.js +4 -3
  482. package/src/engine/graphics3/ShadeCameraAdapter.d.ts +5 -1
  483. package/src/engine/graphics3/ShadeCameraAdapter.d.ts.map +1 -1
  484. package/src/engine/graphics3/ShadeCameraAdapter.js +4 -0
  485. package/src/engine/graphics3/TooltipComponentSystem.d.ts +13 -6
  486. package/src/engine/graphics3/TooltipComponentSystem.d.ts.map +1 -1
  487. package/src/engine/graphics3/TooltipComponentSystem.js +6 -5
  488. package/src/engine/graphics3/VolumetricLightMap.d.ts +5 -2
  489. package/src/engine/graphics3/VolumetricLightMap.d.ts.map +1 -1
  490. package/src/engine/graphics3/VolumetricLightMap.js +2 -1
  491. package/src/engine/graphics3/pose/collect_entity_playbacks.d.ts +26 -0
  492. package/src/engine/graphics3/pose/collect_entity_playbacks.d.ts.map +1 -0
  493. package/src/engine/graphics3/pose/collect_entity_playbacks.js +40 -0
  494. package/src/engine/graphics3/pose/query_entity_node_world_pose.d.ts.map +1 -1
  495. package/src/engine/graphics3/pose/query_entity_node_world_pose.js +74 -101
  496. package/src/engine/input/devices/PointerDevice.d.ts.map +1 -1
  497. package/src/engine/input/devices/PointerDevice.js +7 -6
  498. package/src/engine/input/devices/gamepad/GamepadHandle.d.ts +4 -0
  499. package/src/engine/input/devices/gamepad/GamepadHandle.d.ts.map +1 -1
  500. package/src/engine/input/devices/gamepad/GamepadHandle.js +4 -0
  501. package/src/engine/input/devices/touch/observePinch.d.ts +17 -8
  502. package/src/engine/input/devices/touch/observePinch.d.ts.map +1 -1
  503. package/src/engine/input/devices/touch/observePinch.js +8 -7
  504. package/src/engine/input/ecs/components/InputBinding.d.ts +11 -5
  505. package/src/engine/input/ecs/components/InputBinding.d.ts.map +1 -1
  506. package/src/engine/input/ecs/components/InputBinding.js +5 -4
  507. package/src/engine/input/ecs/ism/InputMapSystem.d.ts +4 -0
  508. package/src/engine/input/ecs/ism/InputMapSystem.d.ts.map +1 -1
  509. package/src/engine/input/ecs/systems/InputControllerSystem.d.ts +1 -1
  510. package/src/engine/input/ecs/systems/InputControllerSystem.d.ts.map +1 -1
  511. package/src/engine/input/ecs/util/TerrainCameraTargetSampler.d.ts +5 -2
  512. package/src/engine/input/ecs/util/TerrainCameraTargetSampler.d.ts.map +1 -1
  513. package/src/engine/input/ecs/util/TerrainCameraTargetSampler.js +2 -1
  514. package/src/engine/intelligence/behavior/ecs/OrbitingBehavior.d.ts +9 -4
  515. package/src/engine/intelligence/behavior/ecs/OrbitingBehavior.d.ts.map +1 -1
  516. package/src/engine/intelligence/behavior/ecs/OrbitingBehavior.js +4 -3
  517. package/src/engine/intelligence/behavior/ecs/SendEventBehavior.d.ts +9 -4
  518. package/src/engine/intelligence/behavior/ecs/SendEventBehavior.d.ts.map +1 -1
  519. package/src/engine/intelligence/behavior/ecs/SendEventBehavior.js +4 -3
  520. package/src/engine/intelligence/behavior/util/syncExecuteBehaviorToCompletion.d.ts +9 -4
  521. package/src/engine/intelligence/behavior/util/syncExecuteBehaviorToCompletion.d.ts.map +1 -1
  522. package/src/engine/intelligence/behavior/util/syncExecuteBehaviorToCompletion.js +4 -3
  523. package/src/engine/intelligence/mcts/MonteCarlo.d.ts +19 -9
  524. package/src/engine/intelligence/mcts/MonteCarlo.d.ts.map +1 -1
  525. package/src/engine/intelligence/mcts/MonteCarlo.js +9 -8
  526. package/src/engine/intelligence/optimization/RandomOptimizer.d.ts +13 -6
  527. package/src/engine/intelligence/optimization/RandomOptimizer.d.ts.map +1 -1
  528. package/src/engine/intelligence/optimization/RandomOptimizer.js +6 -5
  529. package/src/engine/interpolation/InterpolationSystem.d.ts +4 -0
  530. package/src/engine/interpolation/InterpolationSystem.d.ts.map +1 -1
  531. package/src/engine/knowledge/database/StaticKnowledgeDataTable.d.ts +5 -2
  532. package/src/engine/knowledge/database/StaticKnowledgeDataTable.d.ts.map +1 -1
  533. package/src/engine/knowledge/database/StaticKnowledgeDataTable.js +6 -0
  534. package/src/engine/knowledge/database/StaticKnowledgeDataTableDescriptor.d.ts +6 -2
  535. package/src/engine/knowledge/database/StaticKnowledgeDataTableDescriptor.d.ts.map +1 -1
  536. package/src/engine/knowledge/database/StaticKnowledgeDataTableDescriptor.js +4 -0
  537. package/src/engine/knowledge/database/StaticKnowledgeDatabase.d.ts +7 -4
  538. package/src/engine/knowledge/database/StaticKnowledgeDatabase.d.ts.map +1 -1
  539. package/src/engine/knowledge/database/StaticKnowledgeDatabase.js +6 -0
  540. package/src/engine/makeSimpleTaskProgressView.d.ts +10 -4
  541. package/src/engine/makeSimpleTaskProgressView.d.ts.map +1 -1
  542. package/src/engine/makeSimpleTaskProgressView.js +4 -3
  543. package/src/engine/navigation/mesh/build/navmesh_build_topology.d.ts +20 -9
  544. package/src/engine/navigation/mesh/build/navmesh_build_topology.d.ts.map +1 -1
  545. package/src/engine/navigation/mesh/build/navmesh_build_topology.js +9 -8
  546. package/src/engine/network/sim/ActionLog.d.ts +1 -2
  547. package/src/engine/network/sim/ActionLog.d.ts.map +1 -1
  548. package/src/engine/network/sim/ActionLog.js +0 -1
  549. package/src/engine/network/state/InputRing.d.ts +1 -2
  550. package/src/engine/network/state/InputRing.d.ts.map +1 -1
  551. package/src/engine/network/state/InputRing.js +0 -1
  552. package/src/engine/notify/Notification.d.ts +15 -9
  553. package/src/engine/notify/Notification.d.ts.map +1 -1
  554. package/src/engine/notify/Notification.js +5 -4
  555. package/src/engine/options/OptionAbstract.d.ts +4 -0
  556. package/src/engine/options/OptionAbstract.d.ts.map +1 -1
  557. package/src/engine/options/OptionAbstract.js +4 -0
  558. package/src/engine/options/OptionsView.d.ts +10 -4
  559. package/src/engine/options/OptionsView.d.ts.map +1 -1
  560. package/src/engine/options/OptionsView.js +4 -3
  561. package/src/engine/physics/ccd/linear_sweep.d.ts +4 -7
  562. package/src/engine/physics/ccd/linear_sweep.d.ts.map +1 -1
  563. package/src/engine/physics/ccd/linear_sweep.js +3 -1
  564. package/src/engine/physics/cloth/MEASUREMENTS.md +2239 -0
  565. package/src/engine/physics/cloth/PLAN.md +1967 -0
  566. package/src/engine/physics/cloth/build/ClothProxy.d.ts +147 -0
  567. package/src/engine/physics/cloth/build/ClothProxy.d.ts.map +1 -0
  568. package/src/engine/physics/cloth/build/ClothProxy.js +207 -0
  569. package/src/engine/physics/cloth/build/cloth_proxy_from_joints.d.ts +70 -0
  570. package/src/engine/physics/cloth/build/cloth_proxy_from_joints.d.ts.map +1 -0
  571. package/src/engine/physics/cloth/build/cloth_proxy_from_joints.js +256 -0
  572. package/src/engine/physics/cloth/collider/ClothColliderIndex.d.ts +176 -0
  573. package/src/engine/physics/cloth/collider/ClothColliderIndex.d.ts.map +1 -0
  574. package/src/engine/physics/cloth/collider/ClothColliderIndex.js +435 -0
  575. package/src/engine/physics/cloth/collider/ClothColliderKind.d.ts +12 -0
  576. package/src/engine/physics/cloth/collider/ClothColliderKind.d.ts.map +1 -0
  577. package/src/engine/physics/cloth/collider/ClothColliderKind.js +38 -0
  578. package/src/engine/physics/cloth/collider/ClothColliderRecord.d.ts +120 -0
  579. package/src/engine/physics/cloth/collider/ClothColliderRecord.d.ts.map +1 -0
  580. package/src/engine/physics/cloth/collider/ClothColliderRecord.js +137 -0
  581. package/src/engine/physics/cloth/collider/cloth_collider_bounds.d.ts +25 -0
  582. package/src/engine/physics/cloth/collider/cloth_collider_bounds.d.ts.map +1 -0
  583. package/src/engine/physics/cloth/collider/cloth_collider_bounds.js +190 -0
  584. package/src/engine/physics/cloth/collider/cloth_collider_pack.d.ts +44 -0
  585. package/src/engine/physics/cloth/collider/cloth_collider_pack.d.ts.map +1 -0
  586. package/src/engine/physics/cloth/collider/cloth_collider_pack.js +173 -0
  587. package/src/engine/physics/cloth/collider/cloth_collider_sdf.d.ts +94 -0
  588. package/src/engine/physics/cloth/collider/cloth_collider_sdf.d.ts.map +1 -0
  589. package/src/engine/physics/cloth/collider/cloth_collider_sdf.js +275 -0
  590. package/src/engine/physics/cloth/ecs/Cloth.d.ts +145 -0
  591. package/src/engine/physics/cloth/ecs/Cloth.d.ts.map +1 -0
  592. package/src/engine/physics/cloth/ecs/Cloth.js +212 -0
  593. package/src/engine/physics/cloth/ecs/ClothCollider.d.ts +126 -0
  594. package/src/engine/physics/cloth/ecs/ClothCollider.d.ts.map +1 -0
  595. package/src/engine/physics/cloth/ecs/ClothCollider.js +199 -0
  596. package/src/engine/physics/cloth/ecs/ClothColliderFlags.d.ts +9 -0
  597. package/src/engine/physics/cloth/ecs/ClothColliderFlags.d.ts.map +1 -0
  598. package/src/engine/physics/cloth/ecs/ClothColliderFlags.js +32 -0
  599. package/src/engine/physics/cloth/ecs/ClothColliderSystem.d.ts +114 -0
  600. package/src/engine/physics/cloth/ecs/ClothColliderSystem.d.ts.map +1 -0
  601. package/src/engine/physics/cloth/ecs/ClothColliderSystem.js +243 -0
  602. package/src/engine/physics/cloth/ecs/ClothDynamics.d.ts +208 -0
  603. package/src/engine/physics/cloth/ecs/ClothDynamics.d.ts.map +1 -0
  604. package/src/engine/physics/cloth/ecs/ClothDynamics.js +331 -0
  605. package/src/engine/physics/cloth/ecs/ClothDynamicsFlags.d.ts +10 -0
  606. package/src/engine/physics/cloth/ecs/ClothDynamicsFlags.d.ts.map +1 -0
  607. package/src/engine/physics/cloth/ecs/ClothDynamicsFlags.js +66 -0
  608. package/src/engine/physics/cloth/ecs/ClothExclude.d.ts +45 -0
  609. package/src/engine/physics/cloth/ecs/ClothExclude.d.ts.map +1 -0
  610. package/src/engine/physics/cloth/ecs/ClothExclude.js +59 -0
  611. package/src/engine/physics/cloth/ecs/ClothFlags.d.ts +10 -0
  612. package/src/engine/physics/cloth/ecs/ClothFlags.d.ts.map +1 -0
  613. package/src/engine/physics/cloth/ecs/ClothFlags.js +47 -0
  614. package/src/engine/physics/cloth/ecs/ClothInstance.d.ts +429 -0
  615. package/src/engine/physics/cloth/ecs/ClothInstance.d.ts.map +1 -0
  616. package/src/engine/physics/cloth/ecs/ClothInstance.js +479 -0
  617. package/src/engine/physics/cloth/ecs/ClothRig.d.ts +95 -0
  618. package/src/engine/physics/cloth/ecs/ClothRig.d.ts.map +1 -0
  619. package/src/engine/physics/cloth/ecs/ClothRig.js +140 -0
  620. package/src/engine/physics/cloth/ecs/ClothSystem.d.ts +178 -0
  621. package/src/engine/physics/cloth/ecs/ClothSystem.d.ts.map +1 -0
  622. package/src/engine/physics/cloth/ecs/ClothSystem.js +1021 -0
  623. package/src/engine/physics/cloth/ecs/cloth_build_rows.d.ts +90 -0
  624. package/src/engine/physics/cloth/ecs/cloth_build_rows.d.ts.map +1 -0
  625. package/src/engine/physics/cloth/ecs/cloth_build_rows.js +374 -0
  626. package/src/engine/physics/cloth/ecs/cloth_dynamics_library.d.ts +186 -0
  627. package/src/engine/physics/cloth/ecs/cloth_dynamics_library.d.ts.map +1 -0
  628. package/src/engine/physics/cloth/ecs/cloth_dynamics_library.js +283 -0
  629. package/src/engine/physics/cloth/ecs/cloth_dynamics_map.d.ts +235 -0
  630. package/src/engine/physics/cloth/ecs/cloth_dynamics_map.d.ts.map +1 -0
  631. package/src/engine/physics/cloth/ecs/cloth_dynamics_map.js +271 -0
  632. package/src/engine/physics/cloth/ecs/cloth_gather_colliders.d.ts +59 -0
  633. package/src/engine/physics/cloth/ecs/cloth_gather_colliders.d.ts.map +1 -0
  634. package/src/engine/physics/cloth/ecs/cloth_gather_colliders.js +328 -0
  635. package/src/engine/physics/cloth/ecs/cloth_reconstruct_pose.d.ts +13 -0
  636. package/src/engine/physics/cloth/ecs/cloth_reconstruct_pose.d.ts.map +1 -0
  637. package/src/engine/physics/cloth/ecs/cloth_reconstruct_pose.js +288 -0
  638. package/src/engine/physics/cloth/ecs/cloth_seed_rig.d.ts +58 -0
  639. package/src/engine/physics/cloth/ecs/cloth_seed_rig.d.ts.map +1 -0
  640. package/src/engine/physics/cloth/ecs/cloth_seed_rig.js +199 -0
  641. package/src/engine/physics/cloth/ecs/cloth_seed_subtree.d.ts +59 -0
  642. package/src/engine/physics/cloth/ecs/cloth_seed_subtree.d.ts.map +1 -0
  643. package/src/engine/physics/cloth/ecs/cloth_seed_subtree.js +317 -0
  644. package/src/engine/physics/cloth/ecs/cloth_write_back.d.ts +70 -0
  645. package/src/engine/physics/cloth/ecs/cloth_write_back.d.ts.map +1 -0
  646. package/src/engine/physics/cloth/ecs/cloth_write_back.js +212 -0
  647. package/src/engine/physics/cloth/ecs/cloth_write_back_rig.d.ts +49 -0
  648. package/src/engine/physics/cloth/ecs/cloth_write_back_rig.d.ts.map +1 -0
  649. package/src/engine/physics/cloth/ecs/cloth_write_back_rig.js +115 -0
  650. package/src/engine/physics/cloth/playground/README.md +339 -0
  651. package/src/engine/physics/cloth/playground/cloth_playground_build.d.ts +58 -0
  652. package/src/engine/physics/cloth/playground/cloth_playground_build.d.ts.map +1 -0
  653. package/src/engine/physics/cloth/playground/cloth_playground_build.js +333 -0
  654. package/src/engine/physics/cloth/playground/cloth_playground_draw.d.ts +79 -0
  655. package/src/engine/physics/cloth/playground/cloth_playground_draw.d.ts.map +1 -0
  656. package/src/engine/physics/cloth/playground/cloth_playground_draw.js +519 -0
  657. package/src/engine/physics/cloth/playground/collide.html +178 -0
  658. package/src/engine/physics/cloth/playground/collide_build.d.ts +95 -0
  659. package/src/engine/physics/cloth/playground/collide_build.d.ts.map +1 -0
  660. package/src/engine/physics/cloth/playground/collide_build.js +315 -0
  661. package/src/engine/physics/cloth/playground/collide_main.d.ts +2 -0
  662. package/src/engine/physics/cloth/playground/collide_main.d.ts.map +1 -0
  663. package/src/engine/physics/cloth/playground/collide_main.js +720 -0
  664. package/src/engine/physics/cloth/playground/garment.html +182 -0
  665. package/src/engine/physics/cloth/playground/garment_build.d.ts +78 -0
  666. package/src/engine/physics/cloth/playground/garment_build.d.ts.map +1 -0
  667. package/src/engine/physics/cloth/playground/garment_build.js +359 -0
  668. package/src/engine/physics/cloth/playground/garment_main.d.ts +2 -0
  669. package/src/engine/physics/cloth/playground/garment_main.d.ts.map +1 -0
  670. package/src/engine/physics/cloth/playground/garment_main.js +633 -0
  671. package/src/engine/physics/cloth/playground/index.html +200 -0
  672. package/src/engine/physics/cloth/playground/main.d.ts +2 -0
  673. package/src/engine/physics/cloth/playground/main.d.ts.map +1 -0
  674. package/src/engine/physics/cloth/playground/main.js +876 -0
  675. package/src/engine/physics/cloth/playground/rig.html +187 -0
  676. package/src/engine/physics/cloth/playground/rig_build.d.ts +81 -0
  677. package/src/engine/physics/cloth/playground/rig_build.d.ts.map +1 -0
  678. package/src/engine/physics/cloth/playground/rig_build.js +296 -0
  679. package/src/engine/physics/cloth/playground/rig_main.d.ts +2 -0
  680. package/src/engine/physics/cloth/playground/rig_main.d.ts.map +1 -0
  681. package/src/engine/physics/cloth/playground/rig_main.js +955 -0
  682. package/src/engine/physics/cloth/solver/ClothState.d.ts +526 -0
  683. package/src/engine/physics/cloth/solver/ClothState.d.ts.map +1 -0
  684. package/src/engine/physics/cloth/solver/ClothState.js +967 -0
  685. package/src/engine/physics/cloth/solver/cloth_color_particles.d.ts +67 -0
  686. package/src/engine/physics/cloth/solver/cloth_color_particles.d.ts.map +1 -0
  687. package/src/engine/physics/cloth/solver/cloth_color_particles.js +220 -0
  688. package/src/engine/physics/cloth/solver/cloth_contact_find.d.ts +87 -0
  689. package/src/engine/physics/cloth/solver/cloth_contact_find.d.ts.map +1 -0
  690. package/src/engine/physics/cloth/solver/cloth_contact_find.js +343 -0
  691. package/src/engine/physics/cloth/solver/cloth_self_find.d.ts +112 -0
  692. package/src/engine/physics/cloth/solver/cloth_self_find.d.ts.map +1 -0
  693. package/src/engine/physics/cloth/solver/cloth_self_find.js +448 -0
  694. package/src/engine/physics/cloth/solver/cloth_solve_vertex.d.ts +16 -0
  695. package/src/engine/physics/cloth/solver/cloth_solve_vertex.d.ts.map +1 -0
  696. package/src/engine/physics/cloth/solver/cloth_solve_vertex.js +216 -0
  697. package/src/engine/physics/cloth/solver/cloth_solver_constants.d.ts +204 -0
  698. package/src/engine/physics/cloth/solver/cloth_solver_constants.d.ts.map +1 -0
  699. package/src/engine/physics/cloth/solver/cloth_solver_constants.js +213 -0
  700. package/src/engine/physics/cloth/solver/cloth_step.d.ts +122 -0
  701. package/src/engine/physics/cloth/solver/cloth_step.d.ts.map +1 -0
  702. package/src/engine/physics/cloth/solver/cloth_step.js +401 -0
  703. package/src/engine/physics/cloth/solver/cloth_vertex_accumulator.d.ts +54 -0
  704. package/src/engine/physics/cloth/solver/cloth_vertex_accumulator.d.ts.map +1 -0
  705. package/src/engine/physics/cloth/solver/cloth_vertex_accumulator.js +56 -0
  706. package/src/engine/physics/cloth/solver/constraint/cloth_backstop_row.d.ts +95 -0
  707. package/src/engine/physics/cloth/solver/constraint/cloth_backstop_row.d.ts.map +1 -0
  708. package/src/engine/physics/cloth/solver/constraint/cloth_backstop_row.js +285 -0
  709. package/src/engine/physics/cloth/solver/constraint/cloth_bend_row.d.ts +125 -0
  710. package/src/engine/physics/cloth/solver/constraint/cloth_bend_row.d.ts.map +1 -0
  711. package/src/engine/physics/cloth/solver/constraint/cloth_bend_row.js +383 -0
  712. package/src/engine/physics/cloth/solver/constraint/cloth_contact_row.d.ts +129 -0
  713. package/src/engine/physics/cloth/solver/constraint/cloth_contact_row.d.ts.map +1 -0
  714. package/src/engine/physics/cloth/solver/constraint/cloth_contact_row.js +501 -0
  715. package/src/engine/physics/cloth/solver/constraint/cloth_leash_row.d.ts +112 -0
  716. package/src/engine/physics/cloth/solver/constraint/cloth_leash_row.d.ts.map +1 -0
  717. package/src/engine/physics/cloth/solver/constraint/cloth_leash_row.js +346 -0
  718. package/src/engine/physics/cloth/solver/constraint/cloth_self_row.d.ts +75 -0
  719. package/src/engine/physics/cloth/solver/constraint/cloth_self_row.d.ts.map +1 -0
  720. package/src/engine/physics/cloth/solver/constraint/cloth_self_row.js +202 -0
  721. package/src/engine/physics/cloth/solver/constraint/cloth_stretch_row.d.ts +94 -0
  722. package/src/engine/physics/cloth/solver/constraint/cloth_stretch_row.d.ts.map +1 -0
  723. package/src/engine/physics/cloth/solver/constraint/cloth_stretch_row.js +383 -0
  724. package/src/engine/physics/cloth/solver/find_non_finite_cloth_state.d.ts +27 -0
  725. package/src/engine/physics/cloth/solver/find_non_finite_cloth_state.d.ts.map +1 -0
  726. package/src/engine/physics/cloth/solver/find_non_finite_cloth_state.js +104 -0
  727. package/src/engine/physics/ecs/PhysicsSystem.d.ts +5 -7
  728. package/src/engine/physics/ecs/PhysicsSystem.d.ts.map +1 -1
  729. package/src/engine/physics/ecs/PhysicsSystem.js +4 -1
  730. package/src/engine/physics/ecs/RigidBodySerializationUpgrader_0_1.d.ts +6 -0
  731. package/src/engine/physics/ecs/RigidBodySerializationUpgrader_0_1.d.ts.map +1 -1
  732. package/src/engine/physics/fluid/ecs/FluidObstacleSystem.d.ts +4 -4
  733. package/src/engine/physics/narrowphase/compute_penetration.d.ts +26 -23
  734. package/src/engine/physics/narrowphase/compute_penetration.d.ts.map +1 -1
  735. package/src/engine/physics/narrowphase/compute_penetration.js +25 -4
  736. package/src/engine/physics/narrowphase/narrowphase_step.d.ts +16 -23
  737. package/src/engine/physics/narrowphase/narrowphase_step.d.ts.map +1 -1
  738. package/src/engine/physics/narrowphase/narrowphase_step.js +15 -4
  739. package/src/engine/physics/narrowphase/refine_ray_concave.d.ts +4 -6
  740. package/src/engine/physics/narrowphase/refine_ray_concave.d.ts.map +1 -1
  741. package/src/engine/physics/narrowphase/refine_ray_concave.js +3 -1
  742. package/src/engine/physics/narrowphase/refine_ray_hit.d.ts +6 -6
  743. package/src/engine/physics/narrowphase/refine_ray_hit.d.ts.map +1 -1
  744. package/src/engine/physics/narrowphase/refine_ray_hit.js +5 -1
  745. package/src/engine/physics/queries/shape_cast.d.ts +9 -7
  746. package/src/engine/physics/queries/shape_cast.d.ts.map +1 -1
  747. package/src/engine/physics/queries/shape_cast.js +8 -1
  748. package/src/engine/platform/EnginePlatform.d.ts +4 -0
  749. package/src/engine/platform/EnginePlatform.d.ts.map +1 -1
  750. package/src/engine/platform/EnginePlatform.js +4 -0
  751. package/src/engine/plugin/EnginePlugin.d.ts +9 -0
  752. package/src/engine/plugin/EnginePlugin.d.ts.map +1 -1
  753. package/src/engine/plugin/EnginePlugin.js +9 -0
  754. package/src/engine/plugin/EnginePluginManager.d.ts +13 -2
  755. package/src/engine/plugin/EnginePluginManager.d.ts.map +1 -1
  756. package/src/engine/plugin/EnginePluginManager.js +10 -0
  757. package/src/engine/save/StorageBackedList.d.ts +8 -4
  758. package/src/engine/save/StorageBackedList.d.ts.map +1 -1
  759. package/src/engine/save/StorageBackedList.js +3 -2
  760. package/src/engine/scene/Scene.d.ts +10 -0
  761. package/src/engine/scene/Scene.d.ts.map +1 -1
  762. package/src/engine/scene/Scene.js +7 -0
  763. package/src/engine/scene/SceneManager.d.ts +4 -0
  764. package/src/engine/scene/SceneManager.d.ts.map +1 -1
  765. package/src/engine/scene/SceneManager.js +4 -0
  766. package/src/engine/scene/SerializedScene.d.ts +8 -4
  767. package/src/engine/scene/SerializedScene.d.ts.map +1 -1
  768. package/src/engine/scene/SerializedScene.js +3 -2
  769. package/src/engine/scene/transitionToScene.d.ts +11 -5
  770. package/src/engine/scene/transitionToScene.d.ts.map +1 -1
  771. package/src/engine/scene/transitionToScene.js +5 -4
  772. package/src/engine/simulation/Ticker.d.ts +5 -2
  773. package/src/engine/simulation/Ticker.d.ts.map +1 -1
  774. package/src/engine/simulation/Ticker.js +2 -1
  775. package/src/engine/sound/SoundEngine.d.ts +4 -0
  776. package/src/engine/sound/SoundEngine.d.ts.map +1 -1
  777. package/src/engine/sound/SoundEngine.js +4 -0
  778. package/src/engine/sound/material/concrete/json/deserializeSoundMaterialFromJSON.d.ts +7 -3
  779. package/src/engine/sound/material/concrete/json/deserializeSoundMaterialFromJSON.d.ts.map +1 -1
  780. package/src/engine/sound/material/concrete/json/deserializeSoundMaterialFromJSON.js +3 -2
  781. package/src/engine/sound/simulation/ecs/AcousticSimulationSystem.d.ts +10 -0
  782. package/src/engine/sound/simulation/ecs/AcousticSimulationSystem.d.ts.map +1 -1
  783. package/src/engine/sound/sopra/SopraEngine.d.ts +5 -0
  784. package/src/engine/sound/sopra/SopraEngine.d.ts.map +1 -1
  785. package/src/engine/sound/sopra/SopraEngine.js +8 -0
  786. package/src/engine/sound/sopra/definition/BusDefinition.d.ts +4 -0
  787. package/src/engine/sound/sopra/definition/BusDefinition.d.ts.map +1 -1
  788. package/src/engine/sound/sopra/definition/BusDefinition.js +4 -0
  789. package/src/engine/sound/sopra/definition/EventDescription.d.ts +1 -0
  790. package/src/engine/sound/sopra/definition/EventDescription.d.ts.map +1 -1
  791. package/src/engine/sound/sopra/definition/EventDescription.js +4 -0
  792. package/src/engine/sound/sopra/definition/clip/AbstractAudioClip.d.ts +6 -0
  793. package/src/engine/sound/sopra/definition/clip/AbstractAudioClip.d.ts.map +1 -1
  794. package/src/engine/sound/sopra/definition/clip/AbstractAudioClip.js +5 -0
  795. package/src/engine/sound/sopra/definition/clip/BlendContainerAudioClip.d.ts +1 -1
  796. package/src/engine/sound/sopra/definition/clip/ContainerAudioClip.d.ts +1 -0
  797. package/src/engine/sound/sopra/definition/clip/ContainerAudioClip.d.ts.map +1 -1
  798. package/src/engine/sound/sopra/definition/clip/RandomContainerAudioClip.d.ts +1 -1
  799. package/src/engine/sound/sopra/definition/clip/SampleAudioClip.d.ts +10 -2
  800. package/src/engine/sound/sopra/definition/clip/SampleAudioClip.d.ts.map +1 -1
  801. package/src/engine/sound/sopra/definition/clip/SampleAudioClip.js +7 -0
  802. package/src/engine/sound/sopra/definition/clip/SequenceContainerAudioClip.d.ts +1 -1
  803. package/src/engine/sound/sopra/definition/clip/SwitchContainerAudioClip.d.ts +1 -1
  804. package/src/engine/sound/sopra/runtime/BusGraph.d.ts +4 -0
  805. package/src/engine/sound/sopra/runtime/BusGraph.d.ts.map +1 -1
  806. package/src/engine/sound/sopra/runtime/BusGraph.js +4 -0
  807. package/src/engine/sound/sopra/runtime/EventInstance.d.ts +9 -1
  808. package/src/engine/sound/sopra/runtime/EventInstance.d.ts.map +1 -1
  809. package/src/engine/sound/sopra/runtime/EventInstance.js +11 -0
  810. package/src/engine/sound/sopra/runtime/VoiceManager.d.ts +2 -0
  811. package/src/engine/sound/sopra/runtime/VoiceManager.d.ts.map +1 -1
  812. package/src/engine/sound/sopra/runtime/VoiceManager.js +5 -0
  813. package/src/engine/ui/DraggableAspect.d.ts +14 -6
  814. package/src/engine/ui/DraggableAspect.d.ts.map +1 -1
  815. package/src/engine/ui/DraggableAspect.js +6 -5
  816. package/src/engine/ui/GUIEngine.d.ts +73 -26
  817. package/src/engine/ui/GUIEngine.d.ts.map +1 -1
  818. package/src/engine/ui/GUIEngine.js +37 -19
  819. package/src/engine/ui/bindings/DomElementBindingDescription.d.ts +7 -3
  820. package/src/engine/ui/bindings/DomElementBindingDescription.d.ts.map +1 -1
  821. package/src/engine/ui/bindings/DomElementBindingDescription.js +3 -2
  822. package/src/engine/ui/modal/ModalStack.d.ts +4 -0
  823. package/src/engine/ui/modal/ModalStack.d.ts.map +1 -1
  824. package/src/engine/ui/modal/ModalStack.js +4 -0
  825. package/src/engine/ui/notification/AnimatedObjectEmitter.d.ts +4 -0
  826. package/src/engine/ui/notification/AnimatedObjectEmitter.d.ts.map +1 -1
  827. package/src/engine/ui/notification/AnimatedObjectEmitter.js +4 -0
  828. package/src/engine/ui/notification/NotificationManager.d.ts +21 -8
  829. package/src/engine/ui/notification/NotificationManager.d.ts.map +1 -1
  830. package/src/engine/ui/notification/NotificationManager.js +10 -3
  831. package/src/engine/ui/notification/ViewEmitter.d.ts +8 -2
  832. package/src/engine/ui/notification/ViewEmitter.d.ts.map +1 -1
  833. package/src/engine/ui/notification/ViewEmitter.js +6 -1
  834. package/src/engine/ui/scene/SceneGUIContext.d.ts +4 -0
  835. package/src/engine/ui/scene/SceneGUIContext.d.ts.map +1 -1
  836. package/src/engine/ui/scene/SceneGUIContext.js +4 -0
  837. package/src/generation/filtering/numeric/util/populateSampler2DFromCellFilter.d.ts +9 -4
  838. package/src/generation/filtering/numeric/util/populateSampler2DFromCellFilter.d.ts.map +1 -1
  839. package/src/generation/filtering/numeric/util/populateSampler2DFromCellFilter.js +4 -3
  840. package/src/generation/grid/actions/ContinuousGridCellActionWriteObstacle.d.ts +9 -4
  841. package/src/generation/grid/actions/ContinuousGridCellActionWriteObstacle.d.ts.map +1 -1
  842. package/src/generation/grid/actions/ContinuousGridCellActionWriteObstacle.js +4 -3
  843. package/src/generation/grid/generation/GridTaskApplyActionToCells.d.ts +9 -4
  844. package/src/generation/grid/generation/GridTaskApplyActionToCells.d.ts.map +1 -1
  845. package/src/generation/grid/generation/GridTaskApplyActionToCells.js +4 -3
  846. package/src/generation/grid/generation/discrete/GridTaskActionRuleSet.d.ts +9 -4
  847. package/src/generation/grid/generation/discrete/GridTaskActionRuleSet.d.ts.map +1 -1
  848. package/src/generation/grid/generation/discrete/GridTaskActionRuleSet.js +4 -3
  849. package/src/generation/grid/generation/grid/select/CellSupplierBestN.d.ts +11 -5
  850. package/src/generation/grid/generation/grid/select/CellSupplierBestN.d.ts.map +1 -1
  851. package/src/generation/grid/generation/grid/select/CellSupplierBestN.js +5 -4
  852. package/src/generation/grid/generation/road/GridTaskGenerateRoads.d.ts +9 -4
  853. package/src/generation/grid/generation/road/GridTaskGenerateRoads.d.ts.map +1 -1
  854. package/src/generation/grid/generation/road/GridTaskGenerateRoads.js +12 -10
  855. package/src/generation/grid/generation/util/buildDistanceMapToObjective.d.ts +19 -9
  856. package/src/generation/grid/generation/util/buildDistanceMapToObjective.d.ts.map +1 -1
  857. package/src/generation/grid/generation/util/buildDistanceMapToObjective.js +9 -8
  858. package/src/generation/grid/generation/util/buildPathFromDistanceMap.d.ts +17 -8
  859. package/src/generation/grid/generation/util/buildPathFromDistanceMap.d.ts.map +1 -1
  860. package/src/generation/grid/generation/util/buildPathFromDistanceMap.js +8 -7
  861. package/src/generation/markers/GridActionRuleSet.d.ts +11 -5
  862. package/src/generation/markers/GridActionRuleSet.d.ts.map +1 -1
  863. package/src/generation/markers/GridActionRuleSet.js +5 -4
  864. package/src/generation/markers/actions/MarkerNodeActionEntityPlacement.d.ts +9 -4
  865. package/src/generation/markers/actions/MarkerNodeActionEntityPlacement.d.ts.map +1 -1
  866. package/src/generation/markers/actions/MarkerNodeActionEntityPlacement.js +4 -3
  867. package/src/generation/markers/actions/MarkerNodeActionImaginary.d.ts +9 -4
  868. package/src/generation/markers/actions/MarkerNodeActionImaginary.d.ts.map +1 -1
  869. package/src/generation/markers/actions/MarkerNodeActionImaginary.js +4 -3
  870. package/src/generation/markers/actions/MarkerProcessingRule.d.ts +11 -5
  871. package/src/generation/markers/actions/MarkerProcessingRule.d.ts.map +1 -1
  872. package/src/generation/markers/actions/MarkerProcessingRule.js +5 -4
  873. package/src/generation/markers/actions/placement/MarkerNodeEntityProcessorClingToTerrain.d.ts +5 -2
  874. package/src/generation/markers/actions/placement/MarkerNodeEntityProcessorClingToTerrain.d.ts.map +1 -1
  875. package/src/generation/markers/actions/placement/MarkerNodeEntityProcessorClingToTerrain.js +2 -1
  876. package/src/generation/markers/actions/terrain/MarkerNodeActionPaintTerrain.d.ts +13 -6
  877. package/src/generation/markers/actions/terrain/MarkerNodeActionPaintTerrain.d.ts.map +1 -1
  878. package/src/generation/markers/actions/terrain/MarkerNodeActionPaintTerrain.js +6 -5
  879. package/src/generation/markers/emitter/MarkerNodeEmitterPredicated.d.ts +7 -3
  880. package/src/generation/markers/emitter/MarkerNodeEmitterPredicated.d.ts.map +1 -1
  881. package/src/generation/markers/emitter/MarkerNodeEmitterPredicated.js +3 -2
  882. package/src/generation/placement/GridCellPlacementRule.d.ts +15 -7
  883. package/src/generation/placement/GridCellPlacementRule.d.ts.map +1 -1
  884. package/src/generation/placement/GridCellPlacementRule.js +7 -6
  885. package/src/shade/descriptor/ObjectDescriptorBase.d.ts +8 -3
  886. package/src/shade/descriptor/ObjectDescriptorBase.d.ts.map +1 -1
  887. package/src/shade/descriptor/ObjectDescriptorBase.js +7 -2
  888. package/src/shade/descriptor/binding/BindGroupLayoutDescriptor.d.ts +12 -0
  889. package/src/shade/descriptor/binding/BindGroupLayoutDescriptor.d.ts.map +1 -1
  890. package/src/shade/descriptor/binding/BindGroupLayoutDescriptor.js +8 -0
  891. package/src/shade/descriptor/binding/BufferBindingLayout.d.ts +11 -6
  892. package/src/shade/descriptor/binding/BufferBindingLayout.d.ts.map +1 -1
  893. package/src/shade/descriptor/binding/BufferBindingLayout.js +5 -4
  894. package/src/shade/descriptor/binding/SamplerBindingLayout.d.ts +2 -2
  895. package/src/shade/descriptor/binding/SamplerBindingLayout.d.ts.map +1 -1
  896. package/src/shade/descriptor/binding/SamplerBindingLayout.js +1 -1
  897. package/src/shade/descriptor/binding/StorageTextureBindingLayout.d.ts +2 -2
  898. package/src/shade/descriptor/binding/StorageTextureBindingLayout.d.ts.map +1 -1
  899. package/src/shade/descriptor/binding/StorageTextureBindingLayout.js +1 -1
  900. package/src/shade/descriptor/binding/TextureBindingLayout.d.ts +4 -4
  901. package/src/shade/descriptor/binding/TextureBindingLayout.d.ts.map +1 -1
  902. package/src/shade/descriptor/binding/TextureBindingLayout.js +2 -2
  903. package/src/shade/descriptor/blend/BlendComponent.d.ts +6 -6
  904. package/src/shade/descriptor/blend/BlendComponent.d.ts.map +1 -1
  905. package/src/shade/descriptor/blend/BlendComponent.js +3 -3
  906. package/src/shade/descriptor/pipeline/PipelineLayoutDescriptor.d.ts +12 -0
  907. package/src/shade/descriptor/pipeline/PipelineLayoutDescriptor.d.ts.map +1 -1
  908. package/src/shade/descriptor/pipeline/PipelineLayoutDescriptor.js +8 -0
  909. package/src/shade/descriptor/pipeline/compute/ComputePipelineDescriptor.d.ts +18 -5
  910. package/src/shade/descriptor/pipeline/compute/ComputePipelineDescriptor.d.ts.map +1 -1
  911. package/src/shade/descriptor/pipeline/compute/ComputePipelineDescriptor.js +14 -4
  912. package/src/shade/descriptor/pipeline/render/DepthStencilState.d.ts +4 -1
  913. package/src/shade/descriptor/pipeline/render/DepthStencilState.d.ts.map +1 -1
  914. package/src/shade/descriptor/pipeline/render/DepthStencilState.js +3 -0
  915. package/src/shade/descriptor/pipeline/render/FragmentState.d.ts +5 -2
  916. package/src/shade/descriptor/pipeline/render/FragmentState.d.ts.map +1 -1
  917. package/src/shade/descriptor/pipeline/render/FragmentState.js +4 -1
  918. package/src/shade/descriptor/pipeline/render/PrimitiveState.d.ts +8 -8
  919. package/src/shade/descriptor/pipeline/render/PrimitiveState.d.ts.map +1 -1
  920. package/src/shade/descriptor/pipeline/render/PrimitiveState.js +4 -4
  921. package/src/shade/descriptor/pipeline/render/StencilFaceState.d.ts +16 -4
  922. package/src/shade/descriptor/pipeline/render/StencilFaceState.d.ts.map +1 -1
  923. package/src/shade/descriptor/pipeline/render/StencilFaceState.js +12 -0
  924. package/src/shade/descriptor/pipeline/render/VertexState.d.ts +5 -2
  925. package/src/shade/descriptor/pipeline/render/VertexState.d.ts.map +1 -1
  926. package/src/shade/descriptor/pipeline/render/VertexState.js +4 -1
  927. package/src/shade/descriptor/texture/SamplerDescriptor.d.ts +24 -6
  928. package/src/shade/descriptor/texture/SamplerDescriptor.d.ts.map +1 -1
  929. package/src/shade/descriptor/texture/SamplerDescriptor.js +18 -0
  930. package/src/shade/descriptor/texture/TextureDescriptor.d.ts +2 -2
  931. package/src/shade/descriptor/texture/TextureDescriptor.d.ts.map +1 -1
  932. package/src/shade/descriptor/texture/TextureDescriptor.js +1 -1
  933. package/src/shade/device/ShadeGPUCommandContext.d.ts +46 -12
  934. package/src/shade/device/ShadeGPUCommandContext.d.ts.map +1 -1
  935. package/src/shade/device/ShadeGPUCommandContext.js +28 -8
  936. package/src/shade/device/graph/GraphicsExecutionContext.d.ts +6 -0
  937. package/src/shade/device/graph/GraphicsExecutionContext.d.ts.map +1 -1
  938. package/src/shade/device/graph/GraphicsExecutionContext.js +5 -0
  939. package/src/shade/device/graph/TextureResourceDescriptor.d.ts +13 -6
  940. package/src/shade/device/graph/TextureResourceDescriptor.d.ts.map +1 -1
  941. package/src/shade/device/graph/TextureResourceDescriptor.js +6 -5
  942. package/src/shade/device/pass/ShadeGPUComputePassEncoder.d.ts +6 -0
  943. package/src/shade/device/pass/ShadeGPUComputePassEncoder.d.ts.map +1 -1
  944. package/src/shade/device/pass/ShadeGPUComputePassEncoder.js +5 -0
  945. package/src/shade/device/pass/ShadeGPURenderPassEncoder.d.ts +6 -0
  946. package/src/shade/device/pass/ShadeGPURenderPassEncoder.d.ts.map +1 -1
  947. package/src/shade/device/pass/ShadeGPURenderPassEncoder.js +5 -0
  948. package/src/shade/device/pipeline/ComputePipelineManager.d.ts +9 -1
  949. package/src/shade/device/pipeline/ComputePipelineManager.d.ts.map +1 -1
  950. package/src/shade/device/pipeline/ComputePipelineManager.js +6 -0
  951. package/src/shade/device/pipeline/PipelineLayoutManager.d.ts +6 -0
  952. package/src/shade/device/pipeline/PipelineLayoutManager.d.ts.map +1 -1
  953. package/src/shade/device/pipeline/PipelineLayoutManager.js +5 -0
  954. package/src/shade/device/pipeline/RenderPipelineManager.d.ts +7 -1
  955. package/src/shade/device/pipeline/RenderPipelineManager.d.ts.map +1 -1
  956. package/src/shade/device/pipeline/RenderPipelineManager.js +5 -0
  957. package/src/shade/device/shader/ShaderModuleCompiler.d.ts +4 -0
  958. package/src/shade/device/shader/ShaderModuleCompiler.d.ts.map +1 -1
  959. package/src/shade/device/shader/ShaderModuleCompiler.js +4 -0
  960. package/src/shade/device/timing/profile/GPUFrameRecorder.d.ts +6 -0
  961. package/src/shade/device/timing/profile/GPUFrameRecorder.d.ts.map +1 -1
  962. package/src/shade/device/timing/profile/GPUFrameRecorder.js +5 -0
  963. package/src/shade/device/timing/profile/GPUProfileFrame.d.ts +6 -0
  964. package/src/shade/device/timing/profile/GPUProfileFrame.d.ts.map +1 -1
  965. package/src/shade/device/timing/profile/GPUProfileFrame.js +5 -0
  966. package/src/shade/device/timing/profile/GPUProfileSession.d.ts +1 -0
  967. package/src/shade/device/timing/profile/GPUProfileSession.d.ts.map +1 -1
  968. package/src/shade/device/timing/profile/GPUProfileSession.js +4 -0
  969. package/src/shade/device/timing/profile/GPUProfileSpan.d.ts +4 -0
  970. package/src/shade/device/timing/profile/GPUProfileSpan.d.ts.map +1 -1
  971. package/src/shade/device/timing/profile/GPUProfileSpan.js +4 -0
  972. package/src/shade/playground/add_random_meshes.d.ts +19 -8
  973. package/src/shade/playground/add_random_meshes.d.ts.map +1 -1
  974. package/src/shade/playground/add_random_meshes.js +8 -7
  975. package/src/shade/playground/ground_seam/capture_scene_color.d.ts +4 -0
  976. package/src/shade/playground/ground_seam/capture_scene_color.d.ts.map +1 -1
  977. package/src/shade/playground/particle_ecs/index.html +0 -2
  978. package/src/shade/playground/particle_ecs/main.js +8 -29
  979. package/src/shade/playground/particle_system/main.js +8 -21
  980. package/src/shade/playground/particle_system/particle_prototype.js +8 -8
  981. package/src/shade/playground/particle_system/particle_scene.d.ts +0 -61
  982. package/src/shade/playground/particle_system/particle_scene.d.ts.map +1 -1
  983. package/src/shade/playground/particle_system/particle_scene.js +0 -57
  984. package/src/shade/playground/ssr_variance/reference.d.ts +1 -1
  985. package/src/shade/playground/ssr_variance/reference.d.ts.map +1 -1
  986. package/src/shade/playground/vgeo_viewer/README.md +29 -2
  987. package/src/shade/playground/vgeo_viewer/cut_geometry.d.ts.map +1 -1
  988. package/src/shade/playground/vgeo_viewer/cut_geometry.js +3 -40
  989. package/src/shade/playground/vgeo_viewer/main.js +101 -50
  990. package/src/shade/playground/vgeo_viewer/select_cut.d.ts +19 -0
  991. package/src/shade/playground/vgeo_viewer/select_cut.d.ts.map +1 -1
  992. package/src/shade/playground/vgeo_viewer/select_cut.js +53 -9
  993. package/src/shade/renderer/GPUSamplerManager.d.ts +4 -0
  994. package/src/shade/renderer/GPUSamplerManager.d.ts.map +1 -1
  995. package/src/shade/renderer/GPUSamplerManager.js +4 -0
  996. package/src/shade/renderer/GraphicsContext.d.ts +2 -0
  997. package/src/shade/renderer/GraphicsContext.d.ts.map +1 -1
  998. package/src/shade/renderer/GraphicsContext.js +5 -0
  999. package/src/shade/renderer/Renderer.d.ts +14 -4
  1000. package/src/shade/renderer/Renderer.d.ts.map +1 -1
  1001. package/src/shade/renderer/Renderer.js +70 -67
  1002. package/src/shade/renderer/ResourceManager.d.ts +10 -0
  1003. package/src/shade/renderer/ResourceManager.d.ts.map +1 -1
  1004. package/src/shade/renderer/ResourceManager.js +7 -0
  1005. package/src/shade/renderer/animation/GPUAnimationManager.d.ts +18 -11
  1006. package/src/shade/renderer/animation/GPUAnimationManager.d.ts.map +1 -1
  1007. package/src/shade/renderer/animation/GPUAnimationManager.js +2063 -1958
  1008. package/src/shade/renderer/animation/ShadeAnimationChannel.d.ts +2 -0
  1009. package/src/shade/renderer/animation/ShadeAnimationChannel.d.ts.map +1 -1
  1010. package/src/shade/renderer/animation/ShadeAnimationChannel.js +5 -0
  1011. package/src/shade/renderer/animation/ShadeAnimationClip.d.ts +4 -0
  1012. package/src/shade/renderer/animation/ShadeAnimationClip.d.ts.map +1 -1
  1013. package/src/shade/renderer/animation/ShadeAnimationClip.js +4 -0
  1014. package/src/shade/renderer/animation/Skin.d.ts +6 -0
  1015. package/src/shade/renderer/animation/Skin.d.ts.map +1 -1
  1016. package/src/shade/renderer/animation/Skin.js +5 -0
  1017. package/src/shade/renderer/animation/skinning/GPUMeshSkinningContext.d.ts +48 -0
  1018. package/src/shade/renderer/animation/skinning/GPUMeshSkinningContext.d.ts.map +1 -1
  1019. package/src/shade/renderer/animation/skinning/GPUMeshSkinningContext.js +201 -14
  1020. package/src/shade/renderer/binding/BindGroupDescriptor.d.ts +2 -1
  1021. package/src/shade/renderer/binding/BindGroupDescriptor.d.ts.map +1 -1
  1022. package/src/shade/renderer/binding/BindGroupDescriptor.js +4 -0
  1023. package/src/shade/renderer/binding/BindGroupManager.d.ts +1 -0
  1024. package/src/shade/renderer/binding/BindGroupManager.d.ts.map +1 -1
  1025. package/src/shade/renderer/binding/BindGroupManager.js +4 -0
  1026. package/src/shade/renderer/buffer/GPUBufferAllocatorNative.d.ts +4 -0
  1027. package/src/shade/renderer/buffer/GPUBufferAllocatorNative.d.ts.map +1 -1
  1028. package/src/shade/renderer/buffer/GPUBufferAllocatorNative.js +4 -0
  1029. package/src/shade/renderer/buffer/GPUTypedBuffer.d.ts +20 -8
  1030. package/src/shade/renderer/buffer/GPUTypedBuffer.d.ts.map +1 -1
  1031. package/src/shade/renderer/buffer/GPUTypedBuffer.js +11 -6
  1032. package/src/shade/renderer/buffer/graph_inspect_gpu_buffer.d.ts +15 -7
  1033. package/src/shade/renderer/buffer/graph_inspect_gpu_buffer.d.ts.map +1 -1
  1034. package/src/shade/renderer/buffer/graph_inspect_gpu_buffer.js +7 -6
  1035. package/src/shade/renderer/buffer/inspect_gpu_buffer.d.ts +26 -12
  1036. package/src/shade/renderer/buffer/inspect_gpu_buffer.d.ts.map +1 -1
  1037. package/src/shade/renderer/buffer/inspect_gpu_buffer.js +12 -10
  1038. package/src/shade/renderer/buffer/inspect_gpu_buffer_typed.d.ts +13 -6
  1039. package/src/shade/renderer/buffer/inspect_gpu_buffer_typed.d.ts.map +1 -1
  1040. package/src/shade/renderer/buffer/inspect_gpu_buffer_typed.js +6 -5
  1041. package/src/shade/renderer/buffer/table/GPUDatabase.d.ts +13 -5
  1042. package/src/shade/renderer/buffer/table/GPUDatabase.d.ts.map +1 -1
  1043. package/src/shade/renderer/buffer/table/GPUDatabase.js +201 -66
  1044. package/src/shade/renderer/buffer/table/GPUTypedTable.d.ts +97 -3
  1045. package/src/shade/renderer/buffer/table/GPUTypedTable.d.ts.map +1 -1
  1046. package/src/shade/renderer/buffer/table/GPUTypedTable.js +419 -2
  1047. package/src/shade/renderer/buffer/table/GPUTypedTableDescriptor.d.ts +4 -0
  1048. package/src/shade/renderer/buffer/table/GPUTypedTableDescriptor.d.ts.map +1 -1
  1049. package/src/shade/renderer/buffer/table/GPUTypedTableDescriptor.js +4 -0
  1050. package/src/shade/renderer/buffer/table/GPU_TABLE_PARTIAL_UPLOAD_DESCRIPTOR_WORDS.d.ts +14 -0
  1051. package/src/shade/renderer/buffer/table/GPU_TABLE_PARTIAL_UPLOAD_DESCRIPTOR_WORDS.d.ts.map +1 -0
  1052. package/src/shade/renderer/buffer/table/GPU_TABLE_PARTIAL_UPLOAD_DESCRIPTOR_WORDS.js +13 -0
  1053. package/src/shade/renderer/buffer/table/gpu_table_partial_upload_shader.d.ts +17 -0
  1054. package/src/shade/renderer/buffer/table/gpu_table_partial_upload_shader.d.ts.map +1 -0
  1055. package/src/shade/renderer/buffer/table/gpu_table_partial_upload_shader.js +116 -0
  1056. package/src/shade/renderer/buffer/table/single/GPUSingleTypeTable.d.ts +11 -4
  1057. package/src/shade/renderer/buffer/table/single/GPUSingleTypeTable.d.ts.map +1 -1
  1058. package/src/shade/renderer/buffer/table/single/GPUSingleTypeTable.js +9 -3
  1059. package/src/shade/renderer/camera/CameraManager.d.ts +4 -0
  1060. package/src/shade/renderer/camera/CameraManager.d.ts.map +1 -1
  1061. package/src/shade/renderer/camera/CameraManager.js +4 -0
  1062. package/src/shade/renderer/camera/GPUCameraContext.d.ts +4 -2
  1063. package/src/shade/renderer/camera/GPUCameraContext.d.ts.map +1 -1
  1064. package/src/shade/renderer/camera/GPUCameraContext.js +5 -0
  1065. package/src/shade/renderer/extension/FrameContext.d.ts +15 -5
  1066. package/src/shade/renderer/extension/FrameContext.d.ts.map +1 -1
  1067. package/src/shade/renderer/extension/FrameContext.js +7 -0
  1068. package/src/shade/renderer/extension/FrameRecord.d.ts +7 -1
  1069. package/src/shade/renderer/extension/FrameRecord.d.ts.map +1 -1
  1070. package/src/shade/renderer/extension/FrameRecord.js +5 -0
  1071. package/src/shade/renderer/extension/RenderExtension.d.ts +4 -0
  1072. package/src/shade/renderer/extension/RenderExtension.d.ts.map +1 -1
  1073. package/src/shade/renderer/extension/RenderExtension.js +4 -0
  1074. package/src/shade/renderer/geometry/Attribute.d.ts +2 -2
  1075. package/src/shade/renderer/geometry/Attribute.d.ts.map +1 -1
  1076. package/src/shade/renderer/geometry/Attribute.js +1 -1
  1077. package/src/shade/renderer/geometry/GPUGeometryManager.d.ts +30 -2
  1078. package/src/shade/renderer/geometry/GPUGeometryManager.d.ts.map +1 -1
  1079. package/src/shade/renderer/geometry/GPUGeometryManager.js +642 -591
  1080. package/src/shade/renderer/geometry/GPUGeometryMetadata.d.ts +4 -0
  1081. package/src/shade/renderer/geometry/GPUGeometryMetadata.d.ts.map +1 -1
  1082. package/src/shade/renderer/geometry/GPUGeometryMetadata.js +4 -0
  1083. package/src/shade/renderer/geometry/bvh/GPUBLASRefitBatch.d.ts +7 -3
  1084. package/src/shade/renderer/geometry/bvh/GPUBLASRefitBatch.d.ts.map +1 -1
  1085. package/src/shade/renderer/geometry/bvh/GPUBLASRefitBatch.js +3 -2
  1086. package/src/shade/renderer/geometry/bvh/GPUGeometryBVHManager.d.ts +13 -4
  1087. package/src/shade/renderer/geometry/bvh/GPUGeometryBVHManager.d.ts.map +1 -1
  1088. package/src/shade/renderer/geometry/bvh/GPUGeometryBVHManager.js +843 -730
  1089. package/src/shade/renderer/geometry/bvh/GPUGeometryMeshletsBVH.d.ts +12 -0
  1090. package/src/shade/renderer/geometry/bvh/GPUGeometryMeshletsBVH.d.ts.map +1 -1
  1091. package/src/shade/renderer/geometry/bvh/GPUGeometryMeshletsBVH.js +13 -0
  1092. package/src/shade/renderer/geometry/bvh/bvh_to_gpu_buffer.d.ts +11 -5
  1093. package/src/shade/renderer/geometry/bvh/bvh_to_gpu_buffer.d.ts.map +1 -1
  1094. package/src/shade/renderer/geometry/bvh/bvh_to_gpu_buffer.js +5 -4
  1095. package/src/shade/renderer/geometry/meshlet/GPUMeshletManager.d.ts +29 -4
  1096. package/src/shade/renderer/geometry/meshlet/GPUMeshletManager.d.ts.map +1 -1
  1097. package/src/shade/renderer/geometry/meshlet/GPUMeshletManager.js +195 -33
  1098. package/src/shade/renderer/geometry/meshlet/MeshletBatch.d.ts +1 -0
  1099. package/src/shade/renderer/geometry/meshlet/MeshletBatch.d.ts.map +1 -1
  1100. package/src/shade/renderer/geometry/meshlet/MeshletBatch.js +4 -0
  1101. package/src/shade/renderer/geometry/meshlet_batch_to_bvh.d.ts +13 -6
  1102. package/src/shade/renderer/geometry/meshlet_batch_to_bvh.d.ts.map +1 -1
  1103. package/src/shade/renderer/geometry/meshlet_batch_to_bvh.js +6 -5
  1104. package/src/shade/renderer/geometry/sdf/GPUGeometrySDFManager.d.ts +2 -0
  1105. package/src/shade/renderer/geometry/sdf/GPUGeometrySDFManager.d.ts.map +1 -1
  1106. package/src/shade/renderer/geometry/sdf/GPUGeometrySDFManager.js +5 -0
  1107. package/src/shade/renderer/geometry/sdf/shader_sdf_visualize.d.ts +13 -6
  1108. package/src/shade/renderer/geometry/sdf/shader_sdf_visualize.d.ts.map +1 -1
  1109. package/src/shade/renderer/geometry/sdf/shader_sdf_visualize.js +6 -5
  1110. package/src/shade/renderer/geometry/virtual/MICRON_COMPARISON_2026_08_20.md +17 -0
  1111. package/src/shade/renderer/geometry/virtual/VGEO_FORMAT.md +141 -24
  1112. package/src/shade/renderer/geometry/virtual/VIRTUAL_GEOMETRY_DESIGN.md +204 -64
  1113. package/src/shade/renderer/geometry/virtual/VIRTUAL_GEOMETRY_PLAN.md +110 -10
  1114. package/src/shade/renderer/geometry/virtual/VK_LOD_CLUSTERS_COMPARISON_2026_08_20.md +19 -0
  1115. package/src/shade/renderer/geometry/virtual/format/read/VGeoByteSource.d.ts +19 -6
  1116. package/src/shade/renderer/geometry/virtual/format/read/VGeoByteSource.d.ts.map +1 -1
  1117. package/src/shade/renderer/geometry/virtual/format/read/VGeoByteSource.js +26 -7
  1118. package/src/shade/renderer/geometry/virtual/format/read/VGeoContainerReader.d.ts +204 -14
  1119. package/src/shade/renderer/geometry/virtual/format/read/VGeoContainerReader.d.ts.map +1 -1
  1120. package/src/shade/renderer/geometry/virtual/format/read/VGeoContainerReader.js +803 -51
  1121. package/src/shade/renderer/geometry/virtual/format/read/VGeoReadOptions.d.ts +49 -13
  1122. package/src/shade/renderer/geometry/virtual/format/read/VGeoReadOptions.d.ts.map +1 -1
  1123. package/src/shade/renderer/geometry/virtual/format/read/VGeoReadOptions.js +52 -14
  1124. package/src/shade/renderer/geometry/virtual/format/read/tool/VGEO_MAX_AUDIT_BYTES.d.ts +20 -0
  1125. package/src/shade/renderer/geometry/virtual/format/read/tool/VGEO_MAX_AUDIT_BYTES.d.ts.map +1 -0
  1126. package/src/shade/renderer/geometry/virtual/format/read/tool/VGEO_MAX_AUDIT_BYTES.js +19 -0
  1127. package/src/shade/renderer/geometry/virtual/format/read/tool/vgeo_audit_container.d.ts +27 -0
  1128. package/src/shade/renderer/geometry/virtual/format/read/tool/vgeo_audit_container.d.ts.map +1 -0
  1129. package/src/shade/renderer/geometry/virtual/format/read/tool/vgeo_audit_container.js +48 -0
  1130. package/src/shade/renderer/geometry/virtual/format/read/tool/vgeo_install_all_pages.d.ts +29 -0
  1131. package/src/shade/renderer/geometry/virtual/format/read/tool/vgeo_install_all_pages.d.ts.map +1 -0
  1132. package/src/shade/renderer/geometry/virtual/format/read/tool/vgeo_install_all_pages.js +60 -0
  1133. package/src/shade/renderer/geometry/virtual/format/read/vgeo_fetch_byte_source.d.ts +8 -1
  1134. package/src/shade/renderer/geometry/virtual/format/read/vgeo_fetch_byte_source.d.ts.map +1 -1
  1135. package/src/shade/renderer/geometry/virtual/format/read/vgeo_fetch_byte_source.js +32 -2
  1136. package/src/shade/renderer/geometry/virtual/residency/VGeoResidencyManager.d.ts +258 -0
  1137. package/src/shade/renderer/geometry/virtual/residency/VGeoResidencyManager.d.ts.map +1 -0
  1138. package/src/shade/renderer/geometry/virtual/residency/VGeoResidencyManager.js +723 -0
  1139. package/src/shade/renderer/geometry/virtual/residency/VGeoResidencyOptions.d.ts +49 -0
  1140. package/src/shade/renderer/geometry/virtual/residency/VGeoResidencyOptions.d.ts.map +1 -0
  1141. package/src/shade/renderer/geometry/virtual/residency/VGeoResidencyOptions.js +50 -0
  1142. package/src/shade/renderer/global_illumination/brick4/cpu/brick4_bake_for_scene.d.ts +11 -5
  1143. package/src/shade/renderer/global_illumination/brick4/cpu/brick4_bake_for_scene.d.ts.map +1 -1
  1144. package/src/shade/renderer/global_illumination/brick4/cpu/brick4_bake_for_scene.js +5 -4
  1145. package/src/shade/renderer/global_illumination/brick4/cpu/brick4_generate_tree_from_scene.d.ts +12 -5
  1146. package/src/shade/renderer/global_illumination/brick4/cpu/brick4_generate_tree_from_scene.d.ts.map +1 -1
  1147. package/src/shade/renderer/global_illumination/brick4/cpu/brick4_generate_tree_from_scene.js +5 -4
  1148. package/src/shade/renderer/global_illumination/brick4/gpu/bake/brick4_bake_basic.d.ts +11 -5
  1149. package/src/shade/renderer/global_illumination/brick4/gpu/bake/brick4_bake_basic.d.ts.map +1 -1
  1150. package/src/shade/renderer/global_illumination/brick4/gpu/bake/brick4_bake_basic.js +5 -4
  1151. package/src/shade/renderer/global_illumination/lpv/GPULightProbeVolume.d.ts +5 -1
  1152. package/src/shade/renderer/global_illumination/lpv/GPULightProbeVolume.d.ts.map +1 -1
  1153. package/src/shade/renderer/global_illumination/lpv/GPULightProbeVolume.js +4 -0
  1154. package/src/shade/renderer/global_illumination/lpv/LightProbeVolume.d.ts +4 -0
  1155. package/src/shade/renderer/global_illumination/lpv/LightProbeVolume.d.ts.map +1 -1
  1156. package/src/shade/renderer/global_illumination/lpv/LightProbeVolume.js +4 -0
  1157. package/src/shade/renderer/global_illumination/lpv/bake/GPULightProbeVolumeRenderer.d.ts +7 -1
  1158. package/src/shade/renderer/global_illumination/lpv/bake/GPULightProbeVolumeRenderer.d.ts.map +1 -1
  1159. package/src/shade/renderer/global_illumination/lpv/bake/GPULightProbeVolumeRenderer.js +5 -0
  1160. package/src/shade/renderer/global_illumination/lpv/graph_bake_irradiance_lookup_2d.d.ts +11 -5
  1161. package/src/shade/renderer/global_illumination/lpv/graph_bake_irradiance_lookup_2d.d.ts.map +1 -1
  1162. package/src/shade/renderer/global_illumination/lpv/graph_bake_irradiance_lookup_2d.js +5 -4
  1163. package/src/shade/renderer/global_illumination/lpv/lpv_visualise_probes.d.ts +9 -4
  1164. package/src/shade/renderer/global_illumination/lpv/lpv_visualise_probes.d.ts.map +1 -1
  1165. package/src/shade/renderer/global_illumination/lpv/lpv_visualise_probes.js +4 -3
  1166. package/src/shade/renderer/global_illumination/lpv/placement/graph_generate_probe_locations.d.ts +9 -4
  1167. package/src/shade/renderer/global_illumination/lpv/placement/graph_generate_probe_locations.d.ts.map +1 -1
  1168. package/src/shade/renderer/global_illumination/lpv/placement/graph_generate_probe_locations.js +4 -3
  1169. package/src/shade/renderer/global_illumination/lpv/placement/software/lpv_generate_probe_locations2.d.ts +7 -3
  1170. package/src/shade/renderer/global_illumination/lpv/placement/software/lpv_generate_probe_locations2.d.ts.map +1 -1
  1171. package/src/shade/renderer/global_illumination/lpv/placement/software/lpv_generate_probe_locations2.js +3 -2
  1172. package/src/shade/renderer/global_illumination/probe/octahedral/GPUProbeAtlas.d.ts +28 -8
  1173. package/src/shade/renderer/global_illumination/probe/octahedral/GPUProbeAtlas.d.ts.map +1 -1
  1174. package/src/shade/renderer/global_illumination/probe/octahedral/GPUProbeAtlas.js +17 -6
  1175. package/src/shade/renderer/global_illumination/probe/octahedral/border/graph_lpv_paint_border_depth.d.ts +13 -6
  1176. package/src/shade/renderer/global_illumination/probe/octahedral/border/graph_lpv_paint_border_depth.d.ts.map +1 -1
  1177. package/src/shade/renderer/global_illumination/probe/octahedral/border/graph_lpv_paint_border_depth.js +6 -5
  1178. package/src/shade/renderer/global_illumination/probe/octahedral/convolve/graph_lpv_store_sh.d.ts +15 -7
  1179. package/src/shade/renderer/global_illumination/probe/octahedral/convolve/graph_lpv_store_sh.d.ts.map +1 -1
  1180. package/src/shade/renderer/global_illumination/probe/octahedral/convolve/graph_lpv_store_sh.js +7 -6
  1181. package/src/shade/renderer/global_illumination/probe/octahedral/convolve/graph_lvp_atlas_to_sh.d.ts +17 -8
  1182. package/src/shade/renderer/global_illumination/probe/octahedral/convolve/graph_lvp_atlas_to_sh.d.ts.map +1 -1
  1183. package/src/shade/renderer/global_illumination/probe/octahedral/convolve/graph_lvp_atlas_to_sh.js +8 -7
  1184. package/src/shade/renderer/global_illumination/probe/octahedral/convolve/graph_reduce_atlas_to_sh.d.ts +17 -8
  1185. package/src/shade/renderer/global_illumination/probe/octahedral/convolve/graph_reduce_atlas_to_sh.d.ts.map +1 -1
  1186. package/src/shade/renderer/global_illumination/probe/octahedral/convolve/graph_reduce_atlas_to_sh.js +8 -7
  1187. package/src/shade/renderer/global_illumination/sharc/SpatialHashRadianceCache.d.ts +15 -7
  1188. package/src/shade/renderer/global_illumination/sharc/SpatialHashRadianceCache.d.ts.map +1 -1
  1189. package/src/shade/renderer/global_illumination/sharc/SpatialHashRadianceCache.js +7 -6
  1190. package/src/shade/renderer/gpu_primitive/bvh/graph_bvh_build_lbvh.d.ts +19 -9
  1191. package/src/shade/renderer/gpu_primitive/bvh/graph_bvh_build_lbvh.d.ts.map +1 -1
  1192. package/src/shade/renderer/gpu_primitive/bvh/graph_bvh_build_lbvh.js +9 -8
  1193. package/src/shade/renderer/gpu_primitive/prefix_sum/v1/graph_prefix_scan_csdldf.d.ts +9 -4
  1194. package/src/shade/renderer/gpu_primitive/prefix_sum/v1/graph_prefix_scan_csdldf.d.ts.map +1 -1
  1195. package/src/shade/renderer/gpu_primitive/prefix_sum/v1/graph_prefix_scan_csdldf.js +4 -3
  1196. package/src/shade/renderer/gpu_primitive/sort/graph_radix_sort.d.ts +11 -5
  1197. package/src/shade/renderer/gpu_primitive/sort/graph_radix_sort.d.ts.map +1 -1
  1198. package/src/shade/renderer/gpu_primitive/sort/graph_radix_sort.js +5 -4
  1199. package/src/shade/renderer/hiz/HierarchicalZBuffer.d.ts +9 -1
  1200. package/src/shade/renderer/hiz/HierarchicalZBuffer.d.ts.map +1 -1
  1201. package/src/shade/renderer/hiz/HierarchicalZBuffer.js +6 -0
  1202. package/src/shade/renderer/hiz/generate_downsampler_code.d.ts +11 -5
  1203. package/src/shade/renderer/hiz/generate_downsampler_code.d.ts.map +1 -1
  1204. package/src/shade/renderer/hiz/generate_downsampler_code.js +5 -4
  1205. package/src/shade/renderer/hiz/graph_build_hzb.d.ts +13 -6
  1206. package/src/shade/renderer/hiz/graph_build_hzb.d.ts.map +1 -1
  1207. package/src/shade/renderer/hiz/graph_build_hzb.js +6 -5
  1208. package/src/shade/renderer/light/GPULightCollection.d.ts +4 -1
  1209. package/src/shade/renderer/light/GPULightCollection.d.ts.map +1 -1
  1210. package/src/shade/renderer/light/GPULightCollection.js +6 -0
  1211. package/src/shade/renderer/light/LightCollection.d.ts +9 -3
  1212. package/src/shade/renderer/light/LightCollection.d.ts.map +1 -1
  1213. package/src/shade/renderer/light/LightCollection.js +5 -0
  1214. package/src/shade/renderer/light/cluster/cull/graph_cull_lights.d.ts +11 -5
  1215. package/src/shade/renderer/light/cluster/cull/graph_cull_lights.d.ts.map +1 -1
  1216. package/src/shade/renderer/light/cluster/cull/graph_cull_lights.js +17 -14
  1217. package/src/shade/renderer/light/cluster/graph_assign_clsuters.d.ts +13 -6
  1218. package/src/shade/renderer/light/cluster/graph_assign_clsuters.d.ts.map +1 -1
  1219. package/src/shade/renderer/light/cluster/graph_assign_clsuters.js +6 -5
  1220. package/src/shade/renderer/light/cluster/graph_build_light_clusters.d.ts +13 -6
  1221. package/src/shade/renderer/light/cluster/graph_build_light_clusters.d.ts.map +1 -1
  1222. package/src/shade/renderer/light/cluster/graph_build_light_clusters.js +6 -5
  1223. package/src/shade/renderer/light/environment/graph_filter_environment_map.d.ts +7 -3
  1224. package/src/shade/renderer/light/environment/graph_filter_environment_map.d.ts.map +1 -1
  1225. package/src/shade/renderer/light/environment/graph_filter_environment_map.js +3 -2
  1226. package/src/shade/renderer/lightmap/bake/raster/graph_draw_lightmap_viz_buffer.d.ts +11 -5
  1227. package/src/shade/renderer/lightmap/bake/raster/graph_draw_lightmap_viz_buffer.d.ts.map +1 -1
  1228. package/src/shade/renderer/lightmap/bake/raster/graph_draw_lightmap_viz_buffer.js +5 -4
  1229. package/src/shade/renderer/loader/gltf/tiny-gltf.d.ts +1 -1
  1230. package/src/shade/renderer/material/GPUMaterialContext.d.ts +17 -1
  1231. package/src/shade/renderer/material/GPUMaterialContext.d.ts.map +1 -1
  1232. package/src/shade/renderer/material/GPUMaterialContext.js +10 -0
  1233. package/src/shade/renderer/material/GPUMaterialManager.d.ts +19 -5
  1234. package/src/shade/renderer/material/GPUMaterialManager.d.ts.map +1 -1
  1235. package/src/shade/renderer/material/GPUMaterialManager.js +19 -4
  1236. package/src/shade/renderer/material/ShadeMaterial.d.ts +2 -1
  1237. package/src/shade/renderer/material/ShadeMaterial.d.ts.map +1 -1
  1238. package/src/shade/renderer/material/ShadeMaterial.js +4 -0
  1239. package/src/shade/renderer/material/StandardShadeMaterial.d.ts +6 -0
  1240. package/src/shade/renderer/material/StandardShadeMaterial.d.ts.map +1 -1
  1241. package/src/shade/renderer/material/StandardShadeMaterial.js +5 -0
  1242. package/src/shade/renderer/material/resident/GPUResidentMaterialContext.d.ts +12 -0
  1243. package/src/shade/renderer/material/resident/GPUResidentMaterialContext.d.ts.map +1 -1
  1244. package/src/shade/renderer/material/resident/GPUResidentMaterialContext.js +8 -0
  1245. package/src/shade/renderer/particles/DESIGN.md +82 -69
  1246. package/src/shade/renderer/particles/GPUParticleSystem.d.ts +93 -48
  1247. package/src/shade/renderer/particles/GPUParticleSystem.d.ts.map +1 -1
  1248. package/src/shade/renderer/particles/GPUParticleSystem.js +117 -176
  1249. package/src/shade/renderer/particles/ParticleConstants.d.ts +6 -12
  1250. package/src/shade/renderer/particles/ParticleConstants.d.ts.map +1 -1
  1251. package/src/shade/renderer/particles/ParticleConstants.js +6 -13
  1252. package/src/shade/renderer/particles/coherence/graph_particle_bucket.d.ts +4 -4
  1253. package/src/shade/renderer/particles/coherence/graph_particle_bucket.js +6 -6
  1254. package/src/shade/renderer/particles/coherence/particle_program_buckets.d.ts +2 -1
  1255. package/src/shade/renderer/particles/coherence/particle_program_buckets.d.ts.map +1 -1
  1256. package/src/shade/renderer/particles/coherence/particle_program_buckets.js +6 -8
  1257. package/src/shade/renderer/particles/coherence/shader_particle_bucket.d.ts.map +1 -1
  1258. package/src/shade/renderer/particles/coherence/shader_particle_bucket.js +4 -3
  1259. package/src/shade/renderer/particles/data/PARTICLE_COUNTERS.d.ts +10 -14
  1260. package/src/shade/renderer/particles/data/PARTICLE_COUNTERS.d.ts.map +1 -1
  1261. package/src/shade/renderer/particles/data/PARTICLE_COUNTERS.js +10 -14
  1262. package/src/shade/renderer/particles/data/PARTICLE_EMITTER_STRUCT.d.ts +6 -5
  1263. package/src/shade/renderer/particles/data/PARTICLE_EMITTER_STRUCT.d.ts.map +1 -1
  1264. package/src/shade/renderer/particles/data/PARTICLE_EMITTER_STRUCT.js +6 -5
  1265. package/src/shade/renderer/particles/graph_particles.d.ts +19 -32
  1266. package/src/shade/renderer/particles/graph_particles.d.ts.map +1 -1
  1267. package/src/shade/renderer/particles/graph_particles.js +18 -25
  1268. package/src/shade/renderer/particles/graph_particles_avboit.js +16 -16
  1269. package/src/shade/renderer/particles/runtime/EmitterRegistry.d.ts +3 -2
  1270. package/src/shade/renderer/particles/runtime/EmitterRegistry.d.ts.map +1 -1
  1271. package/src/shade/renderer/particles/runtime/EmitterRegistry.js +31 -27
  1272. package/src/shade/renderer/particles/runtime/ParticleEmitter.d.ts +4 -4
  1273. package/src/shade/renderer/particles/runtime/ParticleEmitter.js +4 -4
  1274. package/src/shade/renderer/particles/shaders/chunk_particle_avboit_contribution.js +4 -4
  1275. package/src/shade/renderer/particles/shaders/chunk_particle_billboard_vertex.d.ts +7 -6
  1276. package/src/shade/renderer/particles/shaders/chunk_particle_billboard_vertex.d.ts.map +1 -1
  1277. package/src/shade/renderer/particles/shaders/chunk_particle_billboard_vertex.js +7 -6
  1278. package/src/shade/renderer/particles/shaders/chunk_particle_lighting.d.ts +4 -3
  1279. package/src/shade/renderer/particles/shaders/chunk_particle_lighting.d.ts.map +1 -1
  1280. package/src/shade/renderer/particles/shaders/chunk_particle_lighting.js +4 -3
  1281. package/src/shade/renderer/particles/shaders/chunk_particle_render_math.d.ts +2 -2
  1282. package/src/shade/renderer/particles/shaders/chunk_particle_render_math.js +10 -10
  1283. package/src/shade/renderer/particles/shaders/shader_particle_avboit_draw.js +3 -3
  1284. package/src/shade/renderer/particles/shaders/shader_particle_avboit_splat.d.ts.map +1 -1
  1285. package/src/shade/renderer/particles/shaders/shader_particle_avboit_splat.js +2 -1
  1286. package/src/shade/renderer/particles/shaders/shader_particle_finalize.d.ts.map +1 -1
  1287. package/src/shade/renderer/particles/shaders/shader_particle_finalize.js +13 -16
  1288. package/src/shade/renderer/particles/shaders/shader_particle_render.d.ts.map +1 -1
  1289. package/src/shade/renderer/particles/shaders/shader_particle_render.js +22 -19
  1290. package/src/shade/renderer/path_tracer/accumulating/AccumulatingPathTracer.d.ts +10 -3
  1291. package/src/shade/renderer/path_tracer/accumulating/AccumulatingPathTracer.d.ts.map +1 -1
  1292. package/src/shade/renderer/path_tracer/accumulating/AccumulatingPathTracer.js +12 -2
  1293. package/src/shade/renderer/path_tracer/graph_path_trace_scene.d.ts +7 -3
  1294. package/src/shade/renderer/path_tracer/graph_path_trace_scene.d.ts.map +1 -1
  1295. package/src/shade/renderer/path_tracer/graph_path_trace_scene.js +3 -2
  1296. package/src/shade/renderer/postprocess/bloom/graph_bloom_downsample.d.ts +11 -5
  1297. package/src/shade/renderer/postprocess/bloom/graph_bloom_downsample.d.ts.map +1 -1
  1298. package/src/shade/renderer/postprocess/bloom/graph_bloom_downsample.js +5 -4
  1299. package/src/shade/renderer/postprocess/bloom/graph_postprocess_bloom.d.ts +13 -6
  1300. package/src/shade/renderer/postprocess/bloom/graph_postprocess_bloom.d.ts.map +1 -1
  1301. package/src/shade/renderer/postprocess/bloom/graph_postprocess_bloom.js +11 -9
  1302. package/src/shade/renderer/postprocess/denoise/LigmaDenoiser.d.ts +31 -15
  1303. package/src/shade/renderer/postprocess/denoise/LigmaDenoiser.d.ts.map +1 -1
  1304. package/src/shade/renderer/postprocess/denoise/LigmaDenoiser.js +15 -14
  1305. package/src/shade/renderer/postprocess/denoise/debug/graph_pass_debug_reprojection.d.ts +21 -10
  1306. package/src/shade/renderer/postprocess/denoise/debug/graph_pass_debug_reprojection.d.ts.map +1 -1
  1307. package/src/shade/renderer/postprocess/denoise/debug/graph_pass_debug_reprojection.js +10 -9
  1308. package/src/shade/renderer/postprocess/denoise/graph_atorus_denoise_luma.d.ts +17 -8
  1309. package/src/shade/renderer/postprocess/denoise/graph_atorus_denoise_luma.d.ts.map +1 -1
  1310. package/src/shade/renderer/postprocess/denoise/graph_atorus_denoise_luma.js +8 -7
  1311. package/src/shade/renderer/postprocess/dof/gather/DepthOfFieldU.d.ts +6 -0
  1312. package/src/shade/renderer/postprocess/dof/gather/DepthOfFieldU.d.ts.map +1 -1
  1313. package/src/shade/renderer/postprocess/dof/gather/DepthOfFieldU.js +5 -0
  1314. package/src/shade/renderer/postprocess/dof/raymarch/DepthOfField.d.ts +6 -0
  1315. package/src/shade/renderer/postprocess/dof/raymarch/DepthOfField.d.ts.map +1 -1
  1316. package/src/shade/renderer/postprocess/dof/raymarch/DepthOfField.js +5 -0
  1317. package/src/shade/renderer/postprocess/eye/GPUCameraExposureManager.d.ts +14 -6
  1318. package/src/shade/renderer/postprocess/eye/GPUCameraExposureManager.d.ts.map +1 -1
  1319. package/src/shade/renderer/postprocess/eye/GPUCameraExposureManager.js +6 -4
  1320. package/src/shade/renderer/postprocess/gtao/graph_build_depth_mipmap.d.ts +13 -6
  1321. package/src/shade/renderer/postprocess/gtao/graph_build_depth_mipmap.d.ts.map +1 -1
  1322. package/src/shade/renderer/postprocess/gtao/graph_build_depth_mipmap.js +6 -5
  1323. package/src/shade/renderer/postprocess/gtao/render_copy_texture.d.ts +28 -13
  1324. package/src/shade/renderer/postprocess/gtao/render_copy_texture.d.ts.map +1 -1
  1325. package/src/shade/renderer/postprocess/gtao/render_copy_texture.js +13 -11
  1326. package/src/shade/renderer/postprocess/motion_blur/MotionBlur.d.ts +4 -0
  1327. package/src/shade/renderer/postprocess/motion_blur/MotionBlur.d.ts.map +1 -1
  1328. package/src/shade/renderer/postprocess/motion_blur/MotionBlur.js +4 -0
  1329. package/src/shade/renderer/postprocess/nss/NSS.d.ts +7 -1
  1330. package/src/shade/renderer/postprocess/nss/NSS.d.ts.map +1 -1
  1331. package/src/shade/renderer/postprocess/nss/NSS.js +5 -0
  1332. package/src/shade/renderer/postprocess/ssr/graph_build_depth_max_pyramid.d.ts +9 -4
  1333. package/src/shade/renderer/postprocess/ssr/graph_build_depth_max_pyramid.d.ts.map +1 -1
  1334. package/src/shade/renderer/postprocess/ssr/graph_build_depth_max_pyramid.js +4 -3
  1335. package/src/shade/renderer/postprocess/ssr/ssr_graph_prefilter_color.d.ts +13 -6
  1336. package/src/shade/renderer/postprocess/ssr/ssr_graph_prefilter_color.d.ts.map +1 -1
  1337. package/src/shade/renderer/postprocess/ssr/ssr_graph_prefilter_color.js +6 -5
  1338. package/src/shade/renderer/postprocess/taa/TAA.d.ts +15 -7
  1339. package/src/shade/renderer/postprocess/taa/TAA.d.ts.map +1 -1
  1340. package/src/shade/renderer/postprocess/taa/TAA.js +7 -6
  1341. package/src/shade/renderer/postprocess/velocity/graph_add_camera_velocity.d.ts +13 -6
  1342. package/src/shade/renderer/postprocess/velocity/graph_add_camera_velocity.d.ts.map +1 -1
  1343. package/src/shade/renderer/postprocess/velocity/graph_add_camera_velocity.js +6 -5
  1344. package/src/shade/renderer/rasterize/compute/graph_mesh_frustum_cull.d.ts +11 -5
  1345. package/src/shade/renderer/rasterize/compute/graph_mesh_frustum_cull.d.ts.map +1 -1
  1346. package/src/shade/renderer/rasterize/compute/graph_mesh_frustum_cull.js +5 -4
  1347. package/src/shade/renderer/rasterize/compute/graph_mesh_sphere_cull.d.ts +11 -5
  1348. package/src/shade/renderer/rasterize/compute/graph_mesh_sphere_cull.d.ts.map +1 -1
  1349. package/src/shade/renderer/rasterize/compute/graph_mesh_sphere_cull.js +5 -4
  1350. package/src/shade/renderer/rasterize/execute_rasterization_jobs.d.ts +12 -5
  1351. package/src/shade/renderer/rasterize/execute_rasterization_jobs.d.ts.map +1 -1
  1352. package/src/shade/renderer/rasterize/execute_rasterization_jobs.js +5 -4
  1353. package/src/shade/renderer/rasterize/expand/GPUCollectionLimits.d.ts +2 -0
  1354. package/src/shade/renderer/rasterize/expand/GPUCollectionLimits.d.ts.map +1 -1
  1355. package/src/shade/renderer/rasterize/expand/GPUCollectionLimits.js +5 -0
  1356. package/src/shade/renderer/rasterize/expand/bucket/mesh/graph_meshes_classify_buckets.d.ts +11 -5
  1357. package/src/shade/renderer/rasterize/expand/bucket/mesh/graph_meshes_classify_buckets.d.ts.map +1 -1
  1358. package/src/shade/renderer/rasterize/expand/bucket/mesh/graph_meshes_classify_buckets.js +5 -4
  1359. package/src/shade/renderer/rasterize/expand/bucket/mesh/graph_scene_meshes_cull_and_classify_buckets.d.ts +9 -4
  1360. package/src/shade/renderer/rasterize/expand/bucket/mesh/graph_scene_meshes_cull_and_classify_buckets.d.ts.map +1 -1
  1361. package/src/shade/renderer/rasterize/expand/bucket/mesh/graph_scene_meshes_cull_and_classify_buckets.js +4 -3
  1362. package/src/shade/renderer/rasterize/expand/bucket/meshlet/graph_sort_meshlets_by_bucket_id.d.ts +11 -5
  1363. package/src/shade/renderer/rasterize/expand/bucket/meshlet/graph_sort_meshlets_by_bucket_id.d.ts.map +1 -1
  1364. package/src/shade/renderer/rasterize/expand/bucket/meshlet/graph_sort_meshlets_by_bucket_id.js +5 -4
  1365. package/src/shade/renderer/rasterize/expand/graph_mesh_filter_one_way.d.ts +15 -7
  1366. package/src/shade/renderer/rasterize/expand/graph_mesh_filter_one_way.d.ts.map +1 -1
  1367. package/src/shade/renderer/rasterize/expand/graph_mesh_filter_one_way.js +7 -6
  1368. package/src/shade/renderer/rasterize/expand/graph_mesh_filter_two_way.d.ts +15 -7
  1369. package/src/shade/renderer/rasterize/expand/graph_mesh_filter_two_way.d.ts.map +1 -1
  1370. package/src/shade/renderer/rasterize/expand/graph_mesh_filter_two_way.js +7 -6
  1371. package/src/shade/renderer/rasterize/expand/graph_meshlets_expand.d.ts +13 -6
  1372. package/src/shade/renderer/rasterize/expand/graph_meshlets_expand.d.ts.map +1 -1
  1373. package/src/shade/renderer/rasterize/expand/graph_meshlets_expand.js +6 -5
  1374. package/src/shade/renderer/rasterize/expand/graph_meshlets_filter_one_way.d.ts +17 -8
  1375. package/src/shade/renderer/rasterize/expand/graph_meshlets_filter_one_way.d.ts.map +1 -1
  1376. package/src/shade/renderer/rasterize/expand/graph_meshlets_filter_one_way.js +8 -7
  1377. package/src/shade/renderer/rasterize/expand/graph_meshlets_filter_two_way.d.ts +13 -6
  1378. package/src/shade/renderer/rasterize/expand/graph_meshlets_filter_two_way.d.ts.map +1 -1
  1379. package/src/shade/renderer/rasterize/expand/graph_meshlets_filter_two_way.js +6 -5
  1380. package/src/shade/renderer/rasterize/expand/graph_meshlets_rasterize.d.ts +21 -10
  1381. package/src/shade/renderer/rasterize/expand/graph_meshlets_rasterize.d.ts.map +1 -1
  1382. package/src/shade/renderer/rasterize/expand/graph_meshlets_rasterize.js +10 -9
  1383. package/src/shade/renderer/rasterize/expand/graph_triangles_filter_by_material_side.d.ts +13 -6
  1384. package/src/shade/renderer/rasterize/expand/graph_triangles_filter_by_material_side.d.ts.map +1 -1
  1385. package/src/shade/renderer/rasterize/expand/graph_triangles_filter_by_material_side.js +6 -5
  1386. package/src/shade/renderer/rasterize/expand/graph_triangles_filter_one_way.d.ts +17 -8
  1387. package/src/shade/renderer/rasterize/expand/graph_triangles_filter_one_way.d.ts.map +1 -1
  1388. package/src/shade/renderer/rasterize/expand/graph_triangles_filter_one_way.js +8 -7
  1389. package/src/shade/renderer/rasterize/expand/graph_triangles_filter_two_way.d.ts +13 -6
  1390. package/src/shade/renderer/rasterize/expand/graph_triangles_filter_two_way.d.ts.map +1 -1
  1391. package/src/shade/renderer/rasterize/expand/graph_triangles_filter_two_way.js +6 -5
  1392. package/src/shade/renderer/rasterize/expand/mesh/graph_expand_meshes_to_meshlets.d.ts +15 -7
  1393. package/src/shade/renderer/rasterize/expand/mesh/graph_expand_meshes_to_meshlets.d.ts.map +1 -1
  1394. package/src/shade/renderer/rasterize/expand/mesh/graph_expand_meshes_to_meshlets.js +7 -6
  1395. package/src/shade/renderer/rasterize/fast/graph_extract_meshes_from_bucket.d.ts +11 -5
  1396. package/src/shade/renderer/rasterize/fast/graph_extract_meshes_from_bucket.d.ts.map +1 -1
  1397. package/src/shade/renderer/rasterize/fast/graph_extract_meshes_from_bucket.js +5 -4
  1398. package/src/shade/renderer/rasterize/fast/graph_rasterize_scene_fast.d.ts +9 -4
  1399. package/src/shade/renderer/rasterize/fast/graph_rasterize_scene_fast.d.ts.map +1 -1
  1400. package/src/shade/renderer/rasterize/fast/graph_rasterize_scene_fast.js +4 -3
  1401. package/src/shade/renderer/rasterize/native/avboit/graph_rasterize_meshes_transparent_avboit.d.ts +80 -37
  1402. package/src/shade/renderer/rasterize/native/avboit/graph_rasterize_meshes_transparent_avboit.d.ts.map +1 -1
  1403. package/src/shade/renderer/rasterize/native/avboit/graph_rasterize_meshes_transparent_avboit.js +37 -33
  1404. package/src/shade/renderer/rasterize/native/graph_rasterize_meshes_alpha_tested.d.ts +28 -13
  1405. package/src/shade/renderer/rasterize/native/graph_rasterize_meshes_alpha_tested.d.ts.map +1 -1
  1406. package/src/shade/renderer/rasterize/native/graph_rasterize_meshes_alpha_tested.js +13 -12
  1407. package/src/shade/renderer/rasterize/native/oit/graph_rasterize_meshes_transparent_oit.d.ts.map +1 -1
  1408. package/src/shade/renderer/rasterize/native/oit/graph_rasterize_meshes_transparent_oit.js +12 -11
  1409. package/src/shade/renderer/rasterize/standard/graph_rasterize_remaining_opaque.d.ts.map +1 -1
  1410. package/src/shade/renderer/rasterize/standard/graph_rasterize_remaining_opaque.js +5 -4
  1411. package/src/shade/renderer/rasterize/standard/graph_rasterize_scene.d.ts +9 -4
  1412. package/src/shade/renderer/rasterize/standard/graph_rasterize_scene.d.ts.map +1 -1
  1413. package/src/shade/renderer/rasterize/standard/graph_rasterize_scene.js +4 -3
  1414. package/src/shade/renderer/restir/di/ReSTIRDI.d.ts +10 -0
  1415. package/src/shade/renderer/restir/di/ReSTIRDI.d.ts.map +1 -1
  1416. package/src/shade/renderer/restir/di/ReSTIRDI.js +7 -0
  1417. package/src/shade/renderer/scene/GPUInstancesAccelerationStructure.d.ts +2 -0
  1418. package/src/shade/renderer/scene/GPUInstancesAccelerationStructure.d.ts.map +1 -1
  1419. package/src/shade/renderer/scene/GPUInstancesAccelerationStructure.js +5 -0
  1420. package/src/shade/renderer/scene/GPUSceneContext.d.ts +4 -0
  1421. package/src/shade/renderer/scene/GPUSceneContext.d.ts.map +1 -1
  1422. package/src/shade/renderer/scene/GPUSceneContext.js +15 -0
  1423. package/src/shade/renderer/scene/InstanceBatch.d.ts +11 -3
  1424. package/src/shade/renderer/scene/InstanceBatch.d.ts.map +1 -1
  1425. package/src/shade/renderer/scene/InstanceBatch.js +6 -0
  1426. package/src/shade/renderer/scene/Mesh.d.ts +8 -2
  1427. package/src/shade/renderer/scene/Mesh.d.ts.map +1 -1
  1428. package/src/shade/renderer/scene/Mesh.js +6 -1
  1429. package/src/shade/renderer/scene/SceneManager.d.ts +6 -0
  1430. package/src/shade/renderer/scene/SceneManager.d.ts.map +1 -1
  1431. package/src/shade/renderer/scene/SceneManager.js +5 -0
  1432. package/src/shade/renderer/scene/SkinnedMesh.d.ts +4 -0
  1433. package/src/shade/renderer/scene/SkinnedMesh.d.ts.map +1 -1
  1434. package/src/shade/renderer/scene/SkinnedMesh.js +4 -0
  1435. package/src/shade/renderer/scene/serialization/serialize_scene.d.ts +7 -3
  1436. package/src/shade/renderer/scene/serialization/serialize_scene.d.ts.map +1 -1
  1437. package/src/shade/renderer/scene/serialization/serialize_scene.js +3 -2
  1438. package/src/shade/renderer/shader/ComputeShader.d.ts +64 -29
  1439. package/src/shade/renderer/shader/ComputeShader.d.ts.map +1 -1
  1440. package/src/shade/renderer/shader/ComputeShader.js +29 -23
  1441. package/src/shade/renderer/shader/ImageShader.d.ts +9 -4
  1442. package/src/shade/renderer/shader/ImageShader.d.ts.map +1 -1
  1443. package/src/shade/renderer/shader/ImageShader.js +4 -3
  1444. package/src/shade/renderer/shader/ShaderDescriptor.d.ts +10 -4
  1445. package/src/shade/renderer/shader/ShaderDescriptor.d.ts.map +1 -1
  1446. package/src/shade/renderer/shader/ShaderDescriptor.js +4 -3
  1447. package/src/shade/renderer/shader/chunk/brdf/dfg/generate_dfg_texture.d.ts +7 -3
  1448. package/src/shade/renderer/shader/chunk/brdf/dfg/generate_dfg_texture.d.ts.map +1 -1
  1449. package/src/shade/renderer/shader/chunk/brdf/dfg/generate_dfg_texture.js +6 -4
  1450. package/src/shade/renderer/shader/fullscreen/create_full_quad_pipeline_descriptor.d.ts +13 -6
  1451. package/src/shade/renderer/shader/fullscreen/create_full_quad_pipeline_descriptor.d.ts.map +1 -1
  1452. package/src/shade/renderer/shader/fullscreen/create_full_quad_pipeline_descriptor.js +6 -5
  1453. package/src/shade/renderer/shader/graph/compute/graph_compute_indirect_pass.d.ts +13 -6
  1454. package/src/shade/renderer/shader/graph/compute/graph_compute_indirect_pass.d.ts.map +1 -1
  1455. package/src/shade/renderer/shader/graph/compute/graph_compute_indirect_pass.js +6 -5
  1456. package/src/shade/renderer/shader/graph/compute/graph_compute_pass.d.ts +13 -6
  1457. package/src/shade/renderer/shader/graph/compute/graph_compute_pass.d.ts.map +1 -1
  1458. package/src/shade/renderer/shader/graph/compute/graph_compute_pass.js +6 -5
  1459. package/src/shade/renderer/shader/graph/graph_image_pass.d.ts +27 -13
  1460. package/src/shade/renderer/shader/graph/graph_image_pass.d.ts.map +1 -1
  1461. package/src/shade/renderer/shader/graph/graph_image_pass.js +13 -12
  1462. package/src/shade/renderer/shader/graph/graph_import_raw_buffer.d.ts +15 -7
  1463. package/src/shade/renderer/shader/graph/graph_import_raw_buffer.d.ts.map +1 -1
  1464. package/src/shade/renderer/shader/graph/graph_import_raw_buffer.js +7 -6
  1465. package/src/shade/renderer/shader/graph/graph_import_typed_buffer.d.ts +13 -6
  1466. package/src/shade/renderer/shader/graph/graph_import_typed_buffer.d.ts.map +1 -1
  1467. package/src/shade/renderer/shader/graph/graph_import_typed_buffer.js +6 -5
  1468. package/src/shade/renderer/shader/pass/RenderPassColorAttachmentDescriptor.d.ts +7 -3
  1469. package/src/shade/renderer/shader/pass/RenderPassColorAttachmentDescriptor.d.ts.map +1 -1
  1470. package/src/shade/renderer/shader/pass/RenderPassColorAttachmentDescriptor.js +3 -2
  1471. package/src/shade/renderer/shader/pass/RenderPassDescriptor.d.ts +49 -23
  1472. package/src/shade/renderer/shader/pass/RenderPassDescriptor.d.ts.map +1 -1
  1473. package/src/shade/renderer/shader/pass/RenderPassDescriptor.js +23 -20
  1474. package/src/shade/renderer/shader/resource/ShaderResourceDescriptor.d.ts +6 -0
  1475. package/src/shade/renderer/shader/resource/ShaderResourceDescriptor.d.ts.map +1 -1
  1476. package/src/shade/renderer/shader/resource/ShaderResourceDescriptor.js +9 -0
  1477. package/src/shade/renderer/shader/resource/ShaderResourceGroupDescriptor.d.ts +11 -2
  1478. package/src/shade/renderer/shader/resource/ShaderResourceGroupDescriptor.d.ts.map +1 -1
  1479. package/src/shade/renderer/shader/resource/ShaderResourceGroupDescriptor.js +7 -1
  1480. package/src/shade/renderer/shader/resource/ShaderResourceSetDescriptor.d.ts +10 -3
  1481. package/src/shade/renderer/shader/resource/ShaderResourceSetDescriptor.d.ts.map +1 -1
  1482. package/src/shade/renderer/shader/resource/ShaderResourceSetDescriptor.js +9 -2
  1483. package/src/shade/renderer/shader/type/WGSLAttribute.d.ts +2 -2
  1484. package/src/shade/renderer/shader/type/WGSLAttribute.d.ts.map +1 -1
  1485. package/src/shade/renderer/shader/type/WGSLAttribute.js +1 -1
  1486. package/src/shade/renderer/shader/type/WGSLStructField.d.ts +6 -2
  1487. package/src/shade/renderer/shader/type/WGSLStructField.d.ts.map +1 -1
  1488. package/src/shade/renderer/shader/type/WGSLStructField.js +5 -1
  1489. package/src/shade/renderer/shader/type/WebGPUArray.d.ts +0 -2
  1490. package/src/shade/renderer/shader/type/WebGPUArray.d.ts.map +1 -1
  1491. package/src/shade/renderer/shader/type/WebGPUStruct.d.ts +2 -4
  1492. package/src/shade/renderer/shader/type/WebGPUStruct.d.ts.map +1 -1
  1493. package/src/shade/renderer/shader/type/WebGPUStruct.js +1 -1
  1494. package/src/shade/renderer/shader/type/WebGPUType.d.ts +5 -1
  1495. package/src/shade/renderer/shader/type/WebGPUType.d.ts.map +1 -1
  1496. package/src/shade/renderer/shader/type/WebGPUType.js +4 -0
  1497. package/src/shade/renderer/shadow/evsm/graph_evsm_render_cascade.d.ts +7 -3
  1498. package/src/shade/renderer/shadow/evsm/graph_evsm_render_cascade.d.ts.map +1 -1
  1499. package/src/shade/renderer/shadow/evsm/graph_evsm_render_cascade.js +3 -2
  1500. package/src/shade/renderer/shadow/map/GPUSceneShadowmapContext.d.ts +7 -0
  1501. package/src/shade/renderer/shadow/map/GPUSceneShadowmapContext.d.ts.map +1 -1
  1502. package/src/shade/renderer/shadow/map/GPUSceneShadowmapContext.js +10 -0
  1503. package/src/shade/renderer/shadow/map/Shadowmap.d.ts +12 -0
  1504. package/src/shade/renderer/shadow/map/Shadowmap.d.ts.map +1 -1
  1505. package/src/shade/renderer/shadow/map/Shadowmap.js +8 -0
  1506. package/src/shade/renderer/shadow/map/SpotLightShadowmap.d.ts +2 -2
  1507. package/src/shade/renderer/shadow/map/csm/graph_csm_setup_cascades.d.ts +7 -3
  1508. package/src/shade/renderer/shadow/map/csm/graph_csm_setup_cascades.d.ts.map +1 -1
  1509. package/src/shade/renderer/shadow/map/csm/graph_csm_setup_cascades.js +3 -2
  1510. package/src/shade/renderer/shadow/map/csm_debug_draw_preview.d.ts +11 -5
  1511. package/src/shade/renderer/shadow/map/csm_debug_draw_preview.d.ts.map +1 -1
  1512. package/src/shade/renderer/shadow/map/csm_debug_draw_preview.js +5 -4
  1513. package/src/shade/renderer/shadow/ray/staged/gen/graph_gen_rays.d.ts +13 -6
  1514. package/src/shade/renderer/shadow/ray/staged/gen/graph_gen_rays.d.ts.map +1 -1
  1515. package/src/shade/renderer/shadow/ray/staged/gen/graph_gen_rays.js +6 -5
  1516. package/src/shade/renderer/shadow/ray/staged/trace/graph_trace_rays.d.ts +9 -4
  1517. package/src/shade/renderer/shadow/ray/staged/trace/graph_trace_rays.d.ts.map +1 -1
  1518. package/src/shade/renderer/shadow/ray/staged/trace/graph_trace_rays.js +4 -3
  1519. package/src/shade/renderer/shadow/sdf/brixelizer/Brixelizer.d.ts +11 -5
  1520. package/src/shade/renderer/shadow/sdf/brixelizer/Brixelizer.d.ts.map +1 -1
  1521. package/src/shade/renderer/shadow/sdf/brixelizer/Brixelizer.js +5 -4
  1522. package/src/shade/renderer/shadow/sdf/cascade/CascadedSceneSDF.d.ts +1 -0
  1523. package/src/shade/renderer/shadow/sdf/cascade/CascadedSceneSDF.d.ts.map +1 -1
  1524. package/src/shade/renderer/shadow/sdf/cascade/CascadedSceneSDF.js +4 -0
  1525. package/src/shade/renderer/shadow/sdf/graph_draw_sdf_shadows.d.ts +13 -6
  1526. package/src/shade/renderer/shadow/sdf/graph_draw_sdf_shadows.d.ts.map +1 -1
  1527. package/src/shade/renderer/shadow/sdf/graph_draw_sdf_shadows.js +6 -5
  1528. package/src/shade/renderer/texture/GPUTextureAllocator.d.ts +4 -0
  1529. package/src/shade/renderer/texture/GPUTextureAllocator.d.ts.map +1 -1
  1530. package/src/shade/renderer/texture/GPUTextureAllocator.js +4 -0
  1531. package/src/shade/renderer/texture/GPUTextureContext.d.ts +1 -0
  1532. package/src/shade/renderer/texture/GPUTextureContext.d.ts.map +1 -1
  1533. package/src/shade/renderer/texture/GPUTextureContext.js +4 -0
  1534. package/src/shade/renderer/texture/RenderTarget.d.ts +7 -3
  1535. package/src/shade/renderer/texture/RenderTarget.d.ts.map +1 -1
  1536. package/src/shade/renderer/texture/RenderTarget.js +3 -2
  1537. package/src/shade/renderer/texture/ShadeTexture.d.ts +2 -1
  1538. package/src/shade/renderer/texture/ShadeTexture.d.ts.map +1 -1
  1539. package/src/shade/renderer/texture/ShadeTexture.js +4 -0
  1540. package/src/shade/renderer/texture/TextureManager.d.ts +1 -0
  1541. package/src/shade/renderer/texture/TextureManager.d.ts.map +1 -1
  1542. package/src/shade/renderer/texture/TextureManager.js +4 -0
  1543. package/src/shade/renderer/texture/bindless/GPUBindlessTextureManager.d.ts +3 -0
  1544. package/src/shade/renderer/texture/bindless/GPUBindlessTextureManager.d.ts.map +1 -1
  1545. package/src/shade/renderer/texture/bindless/GPUBindlessTextureManager.js +121 -21
  1546. package/src/shade/renderer/texture/debug_draw_texture.d.ts +9 -4
  1547. package/src/shade/renderer/texture/debug_draw_texture.d.ts.map +1 -1
  1548. package/src/shade/renderer/texture/debug_draw_texture.js +4 -3
  1549. package/src/shade/renderer/texture/download_texture_data.d.ts +17 -6
  1550. package/src/shade/renderer/texture/download_texture_data.d.ts.map +1 -1
  1551. package/src/shade/renderer/texture/download_texture_data.js +10 -5
  1552. package/src/shade/renderer/texture/draw_texture_as_rgba.d.ts +26 -12
  1553. package/src/shade/renderer/texture/draw_texture_as_rgba.d.ts.map +1 -1
  1554. package/src/shade/renderer/texture/draw_texture_as_rgba.js +12 -10
  1555. package/src/shade/renderer/texture/mipmaps/WebGPUMipmapGenerator.d.ts.map +1 -1
  1556. package/src/shade/renderer/texture/mipmaps/WebGPUMipmapGenerator.js +5 -4
  1557. package/src/shade/renderer/texture/source/ShadeImage.d.ts +4 -2
  1558. package/src/shade/renderer/texture/source/ShadeImage.d.ts.map +1 -1
  1559. package/src/shade/renderer/texture/source/ShadeImage.js +5 -0
  1560. package/src/shade/renderer/texture/source/ShadeImageSerializationAdapter.d.ts +12 -0
  1561. package/src/shade/renderer/texture/source/ShadeImageSerializationAdapter.d.ts.map +1 -1
  1562. package/src/shade/renderer/texture/util/make_checkers_texture.d.ts +12 -5
  1563. package/src/shade/renderer/texture/util/make_checkers_texture.d.ts.map +1 -1
  1564. package/src/shade/renderer/texture/util/make_checkers_texture.js +5 -4
  1565. package/src/shade/renderer/texture/virtual/README.md +6 -4
  1566. package/src/shade/renderer/texture/virtual/VirtualTextureManager.d.ts +7 -2
  1567. package/src/shade/renderer/texture/virtual/VirtualTextureManager.d.ts.map +1 -1
  1568. package/src/shade/renderer/texture/virtual/VirtualTextureManager.js +15 -0
  1569. package/src/shade/renderer/texture/virtual/source/VTSourceTiled.d.ts +3 -3
  1570. package/src/shade/renderer/texture/virtual/source/VTSourceTiled.js +3 -3
  1571. package/src/shade/renderer/util/Uint32BufferSamplingStats.d.ts +2 -0
  1572. package/src/shade/renderer/util/Uint32BufferSamplingStats.d.ts.map +1 -1
  1573. package/src/shade/renderer/util/Uint32BufferSamplingStats.js +5 -0
  1574. package/src/shade/renderer/view/GPUViewContext.d.ts +4 -1
  1575. package/src/shade/renderer/view/GPUViewContext.d.ts.map +1 -1
  1576. package/src/shade/renderer/view/GPUViewContext.js +11 -5
  1577. package/src/shade/renderer/view/View.d.ts +6 -0
  1578. package/src/shade/renderer/view/View.d.ts.map +1 -1
  1579. package/src/shade/renderer/view/View.js +5 -0
  1580. package/src/shade/renderer/view/ViewManager.d.ts +11 -1
  1581. package/src/shade/renderer/view/ViewManager.d.ts.map +1 -1
  1582. package/src/shade/renderer/view/ViewManager.js +7 -0
  1583. package/src/shade/renderer/volumetrics/GPUSceneVolumetrics.d.ts +6 -0
  1584. package/src/shade/renderer/volumetrics/GPUSceneVolumetrics.d.ts.map +1 -1
  1585. package/src/shade/renderer/volumetrics/GPUSceneVolumetrics.js +5 -0
  1586. package/src/shade/renderer/volumetrics/GPUViewVolumetrics.d.ts +15 -6
  1587. package/src/shade/renderer/volumetrics/GPUViewVolumetrics.d.ts.map +1 -1
  1588. package/src/shade/renderer/volumetrics/GPUViewVolumetrics.js +11 -5
  1589. package/src/shade/renderer/volumetrics/ParticipatingMediaVolume.d.ts +5 -5
  1590. package/src/shade/renderer/volumetrics/ParticipatingMediaVolume.d.ts.map +1 -1
  1591. package/src/shade/renderer/volumetrics/ParticipatingMediaVolume.js +1 -1
  1592. package/src/shade/renderer/volumetrics/SceneVolumetrics.d.ts +4 -0
  1593. package/src/shade/renderer/volumetrics/SceneVolumetrics.d.ts.map +1 -1
  1594. package/src/shade/renderer/volumetrics/SceneVolumetrics.js +4 -0
  1595. package/src/shade/renderer/volumetrics/build_volumetrics_sun_shadow_transform.d.ts +23 -11
  1596. package/src/shade/renderer/volumetrics/build_volumetrics_sun_shadow_transform.d.ts.map +1 -1
  1597. package/src/shade/renderer/volumetrics/build_volumetrics_sun_shadow_transform.js +11 -10
  1598. package/src/shade/renderer/volumetrics/graph_build_volumetrics.d.ts +37 -18
  1599. package/src/shade/renderer/volumetrics/graph_build_volumetrics.d.ts.map +1 -1
  1600. package/src/shade/renderer/volumetrics/graph_build_volumetrics.js +30 -26
  1601. package/src/view/View.d.ts +8 -3
  1602. package/src/view/View.d.ts.map +1 -1
  1603. package/src/view/View.js +7 -2
  1604. package/src/view/asset/AssetLoaderStatusView.d.ts +7 -3
  1605. package/src/view/asset/AssetLoaderStatusView.d.ts.map +1 -1
  1606. package/src/view/asset/AssetLoaderStatusView.js +3 -2
  1607. package/src/view/common/ListView.d.ts +21 -15
  1608. package/src/view/common/ListView.d.ts.map +1 -1
  1609. package/src/view/common/ListView.js +8 -7
  1610. package/src/view/common/LocalizedLabelView.d.ts +15 -7
  1611. package/src/view/common/LocalizedLabelView.d.ts.map +1 -1
  1612. package/src/view/common/LocalizedLabelView.js +7 -6
  1613. package/src/view/common/TabbedView.d.ts +14 -6
  1614. package/src/view/common/TabbedView.d.ts.map +1 -1
  1615. package/src/view/common/TabbedView.js +6 -4
  1616. package/src/view/controller/controls/BooleanVector3Control.d.ts +1 -1
  1617. package/src/view/controller/controls/BooleanVector3Control.d.ts.map +1 -1
  1618. package/src/view/controller/controls/GuiControl.d.ts +1 -1
  1619. package/src/view/controller/controls/GuiControl.d.ts.map +1 -1
  1620. package/src/view/controller/controls/NativeListController.d.ts +15 -7
  1621. package/src/view/controller/controls/NativeListController.d.ts.map +1 -1
  1622. package/src/view/controller/controls/NativeListController.js +7 -6
  1623. package/src/view/controller/controls/Vector1Control.d.ts +1 -1
  1624. package/src/view/controller/controls/Vector1Control.d.ts.map +1 -1
  1625. package/src/view/currency/CompositeCurrencyLabelView.d.ts +10 -5
  1626. package/src/view/currency/CompositeCurrencyLabelView.d.ts.map +1 -1
  1627. package/src/view/currency/CompositeCurrencyLabelView.js +4 -3
  1628. package/src/view/currency/CurrencyDenominationLabelView.d.ts +7 -3
  1629. package/src/view/currency/CurrencyDenominationLabelView.d.ts.map +1 -1
  1630. package/src/view/currency/CurrencyDenominationLabelView.js +3 -2
  1631. package/src/view/elements/CheckboxView.d.ts +7 -3
  1632. package/src/view/elements/CheckboxView.d.ts.map +1 -1
  1633. package/src/view/elements/CheckboxView.js +3 -2
  1634. package/src/view/elements/DropDownSelectionView.d.ts +9 -4
  1635. package/src/view/elements/DropDownSelectionView.d.ts.map +1 -1
  1636. package/src/view/elements/DropDownSelectionView.js +3 -2
  1637. package/src/view/elements/EmptyView.d.ts +29 -13
  1638. package/src/view/elements/EmptyView.d.ts.map +1 -1
  1639. package/src/view/elements/EmptyView.js +13 -11
  1640. package/src/view/elements/SimpleWindow.d.ts +1 -1
  1641. package/src/view/elements/SimpleWindow.d.ts.map +1 -1
  1642. package/src/view/elements/button/ButtonView.d.ts +15 -7
  1643. package/src/view/elements/button/ButtonView.d.ts.map +1 -1
  1644. package/src/view/elements/button/ButtonView.js +7 -6
  1645. package/src/view/elements/image/ImageView.d.ts +7 -3
  1646. package/src/view/elements/image/ImageView.d.ts.map +1 -1
  1647. package/src/view/elements/image/ImageView.js +3 -2
  1648. package/src/view/elements/image/SvgImageView.d.ts +5 -2
  1649. package/src/view/elements/image/SvgImageView.d.ts.map +1 -1
  1650. package/src/view/elements/image/SvgImageView.js +2 -1
  1651. package/src/view/elements/label/LabeledValueView.d.ts +14 -7
  1652. package/src/view/elements/label/LabeledValueView.d.ts.map +1 -1
  1653. package/src/view/elements/label/LabeledValueView.js +6 -5
  1654. package/src/view/elements/progress/SmoothProgressBar.d.ts +14 -7
  1655. package/src/view/elements/progress/SmoothProgressBar.d.ts.map +1 -1
  1656. package/src/view/elements/progress/SmoothProgressBar.js +6 -5
  1657. package/src/view/elements/progress/segmented/SegmentedResourceBarView.d.ts +9 -4
  1658. package/src/view/elements/progress/segmented/SegmentedResourceBarView.d.ts.map +1 -1
  1659. package/src/view/elements/progress/segmented/SegmentedResourceBarView.js +4 -3
  1660. package/src/view/elements/radial/RadialMenu.d.ts +19 -9
  1661. package/src/view/elements/radial/RadialMenu.d.ts.map +1 -1
  1662. package/src/view/elements/radial/RadialMenu.js +9 -8
  1663. package/src/view/elements/radial/RadialMenuElementDefinition.d.ts +63 -31
  1664. package/src/view/elements/radial/RadialMenuElementDefinition.d.ts.map +1 -1
  1665. package/src/view/elements/radial/RadialMenuElementDefinition.js +30 -28
  1666. package/src/view/elements/radial/RadialProgressView.d.ts +1 -1
  1667. package/src/view/elements/radial/RadialProgressView.d.ts.map +1 -1
  1668. package/src/view/elements/radial/RadialText.d.ts +18 -10
  1669. package/src/view/elements/radial/RadialText.d.ts.map +1 -1
  1670. package/src/view/elements/radial/RadialText.js +7 -6
  1671. package/src/view/elements/tiles2d/Tile.d.ts +12 -6
  1672. package/src/view/elements/tiles2d/Tile.d.ts.map +1 -1
  1673. package/src/view/elements/tiles2d/Tile.js +4 -3
  1674. package/src/view/elements/tiles2d/TileGrid.d.ts +23 -10
  1675. package/src/view/elements/tiles2d/TileGrid.d.ts.map +1 -1
  1676. package/src/view/elements/tiles2d/TileGrid.js +10 -9
  1677. package/src/view/elements/video/VideoView.d.ts +7 -3
  1678. package/src/view/elements/video/VideoView.d.ts.map +1 -1
  1679. package/src/view/elements/video/VideoView.js +3 -2
  1680. package/src/view/game/achievements/AchievementNotificationView.d.ts +7 -3
  1681. package/src/view/game/achievements/AchievementNotificationView.d.ts.map +1 -1
  1682. package/src/view/game/achievements/AchievementNotificationView.js +3 -2
  1683. package/src/view/graphics/GraphicsContextFailureView.d.ts +11 -5
  1684. package/src/view/graphics/GraphicsContextFailureView.d.ts.map +1 -1
  1685. package/src/view/graphics/GraphicsContextFailureView.js +5 -4
  1686. package/src/view/interaction/InteractionCommand.d.ts +11 -5
  1687. package/src/view/interaction/InteractionCommand.d.ts.map +1 -1
  1688. package/src/view/interaction/InteractionCommand.js +5 -4
  1689. package/src/view/interaction/InterfaceCommand.d.ts +32 -15
  1690. package/src/view/interaction/InterfaceCommand.d.ts.map +1 -1
  1691. package/src/view/interaction/InterfaceCommand.js +15 -13
  1692. package/src/view/interaction/createInterfaceCommandButton.d.ts +9 -4
  1693. package/src/view/interaction/createInterfaceCommandButton.d.ts.map +1 -1
  1694. package/src/view/interaction/createInterfaceCommandButton.js +4 -3
  1695. package/src/view/layout/DockPanel.d.ts +11 -5
  1696. package/src/view/layout/DockPanel.d.ts.map +1 -1
  1697. package/src/view/layout/DockPanel.js +5 -4
  1698. package/src/view/layout/DrawerView.d.ts +7 -3
  1699. package/src/view/layout/DrawerView.d.ts.map +1 -1
  1700. package/src/view/layout/DrawerView.js +3 -2
  1701. package/src/view/layout/FloatingPanelView.d.ts +7 -3
  1702. package/src/view/layout/FloatingPanelView.d.ts.map +1 -1
  1703. package/src/view/layout/FloatingPanelView.js +3 -2
  1704. package/src/view/layout/SplitView.d.ts +11 -5
  1705. package/src/view/layout/SplitView.d.ts.map +1 -1
  1706. package/src/view/layout/SplitView.js +5 -4
  1707. package/src/view/math/FunctionGraphView.d.ts +8 -4
  1708. package/src/view/math/FunctionGraphView.d.ts.map +1 -1
  1709. package/src/view/math/FunctionGraphView.js +3 -2
  1710. package/src/view/minimap/MinimapCanvasView.d.ts +10 -4
  1711. package/src/view/minimap/MinimapCanvasView.d.ts.map +1 -1
  1712. package/src/view/minimap/MinimapCanvasView.js +4 -3
  1713. package/src/view/minimap/dom/MinimapCameraView.d.ts +2 -1
  1714. package/src/view/minimap/dom/MinimapCameraView.d.ts.map +1 -1
  1715. package/src/view/minimap/dom/MinimapMarkerView.d.ts +31 -9
  1716. package/src/view/minimap/dom/MinimapMarkerView.d.ts.map +1 -1
  1717. package/src/view/minimap/dom/MinimapTerrainView.d.ts +9 -4
  1718. package/src/view/minimap/dom/MinimapTerrainView.d.ts.map +1 -1
  1719. package/src/view/minimap/dom/MinimapTerrainView.js +3 -2
  1720. package/src/view/task/TaskProgressView.d.ts +7 -3
  1721. package/src/view/task/TaskProgressView.d.ts.map +1 -1
  1722. package/src/view/task/TaskProgressView.js +3 -2
  1723. package/src/view/tooltip/DomTooltipManager.d.ts +6 -0
  1724. package/src/view/tooltip/DomTooltipManager.d.ts.map +1 -1
  1725. package/src/view/tooltip/DomTooltipManager.js +5 -0
  1726. package/src/view/tooltip/DomTooltipObserver.d.ts +4 -0
  1727. package/src/view/tooltip/DomTooltipObserver.d.ts.map +1 -1
  1728. package/src/view/tooltip/DomTooltipObserver.js +4 -0
  1729. package/src/view/tooltip/TooltipManager.d.ts +6 -0
  1730. package/src/view/tooltip/TooltipManager.d.ts.map +1 -1
  1731. package/src/view/tooltip/TooltipManager.js +5 -0
  1732. package/src/view/tooltip/TooltipView.d.ts +7 -3
  1733. package/src/view/tooltip/TooltipView.d.ts.map +1 -1
  1734. package/src/view/tooltip/TooltipView.js +5 -1
  1735. package/src/view/tooltip/VisualTip.d.ts +6 -0
  1736. package/src/view/tooltip/VisualTip.d.ts.map +1 -1
  1737. package/src/view/tooltip/VisualTip.js +5 -0
  1738. package/src/view/tooltip/gml/GMLEngine.d.ts +14 -2
  1739. package/src/view/tooltip/gml/GMLEngine.d.ts.map +1 -1
  1740. package/src/view/tooltip/gml/GMLEngine.js +8 -0
  1741. package/src/view/tooltip/gml/compiler/GMLReferenceCompiler.d.ts +10 -0
  1742. package/src/view/tooltip/gml/compiler/GMLReferenceCompiler.d.ts.map +1 -1
  1743. package/src/view/tooltip/gml/compiler/GMLReferenceCompiler.js +7 -0
  1744. package/src/view/util/DomSizeObserver.d.ts +9 -2
  1745. package/src/view/util/DomSizeObserver.d.ts.map +1 -1
  1746. package/src/view/util/DomSizeObserver.js +6 -1
  1747. package/src/engine/graphics/texture/virtual/NOTES.md +0 -128
  1748. package/src/engine/graphics/texture/virtual/VT_DEFAULT_PAGE_RESOLUTION.d.ts +0 -6
  1749. package/src/engine/graphics/texture/virtual/VT_DEFAULT_PAGE_RESOLUTION.d.ts.map +0 -1
  1750. package/src/engine/graphics/texture/virtual/VT_DEFAULT_PAGE_RESOLUTION.js +0 -5
  1751. package/src/engine/graphics/texture/virtual/VirtualTextureTileLoader.d.ts +0 -49
  1752. package/src/engine/graphics/texture/virtual/VirtualTextureTileLoader.d.ts.map +0 -1
  1753. package/src/engine/graphics/texture/virtual/VirtualTextureTileLoader.js +0 -264
  1754. package/src/engine/graphics/texture/virtual/VirtualTextureUsage.d.ts +0 -44
  1755. package/src/engine/graphics/texture/virtual/VirtualTextureUsage.d.ts.map +0 -1
  1756. package/src/engine/graphics/texture/virtual/VirtualTextureUsage.js +0 -228
  1757. package/src/engine/graphics/texture/virtual/VirtualTextureUsageShader.d.ts +0 -3
  1758. package/src/engine/graphics/texture/virtual/VirtualTextureUsageShader.d.ts.map +0 -1
  1759. package/src/engine/graphics/texture/virtual/VirtualTextureUsageShader.js +0 -73
  1760. package/src/engine/graphics/texture/virtual/debug/ResidencyDebugView.d.ts +0 -14
  1761. package/src/engine/graphics/texture/virtual/debug/ResidencyDebugView.d.ts.map +0 -1
  1762. package/src/engine/graphics/texture/virtual/debug/ResidencyDebugView.js +0 -85
  1763. package/src/engine/graphics/texture/virtual/debug/UsageDebugView.d.ts +0 -12
  1764. package/src/engine/graphics/texture/virtual/debug/UsageDebugView.d.ts.map +0 -1
  1765. package/src/engine/graphics/texture/virtual/debug/UsageDebugView.js +0 -63
  1766. package/src/engine/graphics/texture/virtual/debug/UsagePyramidDebugView.d.ts +0 -12
  1767. package/src/engine/graphics/texture/virtual/debug/UsagePyramidDebugView.d.ts.map +0 -1
  1768. package/src/engine/graphics/texture/virtual/debug/UsagePyramidDebugView.js +0 -243
  1769. package/src/engine/graphics/texture/virtual/tile/VirtualTextureTile.d.ts +0 -30
  1770. package/src/engine/graphics/texture/virtual/tile/VirtualTextureTile.d.ts.map +0 -1
  1771. package/src/engine/graphics/texture/virtual/tile/VirtualTextureTile.js +0 -39
  1772. package/src/engine/graphics/texture/virtual/tile/compose_finger_print.d.ts +0 -9
  1773. package/src/engine/graphics/texture/virtual/tile/compose_finger_print.d.ts.map +0 -1
  1774. package/src/engine/graphics/texture/virtual/tile/compose_finger_print.js +0 -24
  1775. package/src/engine/graphics/texture/virtual/tile/compose_tile_address.d.ts +0 -9
  1776. package/src/engine/graphics/texture/virtual/tile/compose_tile_address.d.ts.map +0 -1
  1777. package/src/engine/graphics/texture/virtual/tile/compose_tile_address.js +0 -26
  1778. package/src/engine/graphics/texture/virtual/tile/decompose_finger_print.d.ts +0 -11
  1779. package/src/engine/graphics/texture/virtual/tile/decompose_finger_print.d.ts.map +0 -1
  1780. package/src/engine/graphics/texture/virtual/tile/decompose_finger_print.js +0 -12
  1781. package/src/engine/graphics/texture/virtual/tile/finger_print_to_tile_address.d.ts +0 -7
  1782. package/src/engine/graphics/texture/virtual/tile/finger_print_to_tile_address.d.ts.map +0 -1
  1783. package/src/engine/graphics/texture/virtual/tile/finger_print_to_tile_address.js +0 -16
  1784. package/src/engine/graphics/texture/virtual/tile/tile_address_to_finger_print.d.ts +0 -7
  1785. package/src/engine/graphics/texture/virtual/tile/tile_address_to_finger_print.d.ts.map +0 -1
  1786. package/src/engine/graphics/texture/virtual/tile/tile_address_to_finger_print.js +0 -35
  1787. package/src/shade/renderer/geometry/virtual/format/prototypeVGEOFormatViewer.d.ts +0 -395
  1788. package/src/shade/renderer/geometry/virtual/format/prototypeVGEOFormatViewer.d.ts.map +0 -1
  1789. package/src/shade/renderer/particles/ParticleRenderMode.d.ts +0 -19
  1790. package/src/shade/renderer/particles/ParticleRenderMode.d.ts.map +0 -1
  1791. package/src/shade/renderer/particles/ParticleRenderMode.js +0 -33
  1792. package/src/shade/renderer/particles/graph_particles_billboard.d.ts +0 -37
  1793. package/src/shade/renderer/particles/graph_particles_billboard.d.ts.map +0 -1
  1794. package/src/shade/renderer/particles/graph_particles_billboard.js +0 -93
  1795. package/src/shade/renderer/particles/sort/graph_particle_sort.d.ts +0 -55
  1796. package/src/shade/renderer/particles/sort/graph_particle_sort.d.ts.map +0 -1
  1797. package/src/shade/renderer/particles/sort/graph_particle_sort.js +0 -130
  1798. package/src/shade/renderer/particles/sort/particle_counting_sort.d.ts +0 -26
  1799. package/src/shade/renderer/particles/sort/particle_counting_sort.d.ts.map +0 -1
  1800. package/src/shade/renderer/particles/sort/particle_counting_sort.js +0 -51
  1801. package/src/shade/renderer/particles/sort/shader_particle_sort.d.ts +0 -14
  1802. package/src/shade/renderer/particles/sort/shader_particle_sort.d.ts.map +0 -1
  1803. package/src/shade/renderer/particles/sort/shader_particle_sort.js +0 -223
@@ -0,0 +1,2239 @@
1
+ # Cloth — measurements
2
+
3
+ > Four milestones, appended in order. §1–§8 are **M0**, the solver core;
4
+ > §9–§15 are **M1**, the component and the system; §16–§23 are **M2**,
5
+ > collision; §24–§29 are **M3**, skinned garments. Nothing above a milestone
6
+ > boundary is edited by the milestone below it — a measurement that turned out to
7
+ > be incomplete is corrected by a later section saying so, not by a rewrite.
8
+
9
+ ---
10
+
11
+ # Cloth — M0 measurements
12
+
13
+ > What the solver core actually does, measured. Written 2026-09-10, against the
14
+ > M0 implementation in `solver/`.
15
+ >
16
+ > Every number here is reproducible from two scripts, both runnable directly
17
+ > under node (through vitest, imported bindings become getters and the
18
+ > cross-module calls that make up the inner loop stop inlining — which is
19
+ > exactly what is being measured):
20
+ >
21
+ > ```
22
+ > node src/engine/physics/cloth/solver/__fixtures__/cloth_constants_sweep.mjs
23
+ > node src/engine/physics/cloth/solver/__fixtures__/cloth_bench.mjs
24
+ > ```
25
+ >
26
+ > There is also a playground, which is where the §6 finding came from:
27
+ > `npm run dev --workspace @woosh/meep-engine`, then
28
+ > `/src/engine/physics/cloth/playground/`. Its presets are the interesting rows
29
+ > of this document, one click each.
30
+
31
+ ---
32
+
33
+ ## 1. What M0 proved wrong in PLAN.md
34
+
35
+ Six things, in the order they were found. Each is folded back into the design
36
+ document; this is the evidence.
37
+
38
+ | # | The design said | The measurement said |
39
+ |---|---|---|
40
+ | 0 | §6 — a stretch row carries a material stiffness `k_stretch` | A *penalty* stiffer than about `8·(m/h²)` makes the step **add** energy — measured at +6.8 J on a sheet whose whole potential is 1.2 J — and no iteration count removes it. Cloth's stretch rows have to be hard. §6 below. |
41
+ | 1 | §5.3 — an SPD Hessian means "no update can increase the local energy" | SPD buys a descent **direction**. A full Newton step of 1 overshoots and climbs where the model stops resembling the energy. §5.3 below. |
42
+ | 2 | §5.2 — drop the geometric-stiffness term `fc·∂²C/∂x²` entirely | Its PSD half is what stops the update overshooting sideways. Keep it; the NSD half is still dropped. §5.1 |
43
+ | 3 | §5.2 — the multiplier and the penalty band apply to every row | They apply only to **hard** rows. On a soft row the multiplier drives `C → 0` and makes a 1 kN/m spring 100× stiffer than Hooke. §3 |
44
+ | 4 | §5.2 — `k_min` and `k_max` are stiffnesses | They are only meaningful as **ratios of the row's own `m/h²`** — the same ratio works across five decades of particle mass; a fixed stiffness does not. §4 |
45
+ | 5 | §5.2 — the 3×3 solve "never fails" | The *cofactor* solve fails: a determinant of −4.8e8 on a matrix with eigenvalues 0.12, 0.12, 5.4e8. LDLᵀ does not. §5.2 |
46
+ | 6 | §17 — under 2 ms per frame per character | **3.50 ms** best case, 4.42 ms median, for 1,024 particles at 2×4. Over by 1.75×. And gathering neighbours is *not* what dominates. §7 |
47
+
48
+ A seventh is a gap rather than an error: §7 P5's jitter mechanism (`γ` decaying
49
+ warm-started duals) only reaches hard rows, because a soft row has no multiplier
50
+ to decay. §6.
51
+
52
+ ---
53
+
54
+ ## 2. The constants
55
+
56
+ ```
57
+ α = 0.25 γ = 1 β = 1e5 (unexercised) k_min = k_max = 8·(m/h²)
58
+ ```
59
+
60
+ `cloth_solver_constants.js` carries them and says why. The short version:
61
+
62
+ - **α and γ act only through their product.** At a fixed `α·γ` the answer does
63
+ not move at all between `γ = 0.3` and `γ = 1`. `γ` sits at 1 because its
64
+ second job — decaying the penalty — has nothing to do while the band is a
65
+ single point.
66
+ - **`α·γ ≥ 0.5` diverges.** 0.25 is a factor of two clear.
67
+ - **`k_min = k_max` disables the ramp**, which measured as good as any ramped
68
+ alternative for M0's persistent rows and removes a scale-dependence that a
69
+ live ramp reintroduces. The ramp exists for *transient* rows — a contact that
70
+ should arrive soft rather than shock the mesh on its first frame — and M0 has
71
+ none, so **β cannot be chosen from M0 data and M2 must measure it.**
72
+
73
+ ### α·γ against the penalty ceiling — 20-link hard chain
74
+
75
+ Cells are `worst |C|/L₀` / `kinetic energy after 400 steps, J`. The kinetic
76
+ column is the one to read: past `α·γ = 0.3` the chain stops settling long before
77
+ it stops being finite.
78
+
79
+ ```
80
+ k_max/(m/h²) α·γ=0 α·γ=0.1 α·γ=0.2 α·γ=0.25 α·γ=0.3 α·γ=0.4 α·γ=0.5 α·γ=0.6
81
+ 1 3.6e-1/3e-7 3.1e-1/2e-7 2.8e-1/1e-7 2.6e-1/4e-7 2.4e-1/1e-6 2.2e-1/3e-6 1.7e-1/2e-3 8.5e-1/5e-3
82
+ 2 1.9e-1/1e-10 1.7e-1/2e-11 1.5e-1/3e-10 1.4e-1/2e-9 1.3e-1/5e-11 1.0e-1/1e-7 9.7e-2/3e-3 diverged
83
+ 4 1.0e-1/1e-13 9.1e-2/1e-13 7.9e-2/1e-12 7.3e-2/2e-12 6.7e-2/3e-12 5.7e-2/3e-7 2.8e-1/3e-2 diverged
84
+ 8 5.6e-2/2e-13 4.9e-2/3e-14 4.1e-2/3e-13 3.8e-2/1e-11 3.5e-2/2e-9 6.6e-2/3e-4 diverged diverged
85
+ 16 4.9e-2/1e-5 2.5e-2/1e-10 2.1e-2/1e-6 4.1e-2/7e-5 3.3e-2/2e-4 2.7e-2/1e-3 diverged diverged
86
+ 32 5.5e-2/5e-5 4.9e-2/5e-5 4.4e-2/4e-5 4.1e-2/4e-5 3.9e-2/4e-5 7.6e-2/1e-3 diverged diverged
87
+ 128 7.0e-2/3e-4 6.4e-2/2e-4 5.9e-2/2e-4 5.7e-2/2e-4 5.5e-2/2e-4 5.0e-2/2e-4 diverged diverged
88
+ 1024 1.3e-1/2e-3 7.3e-2/3e-4 7.6e-2/5e-4 7.3e-2/4e-4 7.1e-2/4e-4 6.6e-2/4e-4 diverged diverged
89
+ ```
90
+
91
+ ---
92
+
93
+ ## 3. Soft rows must not carry a multiplier
94
+
95
+ The first thing the sweep established, and it reshaped everything after it.
96
+
97
+ A row whose material stiffness is finite is representable as a plain penalty,
98
+ and **a plain penalty at the material stiffness is the material law**. There is
99
+ nothing for a multiplier to add, and adding one anyway is not a small error:
100
+ `λ ← λ + k·C` is an augmented Lagrangian on the equality `C = 0`, so it drives
101
+ `C` to zero whatever `k` is. A 0.05 kg mass on a 1 kN/m spring, whose analytic
102
+ extension is 0.49 mm, settled at **4.8 µm — a hundred times stiffer than it was
103
+ authored as.**
104
+
105
+ The fix is that a row is **hard** exactly when its stiffness is `Infinity`,
106
+ which makes §6's table literal rather than introducing a threshold. A hard row
107
+ gets the augmented Lagrangian; a soft row is a pure penalty and carries no
108
+ multiplier. Afterwards a soft row reads exactly Hooke, and reads it whatever the
109
+ five constants are doing:
110
+
111
+ ```
112
+ chosen extension/Hooke = 1.0000
113
+ α=0 extension/Hooke = 1.0000
114
+ α=1 γ=1 extension/Hooke = 1.0000
115
+ β=0 extension/Hooke = 1.0000
116
+ band ×1024 extension/Hooke = 1.0000
117
+ ```
118
+
119
+ That insensitivity is what makes α, β, γ and the band honest as *global* solver
120
+ internals rather than things an author would eventually have to reach for.
121
+
122
+ ### What the multiplier actually buys
123
+
124
+ Not a smaller residual. Measured across chain depths of 5 to 40 and stiffnesses
125
+ from 1e2 to 1e9 at the same budget, a hard row and a stiff penalty give
126
+ comparable `|C|/L₀`, and which wins depends on the phase of the oscillation the
127
+ snapshot catches. What it buys is **settling**: a hard 20-link chain comes to
128
+ rest at 1e-14 J where the same chain on a penalty of any stiffness sits in a
129
+ limit cycle at 1e-4 J. Ten orders of magnitude, and it is §7 P5 rather than P2.
130
+
131
+ ---
132
+
133
+ ## 4. The penalty band is a ratio, not a stiffness
134
+
135
+ Same 20-link hard chain, `α·γ = 0.25`, with `k_max` held at a fixed **multiple**
136
+ of the row's own `m/h²` while the particle mass moves across five decades. The
137
+ residual column repeats exactly; against a fixed stiffness in N/m it does not.
138
+
139
+ ```
140
+ mass (kg) m/h² ×0.3 ×1 ×2 ×4 ×8 ×16 ×64 ×256
141
+ 5e-6 7.2e-2 7.4e-1/4e-6 2.6e-1/4e-9 1.4e-1/2e-11 7.3e-2/2e-14 3.8e-2/1e-13 4.1e-2/7e-7 4.8e-2/1e-6 6.5e-2/3e-6
142
+ 5e-4 7.2e+0 7.4e-1/4e-4 2.6e-1/4e-7 1.4e-1/2e-9 7.3e-2/2e-12 3.8e-2/1e-11 4.1e-2/7e-5 4.8e-2/1e-4 6.5e-2/3e-4
143
+ 5e-2 7.2e+2 7.4e-1/4e-2 2.6e-1/4e-5 1.4e-1/2e-7 7.3e-2/2e-10 3.8e-2/1e-9 4.1e-2/7e-3 4.8e-2/1e-2 6.5e-2/3e-2
144
+ 5e+0 7.2e+4 7.4e-1/4e+0 2.6e-1/4e-3 1.4e-1/2e-5 7.3e-2/2e-8 3.8e-2/2e-7 4.1e-2/7e-1 4.8e-2/1e+0 6.5e-2/3e+0
145
+ ```
146
+
147
+ §5.2's own prose already names `k_max/(m/h²)` as the quantity that matters. It
148
+ stopped one step short of making the ratio the parameter.
149
+
150
+ The optimum is ×8: below it the row is too soft to converge, above it the chain
151
+ stops settling (the kinetic column climbs by four orders of magnitude between
152
+ ×8 and ×16). The row's scale is its **effective** inertia along the constraint,
153
+ `1/((wᵢ + wⱼ)·h²)`, so a row with one pinned end sees the free particle's own
154
+ `m/h²` and an interior row sees half of it.
155
+
156
+ ---
157
+
158
+ ## 5. The vertex update
159
+
160
+ ### 5.1 The geometric-stiffness term, half of it
161
+
162
+ For a distance row `∂²C/∂x² = (I − g gᵀ)/L`, which is positive semidefinite
163
+ exactly when the row is in tension. Dropping the whole term — §5.2's
164
+ instruction — leaves `H` underestimating the curvature perpendicular to the row
165
+ by `fc/L`, so the update overshoots sideways once that passes the mass term.
166
+ One free particle between two anchors, stepping the tension up:
167
+
168
+ ```
169
+ m/h² fc/L ratio ΔE/E with the term dropped with its PSD half kept
170
+ 1.44e+2 1.06e+2 7.33e-1 −65.6% −62.9%
171
+ 1.44e+2 5.53e+2 3.84e+0 +21.9% −30.1%
172
+ 1.44e+2 5.53e+4 3.84e+2 +80.8% −33.9%
173
+ 1.44e+2 1.45e+6 1.01e+4 +718.0% −22.6%
174
+ 1.44e+2 9.94e+6 6.90e+4 +4140.0% −19.1%
175
+ ```
176
+
177
+ The crossover is exactly where the theory puts it, at `fc/L ≈ m/h²`. Keeping the
178
+ PSD half costs nothing structurally: every term in `H` is still positive
179
+ semidefinite on top of a positive definite mass term, so the SPD-by-construction
180
+ argument is intact and there is still no threshold. The compression half stays
181
+ dropped, and dropping it there is conservative — it makes the step shorter than
182
+ Newton, not longer.
183
+
184
+ The term is added whether or not the row is at a clamp. A saturated row applies
185
+ a force of constant *magnitude*, but that force still swings as the row rotates,
186
+ so its geometric curvature is real even though its penalty curvature is gone.
187
+
188
+ ### 5.2 LDLᵀ, not a cofactor inverse
189
+
190
+ The two agree in exact arithmetic. In `Float64` they do not. A vertex carrying
191
+ one very stiff row against a small mass term assembles
192
+
193
+ ```
194
+ H = [[1.7099e+8, −2.1651e+8, 1.2729e+8],
195
+ [ , 2.7415e+8, −1.6118e+8],
196
+ [ , , 9.4759e+7]]
197
+
198
+ eigenvalues 1.198e−1, 1.198e−1, 5.399e+8 (all positive; condition 4.5e9)
199
+ true determinant 7.752e+6
200
+ cofactor determinant −4.828e+8 ← wrong sign
201
+ LDLᵀ pivots 1.710e+8, 3.120e−1, 1.453e−1 (product 7.752e+6, exact)
202
+ ```
203
+
204
+ The determinant is a sum of triple products that has to cancel by the condition
205
+ number squared; the factorisation never forms them. The dev-build assertion
206
+ checks the three pivots, which *is* positive definiteness rather than a proxy
207
+ for it, and it held across every update in the fuzz.
208
+
209
+ ### 5.3 A descent direction is not a monotone step
210
+
211
+ `Δ = H⁻¹f` with `H` positive definite gives `f·Δ = fᵀH⁻¹f > 0`. That guarantees
212
+ the energy falls for a *small enough* step. The update takes a full step of 1,
213
+ and where the quadratic model stops resembling the energy, a full step climbs.
214
+ Walking one such step:
215
+
216
+ ```
217
+ t E(x₀ + t·Δ) ΔE
218
+ 0 −1.9122412072e+7 0
219
+ 1e−9 −1.9122412098e+7 −2.6e−2 falling
220
+ 1e−7 −1.9122414636e+7 −2.6e+0 falling
221
+ 1e−5 −1.9122668457e+7 −2.6e+2 falling
222
+ 1e−3 −1.9133645206e+7 −1.1e+4 falling — this is the minimum
223
+ 1e−2 −1.8901856618e+7 +2.2e+5 past it
224
+ 0.5 −3.1478025715e+6 +1.6e+7
225
+ 1 +1.9273328443e+7 +3.8e+7 the step the solver takes
226
+ ```
227
+
228
+ The direction is right; the length is a thousand times too long. So the step is
229
+ capped at the **shortest row incident on the particle** — the distance over
230
+ which "the direction to a neighbour" means anything. That radius is the mesh's
231
+ own geometry rather than a tuned constant, it is already in hand from the
232
+ accumulation, and for cloth in any ordinary motion it never binds.
233
+
234
+ With all three corrections in place:
235
+
236
+ | | fraction of updates that climb | worst, relative to the local energy scale |
237
+ |---|---|---|
238
+ | realistic cape, hard rows | 0.0040% | 8.6e−2 |
239
+ | realistic cape, soft rows | 0.0041% | 1.5e−1 |
240
+ | absurd fuzz, 3.0M updates | 1.52% | 1.00 |
241
+
242
+ Those are the thresholds the standing gate in `cloth_solve_vertex.spec.js` holds
243
+ the solver to.
244
+
245
+ ---
246
+
247
+ ## 6. Settling, and the gap in P5
248
+
249
+ At the chosen constants a **hard** chain settles hard: a 20-link chain reaches
250
+ 1e-11 J and an 80-link one 1e-9 J, and the residual falls monotonically with the
251
+ iteration budget with nothing diverging at any depth.
252
+
253
+ ```
254
+ iterations n=1 n=2 n=5 n=10 n=20 n=40 n=80
255
+ 1 3.2e-3/0e+0 6.4e-3/1e-16 4.6e-2/3e-5 9.5e-2/6e-7 1.3e-1/2e-3 1.2e+0/2e-2 9.6e-1/3e-1
256
+ 2 3.2e-4/0e+0 4.2e-3/0e+0 1.4e-2/2e-16 3.4e-2/1e-6 1.4e-1/6e-4 1.2e-1/7e-3 8.9e-1/1e-2
257
+ 4 3.9e-6/0e+0 4.1e-4/0e+0 6.8e-3/1e-16 1.7e-2/2e-15 3.8e-2/1e-11 9.0e-2/3e-5 1.4e-1/7e-3
258
+ 8 0.0e+0/0e+0 2.9e-5/1e-17 1.7e-3/1e-16 7.2e-3/1e-15 1.7e-2/9e-14 3.8e-2/8e-13 8.0e-2/1e-4
259
+ 16 0.0e+0/0e+0 2.8e-7/0e+0 4.1e-4/5e-16 2.1e-3/1e-15 6.9e-3/3e-14 1.6e-2/2e-13 3.6e-2/9e-10
260
+ ```
261
+
262
+ A **soft** row above a certain stiffness does not settle at all, and the reason
263
+ is worse than "nothing is damping it".
264
+
265
+ The threshold is the same ratio §4 turns up: **`k/(m/h²)`**. Below about 8 the
266
+ step is dissipative and the cloth comes to rest; above it the cloth sustains a
267
+ limit cycle for as long as you run it. Measured on a 16×20 sheet, 0.3 kg, hung
268
+ from the top edge at 60 Hz × 2 substeps × 4 iterations, over 1,500 steps:
269
+
270
+ ```
271
+ row k/(m/h²) final kinetic energy
272
+ hard (AL, k pinned at ×8) 8 1.9e-12 J settles
273
+ soft, 1e2 N/m 7.4 7.4e-09 J settles
274
+ soft, 1e3 N/m 74 1.9e-02 J does not
275
+ soft, 1e4 N/m 740 7.4e-03 J does not
276
+ soft, 1e5 N/m 7400 2.9e-02 J does not
277
+ soft, 1e4 at 16 iterations 740 3.3e-03 J does not
278
+ soft, 1e4 at 8 substeps 740 1.4e-03 J does not
279
+ ```
280
+
281
+ More iterations and more substeps shrink it; neither removes it.
282
+
283
+ And the step is **adding energy**, not merely failing to remove it. Tracking the
284
+ full mechanical energy — kinetic plus gravitational plus elastic — from the rest
285
+ configuration:
286
+
287
+ ```
288
+ soft 1e2 (ratio 7) −0.016 J, and flat from step 300 onwards dissipative
289
+ soft 1e4 (ratio 740) +6.8 J, wandering between +1 and +7 J creating it
290
+ ```
291
+
292
+ For scale, that sheet's entire gravitational potential over its own length is
293
+ about 1.2 J, so at ratio 740 the solve manufactures several times the whole
294
+ system's energy budget and then holds it there. It stays bounded — the SPD
295
+ Hessian and the trust region cap every individual step — but bounded is not
296
+ rest.
297
+
298
+ Two consequences.
299
+
300
+ **§7 P5's mechanism covers hard rows only.** `γ` decays a multiplier and a soft
301
+ row has none, so no value of any solver constant reaches this. What does reach
302
+ it is `ClothDynamics#damping`, which arrives with the component in M1 — which
303
+ means damping is load-bearing for P5 rather than a taste control, and M1's spec
304
+ has to gate on a soft cloth actually settling.
305
+
306
+ **§6's assignment of stretch to a soft material stiffness does not survive.**
307
+ Real fabric wants a stretch stiffness far above `8·(m/h²)` — for a half-gram
308
+ particle at 60 Hz × 2 substeps that boundary is around 60 N/m, which is a rubber
309
+ band, not a fabric. So a cloth's stretch rows have to be **hard**, and the
310
+ augmented Lagrangian is not an optional refinement over a stiff penalty: it is
311
+ the only formulation of that row that rests. That is the same conclusion §3
312
+ reaches from the other direction, and it is why the playground defaults to hard
313
+ rows.
314
+
315
+ ### Iteration-count insensitivity
316
+
317
+ §5.1 claims that adding iterations converges towards the *same* answer rather
318
+ than changing which answer it is. On the cape (20×30 at 2 cm, inextensible, hung
319
+ from its top edge and dropped through 90°), the hem across the budget:
320
+
321
+ ```
322
+ iterations= 1 hem=−0.6450 m residual=7.2e-1
323
+ iterations= 2 hem=−0.6201 m residual=2.0e-1
324
+ iterations= 4 hem=−0.5993 m residual=7.5e-2
325
+ iterations= 8 hem=−0.5466 m residual=7.2e-2
326
+ iterations=16 hem=−0.5626 m residual=1.4e-2
327
+ iterations=32 hem=−0.5459 m residual=8.0e-3
328
+ ```
329
+
330
+ The sheet is 0.58 m long, so the answer moves 18% of its own length between 1
331
+ iteration and 32, and the residual moves by two orders of magnitude. The claim
332
+ holds in the sense that matters — the answer converges rather than changing
333
+ character, and one iteration is stable rather than broken — but "insensitive" is
334
+ too strong for a mesh 30 rows deep at this budget. §7 P2's tether row is what
335
+ closes that gap, and it lands in M1.
336
+
337
+ ### Hostile regimes
338
+
339
+ All eight survive at the chosen constants.
340
+
341
+ ```
342
+ stiff + 5 fps ok 1 kg particles on 1e8 N/m rows, 1 substep, 1 iteration
343
+ light + 240 fps ok 10 mg particles, 4 substeps, 8 iterations
344
+ 10 m spacing ok a 6×6 sheet with 10 m between particles at 15 fps
345
+ a thousand g ok gravity at −9810 m/s²
346
+ soft as water ok 1e−2 N/m rows (sags 123 m, which is correct)
347
+ zero g, 100 m/s ok no gravity, particles thrown at 100 m/s
348
+ inextensible ok stiffness Infinity
349
+ inextensible cape ok 600 particles, stiffness Infinity
350
+ ```
351
+
352
+ ---
353
+
354
+ ## 7. The performance budget
355
+
356
+ §17 budgets **under 2 ms per frame per character**, for about 1,000 particles at
357
+ 2 substeps × 4 iterations, and says the figure is an estimate to be replaced by
358
+ a measurement. Replaced:
359
+
360
+ ```
361
+ # 1024 particles (32×32 patch at 2 cm, 0.5 kg), 2 substeps × 4 iterations
362
+ # 2945 stretch rows, 2821 bend rows, 4 colours, 370.4 KiB of state
363
+ # 8192 vertex updates per frame, 16.8 row incidences per particle
364
+ # Node v24.15.0 on win32/x64, 1200 warm-up frames then 1500 measured, 4 rounds
365
+
366
+ round minima 3.504 3.506 3.644 3.484 best 3.48 ms, spread ±5%
367
+ ```
368
+
369
+ **3.48 ms against a 2.000 ms budget — over by 1.74×**, and 3.55 ms when the
370
+ benchmark runs the same configuration alongside its four variants. The minimum is the
371
+ headline because it is what varies least between runs; a cloth's median moves by
372
+ a factor of two depending on whether it is still swinging, and the mean and p95
373
+ move with whatever else the machine is doing.
374
+
375
+ ### What the frame is made of
376
+
377
+ Deleting the workload piece by piece, all five variants in one run so the
378
+ comparison is internally consistent:
379
+
380
+ ```
381
+ variant MIN ms median share of the frame
382
+ everything 3.552 5.023
383
+ no bend rows 2.688 3.267 bend rows 0.864 ms 24.3%
384
+ no stretch rows 1.133 2.055 stretch rows 2.419 ms 68.1%
385
+ no rows at all 0.253 0.490 everything else 7.1%
386
+ shuffled within each colour 3.563 4.771 locality +0.3%
387
+ ```
388
+
389
+ The rows are the frame; predict, warm start, the dual updates and integrate
390
+ together are 7% of it, and the cost is close to linear in both particles and
391
+ sweeps. The split between the two row kinds moves by a few points between runs
392
+ — bend read 18% in one run and 24% in another — so treat it as "stretch is most
393
+ of it, bend is most of the rest".
394
+
395
+ Two things this table does **not** license, and an earlier draft of this
396
+ document claimed both.
397
+
398
+ It does not say a stretch row costs four times what a bend row costs *per
399
+ visit*. The three variants are in different physical states — a cloth with no
400
+ stretch rows is in free fall rather than draping — so the split measures what
401
+ each row kind *causes* in a running step, not the arithmetic in its accumulate.
402
+
403
+ And it does not license attributing the stretch share to any particular part of
404
+ that accumulate. See below.
405
+
406
+ ### A warning, because M2, M4 and M5 are told to re-measure
407
+
408
+ **An isolated loop over one accumulate measures the wrong workload.** Without
409
+ `predict` and `integrate` around it, the solve converges after a few passes and
410
+ the positions stop changing; from then on the loop reads a static array with
411
+ perfectly predictable branches, and every number it produces is of a cloth that
412
+ has stopped moving.
413
+
414
+ The size of the error, measured both ways on the same mesh:
415
+
416
+ ```
417
+ isolated loop by deletion, in the running step
418
+ bend accumulate 0.72 ms 0.70 ms agree
419
+ stretch accumulate 0.47 ms 2.64 ms disagree, 5.6×
420
+ both 1.19 ms 3.34 ms
421
+ ```
422
+
423
+ Bend agrees; stretch does not, and the gap is most of the frame. The dev-build
424
+ assertion machinery is not the explanation — the non-finite tripwire and the
425
+ pivot assertion's message together are 0.118 ms, 3.4% of the step. Nor is it
426
+ `cloth_solve_vertex`'s own arithmetic: the eight colour sweeps called exactly as
427
+ `cloth_step` calls them come to 1.88 ms, and driven on their own — with no
428
+ predict to disturb the cloth — they too are measuring a converged mesh.
429
+
430
+ The honest statement is that **only the end-to-end figures here are
431
+ trustworthy**, and the per-row breakdown an earlier draft gave has been removed
432
+ rather than reconciled. Whoever re-measures at M2 should keep the whole step
433
+ running and vary one thing at a time.
434
+
435
+ ### Gathering neighbours is not what dominates
436
+
437
+ §17 predicted it would. The controlled test is to **move every particle to a
438
+ different slot inside its own colour range**. The colouring is untouched — a
439
+ particle's colour *is* which range it sits in, and every particle stays in its
440
+ own — so the sweep does the same work in the same order over the same rows with
441
+ the same branches, and the only thing that moves is the address each particle
442
+ lives at.
443
+
444
+ The control is exact, and checkably so: the reference cloth and the shuffled one
445
+ produce **bit-identical** trajectories, agreeing on the hem position to six
446
+ decimals and on kinetic energy to five significant figures after 200 steps.
447
+
448
+ ```
449
+ 1024 particles, 370 KiB of state +0.3%
450
+ ```
451
+
452
+ Destroying within-colour locality entirely costs nothing measurable at the size
453
+ §17 budgets for — the whole state fits in L2 — so **§17's "gathering neighbour
454
+ positions is what will actually dominate" is wrong**, and there is no
455
+ memory-layout optimisation to win here. Whether that survives at four times the
456
+ size is *not* measured: a cruder probe suggested around 11% at 4,096 particles,
457
+ but that probe relabelled the source vertices, which also changed the greedy
458
+ colouring from four colours to ten, so it is not quotable.
459
+
460
+ Two earlier drafts got this wrong before this one got it right. The first used a
461
+ variant labelled "mesh order, not colour order" that did nothing of the kind —
462
+ it left the particles in colour-permuted storage and merely collapsed the colour
463
+ loop. The second relabelled the source numbering, which moves the particles but
464
+ changes the colouring with them. Only shuffling *within* a colour isolates the
465
+ one variable, and it was worth three attempts because this is the number that
466
+ contradicts the plan.
467
+
468
+ ### Scaling, and what fits
469
+
470
+ Four rounds each, so the spread is the figure's real precision:
471
+
472
+ ```
473
+ config round minima best spread
474
+ 1024 @ 2×4 (the §17 workload) 3.504 3.506 3.644 3.484 3.48 ±5%
475
+ 1024 @ 2×2 (half the iterations) 1.700 1.713 1.695 1.716 1.69 ±1% inside
476
+ 1024 @ 1×4 (half the substeps) 1.683 1.734 1.765 1.703 1.68 ±5% inside
477
+ 484 @ 2×4 (half the particles) 1.543 1.586 1.595 1.605 1.54 ±4% inside
478
+ 256 @ 2×4 0.792 0.804 0.791 0.785 0.79 ±2% inside
479
+ ```
480
+
481
+ §18's levers, priced:
482
+
483
+ | Lever | Result |
484
+ |---|---|
485
+ | Fewer iterations — "safe, the solver is stable at one" | 1,024 particles at 2×2: **1.69 ms**, comfortably inside |
486
+ | Fewer particles in the proxy | ~500 particles at the full 2×4: **1.54 ms** |
487
+ | Fewer substeps | 1,024 at 1×4: **1.68 ms** |
488
+ | The barycentric binding fallback (§11.2) | not needed to reach the budget |
489
+
490
+ Any one lever is enough on its own, and they compose. What the budget is *not*
491
+ reachable at is 1,000 particles at 2×4, which is the figure §17 wrote down.
492
+
493
+ **Note what the worker does not do.** §12 moves this off the main thread; it does
494
+ not make it cheaper. "2 ms on the worker" with several characters in flight is a
495
+ scheduling question this measurement does not answer.
496
+
497
+ ## 8. Topology note
498
+
499
+ The benchmark's 32×32 patch carries **16.8 row incidences per particle** against
500
+ §17's "about a dozen". That is the honest number for a triangulated sheet with a
501
+ stretch row per edge — including the quad diagonals — and a quadratic bend row
502
+ per interior edge, and it makes this measurement about 40% conservative against
503
+ the workload §17 imagined. A proxy that dropped the diagonals, or used a
504
+ quad-dominant mesh, would carry fewer.
505
+
506
+ ---
507
+
508
+ # Cloth — M1 measurements
509
+
510
+ > Written 2026-09-10, against the M1 implementation in `ecs/`. Everything above
511
+ > this line is M0's and unchanged.
512
+ >
513
+ > Two scripts, both runnable directly under node — the M0 note applies unchanged,
514
+ > and for the same reason:
515
+ >
516
+ > ```
517
+ > node src/engine/physics/cloth/ecs/__fixtures__/cloth_m1_measure.mjs
518
+ > node src/engine/physics/cloth/ecs/__fixtures__/cloth_library_bench.mjs
519
+ > ```
520
+ >
521
+ > And a second playground page, `playground/rig.html`, which is the entity
522
+ > subtree rather than the solver: a real `EntityManager`, real entities, and
523
+ > `ClothSystem` walking and writing back.
524
+
525
+ ---
526
+
527
+ ## 9. What M1 proved wrong in PLAN.md
528
+
529
+ Six things, and the first three are sign and scale errors in §6 and §7 that the
530
+ implementation could not have been written around.
531
+
532
+ | # | The design said | The measurement said |
533
+ |---|---|---|
534
+ | 0 | §6 — slack, tether and strain-limit rows clamp to `(−∞, 0]` | Under the solver's own `f -= fc·g` that is the force which pushes a distance row **apart**. A row bounding a distance from *above* needs `[0, +∞)`, and with the table's clamp it never binds at all. §10 |
535
+ | 1 | §3.4 — the leash radius is `slack · d_geo,i` | That makes `slack = 1` a real constraint: a rope hanging straight down cannot swing through 90°, because its tip would move `√2·d_geo`. `2·d_geo` is *provably* inactive given the tether, so the map is `2·slack·d_geo`. §10 |
536
+ | 2 | §7 P1 — the velocity clamp is derived from `thickness` and `h` | `thickness` is a contact radius, so a clamp built from it is a **tunnelling** bound, and a tunnelling bound sits below ordinary cloth speeds: silk at 4 mm gives 0.24 m/s against a measured 29 m/s. The scale that works is the solver's own correction authority. §13 |
537
+ | 3 | §11.1 — "bend rows along each chain" | A chain has no diamond to build a quadratic hinge stencil on. A **skip row** — an ordinary stretch row to the grandparent — costs no new row kind and holds a curved rest shape the quadratic stencil explicitly cannot. §11 |
538
+ | 4 | §17 — the levers each close the 2 ms budget on their own | M1's rows changed the arithmetic. 1,024 particles at 2×4 is **4.61 ms**, not M0's 3.41, and **no single lever reaches 2 ms**. Every garment entry spends two. §14 |
539
+ | 5 | §6 — a strain-limit row governs how far the fabric may extend | It removes about a third of the peak over-stretch at every budget and **never reaches its own allowance** — at `stretch = 1` it asks for 0.1% and delivers 5.9% at 1×1. `ClothDynamics#stretch` is the weakest field in the parameter set. §11 |
540
+ | 6 | §11.1 — the write-back writes `Transform64` | It has to write the **local** `TransformAttachment#transform` too. Writing only the world one leaves the pose one announcement away from being replaced by the authored one, which makes where cloth runs a correctness question; writing both makes a recomposition reproduce it to 1.7e-15 m. §15 |
541
+
542
+ And one thing §4.1 flagged as possibly impossible, which turned out to be
543
+ exactly that: **neither of the engine's two ordering mechanisms can place cloth
544
+ after a poser**, for a structural reason rather than an arithmetic one. What M1
545
+ ships is not a third mechanism — it is a write-back that does not need one. §15.
546
+
547
+ ---
548
+
549
+ ## 10. The leash: tether, slack, and the bound that is not unconditional
550
+
551
+ ### The tether is what makes a low budget viable
552
+
553
+ A 30-link × 3-strand rig at 5 cm, authored horizontally and dropped through
554
+ ninety degrees, `worst max(‖x − p_anchor‖ / d_geo)` over 600 steps:
555
+
556
+ ```
557
+ budget tethered no tether
558
+ 1x1 1.0155 1.4650
559
+ 1x2 1.0039 1.1899
560
+ 2x2 1.0020 1.0568
561
+ 2x4 1.0012 1.0199
562
+ ```
563
+
564
+ That is §7 P2's claim with a number on it. At one iteration per substep the
565
+ untethered rig reaches **half again its own length** — the rubber cape — and the
566
+ tethered one is inside 1.6%. Note the second column at 2×4: four times the
567
+ budget gets the untethered rig to 1.020, which is still worse than one iteration
568
+ *with* tethers. The tether is not a cheaper way to buy convergence; it answers a
569
+ question the per-edge rows cannot, because a per-edge force travels one hop per
570
+ iteration and a long-range row does not travel at all.
571
+
572
+ ### The clamp direction, which §6 has backwards
573
+
574
+ The solver applies `f -= fc·g`, so a **positive** `fc` on a distance row pulls
575
+ its two ends together — that is what `cloth_stretch_row.js` means when it adds
576
+ geometric stiffness for a row "in tension" at `fc > 0`. A row that bounds a
577
+ distance from above must therefore admit positive force and no negative force.
578
+
579
+ §6's table gives Slack, Tether and Strain limit `f_min = −∞, f_max = 0`, which
580
+ admits only the force that pushes the two ends apart. Such a row does not bind
581
+ weakly; it never binds at all, and it would drive a particle *away* from its
582
+ leash centre. The table's collision and self-collision rows are consistent with
583
+ the correct rule once you notice that the collision row writes `C` with the
584
+ opposite sense, so the fix is one column in three rows plus the gloss above it:
585
+ "`[0, +∞)` is push-only, `(−∞, 0]` is pull-only" is only true relative to a
586
+ particular sign of `C`. The exact rule is **`[0, +∞)` admits only forces that
587
+ reduce `C`, and `(−∞, 0]` only forces that increase it.**
588
+
589
+ `cloth_leash_row.spec.js` demonstrates it directly: a particle five metres out
590
+ on a two-metre leash assembles `f = (−30, 0, 0)`, and under §6's clamp that is
591
+ clamped to zero.
592
+
593
+ ### `slack = 1` was a constraint, and should not have been
594
+
595
+ §3.4 sets each particle's leash radius to `slack · d_geo,i`, and says `slack = 1`
596
+ means "a particle may be anywhere within its own reach of its animated
597
+ position". It does mean that, and that is a real bound: a rope hanging straight
598
+ down cannot swing through ninety degrees, because its tip has to move `√2·d_geo`
599
+ to get there and its leash is `d_geo`.
600
+
601
+ The radius at which the row is provably inert is `2·d_geo`, and the proof is two
602
+ lines. The tether already holds every particle within `d_geo` of the anchor; the
603
+ animated position it is leashed to is also within `d_geo` of the anchor, since a
604
+ chord is never longer than the arc it subtends; so by the triangle inequality the
605
+ two are never more than `2·d_geo` apart. `r_i = 2·slack·d_geo,i` therefore makes
606
+ `slack = 1` mean exactly "no leash", with no sentinel value and no
607
+ discontinuity — the row is simply not built, because a row that cannot bind is
608
+ not worth visiting.
609
+
610
+ ### The bound is conditional on the solver's correction authority
611
+
612
+ The trust region caps each vertex update at the shortest row incident on the
613
+ particle (§5.3), so one fixed step can move a particle at most
614
+ `shortest_row · substeps · iterations`. Past that, a bound is not being violated
615
+ so much as not being given a chance to act. The same rig, kicked sideways:
616
+
617
+ ```
618
+ budget kick correction authority worst final
619
+ 1x1 2 m/s 3.0 m/s 1.043 1.0025
620
+ 1x1 6 m/s 3.0 m/s 1.227 1.0025
621
+ 1x1 16 m/s 3.0 m/s 6.867 1.0025
622
+ 2x4 2 m/s 24.0 m/s 1.003 1.0000
623
+ 2x4 6 m/s 24.0 m/s 1.001 1.0000
624
+ 2x4 16 m/s 24.0 m/s 1.063 1.0000
625
+ ```
626
+
627
+ A kick five times the authority reaches **6.9× the cloth's own reach**; the same
628
+ kick against eight times the authority reaches 1.06×. The excursion is transient
629
+ in every case — the final column is the reachable-set guarantee of §7 P4(c)
630
+ holding, error not accumulating — but "no particle is ever further from the
631
+ anchor than `d_geo`" is not true as stated, and §7 P2 should say what it is
632
+ conditional on.
633
+
634
+ This is also where M1's velocity clamp comes from. §13.
635
+
636
+ ---
637
+
638
+ ## 11. The strain limit, and what `stretch` is worth
639
+
640
+ A 24-link rope at 5 cm, authored horizontally and dropped, `worst max(link
641
+ length / rest length)` over 600 steps. "Allowance" is what
642
+ `cloth_strain_allowance(stretch)` asks for:
643
+
644
+ ```
645
+ budget stretch allowance with the row without it
646
+ 1x1 0.2 1.0829 1.0863 1.0922
647
+ 1x1 0.5 1.0158 1.0631 1.0922
648
+ 1x1 1.0 1.0010 1.0586 1.0922
649
+ 2x2 0.2 1.0829 1.0351 1.0351
650
+ 2x2 0.5 1.0158 1.0289 1.0351
651
+ 2x2 1.0 1.0010 1.0216 1.0351
652
+ 2x4 0.2 1.0829 1.0140 1.0140
653
+ 2x4 0.5 1.0158 1.0140 1.0140
654
+ 2x4 1.0 1.0010 1.0094 1.0140
655
+ ```
656
+
657
+ Two readings, and the second is the important one.
658
+
659
+ **The row works**: it removes 34–38% of the peak over-stretch, consistently, at
660
+ every budget. On a chain that costs nothing measurable and it is worth having.
661
+
662
+ **And it does not do what §6 says it does.** At `stretch = 1` it asks for 0.1%
663
+ of strain and delivers 5.9% at 1×1 — a factor of fifty out. The reason is
664
+ structural rather than a tuning failure: a strain-limit row is a *second hard
665
+ row on the same edge with the same gradient*, so it competes for the same trust
666
+ region and the same penalty band as the fabric row it is backing up. It can add
667
+ force in a direction force is already being added in, and nothing more.
668
+
669
+ The consequence for the parameter set is that **`stretch` is a weak control over
670
+ most of its range**. Below about `stretch = 0.35` its allowance is looser than
671
+ what a hard row does unaided and the row is inert — see the 0.2 rows, where
672
+ adding it changes nothing at 2×2 and 2×4. Above it the row helps but cannot
673
+ reach what it was asked for. The library says so by which entries set
674
+ `ClothDynamicsFlags.StrainLimit`: the ones at 2×4, where the residual is already
675
+ around 1%, clear it; the ones at 2×2 and the chains keep it.
676
+
677
+ ---
678
+
679
+ ## 12. Settling, sleep, and the damping gate
680
+
681
+ ### Every library fabric settles and sleeps
682
+
683
+ A 12-link chain at 8 cm, set swinging at 3 m/s, run until the sleep test fires
684
+ (30 consecutive steps with no particle faster than `1e-3 · reach` per second):
685
+
686
+ ```
687
+ SILK 770 steps ROPE 501
688
+ COTTON 438 CHAIN 285
689
+ DENIM 220 HAIR 295
690
+ LEATHER 238
691
+ ```
692
+
693
+ Twelve seconds at the slowest, and the order is the damping order, which is what
694
+ it should be. Sleep stops the step **and the write-back**, which is what makes
695
+ §7 P5's "bit-identical across the following 300 steps" a fact rather than a
696
+ hope: a pose that is not rewritten cannot drift, and one that is rewritten from
697
+ unchanged inputs is only probably identical.
698
+
699
+ ### Damping is load-bearing, and here is the size of it
700
+
701
+ `MEASUREMENTS.md` §6 measured that a **soft** row above about `8·(m/h²)` makes
702
+ the step add energy, and that no solver constant reaches it because `α·γ` decays
703
+ a multiplier and a soft row has none. M1's mapping never produces such a cloth —
704
+ `stretch` maps to `Infinity` precisely because of that measurement — so the row
705
+ stiffness is written in by hand to reproduce it. A 16-link rope at 5 cm with its
706
+ stretch rows forced to 1e5 N/m, a ratio of about 350 against the particle's
707
+ `m/h²` of 288, after 1,500 steps:
708
+
709
+ ```
710
+ damping kinetic energy
711
+ 0 2.90e-03 J the limit cycle
712
+ 0.02 6.18e-05 J
713
+ 0.05 2.39e-05 J
714
+ 0.12 1.28e-06 J the library's own value
715
+ 0.3 7.30e-11 J
716
+ 1 1.82e-12 J
717
+ ```
718
+
719
+ Three orders of magnitude between undamped and the library default, and seven at
720
+ the top of the range. Note what damping does *not* do: it does not stop the step
721
+ adding energy, it removes energy faster than the step adds it. The equilibrium
722
+ is bounded rather than zero, which is why the numbers keep falling all the way
723
+ to `damping = 1` instead of hitting a floor.
724
+
725
+ ---
726
+
727
+ ## 13. Teleport, locomotion, and where the velocity clamp comes from
728
+
729
+ ### Teleport
730
+
731
+ A 16-link rope at 10 cm, swinging on an anchor that has been moving, then
732
+ teleported a kilometre:
733
+
734
+ ```
735
+ mode teleports peak speed first-step local shift tip
736
+ Reset 1 0.000 m/s 1.4890 m (1000.000, −1.600)
737
+ Keep 1 5.582 m/s 0.0779 m (1000.003, −1.600)
738
+ ```
739
+
740
+ `Reset` re-seeds at the animated pose with zero velocity and the stabilisation
741
+ window ramps the velocity limit back from nothing over 20 steps; the peak speed
742
+ of exactly zero is what a rope authored hanging straight down does when it is
743
+ put back exactly there. `Keep` carries the shape across: the first-step shift is
744
+ one step of ordinary motion, against a metre and a half for the reset, and the
745
+ peak of 5.6 m/s is the swing it was already carrying.
746
+
747
+ **`Keep` is free, and that is a property of the frame rather than a
748
+ coincidence.** MagicaCloth2's `Keep` applies the anchor delta rigidly to every
749
+ particle; in a frame anchored to the cloth's own entity the particles are
750
+ already anchor-relative, so "apply the delta" is doing nothing at all. The
751
+ implementation of `ClothFlags.TeleportKeep` is a `return`.
752
+
753
+ ### Fast locomotion
754
+
755
+ 20 links at 10 cm, the anchor running a square wave in velocity — sprint, stop
756
+ dead, sprint back, stop dead, one second a phase, fifteen seconds. "Peak" is the
757
+ fastest particle in the cloth-local frame, which is what the clamp bounds:
758
+
759
+ ```
760
+ entry peak clamp headroom teleports worst tether
761
+ SILK 29.32 m/s 192.0 m/s 6.5x 0 1.0000
762
+ COTTON 13.97 192.0 13.7 0 0.9999
763
+ DENIM 13.29 96.0 7.2 0 1.0035
764
+ LEATHER 16.80 96.0 5.7 0 1.0018
765
+ ROPE 13.11 192.0 14.6 0 1.0004
766
+ CHAIN 11.32 288.0 25.4 0 1.0003
767
+ HAIR 13.19 192.0 14.6 0 0.9996
768
+ ```
769
+
770
+ Nothing teleports — a sprint is locomotion and the threshold knows it — nothing
771
+ leaves its own reach by more than 0.35%, and the smallest headroom over the
772
+ clamp in the whole library is 5.7×.
773
+
774
+ ### Why the clamp is not derived from `thickness`
775
+
776
+ §7 P1 asks for a "per-particle velocity clamp derived from `thickness` and `h`",
777
+ and the table above is why that cannot be M1's clamp. `thickness` is a contact
778
+ radius. A clamp built from it answers "may a swept contact still catch this
779
+ particle", and the answer to that sits *below* ordinary cloth speeds rather than
780
+ above them: silk is 4 mm thick, so at 60 Hz one radius per step is 0.24 m/s
781
+ against the 29.3 m/s the same silk reaches behind a sprinter. Any multiple large
782
+ enough to stop the clamp being a *behaviour* for silk is large enough to be
783
+ meaningless for leather, whose thickness is five times silk's and whose speeds
784
+ are not.
785
+
786
+ The scale that does work is the solver's own **correction authority**,
787
+ `shortest_row · substeps · iterations / dt` — the quantity §10 measured a cloth
788
+ losing its bound past. A clamp at four times it is a bound on the solver being
789
+ asked to do more than it can, it scales with the mesh and the budget rather than
790
+ with a radius nothing reads until M2, and the headroom column above says it is a
791
+ backstop rather than a behaviour. M2 still needs the tunnelling bound; it is a
792
+ different number for a different job and it arrives with the contacts.
793
+
794
+ ### Inertia
795
+
796
+ The same profile, 10 links, measuring how far the tip lags the anchor:
797
+
798
+ ```
799
+ inertia 0 0.0000 m welded into the anchor frame
800
+ inertia 0.25 0.2031 m
801
+ inertia 0.5 0.3681 m
802
+ inertia 0.75 0.5249 m
803
+ inertia 1 0.6522 m feels all of it
804
+ ```
805
+
806
+ Monotone, and zero at zero to the last digit — a cloth that feels none of its
807
+ anchor's motion hangs from a sprinting anchor exactly as it would from a
808
+ stationary one, which is what makes `inertia` a dial rather than a switch with a
809
+ meaningless middle.
810
+
811
+ ---
812
+
813
+ ## 14. The performance budget, again
814
+
815
+ M0 measured the §17 workload at 3.48 ms and priced three levers that each closed
816
+ it. **M1 added rows, and the levers no longer close it.** A 32×32 sheet at 2 cm,
817
+ 2 substeps × 4 iterations, adding M1's rows one at a time to M0's:
818
+
819
+ ```
820
+ rows particles / stretch / bend / leash best
821
+ M0 rows only 1024 2945 2821 0 3.412 ms
822
+ + strain limit 1024 5890 2821 0 4.145 ms
823
+ + tether 1024 5890 2821 992 4.505 ms
824
+ + slack 1024 5890 2821 1984 4.605 ms
825
+ ```
826
+
827
+ The strain limit is the expensive one, at 0.73 ms — it doubles the stretch
828
+ table, and §7 already said the stretch rows are 69% of the frame. The tether is
829
+ 0.36 ms and load-bearing. The slack row is 0.10 ms.
830
+
831
+ Against that, the levers:
832
+
833
+ ```
834
+ config with strain limit without it
835
+ 1024 @ 2x4 4.669 ms OVER 4.146 ms OVER
836
+ 1024 @ 2x2 2.380 OVER 2.106 OVER
837
+ 1024 @ 1x4 2.395 OVER 2.071 OVER
838
+ 1024 @ 1x2 1.167 inside 1.030 inside
839
+ 576 @ 2x2 1.280 inside 1.096 inside
840
+ 484 @ 2x4 2.533 OVER 2.019 OVER
841
+ 484 @ 2x2 1.093 inside 0.909 inside
842
+ 400 @ 2x4 1.721 inside 1.493 inside
843
+ 324 @ 2x4 1.400 inside 1.259 inside
844
+ 256 @ 2x4 1.107 inside 0.959 inside
845
+ ```
846
+
847
+ **No single lever reaches 2 ms.** M0's three — half the iterations, half the
848
+ substeps, half the particles — land at 2.38, 2.40 and 2.53 respectively. Every
849
+ one of them lands *inside* when a second lever is spent with it, and that is what
850
+ the library ships:
851
+
852
+ ```
853
+ entry budget particles / stretch / bend / leash / colours best
854
+ SILK 2x4 400 1121 1045 760 4 1.488 ms
855
+ COTTON 2x4 400 1121 1045 760 4 1.484 ms
856
+ DENIM 2x2 576 3266 1541 1104 4 1.256 ms
857
+ LEATHER 2x2 576 3266 1541 1104 4 1.248 ms
858
+ ROPE 2x4 41 119 0 40 3 0.043 ms
859
+ CHAIN 2x6 41 119 0 40 3 0.064 ms
860
+ HAIR 2x4 400 1121 1045 760 4 1.429 ms
861
+ ```
862
+
863
+ Node v24.15.0 on win32/x64, 600 warm-up frames then 900 measured, 3 rounds, the
864
+ minimum of the minima. The M0 warning still applies and was heeded: each round
865
+ builds a fresh cloth, because a benchmark that reuses a settled one measures a
866
+ converged mesh.
867
+
868
+ Two notes for whoever re-measures at M2. The 3.412 ms in the first table against
869
+ M0's 3.48 for the same workload is the two harnesses agreeing to 2%, which is
870
+ inside M0's own ±5% spread — the row counts and the topology are the same patch.
871
+ And the unreconciled factor-of-five between deletion and isolated-loop
872
+ attribution that §7 records is **not** resolved here; nothing in M1 re-opened it,
873
+ and nothing here should be quoted as having settled it.
874
+
875
+ ---
876
+
877
+ ## 15. System ordering: not expressible, and not needed
878
+
879
+ §4.1 named this as M1's to establish and admitted the honest possibility that it
880
+ needs a mechanism the engine does not have. The first half is true. The second
881
+ half was the wrong conclusion to draw from it.
882
+
883
+ ### Why neither mechanism reaches it
884
+
885
+ The engine orders systems two ways: registration order, and what each system
886
+ declares in `components_used`. `EntityManager#updateExecutionOrder` scores each
887
+ system as a **sum** over the components it references, weighting `Create` above
888
+ `Write` above `Read`, and sorts descending. A score can therefore only be
889
+ *raised* by touching more components or touching them at a higher access level —
890
+ so the only way to sort **later** is to touch strictly less than the system you
891
+ have to follow, and a consumer of a posed hierarchy touches strictly more.
892
+
893
+ Measured, with the real systems and a poser registered *first*:
894
+
895
+ ```
896
+ ClothSystem -> TransformAttachmentSystem -> PoserSystem
897
+ ```
898
+
899
+ Registration order cannot rescue it, because ties break by registration and this
900
+ is not a tie. Declaring less is not honestly available either — cloth reads
901
+ `Cloth` to know which entities it owns, and `ClothExclude` and
902
+ `TransformAttachment` to walk them.
903
+
904
+ ### What the declaration does buy
905
+
906
+ Half of the ordering, and the half that is a real data dependency. Cloth **writes**
907
+ `TransformAttachment#transform` and `TransformAttachmentSystem` **reads** it, so
908
+ writer-before-reader puts cloth first and the attachment system publishes its
909
+ result. That falls out of `components_used` with nothing else asked for, and it
910
+ is the first line of the order above.
911
+
912
+ ### What M1 did about the other half
913
+
914
+ **A first attempt added a third mechanism** — an execution-phase number on
915
+ `System`, sorted ahead of the score, with a `PostPose` value that `ClothSystem`
916
+ declared. It worked, and it was wrong twice over: it put the vocabulary of
917
+ animation and posing into `engine/ecs`, a layer that has none, and it bought an
918
+ ordering the design should not have needed. It is recorded here because the
919
+ reasoning that produced it — "the relation is real, the scheduler cannot express
920
+ it, therefore extend the scheduler" — is exactly the reasoning to be suspicious
921
+ of.
922
+
923
+ What ships instead removes the need. Cloth writes each node's **local**
924
+ `TransformAttachment#transform` alongside its world `Transform64`, so a hierarchy
925
+ recomposition reproduces the simulated pose instead of replacing it with the
926
+ authored one:
927
+
928
+ ```
929
+ a full recomposition after the write-back moves the pose by 1.665e-15 m
930
+ ```
931
+
932
+ (Compared over the matrix. The quaternion can come back **negated** —
933
+ `multiplyTransforms` decomposes the matrix it just wrote, and `q` and `−q` name
934
+ one rotation, so the sign is the decomposition's to choose. Worth knowing before
935
+ writing any bit-identity assertion over a `Transform64`.)
936
+
937
+ With that, where cloth runs is a quality question. Running before the poser means
938
+ reading last step's anchor pose, so the **shape** is one fixed step stale; the
939
+ **position** is not, because the attachment cascade carries the whole subtree
940
+ rigidly with the anchor from cloth's own local transforms. A 16-link, 1.6 m rope,
941
+ worst world-space difference per node between the two orderings:
942
+
943
+ ```
944
+ profile 61 steps 121 steps 240 steps 900 steps
945
+ walk 2.4 m/s 0.046 m 0.032 m 0.050 m 0.049 m
946
+ sprint ±9 m/s 0.149 m 0.131 m 0.349 m 0.142 m
947
+ ```
948
+
949
+ Three per cent of the cloth's own length under ordinary motion, up to a fifth of
950
+ it at the sharpest velocity reversal a square wave produces, and **not
951
+ accumulating** — the same figure after fifteen seconds as after two, because the
952
+ leash and the tether bound the reachable set.
953
+
954
+ **`InverseKinematicsSystem` is the same shape and reaches the same conclusion.**
955
+ It reads world `Transform64`s "the hierarchy has already composed" and writes
956
+ local ones back, which is the arrangement above, and is why its scoring being
957
+ ambiguous matters less than it looks.
958
+
959
+ ---
960
+
961
+ # Cloth — M2 measurements
962
+
963
+ > Written 2026-09-10, against the M2 implementation in `collider/`, the contact
964
+ > and backstop rows in `solver/constraint/`, and `core/geom/3d/shape/sdf/`.
965
+ > Everything above this line is M0's and M1's and is unchanged.
966
+ >
967
+ > Two scripts, both runnable directly under node — the M0 note applies unchanged,
968
+ > and for the same reason:
969
+ >
970
+ > ```
971
+ > node src/engine/physics/cloth/solver/__fixtures__/cloth_m2_measure.mjs
972
+ > node src/engine/physics/cloth/solver/__fixtures__/cloth_m2_band.mjs
973
+ > ```
974
+ >
975
+ > And a third playground page, `playground/collide.html`, which is the packed
976
+ > collider table rather than the ECS: six scenes, a sweep toggle, and the two
977
+ > contact-band sliders live.
978
+
979
+ ---
980
+
981
+ ## 16. What M2 proved wrong in PLAN.md
982
+
983
+ Six things. The first is a sign error in the design that would have been silent,
984
+ and the second is one M2 made itself and then measured its way out of.
985
+
986
+ | # | The design said | The measurement said |
987
+ |---|---|---|
988
+ | 0 | §8.2 — swept collision interpolates "between the previous and current **matrices**" | A component-wise lerp of two rotation matrices is not a rotation. In the rotation plane it scales by `cos(θ/2)`, so the shape it poses **shrinks**: at the half-radian per step `CLOTH_ANCHOR_ROTATION_LIMIT` already calls a spin, a 25 cm collider loses 7.8 mm halfway through every step — *twice* a silk garment's thickness. A rigid pose interpolates as a translation and a quaternion. §19 |
989
+ | 1 | §8.2 — the sweep is what stops a fast collider being missed | Only if the contact **set** is swept too. Discovery evaluates at the end-of-step pose, so a capsule that crossed the cloth *within* the step is nowhere near it by then: at 20 m/s the pass created **zero rows** and the sheet was untouched — not tunnelled through so much as never noticed. Adding the collider's travel to the discovery reach costs one subtraction a record and makes 2 to 40 m/s behave alike. §20 |
990
+ | 2 | §6 — the collision row carries `k_contact` and friction carries `k_friction` | By M0's own rule a stiffness that is not `Infinity` is a **soft** row, and a soft row's whole force is `k·C` with `k` capped at `8·(m/h²)` — 4.6 N at one thickness of penetration, against the 11 to 376 N the hard row actually produced on a sheet arriving at 1 to 8 m/s. Both rows are hard. §18 |
991
+ | 3 | §6 — friction clamps at `±μ·f_n` | That is the *signed-slip* formulation, which needs a tangent basis chosen per contact — and any choice continuous frame to frame is state, which is what §7 P4(a) exists to keep out. Written as the magnitude of the slip the row is `[0, μ·f_n]`, the same physics with no basis. §18 |
992
+ | 4 | §5.4 — contact rows "never enter" `ClothState` and are applied Jacobi-style | A collider contact is **unary** — one particle against a surface fixed for the substep — so it couples no two particles and there is no Gauss-Seidel/Jacobi distinction to make. It accumulates in the vertex update like a leash row. What is true is that it comes and goes, which is a *storage* problem and not an ordering one. §18 |
993
+ | 5 | §5.2 — Chebyshev acceleration is "available and disabled" | Built, measured against the contacts it is gated on, and removed. It does not help at any spectral radius tried, costs 2–5%, and diverges past `ρ = 0.9`. §21 |
994
+
995
+ And one thing that is a property of a configuration rather than of the solver,
996
+ recorded because it looks like a solver failure: **an exactly axis-aligned rope
997
+ pushed by an exactly axis-aligned plane has no lateral degree of freedom to
998
+ buckle into**, and folds into an accordion that is an exact equilibrium. §22.
999
+
1000
+ ---
1001
+
1002
+ ## 17. The contact penalty band, and `β` at last
1003
+
1004
+ M0 chose `k_min = k_max` — no ramp — and said so honestly: the ramp exists for
1005
+ **transient** rows, a contact that should arrive soft rather than shock the mesh
1006
+ on its first frame, and M0 had none. M1 had none either. M2 has them, and this
1007
+ is that measurement.
1008
+
1009
+ A 400-particle sheet, 4 mm thick, dropped flat onto a ground plane at 2 substeps
1010
+ × 4 iterations. Cells are worst penetration in metres over the run / kinetic
1011
+ energy after 240 steps. **Every configuration in the grid settles to a resting
1012
+ penetration of 7.9e-8 m** — the differences below are entirely about the
1013
+ transient.
1014
+
1015
+ ```
1016
+ arriving at 3 m/s
1017
+
1018
+ k_min/k_max β=0e+0 β=1e+2 β=1e+3 β=1e+4 β=1e+5
1019
+ × 0.00781 1.08e-2/7.65e-9 1.08e-2/2.83e-8 1.08e-2/1.54e-8 1.08e-2/6.91e-9 1.08e-2/4.06e-6
1020
+ × 0.03125 1.08e-2/2.04e-8 1.08e-2/1.56e-8 1.08e-2/3.20e-8 1.08e-2/4.85e-8 1.08e-2/6.42e-5
1021
+ × 0.12500 1.08e-2/2.89e-6 1.08e-2/2.92e-6 1.08e-2/3.19e-6 1.08e-2/7.42e-6 1.08e-2/4.85e-4
1022
+ × 0.50000 2.22e-2/9.77e-3 2.26e-2/1.38e-2 2.29e-2/3.36e-2 1.99e-2/2.08e-2 2.03e-2/5.71e-3
1023
+ × 1.00000 1.60e-2/1.11e-2 1.60e-2/1.11e-2 1.60e-2/1.11e-2 1.60e-2/1.11e-2 1.60e-2/1.11e-2
1024
+
1025
+ arriving at 8 m/s
1026
+
1027
+ k_min/k_max β=0e+0 β=1e+2 β=1e+3 β=1e+4 β=1e+5
1028
+ × 0.00781 1.12e-1/2.51e+0 9.51e-2/3.99e-2 8.11e-2/1.09e-1 1.16e-1/2.55e-1 1.14e-1/2.65e-2
1029
+ × 0.03125 1.06e-1/1.95e+0 1.11e-1/2.74e-1 8.55e-2/1.16e-1 8.99e-2/5.01e-1 8.05e-2/6.16e-1
1030
+ × 0.12500 1.22e-1/5.80e-1 1.18e-1/8.35e-2 9.92e-2/2.77e-1 1.28e-1/2.42e-1 1.25e-1/8.04e-2
1031
+ × 0.50000 1.21e-1/2.48e-1 1.19e-1/2.02e-1 1.25e-1/2.29e-1 1.05e-1/2.65e-1 8.47e-2/2.27e-1
1032
+ × 1.00000 9.34e-2/2.76e-1 9.34e-2/2.76e-1 9.34e-2/2.76e-1 9.34e-2/2.76e-1 9.34e-2/2.76e-1
1033
+ ```
1034
+
1035
+ The bottom row is flat across `β` because at `k_min = k_max` the penalty is
1036
+ already at the ceiling and `min(k + β|C|, k_max)` has nothing to do — which is
1037
+ exactly M0's configuration, reproduced here as the control.
1038
+
1039
+ **The floor is what matters, and lower is better.** At `×1` a 3 m/s landing peaks
1040
+ at 18.9 N of contact force and settles at 1.1e-2 J; at `×1/8` it peaks at 0.16 N
1041
+ and settles at 2.9e-6 J, and the *penetration improves* from 1.6 cm to 1.1 cm at
1042
+ the same time. Below about `×1/8` the penetration column stops moving entirely —
1043
+ 1.08e-2 to three figures from `×1/8` down to `×1/128`.
1044
+
1045
+ That flatness is the augmented Lagrangian working as designed and is worth
1046
+ stating plainly: **the penalty only has to be large enough to generate a
1047
+ multiplier**, and the multiplier carries the load. A stiffer floor buys nothing
1048
+ except a harder first frame.
1049
+
1050
+ **`β` earns its place at the fast arrival and nowhere else.** At 3 m/s every
1051
+ value from 0 to 1e4 is indistinguishable. At 8 m/s, `β = 0` leaves the penalty at
1052
+ the floor for the whole impact and the residual energy is 1.95 to 2.51 J against
1053
+ 0.11 to 0.12 J at `β = 1e3`; and `β = 1e5` reaches the ceiling on millimetre
1054
+ violations, giving back most of what the low floor bought — 6.4e-5 J against
1055
+ 3.2e-8 J on the gentle landing.
1056
+
1057
+ **Chosen: `k_min = k_max/32`, `β = 1e3`.** The floor sits in the middle of the
1058
+ flat region with two decades of ramp above it; `β` sits in the middle of the
1059
+ range where the fast arrival is well behaved and the slow one is unaffected.
1060
+
1061
+ ### The other direction a contact arrives from
1062
+
1063
+ The grid above is cloth arriving at a stationary collider. A garment's contacts
1064
+ are mostly the other way round — a bone driven into stationary cloth — and a
1065
+ floor low enough to make a landing gentle could plausibly be a floor a pushed
1066
+ collider gets further through. Measured, on a sphere driven 6 cm into a hanging
1067
+ cape at 1 m/s, beside the same landing:
1068
+
1069
+ ```
1070
+ floor cape: sphere driven in at 1 m/s sheet: landing at 3 m/s
1071
+ worst resting kinetic worst force N kinetic
1072
+ ×1.00000 3.02e-3 3.96e-4 3.59e-2 1.32e-2 1.963 2.11e-3
1073
+ ×0.25000 2.60e-3 2.95e-4 2.44e-2 1.08e-2 0.805 1.41e-4
1074
+ ×0.12500 2.56e-3 3.04e-4 2.56e-2 1.08e-2 0.800 2.67e-5
1075
+ ×0.03125 2.66e-3 2.90e-4 2.25e-2 1.08e-2 0.803 9.99e-7
1076
+ ×0.00781 2.71e-3 3.08e-4 2.36e-2 1.08e-2 0.805 5.35e-8
1077
+
1078
+ and the same cape with the sphere driven in faster:
1079
+
1080
+ floor 1 m/s 3 m/s 8 m/s (worst penetration, m)
1081
+ ×1.00000 3.02e-3 6.54e-3 3.55e-2
1082
+ ×0.12500 2.56e-3 5.53e-3 3.14e-2
1083
+ ×0.03125 2.66e-3 5.69e-3 3.25e-2
1084
+ ```
1085
+
1086
+ They do not disagree. The cape's penetration stays inside its own 4 mm thickness
1087
+ at every floor and at every speed up to 3 m/s, and the lower floors are
1088
+ marginally *better* rather than worse. The choice above holds on both.
1089
+
1090
+ ---
1091
+
1092
+ ## 18. The contact row: hard, and what a soft one could have delivered
1093
+
1094
+ §6's table gives Collision a stiffness `k_contact` and Friction a `k_friction`,
1095
+ and M0's rule makes that literal: **a row is hard exactly when its stiffness is
1096
+ `Infinity`**, so a named stiffness is a statement that both rows are soft
1097
+ penalties.
1098
+
1099
+ A soft row's entire force is `k·C`, and M0 measured the largest `k` a soft row
1100
+ may carry and still dissipate: `8·(m/h²)`. So the most force a soft contact can
1101
+ produce before the cloth is a full thickness inside the collider is
1102
+ `8·(m/h²)·thickness`. Against what the hard row actually had to produce:
1103
+
1104
+ ```
1105
+ a soft row's ceiling at one thickness of penetration: 4.608 N
1106
+
1107
+ arriving at 0.0 m/s: the hard row produced 0.582 N ( 0.13× the ceiling)
1108
+ arriving at 1.0 m/s: 11.063 N ( 2.40×)
1109
+ arriving at 3.0 m/s: 18.908 N ( 4.10×)
1110
+ arriving at 8.0 m/s: 375.655 N (81.52×)
1111
+ ```
1112
+
1113
+ A cloth that is merely *resting* is inside what a soft row could do — 13% of it.
1114
+ Anything that arrives is not. A soft contact row is therefore a contact that
1115
+ holds a draped garment and fails every time the garment is put down, and the
1116
+ failure is proportional to the impact.
1117
+
1118
+ Both rows are hard: `Infinity` stiffness, the penalty band of §17, and the
1119
+ multiplier carrying the load.
1120
+
1121
+ ### Friction against the analytic answer
1122
+
1123
+ Coulomb says a body sticks when `μ > tan θ` and slides when it does not. A 20×20
1124
+ sheet released on an inclined plane, metres travelled downhill in four seconds:
1125
+
1126
+ ```
1127
+ slope tan θ μ=0.0 μ=0.2 μ=0.4 μ=0.7 μ=1.2
1128
+ 10° 0.1763 6.9139 0.0001 0.0000 0.0000 0.0000
1129
+ 20° 0.3640 13.5772 5.6235 0.0001 0.0001 0.0000
1130
+ 30° 0.5774 19.6705 11.7592 5.0431 0.0002 0.0001
1131
+ 40° 0.8391 24.5862 16.9339 10.5951 2.8836 0.0002
1132
+ 50° 1.1918 27.4699 20.5496 14.9029 8.1086 0.0007
1133
+ ```
1134
+
1135
+ The transition sits on `tan θ` in every row: 0.2 sticks at 10° and slides at 20°,
1136
+ 0.4 sticks at 20° and slides at 30°, 0.7 sticks at 30° and slides at 40°, 1.2
1137
+ sticks at 50°. The sticking cells are tenths of a millimetre over four seconds,
1138
+ which is the row holding rather than creeping.
1139
+
1140
+ **The clamp is `[0, μ·f_n]`, not `±μ·f_n`.** §6's symmetric pair is the
1141
+ signed-slip formulation: a row whose `C` is a displacement along a chosen
1142
+ tangent. This row's `C` is the *magnitude* of the slip in the tangent plane, so
1143
+ `C ≥ 0` always and the negative half of the clamp would name a force pulling the
1144
+ particle further from where it stuck. Writing it as a magnitude is also what
1145
+ removes the tangent basis — a signed row needs two of them per contact, and any
1146
+ choice that is continuous frame to frame carries state, which is the thing §7
1147
+ P4(a) exists to keep out of this system.
1148
+
1149
+ **The cap reads the current iteration's normal force, not the previous
1150
+ iteration's multiplier.** VBD uses the multiplier, which is one iteration stale
1151
+ and therefore exactly zero on a contact's first iteration — so at the one
1152
+ iteration per substep §5.1 says the solver must be usable at, friction would
1153
+ never act at all.
1154
+
1155
+ ### Contacts are unary, so §5.4's Jacobi treatment is not needed here
1156
+
1157
+ §5.4 says contact rows "cannot be pre-coloured", are "accumulated into a
1158
+ per-particle scratch buffer and applied Jacobi-style", and that this is what
1159
+ makes a step deterministic regardless of how many contacts a particle picked up.
1160
+
1161
+ Half of that is a solution to a problem a *collider* contact does not have. A
1162
+ contact against a collider touches **one** particle: the collider is fixed for
1163
+ the substep, so the row couples no two particles, so there is no Gauss-Seidel
1164
+ versus Jacobi distinction to make and nothing to keep out of the colouring. It
1165
+ accumulates in the vertex update exactly like a leash row, in colour order, and
1166
+ the step is deterministic because the contact *set* is built by one pass in a
1167
+ fixed order over a fixed table.
1168
+
1169
+ What is true is that a contact comes and goes, so it cannot be a CSR table sized
1170
+ at build time. M2's answer is a fixed **four slots per particle** inside
1171
+ `ClothState`'s own buffer, rebuilt each step, keyed on the collider's index
1172
+ handle so a multiplier survives the rebuild. §5.4's reasoning applies unchanged
1173
+ to M4's particle-particle rows, which really are pairs.
1174
+
1175
+ Four slots is generous. On the 20-collider budget scene, over 100 steps × 1,024
1176
+ particles: **zero particle-steps reached the slot limit**, and the mean occupancy
1177
+ was 0.10 slots per particle. The cost of the generosity is 36 words per particle
1178
+ — 147 KB at 1,024 particles against `ClothState`'s 370 KiB, a 40% increase in
1179
+ state for a structure that was never more than a quarter full. It is kept at four
1180
+ because the case it is sized for is an armpit rather than a sheet on a floor, and
1181
+ M3's garments are where that will be visible.
1182
+
1183
+ ---
1184
+
1185
+ ## 19. The interpolated pose is a rigid pose, not a lerp of matrices
1186
+
1187
+ §8.2 says swept behaviour "comes from interpolating the collider's pose between
1188
+ the previous and current **matrices** at the substep's fraction". That is the one
1189
+ part of §8 that does not work, and the reason is arithmetic rather than taste: a
1190
+ component-wise lerp of two rotation matrices is not a rotation matrix. Halfway
1191
+ through a turn of `θ` its columns are shorter by `cos(θ/2)` in the rotation
1192
+ plane, so the shape it poses is *shrunk*.
1193
+
1194
+ ```
1195
+ θ (rad) |lerp(I,R)·x| shrink on a 25 cm collider vs a 4 mm cloth
1196
+ 0.050 0.999688 0.078 mm 0.02×
1197
+ 0.100 0.998750 0.312 mm 0.08×
1198
+ 0.250 0.992198 1.951 mm 0.49×
1199
+ 0.500 0.968912 7.772 mm 1.94×
1200
+ 1.000 0.877583 30.604 mm 7.65×
1201
+ 1.571 0.707107 73.223 mm 18.31×
1202
+ ```
1203
+
1204
+ `CLOTH_ANCHOR_ROTATION_LIMIT` is half a radian per step, so 0.5 is the fastest
1205
+ rotation a cloth is allowed to see, and the shrink there is already twice a
1206
+ garment's thickness. A collider that shrinks by twice the cloth's thickness
1207
+ halfway through every step is a collider cloth passes through for reasons that
1208
+ have nothing to do with speed.
1209
+
1210
+ A translation and a quaternion interpolate rigidly by construction — the
1211
+ quaternion is renormalised, so its column reads 1.000000 at every angle — and
1212
+ that is what `ClothColliderRecord` stores. The `nlerp` is not constant angular
1213
+ velocity and over the fraction of a fixed step it does not need to be.
1214
+
1215
+ ---
1216
+
1217
+ ## 20. Sweeping the poses is not enough; the *set* has to be swept too
1218
+
1219
+ M2 built §8.2's pose interpolation, measured it against a capsule driven through
1220
+ a hanging sheet, and found it doing nothing at all above 5 m/s. The reason was
1221
+ not the interpolation.
1222
+
1223
+ `cloth_contact_find` runs once per step and evaluates the field at the
1224
+ **end-of-step** pose. A collider that crossed the cloth *within* the step is
1225
+ already past it by then, so the speculative margin — twice the contact offset,
1226
+ 8 mm on a garment — finds nothing, no row is created, and the swept poses have
1227
+ nothing to act through.
1228
+
1229
+ ```
1230
+ speed pose worst penetration deep rows/step
1231
+ 2 m/s swept (§8.2) 1.85e-2 m 0 16.4
1232
+ 2 m/s end-of-step 3.99e-2 m 4 7.2
1233
+ 5 m/s swept (§8.2) 3.38e-2 m 1 14.5
1234
+ 5 m/s end-of-step 0.00e+0 m 0 1.4
1235
+ 10 m/s swept (§8.2) 3.08e-4 m 0 31.3
1236
+ 10 m/s end-of-step 0.00e+0 m 0 1.4
1237
+ 20 m/s swept (§8.2) 0.00e+0 m 0 94.8
1238
+ 20 m/s end-of-step 0.00e+0 m 0 0.0
1239
+ 40 m/s swept (§8.2) 0.00e+0 m 0 160.0
1240
+ 40 m/s end-of-step 0.00e+0 m 0 0.0
1241
+ ```
1242
+
1243
+ Read the last column first. "end-of-step" — the previous pose set equal to the
1244
+ current one, which is what §8.2 would be without the sweep — creates **no rows at
1245
+ all** at 20 and 40 m/s. Its zero penetration is not a contact working; it is a
1246
+ capsule passing through a sheet that never knew it was there. "deep" counts
1247
+ particle-steps more than half a capsule radius inside, and the swept column holds
1248
+ it at zero or one across the whole range.
1249
+
1250
+ The fix is one subtraction per record per step: **the discovery reach includes
1251
+ how far the collider moved.** A particle within `offset·(1 + margin) + travel` of
1252
+ the end-of-step surface gets a row, which stays clamped out until a substep's
1253
+ interpolated pose actually brings the collider onto it.
1254
+
1255
+ That is also the honest boundary of P3. The *set* is swept by this margin and the
1256
+ *poses* by `cloth_collider_pose_at`, and both are translation-first: a collider
1257
+ spinning fast enough that a point on its surface travels more than its own radius
1258
+ within one substep is still missed, and more substeps is the answer to it.
1259
+
1260
+ ---
1261
+
1262
+ ## 21. Chebyshev acceleration: built, measured, removed
1263
+
1264
+ §5.2 carries Chebyshev acceleration as "available and disabled by default, turned
1265
+ on per-dynamics only where it measurably helps", gated on a particle not being in
1266
+ contact this step — which is why M0 and M1 could not evaluate it and M2 is the
1267
+ first milestone that can.
1268
+
1269
+ Implemented as the paper specifies: `ω₁ = 1`, `ω₂ = 2/(2−ρ²)`, `ωₙ = 4/(4−ρ²ωₙ₋₁)`,
1270
+ applied as `x ← ω(x − x^(k−1)) + x^(k−1)` after each colour sweep, skipping every
1271
+ particle with a contact slot.
1272
+
1273
+ ```
1274
+ a 400-particle sheet landing at 3 m/s
1275
+
1276
+ ρ worst pen. resting pen. kinetic@240 ms/step
1277
+ 0.00 1.60e-2 7.90e-8 1.11e-2 3.604
1278
+ 0.50 1.42e-2 7.90e-8 1.67e-2 3.773
1279
+ 0.80 1.70e-2 7.90e-8 1.50e-2 3.682
1280
+ 0.90 7.72e-2 4.71e-2 7.60e+1 3.345
1281
+ 0.95 4.05e+10 3.66e+10 3.87e+26 3.588
1282
+ 0.99 diverged — a Hessian pivot reached Infinity
1283
+
1284
+ a hanging cape with a sphere pushed 6 cm into it, where most particles
1285
+ are free and the acceleration has room:
1286
+
1287
+ ρ=0.00 worst 5.78e-4 resting 3.00e-4 kinetic 4.70e-4
1288
+ ρ=0.80 worst 3.31e-4 resting 3.10e-4 kinetic 4.90e-3
1289
+ ρ=0.95 worst 3.06e-3 resting 0.00e+0 kinetic 1.68e+46
1290
+ ```
1291
+
1292
+ The best cell in the table is the cape at `ρ = 0.8`, which takes a third off the
1293
+ penetration and pays ten times the residual kinetic energy for it — a livelier
1294
+ cloth, not a better-converged one. Everything else is inside the run-to-run
1295
+ spread or worse, the cost is 2–5%, and the top of the parameter range detonates.
1296
+
1297
+ Removed. The grid is here so that a future attempt starts from the numbers rather
1298
+ than from the idea, and `cloth_step.js` says where the branch was.
1299
+
1300
+ ---
1301
+
1302
+ ## 22. A rope with no lateral freedom stands on its own end
1303
+
1304
+ Not a solver defect, and recorded because it looks exactly like one.
1305
+
1306
+ A rope authored exactly along −Y, compressed by a floor whose normal is exactly
1307
+ +Y, has every force, every constraint gradient and every position on one axis.
1308
+ There is no lateral component anywhere in the system, so the accordion fold it
1309
+ lands in is an **exact equilibrium**: every link is at its rest length, the
1310
+ residual is zero, and nothing — including §7 P4(d)'s escape hatch, which watches
1311
+ the residual — has anything to act on.
1312
+
1313
+ An 8-link rope of 10 cm links, hanging from the origin onto a floor at −0.4:
1314
+
1315
+ ```
1316
+ lean tip y after 200 steps what it did
1317
+ 0 −0.201 folded, and stayed folded
1318
+ 0.001 −0.385 lay down, one thickness clear of the floor
1319
+ 0.01 −0.385 the same
1320
+ ```
1321
+
1322
+ `lean` is a lateral offset per link as a fraction of the link length, so 0.001 is
1323
+ a millimetre across a 10 cm link. **One part in a thousand is enough**, and no
1324
+ authored scene is closer to symmetric than that. The tip of the leaning rope
1325
+ lands at −0.385 against a floor at −0.4 and a `CLOTH_ROPE` thickness of 15 mm,
1326
+ which is the contact row holding it exactly one offset clear.
1327
+
1328
+ Recorded rather than fixed. The fix would be a lateral perturbation injected by
1329
+ the solver, which is noise added to a system whose whole design commitment is
1330
+ that it does not need any.
1331
+
1332
+ ---
1333
+
1334
+ ## 23. The frame budget with contacts in it
1335
+
1336
+ M1 measured the §17 workload — 1,024 particles at 2 substeps × 4 iterations on a
1337
+ 32×32 patch — at 4.61 ms and re-sized the library around it. M2 adds a broadphase
1338
+ pass per particle per step, up to four contact rows per particle, and two field
1339
+ evaluations per contact per iteration.
1340
+
1341
+ ```
1342
+ no collider system 4.426 ms 0 contact rows
1343
+ 1 collider, out of range 4.473 ms + 1.1% 0 contact rows
1344
+ 1 collider, touching 5.485 ms + 23.9% 4 contact rows
1345
+ 4 colliders, touching 5.077 ms + 14.7% 41 contact rows
1346
+ 8 colliders, touching 4.610 ms + 4.2% 72 contact rows
1347
+ 20 colliders, touching 4.829 ms + 9.1% 107 contact rows
1348
+ ```
1349
+
1350
+ **Read the range, not the rows.** The column is not monotone in the collider
1351
+ count — one collider costs more than eight — because the variants sit in
1352
+ different physical states, which is the same warning §7 gave about attributing
1353
+ cost by deletion. A cloth draped over a sphere is not the same workload as one
1354
+ hanging free, whatever the row count says.
1355
+
1356
+ What the table does license: **the collision layer costs between nothing and a
1357
+ quarter of a frame, and does not scale with the collider count over the range a
1358
+ character occupies.** The broadphase — a particle against a collider's swept AABB
1359
+ — is the part that does scale, and one collider out of range costs 1.1%, so
1360
+ twenty of them out of range would be about a fifth of a frame and worth a
1361
+ per-cloth spatial structure if a scene ever wants that many.
1362
+
1363
+ **The library is not re-sized.** M1's entries were chosen against 4.61 ms for the
1364
+ §17 workload and M2 measures 4.43 ms for the same thing — agreement to 4%, inside
1365
+ M1's own ±5% spread — and the worst contact case lands at 5.49 ms, which is 19%
1366
+ over M1's figure on a workload the library already spends two levers to avoid.
1367
+ Every entry's own budget is unchanged; §17's table stands. M4's self-collision is
1368
+ the next thing that could move it, and §17 already says so.
1369
+
1370
+ ---
1371
+
1372
+ # Cloth — M3 measurements
1373
+
1374
+ > Written 2026-09-10, against the M3 implementation in `build/` and the rig path
1375
+ > in `ecs/`. Everything above this line is M0's, M1's and M2's and is unchanged.
1376
+ >
1377
+ > Two scripts, both runnable directly under node — the M0 note applies unchanged:
1378
+ >
1379
+ > ```
1380
+ > node src/engine/physics/cloth/ecs/__fixtures__/cloth_m3_measure.mjs
1381
+ > node src/engine/physics/cloth/build/__fixtures__/cloth_m3_joint_budget.mjs
1382
+ > ```
1383
+ >
1384
+ > And a fourth playground page, `playground/garment.html`, which is a `Node3D`
1385
+ > skeleton with a `Skin` over it and a garment built out of some of its joints.
1386
+
1387
+ ---
1388
+
1389
+ ## 24. What M3 proved wrong in PLAN.md
1390
+
1391
+ Four things, and the first is the one the whole rig path turns on.
1392
+
1393
+ | # | The design said | The measurement said |
1394
+ |---|---|---|
1395
+ | 0 | §11.2 — the writable handle is "the joint's `Node3D.transform_local` — **the same handle the animation systems write**" | The animation systems do not write it. `TransformAuthority` is explicit: a node a clip drives is `GPU`, and "the CPU allocates and seeds the row, then never writes to it again, so the node's own `transform_local` stops describing it and should not be read as if it did". Cloth writing it on such a node writes to something nothing reads. The seed **claims `CPU`** on every joint it drives, which takes those joints away from the animation — the right trade for a cape, and an authoring error for a garment whose joints are also keyed. §25 |
1396
+ | 1 | §11.1 — the rig path is "where the animated pose comes from the skeleton and **is live**" | Not for a rigged garment, and for the reason above: cloth owns those joints, so nothing else poses them, so their authored pose is the proxy's baked bind pose — constant in the anchor's frame, exactly as a rope's is. What moves is the anchor. The live case is the *unrigged* path, where the targets are mesh vertices skinned to the character's skeleton. §25 |
1397
+ | 2 | §11.3 step 5 — the fixed set comes from skin weights | That is the right rule for the unrigged path, where the particles are mesh vertices and there is no joint tree. For a rigged garment the **topology** is the answer: a joint whose parent is outside the named set is a joint the garment hangs from, and they all have to hang from the same bone. No weights are read. §25 |
1398
+ | 3 | §11.2's table — "output joints, order of magnitude, skirt: ~60" | For a 64 cm cape driven by a gust, 60 joints leaves a worst-case reconstruction error of about 5% of the garment's own size — five grid cells. RMS error goes as **1/joints** and the worst as **N^−0.83**; getting the worst inside a garment's own thickness needs about a thousand. §28 |
1399
+
1400
+ And one finding that is not a correction but is the thing an author will hit
1401
+ first: **a garment authored inside its own body collider reads as a tether
1402
+ failure.** §29.
1403
+
1404
+ ---
1405
+
1406
+ ## 25. The two paths are the same solver, and the number is zero
1407
+
1408
+ §11 claims the entity path and the rig path are "the solver, identical either
1409
+ way; only seeding and write-back differ". That is a claim about trajectories and
1410
+ it is checkable: build the same garment twice — five strips of seven links under
1411
+ one anchor, once as an entity subtree and once as the joints of a `Skin` —
1412
+ drive both the same way, and compare the particles in the cloth's own frame.
1413
+
1414
+ ```
1415
+ fabric motion worst disagreement as a fraction of the shortest link
1416
+ SILK still 0.00e+0 m 0.00e+0
1417
+ SILK walk 0.00e+0 m 0.00e+0
1418
+ SILK sprint 0.00e+0 m 0.00e+0
1419
+ DENIM still 0.00e+0 m 0.00e+0
1420
+ DENIM walk 0.00e+0 m 0.00e+0
1421
+ DENIM sprint 0.00e+0 m 0.00e+0
1422
+ CHAIN still 0.00e+0 m 0.00e+0
1423
+ CHAIN walk 0.00e+0 m 0.00e+0
1424
+ CHAIN sprint 0.00e+0 m 0.00e+0
1425
+ ```
1426
+
1427
+ **Bit-identical**, across three fabrics and three motion profiles, after 600
1428
+ steps. Not "agreeing to rounding" — the same bits.
1429
+
1430
+ That is not luck and it is worth saying why, because it is the shape the code was
1431
+ given to make it true. M3 moved the row builder out of `cloth_seed_subtree.js`
1432
+ into `cloth_build_rows.js`, and the two seeders' *entire* job is to produce a
1433
+ `node_parent` array and an `animated_position` array. Everything after that —
1434
+ geodesics, link rows, strain limits, skip rows, leashes, the colouring, the
1435
+ `ClothState` — is one function called by both. A second copy for the rig path
1436
+ would have made §11's claim true of the solver and false of everything above it,
1437
+ and this table is what that would have cost.
1438
+
1439
+ The write-back is the same story one level up: `cloth_reconstruct_pose.js` turns
1440
+ particles into a pose and stops, and the two writers put that pose onto an
1441
+ entity's `Transform64` + `TransformAttachment` or onto a `Node3D`.
1442
+
1443
+ ### Cloth takes the joints, and that is the design rather than a side effect
1444
+
1445
+ §11.2 says the writable handle is `Node3D.transform_local`, "the same handle the
1446
+ animation systems write". They do not. `TransformAuthority`'s own docblock is
1447
+ unambiguous:
1448
+
1449
+ > The GPU owns the TRS — animation clips, effects, anything writing through the
1450
+ > pose accumulator. The CPU allocates and seeds the row, then never writes to it
1451
+ > again, so the node's own `transform_local` stops describing it and should not
1452
+ > be read as if it did.
1453
+
1454
+ And `instantiate_scene_bundle` stamps `TransformAuthority.GPU` on every node a
1455
+ clip channel targets. So a cape joint that an artist keyed — even with a
1456
+ placeholder curve — is a joint whose `transform_local` nothing reads, and cloth
1457
+ writing it would be writing into a field that stopped being the truth.
1458
+
1459
+ `cloth_seed_rig` therefore **claims `TransformAuthority.CPU`** on every joint it
1460
+ drives. The consequence is stated rather than hidden: those joints stop being
1461
+ animatable by a clip, because two writers of one row is the race the enum exists
1462
+ to prevent. For a cape that is the point of simulating it. For a garment whose
1463
+ joints are also keyed it is an authoring error, and the claim is where it
1464
+ surfaces.
1465
+
1466
+ ### The anchor's pose is computed, never read back
1467
+
1468
+ A joint of an animated skeleton has no CPU-side `transform_global` — nothing
1469
+ maintains it — so the rig path evaluates the anchor's world pose with
1470
+ `pose_evaluate_world` over the clips the entity is playing. That is the engine's
1471
+ own sanctioned answer to "where is this bone", the one
1472
+ `query_entity_node_world_pose` gives gameplay, and using it means a cape and a
1473
+ scabbard on the same shoulder are placed by the same evaluator off the same
1474
+ clock. M3 lifted `collect_entity_playbacks` out of that query so both callers
1475
+ gather the same playbacks rather than two lists that could disagree.
1476
+
1477
+ ---
1478
+
1479
+ ## 26. The tether on a fanned garment
1480
+
1481
+ Worst `max(|x − anchor| / d_geo)` over 600 steps, both paths, five strips of
1482
+ seven.
1483
+
1484
+ ```
1485
+ fabric motion entity path rig path
1486
+ SILK still 1.0005 1.0005
1487
+ SILK walk 1.0027 1.0027
1488
+ SILK sprint 1.1254 1.1254
1489
+ DENIM still 1.0026 1.0026
1490
+ DENIM walk 1.0019 1.0019
1491
+ DENIM sprint 1.4561 1.4561
1492
+ CHAIN still 1.0002 1.0002
1493
+ CHAIN walk 1.0029 1.0029
1494
+ CHAIN sprint 1.1738 1.1738
1495
+ ```
1496
+
1497
+ Resting and walking are inside 0.3%, which is M1's own figure. **Sprinting is
1498
+ not**, and denim reaches 1.46.
1499
+
1500
+ The two columns being identical is the point: this is not the rig path failing,
1501
+ it is §7 P2's conditional bound showing on a shape M1 did not measure. M1's
1502
+ profile drove a **20-link rope of uniform 10 cm links with a 2 m reach**, and a
1503
+ ±9 m/s square wave moves the anchor 15 cm a step — 7% of that reach. The garment
1504
+ here has a 0.68 m reach, so the same 15 cm is 22% of it, and it is a *fan*: five
1505
+ strips whose first links are nearly horizontal, so a sideways reversal loads them
1506
+ across rather than along.
1507
+
1508
+ Denim is worst because it is the entry that spends its levers on particles rather
1509
+ than on iterations: 2×2 against silk's 2×4, so half the correction authority for
1510
+ the same displacement. That is the library's own trade, priced.
1511
+
1512
+ The excursion is transient in every case and nothing teleports. What it says is
1513
+ that §7 P2's "no particle is ever further from the anchor than `d_geo`" needs its
1514
+ conditional read as a statement about **the anchor's displacement against the
1515
+ garment's reach**, not only against the shortest row: a short, wide garment on a
1516
+ fast anchor is the case that finds it.
1517
+
1518
+ ---
1519
+
1520
+ ## 27. What the rig path costs
1521
+
1522
+ The same garment, the same steps, the same fabric, best of three rounds.
1523
+
1524
+ ```
1525
+ garment entity path rig path difference
1526
+ 5 strips × 7 (35 joints) 0.0988 ms 0.1034 ms +4.6%
1527
+ 3 strips × 9 (27 joints) 0.0861 ms 0.0883 ms +2.5%
1528
+ 12 strips × 10 (120) 0.3082 ms 0.3183 ms +3.2%
1529
+ ```
1530
+
1531
+ Two to five per cent, which is the CPU pose evaluation of the anchor joint plus a
1532
+ `Node3D` write-back in place of a `Transform64` one. The anchor evaluation is a
1533
+ walk up the joint chain per cloth per step and does not scale with the garment,
1534
+ which is why the largest garment shows the smallest relative difference.
1535
+
1536
+ For scale against §17's budget: 120 joints is 0.32 ms, and a garment's joint
1537
+ count is a *proxy* rather than a simulation resolution — the whole point of §11.2's
1538
+ three tiers is that a 5,000-vertex render mesh rides 120 joints. Nothing in the
1539
+ library needs re-sizing.
1540
+
1541
+ ---
1542
+
1543
+ ## 28. How many joints a drape takes — §18's open question
1544
+
1545
+ §18 carries the unrigged path's joint budget as open, with the mitigation that
1546
+ **M3 measures the fidelity curve before fixing a budget**. The unrigged runtime
1547
+ path is not in M3; this is the experiment that says what it would cost.
1548
+
1549
+ A 33×33 cape at 2 cm — 1,089 particles, 64 cm square, pinned along its top edge
1550
+ and driven by a gust — is simulated at full resolution and is the reference. A
1551
+ `k × k` grid of those particles is nominated as joints; every particle is bound
1552
+ to the four nearest of them in the mesh's own parameter space with
1553
+ inverse-distance weights, which is exactly what a four-weight palette does; and
1554
+ the garment is reconstructed each frame by linear blend skinning from the joints'
1555
+ fitted frames.
1556
+
1557
+ ```
1558
+ joints RMS error worst as % of the garment degenerate frames
1559
+ 4 6.13e-2 m 1.92e-1 m 29.93% 0
1560
+ 9 2.14e-2 m 1.22e-1 m 19.13% 0
1561
+ 16 1.19e-2 m 7.51e-2 m 11.73% 0
1562
+ 25 8.01e-3 m 6.81e-2 m 10.65% 0
1563
+ 36 5.92e-3 m 5.10e-2 m 7.97% 0
1564
+ 49 4.44e-3 m 3.97e-2 m 6.21% 0
1565
+ 81 2.77e-3 m 2.36e-2 m 3.69% 0
1566
+ 121 2.04e-3 m 1.90e-2 m 2.97% 0
1567
+ 289 9.35e-4 m 5.60e-3 m 0.88% 0
1568
+ ```
1569
+
1570
+ **RMS error is inversely proportional to the joint count** — `RMS × joints` is
1571
+ 0.245 at 4 joints and 0.270 at 289, flat across a factor of 72 — and the worst
1572
+ case falls more slowly, as about `N^−0.83`.
1573
+
1574
+ That gives the budget its shape. §11.2's table guesses "~60 output joints" for a
1575
+ skirt; at 60 the worst-case error on this cape is about 5% of its own size, which
1576
+ is five grid cells and reads as faceting. Putting the worst inside **one grid
1577
+ cell** takes about 120 joints; inside the garment's own 4 mm thickness takes
1578
+ about a thousand, which is not a budget, it is the simulation resolution again.
1579
+
1580
+ So the honest statement for a future unrigged path is: **80 to 120 joints for a
1581
+ cape of this size, and the four-weight palette is what sets that** — the error at
1582
+ 289 joints is still 0.88%, and it is not the frames that are losing it.
1583
+
1584
+ ### The frames did not degenerate, and that is measured rather than argued
1585
+
1586
+ §18's second open risk is that "a fold that collapses a triangle fan has no
1587
+ well-defined frame". The run counts a frame as degenerate when either fitted
1588
+ tangent falls below 1e-4 m. **Across 800 frames × up to 121 joints, in the table
1589
+ above and in a deliberately crumpled variant — bending at 1e-7 and a gust four
1590
+ times as hard — the count is zero:**
1591
+
1592
+ ```
1593
+ joints RMS error worst as % of the garment degenerate frames
1594
+ 16 3.69e-2 m 1.52e-1 m 23.82% 0
1595
+ 36 1.94e-2 m 8.97e-2 m 14.01% 0
1596
+ 81 1.05e-2 m 5.12e-2 m 8.00% 0
1597
+ 121 8.17e-3 m 4.86e-2 m 7.60% 0
1598
+ ```
1599
+
1600
+ The mechanism is worth stating, because it is why it did not happen rather than a
1601
+ promise that it cannot. A tangent is a difference across **two links**, and the
1602
+ stretch rows are hard, so each of those links holds its length; the only way the
1603
+ difference vanishes is a fold of exactly 180° at the joint's own vertex, which is
1604
+ a measure-zero configuration the bend rows are actively pushing away from. It is
1605
+ *possible* — hard rows do not forbid it — and a future unrigged path should keep
1606
+ the epsilon and the fallback rather than delete them on the strength of a zero.
1607
+
1608
+ What the crumpled variant does show is that the error roughly triples: a garment
1609
+ with no bending resistance needs about three times the joints for the same
1610
+ fidelity, which is the other half of the budget question and says that the number
1611
+ is per-fabric rather than per-garment.
1612
+
1613
+ ---
1614
+
1615
+ ## 29. A garment authored inside its own body reads as a tether failure
1616
+
1617
+ Not a correction, and the first thing an author will hit.
1618
+
1619
+ The M3 playground's first cape was authored 9 cm behind the chest, and the
1620
+ character's torso collider was a capsule of 16 cm radius on the spine — so the
1621
+ garment's first links started **inside the body**. What that looks like is not a
1622
+ garment stuck in a torso. It looks like this:
1623
+
1624
+ ```
1625
+ worst |x − anchor| / d_geo, a cape at rest, no motion at all
1626
+
1627
+ with the body colliders 1.3117
1628
+ without them 1.0000
1629
+ ```
1630
+
1631
+ The contact row pushes the first links out of the collider, the tether row pulls
1632
+ them back, the contact wins — measured at 363 N of multiplier on a link holding
1633
+ a 0.12 kg strip — and the readout says the tether is failing by 31%. It is not.
1634
+ Both rows are doing exactly what they are for, and the configuration is one
1635
+ neither of them should ever have been given.
1636
+
1637
+ §11.3's step 10 is the answer and it says so: the build validates "that the
1638
+ skinned bind pose is collision-free against the character's `ClothCollider` set",
1639
+ and fails loudly with the offending vertex and collider named. **M3 does not
1640
+ build that check** — `cloth_proxy_from_joints` has a joint tree and no collider
1641
+ set — and this measurement is the argument for it being the next thing the build
1642
+ gains rather than a nicety. Moving the garment 21 cm back and shrinking the torso
1643
+ capsule to 13 cm returns the resting figure to 1.0022.
1644
+
1645
+ ---
1646
+
1647
+ # Cloth — M4 measurements
1648
+
1649
+ > Written 2026-09-11, against the M4 implementation in `solver/` and the grid in
1650
+ > `core/geom/3d/hash-grid/`. Everything above this line is M0's, M1's, M2's and
1651
+ > M3's and is unchanged.
1652
+ >
1653
+ > Two scripts, both runnable directly under node — the M0 note applies unchanged:
1654
+ >
1655
+ > ```
1656
+ > node src/engine/physics/cloth/solver/__fixtures__/cloth_m4_measure.mjs
1657
+ > node src/engine/physics/cloth/ecs/__fixtures__/cloth_library_bench.mjs
1658
+ > ```
1659
+ >
1660
+ > The second is M1's, extended here with the section that prices self-collision
1661
+ > against each entry's own size and budget.
1662
+ >
1663
+ > **A folding sheet is chaotic**, and one run of one gust says nothing about a
1664
+ > parameter. Every folding measurement below is the mean over **twelve gust
1665
+ > realisations** — the same sheet, the same everything, twelve phases and rates
1666
+ > of the driving gust. The first version of §32 ran one realisation per row, and
1667
+ > at one the noise was larger than the effect and pointed at a different answer.
1668
+
1669
+ ---
1670
+
1671
+ ## 30. What M4 proved wrong in PLAN.md
1672
+
1673
+ Four things, and the first is the one the whole tier turns on.
1674
+
1675
+ | # | The design said | The measurement said |
1676
+ |---|---|---|
1677
+ | 0 | §9 — pairs closer than `r_i + r_j` get the unilateral row from §6, whose `r` reads as the same `ClothDynamics#thickness` a collider contact uses | Not at a garment's real proportions. A fabric is 4 to 20 mm thick and a proxy's particles are 2 to 8 cm apart, so the two layers of a fold are almost never within a fabric thickness of each other. At the fabric's own 6 mm the row removes **21%** of a folding sheet's self-intersections; at half the shortest row — a diameter of one particle spacing — it removes **82%**. The radius is a property of *the proxy*, not of the cloth it stands for. §31 |
1678
+ | 1 | §14.2 — a 3D uniform hash grid "modelled on `core/geom/2d/hash-grid/SpatialHashGrid.js`" | The 2D grid is a **persistent, incremental** structure: a bounded array of cells, elements that are AABBs and carry identity, and insert/remove/move as the primitive operations. Cloth's grid is none of those. Its elements are points with no identity across steps, its domain is unbounded, and every particle moves every step — so the operation that matters is *rebuild*, and insert/remove never runs at all. `PointHashGrid3` is a counting sort into a power-of-two hash and shares no structure with the 2D grid. The rebuild is 10% to 12% of the step it sits in front of, and most of everything self-collision costs. §34 |
1679
+ | 2 | §9 — the flag is "set on the library entries that need it (skirts, long coats, hair) and clear on the ones that do not (capes, ponytails, banners)" | That list is drawn along the wrong axis. What decides is not what the garment *is* but how far the fabric bends: the floppier the fabric the more it passes through itself. Silk, hair and cotton tangle 8 to 11 times a sample and the row removes 71% to 81%; leather tangles 0.18 times and the row makes it *worse*. §33 |
1680
+ | 3 | §9 — "Both tiers derive their normals from the proxy's surface orientation, per P4(a)" | M4a's normal is the line between the two particles, because a particle pair has no surface in it. What P4(a) actually asks for — nothing history-dependent, no "which side was this on last frame" to latch onto — the pair normal satisfies completely and more simply: recomputed every iteration from the current positions, with no multiplier, no warm start and no identity across steps. The sentence is right about M4b, where a point-triangle stencil genuinely needs an orientation to choose a side. |
1681
+
1682
+ **And two findings with no line in PLAN.md to correct**, because §9 never wrote a
1683
+ radius down at all. `max(thickness, shortest_row/2)` has an upper end and leather
1684
+ is on it (§36) — and that upper end has to be *measured* rather than reasoned
1685
+ from a sheet's topology, because the geometry M3 ships is not a sheet (§37).
1686
+
1687
+ Two things the implementation **confirmed** rather than corrected, both of them
1688
+ places where an earlier milestone wrote down what M4 would find:
1689
+
1690
+ - **§5.4's Jacobi paragraph.** M2 measured that a *collider* contact is unary
1691
+ and needs none of it, and left the paragraph standing "for M4's rows, which
1692
+ really are pairs". They are, and it does. `cloth_self_row.js` accumulates the
1693
+ pair list into a per-particle `(f, H)` scratch once per iteration and every
1694
+ vertex update adds its own entry, which is what keeps the step independent of
1695
+ the order the colours were swept in.
1696
+ - **§9's "it prevents the great majority of visible interpenetration".** 82% of
1697
+ it, at the radius §31 settles on. The tier's stated limit — cloth passing
1698
+ *between* particles — is real and is what the other 18% is: §35 went looking
1699
+ for a cheaper explanation, a pair search running one step behind the solver,
1700
+ and ruled it out.
1701
+
1702
+ ---
1703
+
1704
+ ## 31. The radius is the proxy's resolution, not the fabric's thickness
1705
+
1706
+ §6 writes the row as `‖x_i − x_j‖ − (r_i + r_j)` and §9 says the pairs that get
1707
+ one are those "closer than `r_i + r_j`". Both read naturally as the same `r` a
1708
+ collider contact uses, which is `ClothDynamics#thickness` — how thick the fabric
1709
+ is. M4 was built that way and it barely worked: on a folding garment the pair
1710
+ list held **1.6 to 3.7 pairs a step across the whole cloth**, and no stiffness
1711
+ made the sheet stop passing through itself.
1712
+
1713
+ The arithmetic is not subtle once it is written down. A fabric is 4 to 20 mm
1714
+ thick. A proxy's particles are 2 to 8 cm apart. Two layers of a fold are within
1715
+ a *fabric thickness* of each other only when their particles happen to line up,
1716
+ and nothing makes them line up.
1717
+
1718
+ A 12×12 sheet at 2 cm spacing, 6 mm thick, driven into a fold. Only the radius
1719
+ moves; the stiffness, the gust and the mesh are held fixed. "Crossings" counts
1720
+ edges passing through triangles they share no vertex with — §17's own metric —
1721
+ sampled every twentieth step and averaged over twelve gust realisations. The
1722
+ same sheet with no row at all sits at **11.39**.
1723
+
1724
+ ```
1725
+ radius diameter pairs/step crossings: mean / worst overlap mean
1726
+
1727
+ 3 mm 6 mm 0.5 10.60 / 156 5.2 mm
1728
+ 6 mm 12 mm 2.6 9.00 / 190 10.7 mm <- the fabric thickness
1729
+ 8 mm 16 mm 3.9 5.33 / 86 14.4 mm
1730
+ 10 mm 20 mm 4.8 2.03 / 71 18.4 mm <- half the shortest row
1731
+ 12 mm 24 mm 5.5 0.91 / 64 20.1 mm
1732
+ 16 mm 32 mm 8.2 0.02 / 5 24.8 mm
1733
+ ```
1734
+
1735
+ At the fabric's own thickness the row removes 21% of the crossings. At half the
1736
+ shortest row — a diameter of exactly one particle spacing — it removes 82%. The
1737
+ radius is a property of **the proxy**, and `ClothState#self_radius` is a separate
1738
+ field from `contact_radius` for that reason: a collider contact really is about
1739
+ how thick the cloth is, and this is not.
1740
+
1741
+ `ClothSystem` writes `max(thickness, shortest_row / 2)`, under a ceiling §36 and
1742
+ §37 derive. The `max` is not decoration: a heavy fabric on a coarse proxy — 2 cm
1743
+ of leather on 3 cm particles — is the one case where the fabric is the longer of
1744
+ the two lengths, and there the thickness is right.
1745
+
1746
+ ### The column does not turn over, and the reason to stop is not in it
1747
+
1748
+ 12 mm is better than 10, and 16 mm — a diameter of 1.6 particle spacings — very
1749
+ nearly eliminates crossings. §36 carries the sweep further and it keeps
1750
+ improving right up to a cliff at two spacings that has nothing to do with
1751
+ crossings at all.
1752
+
1753
+ **So the shipped value is not the minimum of this table, and it would be
1754
+ dishonest to present it as one.** Half the shortest row is a *fidelity* choice:
1755
+ a self-collision radius is the cloth's apparent half-thickness, and at a
1756
+ diameter of 1.6 spacings a silk cape on 8 cm particles would hold the two layers
1757
+ of a fold nearly 13 cm apart. For 4 mm of silk that is absurd, and no crossing
1758
+ count can see it — the metric being optimised cannot measure the thing that
1759
+ stops the optimisation. A diameter of one particle spacing is the largest
1760
+ separation the proxy can be said to *mean*, since it is the mesh's own finest
1761
+ feature, and it delivers §9's "great majority" at 82%.
1762
+
1763
+ What would settle it properly is a number M4 does not have: what the search
1764
+ costs as a function of cell size. §34 shows the search is nearly all of the cost
1765
+ and that it scales with particles, but a wider radius is a wider *cell*, and
1766
+ every walk then visits more candidates. Someone who wants a stricter garment can
1767
+ raise the radius today — the table above is the dial, and the ceiling in §36 is
1768
+ where it stops — but they should measure that first.
1769
+
1770
+ ---
1771
+
1772
+ ## 32. How stiff the row has to be, and what it is actually for
1773
+
1774
+ Same sheet, same gust, radius fixed at half the shortest row; the penalty moves.
1775
+ `CLOTH_SELF_RATIO` is a multiple of `m_eff/h²` exactly as the bend and leash
1776
+ bands are, and `m_eff` for a pair with two free ends is half a particle.
1777
+
1778
+ ```
1779
+ k / (m_eff/h²) overlap: mean / worst crossings: mean / worst / rest pairs kinetic
1780
+
1781
+ 0 19.4 / 19.7 mm 11.39 / 146 / 0.0 0.0 6.86e-3
1782
+ 1 17.4 / 19.2 mm 3.42 / 51 / 0.0 6.9 6.63e-3
1783
+ 2 16.6 / 19.3 mm 3.36 / 76 / 0.0 5.8 5.81e-3
1784
+ 4 17.2 / 19.3 mm 2.75 / 83 / 0.0 4.8 6.28e-3
1785
+ 8 18.4 / 19.8 mm 2.03 / 71 / 0.0 4.8 7.57e-3
1786
+ 16 16.8 / 19.5 mm 2.03 / 96 / 0.0 4.6 7.00e-3
1787
+ 32 16.8 / 19.3 mm 2.45 / 123 / 0.0 4.4 5.24e-3
1788
+ 64 17.5 / 19.5 mm 3.87 / 125 / 0.0 4.3 6.81e-3
1789
+ ```
1790
+
1791
+ Four readings, and the last two are the ones worth keeping.
1792
+
1793
+ **Most of the win is in having a row at all.** 11.39 crossings a sample without
1794
+ one, 3.42 with the softest row in the table. The remaining sweep moves it from
1795
+ 3.42 to 2.03 — a third of what the first newton bought.
1796
+
1797
+ **The mean bottoms at 8 to 16 and the worst case gets steadily worse the whole
1798
+ way up.** 51 crossings at the worst realisation with `k = 1`, 125 with `k = 64`.
1799
+ A stiff penalty removes the average tangle and creates a rarer, larger one: it
1800
+ throws a particle hard enough to put the sheet through itself somewhere the row
1801
+ was not looking. `CLOTH_SELF_RATIO` ships at **8**, which is the joint minimum of
1802
+ the mean and is well down the worst-case curve.
1803
+
1804
+ **M0's dissipative band does not bind this row.** M0 measured that a soft row
1805
+ stiffer than about `8·(m/h²)` makes the step add energy rather than lose it, and
1806
+ `cloth_step` originally justified the ratio by that ceiling. The kinetic column
1807
+ says otherwise: across a sixty-four-fold range of stiffness it moves between
1808
+ 5.2e-3 and 7.6e-3 with no trend at all. The band was measured on rows that are
1809
+ **on every step** — a bend row, a leash. A self-collision row is one-sided and
1810
+ vanishes the instant it is satisfied, so it does work only while it is
1811
+ compressing and has no standing spring to pump. Eight is the right number here
1812
+ and the band is not the reason; the comment in `cloth_step.js` no longer claims
1813
+ it is.
1814
+
1815
+ **The row never achieves its own separation, and it is not meant to.** The
1816
+ overlap column is `diameter − distance` at the worst governed pair, and it barely
1817
+ moves: 19.4 mm without the row and 16.6 to 18.4 mm with it, out of a 20 mm
1818
+ diameter. Inside a fold the hard stretch rows are holding the sheet's own
1819
+ geometry and a soft penalty cannot outvote them. What it can do is decide *which
1820
+ side* of the fold a particle ends up on, which is what a crossing count measures
1821
+ and what §9 asks the tier for.
1822
+
1823
+ ### The settled sheet is clean either way, which is the whole flag question
1824
+
1825
+ The `rest` column is zero in every row of the table, the `k = 0` row included. A
1826
+ sheet with no bending resistance flattens itself once the gust stops and takes
1827
+ its tangles out with it. Every crossing counted above happened while the cloth
1828
+ was *moving*.
1829
+
1830
+ That is not a small caveat, it is the shape of the answer: if tangling were
1831
+ transient for every fabric, the flag would never be worth setting. It is not —
1832
+ what makes a tangle stay is bending. §33.
1833
+
1834
+ ---
1835
+
1836
+ ## 33. Which entries set the flag, and what it costs them
1837
+
1838
+ §9 says the flag is "set on the library entries that need it (skirts, long
1839
+ coats, hair) and clear on the ones that do not (capes, ponytails, banners)".
1840
+ That list is drawn along what the garment *is*. The measurement is drawn along
1841
+ how far the fabric bends, and it separates the entries far more sharply.
1842
+
1843
+ The same folding sheet, twelve realisations, with each library entry's own
1844
+ `bend` — a ratio of the bend row's inertial scale, mapped the way
1845
+ `cloth_build_rows` maps it — and nothing else changed.
1846
+
1847
+ ```
1848
+ entry bend row? crossings: mean / worst pairs removed
1849
+
1850
+ SILK 0.04 none 8.08 / 167 0.0
1851
+ SILK 0.04 with 2.37 / 77 4.5 71%
1852
+ HAIR 0.20 none 10.62 / 139 0.0
1853
+ HAIR 0.20 with 1.98 / 71 4.4 81%
1854
+ COTTON 0.25 none 9.36 / 135 0.0
1855
+ COTTON 0.25 with 1.99 / 49 4.7 79%
1856
+ DENIM 0.62 none 3.59 / 103 0.0
1857
+ DENIM 0.62 with 1.37 / 70 2.2 62%
1858
+ LEATHER 1.00 none 0.18 / 39 0.0
1859
+ LEATHER 1.00 with 0.41 / 44 0.3 -137%
1860
+ ```
1861
+
1862
+ **Leather does not tangle, and the row makes it worse.** 0.18 crossings a sample
1863
+ unaided — call it none — and 0.3 pairs a step, which is the row finding almost
1864
+ nothing and pushing on a sheet that had not asked. A fabric at the top of the
1865
+ bend scale will not fold tightly enough to pass through itself; there is nothing
1866
+ for the tier to prevent, and the handful of pairs it does find are noise it is
1867
+ adding rather than removing. The sign of that last column is the whole argument
1868
+ for the flag being off by default.
1869
+
1870
+ **Denim tangles a third as much as cotton** and the row removes 62% of it. It is
1871
+ the one genuinely marginal entry, and it is also the entry that has already spent
1872
+ both of its performance levers (§17): 576 particles at 2×2. It stays clear.
1873
+
1874
+ **Silk, cotton and hair are where the tier earns its keep** — 8 to 11 crossings a
1875
+ sample unaided, 71% to 81% of them gone. Cotton is "the default fabric, and the
1876
+ one every other entry is a deviation from", and a default that shows nine
1877
+ crossings in every sample taken while it moves is a bad default.
1878
+
1879
+ So the flag moves from one entry to three: `CLOTH_SILK` and `CLOTH_COTTON` join
1880
+ `CLOTH_HAIR`. `CLOTH_DENIM`, `CLOTH_LEATHER`, `CLOTH_ROPE` and `CLOTH_CHAIN`
1881
+ stay clear — the first two on the table above, the chains because a chain has no
1882
+ surface to pass through and a coiling rope is a case this measurement does not
1883
+ cover.
1884
+
1885
+ ### What that costs
1886
+
1887
+ The solver-level figure first, on the folding sheet, so the shape of the cost is
1888
+ visible before the entries are priced:
1889
+
1890
+ ```
1891
+ particles without with delta pairs/step slots full
1892
+
1893
+ 144 0.445 ms 0.508 ms 14.3% 2.6 0
1894
+ 256 0.813 ms 0.936 ms 15.1% 7.1 0
1895
+ 484 1.541 ms 1.806 ms 17.2% 20.6 0
1896
+ 1024 3.491 ms 4.100 ms 17.5% 36.0 0
1897
+ ```
1898
+
1899
+ Flat at 14% to 18%, and the pair list never once hit its cap — 36 pairs a step
1900
+ across 1,024 particles at the widest, against a ceiling of eight per particle.
1901
+ The cost is not in the pairs; §34 says where it is.
1902
+
1903
+ And then every entry at its own size, its own budget and its own row set, from
1904
+ `cloth_library_bench.mjs` — the same harness M1 sized the library with, driven by
1905
+ a gust so the pair list is doing work:
1906
+
1907
+ ```
1908
+ SILK 2x4 1.427 ms -> 1.802 ms 26.3% inside pairs 318.0 full 0
1909
+ COTTON 2x4 1.478 ms -> 1.802 ms 22.0% inside pairs 325.1 full 0
1910
+ DENIM 2x2 1.297 ms -> 1.765 ms 36.1% inside pairs 607.8 full 0
1911
+ LEATHER 2x2 1.315 ms -> 1.828 ms 39.0% inside pairs 740.2 full 0
1912
+ ROPE 2x4 0.116 ms -> 0.129 ms 11.5% inside pairs 0.0 full 0
1913
+ CHAIN 2x6 0.165 ms -> 0.183 ms 11.0% inside pairs 0.0 full 0
1914
+ HAIR 2x4 1.438 ms -> 1.798 ms 25.1% inside pairs 315.7 full 0
1915
+ ```
1916
+
1917
+ **Every entry stays inside 2 ms, and the three that set the flag have about a
1918
+ tenth of a frame left.** 1.80 ms against 2.00 for silk, cotton and hair — which
1919
+ is the thinnest headroom in the library and is the thing to watch when M5 or M6
1920
+ adds anything to the step. The bare figures agree with M1's to within 4%
1921
+ (silk 1.427 against a claimed 1.49, denim 1.297 against 1.28), so **no entry is
1922
+ re-sized**: §17's table stands, and self-collision is spent out of headroom
1923
+ rather than out of a lever.
1924
+
1925
+ The delta here — 22% to 26% — is larger than the 14% to 17% above because this
1926
+ harness folds a 400-particle sheet hard enough to find 318 pairs a step against
1927
+ the folding sheet's 5. That is the honest worst case for a garment of this size,
1928
+ and it is the figure the entries were checked against.
1929
+
1930
+ **The chains find nothing**, which is the measurement behind leaving `CLOTH_ROPE`
1931
+ and `CLOTH_CHAIN` clear: 0.0 pairs a step, and the 11% they still pay is the
1932
+ grid being built and walked for a cloth that will never have a pair in it. A
1933
+ hanging chain's nearest ungoverned particles are three links apart and its links
1934
+ are 5 cm long; nothing about a rope brings them within one link of each other
1935
+ except coiling, which this harness does not do.
1936
+
1937
+ **Leather is the entry the §36 clamp is for.** Before it, this same row read
1938
+ 1,398 pairs a step — the row had found the mesh rather than a fold. Clamped, its
1939
+ radius comes down from 20 mm to 16 mm and it reads 740, and those are folds. It
1940
+ still does not set the flag.
1941
+
1942
+ (§37 later replaced the ceiling's *derivation* without moving any number here:
1943
+ every entry's radius on this harness is identical under both rules, because on a
1944
+ sheet the closest ungoverned pair is exactly two hops. The bench takes the
1945
+ production path so that stays true rather than being assumed.)
1946
+
1947
+ ### The other cost is memory, and four of seven entries pay it for nothing
1948
+
1949
+ `ClothState` is one `ArrayBuffer`, sized at seed, and M4's three regions —
1950
+ `self_pair`, `self_force`, `self_hessian` — are in it whether or not the flag
1951
+ is ever set. On the §17 workload:
1952
+
1953
+ ```
1954
+ 1,024 particles, 2,945 stretch rows, 2,821 bend rows
1955
+
1956
+ whole state buffer 637,344 bytes
1957
+ self-collision 102,400 bytes 16.1%
1958
+ ```
1959
+
1960
+ Four of the seven library entries never read a byte of it. The reason it is
1961
+ unconditional is that the flag can be toggled without a reseed today —
1962
+ `cloth_dynamics_change_needs_reseed` returns false for it, because nothing in
1963
+ the row tables depends on it — so a lazily-sized region would have to become a
1964
+ reseed trigger. That is a change to the reseed contract for 100 KB a garment,
1965
+ and M4 leaves it: **recorded, not fixed**, and the number is here so whoever
1966
+ decides has it.
1967
+
1968
+ ---
1969
+
1970
+ ## 34. The grid is the cost, and it is not the 2D grid
1971
+
1972
+ §14.2 asks for "a 3D uniform hash grid, modelled on
1973
+ `core/geom/2d/hash-grid/SpatialHashGrid.js`". What landed shares the *idea* and
1974
+ none of the structure, and the reason is worth writing down because the next
1975
+ person to want a broadphase in `core` will read that sentence too.
1976
+
1977
+ The 2D grid is **persistent and incremental**. Its cells are a bounded array
1978
+ sized at construction, its elements are AABBs that carry identity and user data,
1979
+ and its primitives are `element_insert`, `element_remove` and the linked-list
1980
+ surgery that moves one between cells. That is the right shape for a world of
1981
+ things that mostly sit still and occasionally move — which is what it was built
1982
+ for.
1983
+
1984
+ A cloth's particles are the opposite of that in all four respects. They are
1985
+ **points**, not boxes. They carry **no identity across steps** — a pair list is
1986
+ rebuilt from scratch every step precisely because there is nothing on a pair
1987
+ worth keeping (`cloth_self_row.js`). Their domain is **unbounded**: a garment
1988
+ travels with its character and a fixed cell array would have to be re-based every
1989
+ frame. And **every particle moves every step**, so the incremental primitive
1990
+ never gets to be incremental; a full pass of remove-and-reinsert is a rebuild
1991
+ with extra bookkeeping.
1992
+
1993
+ `PointHashGrid3` is therefore a counting sort — count per bucket, prefix-sum,
1994
+ scatter — into a power-of-two hash of the integer cell, and it has no insert, no
1995
+ remove and no element identity at all. Two files, one word in common.
1996
+
1997
+ ### The rebuild is most of what self-collision costs
1998
+
1999
+ Which makes it the thing to defend. The same folding sheet, timing the pair
2000
+ search separately from the step it feeds:
2001
+
2002
+ ```
2003
+ particles step search rows search as % of the whole
2004
+
2005
+ 144 0.442 ms 0.048 ms 0.010 ms 9.6%
2006
+ 256 0.806 ms 0.113 ms 0.001 ms 12.3%
2007
+ 484 1.615 ms 0.217 ms 0.011 ms 11.8%
2008
+ 1024 3.547 ms 0.482 ms 0.164 ms 11.5%
2009
+ ```
2010
+
2011
+ `step` is the solver with no pairs at all; `search` is `cloth_self_find`;
2012
+ `rows` is what the pairs then cost inside the solve, taken as the difference
2013
+ between two runs. That last column is a difference of two minima from separate
2014
+ runs and at 484 it comes out *negative*, which is the harness saying the quantity
2015
+ is below its own noise floor rather than saying the rows are free. Read it as
2016
+ "small": between 0.005 and 0.14 ms against a search of 0.05 to 0.50.
2017
+
2018
+ So the **search is most of it and the rows are the remainder** — two thirds to
2019
+ all of it across the four sizes, and the spread is the `rows` column's noise
2020
+ rather than anything about the sizes. And the search scales the way a counting
2021
+ sort does: linear in particles to within the noise, with no term in the pair
2022
+ count at all. §9's "O(n) with a small constant" is right about the shape and
2023
+ optimistic about the constant — half a microsecond a particle, which is 11% of
2024
+ a frame at the §17 workload.
2025
+
2026
+ The consequence for whoever takes M4b — point-triangle and edge-edge — is that
2027
+ the extra stencils are not what will cost; they ride on a grid that has already
2028
+ been built. The estimate in §9 that M4b "roughly triples the self-collision cost"
2029
+ is the thing to re-measure first, and this table is the reason to doubt it.
2030
+
2031
+ ---
2032
+
2033
+ ## 35. What is left is not the search being one step behind
2034
+
2035
+ `ClothSystem` calls `cloth_self_find` and then `cloth_step`. The pair set is
2036
+ therefore discovered from the positions the *previous* step left, and the row
2037
+ acts on positions `cloth_predict` has already moved. A pair that becomes a
2038
+ contact **during** the step is not in the list, and by the time the next step
2039
+ looks, the two particles have already crossed.
2040
+
2041
+ That is the shape of the gap §20 found in the contact set, where the answer was
2042
+ to widen the discovery reach by the collider's own travel —
2043
+ `cloth_contact_find` carries `CLOTH_CONTACT_MARGIN` and adds `TRAVEL[record]`
2044
+ for it. The self-collision search has no equivalent, and §32 leaves 2.03
2045
+ crossings a sample unaccounted for. The obvious suspicion is that they are the
2046
+ same thing.
2047
+
2048
+ They are not. Here the search runs at a multiple of the row's radius while the
2049
+ row is unchanged, so the extra pairs are found and then found to be out of
2050
+ contact — which is what a travel margin would do:
2051
+
2052
+ ```
2053
+ search radius pairs/step crossings: mean / worst slots full
2054
+
2055
+ 1.0x 4.8 2.03 / 71 0
2056
+ 1.5x 32.3 2.13 / 69 0
2057
+ 2.0x 187.8 1.77 / 110 0
2058
+ 3.0x 738.9 4.76 / 89 0
2059
+ ```
2060
+
2061
+ **The pair list grows a hundred and fifty times over and the crossing count does
2062
+ not move.** 2.03 at the shipped width, 2.13 at one and a half, 1.77 at two —
2063
+ inside the spread of twelve realisations — and then *worse* at three.
2064
+
2065
+ So the residual is not a discovery problem. It is the limit §9 states and does
2066
+ not hide: a particle-particle row can only act when two **particles** are close,
2067
+ and a sheet can pass through itself between them. No width of search reaches
2068
+ that, because the thing that needs a row is a point against a triangle and there
2069
+ is no point-triangle row here. This is M4b's, and M4b is deferred.
2070
+
2071
+ **Why three times over is worse rather than merely wasteful.** The list holds
2072
+ `CLOTH_SELF_PAIRS_PER_PARTICLE` — eight per particle — and a particle at the cap
2073
+ keeps the eight it found *first in grid order*. At the shipped radius every
2074
+ candidate inside it is in contact, so which eight is arbitrary among equals. At
2075
+ three times it, almost none of them are, and the budget goes on pairs that will
2076
+ be discarded a moment later by the distance test while the pairs that mattered
2077
+ never make the list. The cap is what turns a wider search from a cost into a
2078
+ regression, and it is the thing to redesign first if anyone does want a swept
2079
+ search: a second radius with its own budget, or the search moved inside the
2080
+ substep loop after `cloth_predict`.
2081
+
2082
+ ---
2083
+
2084
+ ## 36. `max(thickness, …)` has an upper end, and leather is over it
2085
+
2086
+ §31 settles the radius at half the shortest row and keeps a `max` against the
2087
+ fabric's thickness, for the case it named: a heavy fabric on a coarse proxy,
2088
+ where the fabric is the longer of the two lengths. Nobody looked at where that
2089
+ branch stops being safe.
2090
+
2091
+ **On this topology the nearest pair no row governs is two hops away.** One hop is
2092
+ a stretch row. The mesh diagonal is a stretch row too. The two vertices *across*
2093
+ a diagonal are the four particles of a bend stencil. Everything closer than two
2094
+ hops is excluded by construction — which is exactly what makes half a hop the
2095
+ right radius, and it also means a **diameter** that reaches two hops puts a flat,
2096
+ undisturbed sheet in contact with itself everywhere.
2097
+
2098
+ The same folding sheet, sweeping the diameter as a multiple of the particle
2099
+ spacing, with pairs counted both while it folds and after it settles:
2100
+
2101
+ ```
2102
+ diameter / spacing pairs while folding pairs at rest crossings
2103
+ diameter / spacing pairs while folding pairs at rest crossings
2104
+
2105
+ 0.5x 1.8 0.4 10.76
2106
+ 0.8x 3.9 0.0 5.33
2107
+ 1.0x 4.8 0.0 2.03
2108
+ 1.4x 6.1 0.0 0.18
2109
+ 1.8x 13.1 0.0 0.04
2110
+ 1.9x 22.4 0.0 0.03
2111
+ 2.0x 103.7 78.7 0.02
2112
+ 2.2x 220.5 218.0 0.00
2113
+ ```
2114
+
2115
+ And where the library lands on a 2 cm proxy, under `max(thickness, 10 mm)`:
2116
+
2117
+ ```
2118
+ SILK thickness 4 mm -> radius 10 mm = 1.0x spacing
2119
+ HAIR thickness 6 mm -> radius 10 mm = 1.0x spacing
2120
+ COTTON thickness 8 mm -> radius 10 mm = 1.0x spacing
2121
+ DENIM thickness 14 mm -> radius 14 mm = 1.4x spacing
2122
+ LEATHER thickness 20 mm -> radius 20 mm = 2.0x spacing
2123
+ ```
2124
+
2125
+ **The cliff is exactly where the topology says, and it is a cliff.** At 1.9
2126
+ spacings a settled sheet has no pairs at all; at 2.0 it has seventy-nine, and at
2127
+ 2.2 it has two hundred and eighteen — on a cloth that is hanging still. Nothing
2128
+ about the fold changed. The row simply reached the first pair the mesh had not
2129
+ already claimed, and from there it is in contact with itself everywhere, for
2130
+ ever, pushing a flat sheet apart with a force that has nothing to resolve.
2131
+
2132
+ Note also that the crossing column is *still improving* across the cliff. A
2133
+ measurement that only counted crossings would walk straight over it, which is
2134
+ the argument for the "pairs at rest" column existing.
2135
+
2136
+ **Leather is on the number.** 20 mm of hide on a 20 mm proxy gives the row a
2137
+ diameter of exactly two spacings. Before the clamp, the library bench found it
2138
+ **1,398 pairs a step** on a 576-particle sheet — more than two per particle, on
2139
+ a cloth that was barely folded. Silk found 318 on the same harness.
2140
+
2141
+ The radius is now clamped at both ends, and the ceiling leaves two tenths of a
2142
+ spacing between itself and the cliff — the table says the sheet is clean well
2143
+ before that. **§37 then makes the ceiling a measured length rather than a
2144
+ multiple of the shortest row**, because the two-hop argument above is a fact
2145
+ about *sheets* and a rigged garment is not one. On a sheet the two agree
2146
+ exactly, so nothing in this section moves.
2147
+
2148
+ This is the one M4 finding with no line in PLAN.md to correct: §9 never wrote a
2149
+ radius down at all, which is how the whole question stayed open long enough to
2150
+ be got wrong twice — once too small, once too large.
2151
+
2152
+ ---
2153
+
2154
+ ## 37. What a rigged garment shows that a sheet cannot
2155
+
2156
+ Everything from §31 to §36 was measured on a triangulated sheet, because a sheet
2157
+ is the only thing in the system with a *surface* to pass through. The
2158
+ playground's cape is not a sheet. It is five strips of seven links, and **nothing
2159
+ joins one strip to the next** — §11.3's proxy is joint indices and a topology,
2160
+ and that topology is a set of chains.
2161
+
2162
+ Two things follow, and the second is a correction.
2163
+
2164
+ ### Without the row a cape collapses to half the width it was drawn at
2165
+
2166
+ ```
2167
+ the playground's cape — 5 strips of 7, silk, settled from the bind pose
2168
+
2169
+ bind pose 0.340 m wide
2170
+ settled, no self-collision 0.178 m −48%
2171
+ settled, with it 0.351 m +3%
2172
+ ```
2173
+
2174
+ Nothing holds the strips apart but this row. Under gravity each one swings
2175
+ inward and they end up occupying the same space, so the cape settles at half the
2176
+ width the artist drew and its strips hang through one another. **This is the
2177
+ first thing in M4 that self-collision visibly does on the geometry M3 actually
2178
+ ships**, and no sheet measurement could have found it: a sheet's neighbouring
2179
+ columns are held apart by the stretch rows between them, and a cape's strips have
2180
+ nothing between them at all.
2181
+
2182
+ It is also the answer to a question §32 left open. There, every tangle was
2183
+ transient — the sheet untied itself whenever the gust stopped, which is why
2184
+ §17's escape hatch still has nothing to escape from. This one is not transient.
2185
+ It is what the garment settles *into*.
2186
+
2187
+ ### And the ceiling has to be measured, not derived from the shortest row
2188
+
2189
+ §36 clamps the radius at four fifths of the shortest row, reasoning from a
2190
+ sheet: the nearest pair no row governs is two hops away, so four fifths of one
2191
+ hop leaves a margin. On a sheet that is exactly right —
2192
+ `cloth_self_closest_free_pair` returns 2.0000× the spacing at both 2 cm and
2193
+ 5 cm, and the two ceilings agree to the precision Float32 positions carry.
2194
+
2195
+ On the cape they do not agree at all:
2196
+
2197
+ ```
2198
+ shortest row — a link, along a strip 0.0801 m
2199
+ two hops, which a sheet would predict 0.1602 m
2200
+ the closest ungoverned pair, measured 0.0850 m
2201
+ ```
2202
+
2203
+ The gap *between* strips is half what the link length implies, because it is a
2204
+ different length entirely: the artist put those joints where the garment needed
2205
+ them, and nothing relates that to how finely each strip is subdivided. Derived
2206
+ from the shortest row the ceiling came out at 0.064 m, the 0.040 m floor took
2207
+ precedence, and the settled cape carried **three pairs permanently in contact** —
2208
+ lateral ones, with nothing to do with folding. Measured, the ceiling is 0.034 m
2209
+ and the settled cape carries **none**.
2210
+
2211
+ So `CLOTH_SELF_RADIUS_MAX_RATIO` is two fifths of `ClothInstance#closest_free_pair`
2212
+ rather than four fifths of the shortest row, and `closest_free_pair` is measured
2213
+ once at seed, in the bind pose, by the same grid and the same exclusion set the
2214
+ pair search uses.
2215
+
2216
+ **§31 through §36 are unaffected.** Every one of them was taken on a sheet, where
2217
+ the new rule reproduces the old one to the precision the positions carry, and
2218
+ `cloth_self_radius.spec.js` pins exactly that so it cannot drift.
2219
+
2220
+ ### What measuring it costs
2221
+
2222
+ Once per seed, and every cloth pays it whether or not the flag is set, because
2223
+ the flag can be turned on later without a re-seed:
2224
+
2225
+ ```
2226
+ 1,024 particles, 2,945 stretch rows, 2,821 bend rows
2227
+
2228
+ the exclusion set 1.792 ms
2229
+ the free-pair walk 0.664 ms
2230
+ 2.455 ms, once
2231
+ ```
2232
+
2233
+ The exclusion set is the larger half and it is not new work — it was built
2234
+ lazily on the first self-collision step before, so a cloth that sets the flag
2235
+ paid it anyway. What is new is that a cloth which never sets the flag now pays
2236
+ it too, at seed, alongside the subtree walk and the graph colouring that seeding
2237
+ already does. Nothing pays it per step.
2238
+
2239
+ ---