@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,1967 @@
1
+ # Cloth — Design
2
+
3
+ > Design document. Written 2026-09-10; **M0, M1, M2 and M3's rigged path are implemented**, and
4
+ > every place they contradicted it has been corrected in place with the measurement named beside it.
5
+ > §17 says what is done and what is not; `MEASUREMENTS.md` is the evidence.
6
+ >
7
+ > Scope: a cloth and soft-chain simulator that lives inside `engine/physics`, collides against the
8
+ > `Collider` components the rest of the engine already authors, runs on a worker, and is safe to ship
9
+ > with its defaults untouched.
10
+
11
+ ---
12
+
13
+ ## 1. What this is
14
+
15
+ One solver over particles, driven by components:
16
+
17
+ - **`Cloth`** — the thing that simulates. Put it on an entity and that entity's transform subtree
18
+ becomes a simulated chain: a rope, a chain, a hanging sign, a mooring line.
19
+ - **`ClothRig`** — add it alongside `Cloth` and the particles are the **joints of a skinned model**
20
+ rather than the entity subtree. This is what makes a cape, a skirt, a banner on a character.
21
+ - **`ClothCollider`** — the marker that opts an existing `(Collider, Transform64)` entity into being
22
+ something cloth collides with. This is the `RigidBody`-analogue: it says *this collider participates*,
23
+ and carries only what cloth needs that `Collider` does not already say.
24
+
25
+ That last component follows a pattern the engine already has twice. `AcousticBody` opts a collider
26
+ into the acoustic simulation and carries an `AcousticMaterial`; `FluidObstacle` opts a collider into
27
+ the fluid simulation and carries an inflation radius. `ClothCollider` is the third instance of the
28
+ same idea, and it should read like a sibling of those two, not like a new invention.
29
+
30
+ The design commitments, in priority order, because they conflict and the ordering is the design:
31
+
32
+ 1. **It does not explode.** Not at 5 fps, not at 500, not when a parameter is absurd, not when a
33
+ character teleports, not when a collider is spawned inside the cloth.
34
+ 2. **It does not get stuck.** The set of configurations the simulation can reach is bounded around
35
+ the animated pose, and error cannot accumulate across steps.
36
+ 3. **It works untouched.** Adding a `Cloth` component with default values to a correctly authored
37
+ garment produces shippable motion. Tuning is an optimisation, never a prerequisite.
38
+ 4. **It is cheap.** A CPU worker budget measured in low single-digit milliseconds per character.
39
+ 5. **It is accurate.** Last, deliberately. Cloth that is 10% too stiff and never misbehaves beats
40
+ cloth that is correct and occasionally detonates.
41
+
42
+ ---
43
+
44
+ ## 2. Non-goals
45
+
46
+ - **Garment authoring.** No pattern cutting, no sewing, no pressure/inflation. Import a mesh.
47
+ - **Woven anisotropy.** No warp/weft/shear tensor. That needs UV-aligned quad topology and a
48
+ material model this design does not carry. Cloth here is isotropic with a bend modulus.
49
+ - **Penetration-free guarantees.** IPC-class methods (`C-IPC`, `GIPC`) guarantee no intersection ever,
50
+ at a cost per step this budget cannot pay. We guarantee bounded, self-correcting penetration.
51
+ - **Cloth pushing rigid bodies.** Coupling is one-way: colliders move cloth. Two-way coupling into
52
+ `PhysicsSystem`'s velocity solver is a later question and the constraint model leaves room for it
53
+ (§6), but it is not in scope.
54
+ - **Tearing, plasticity, burning.**
55
+ - **GPU simulation.** The engine has a mature WebGPU path and a particle VM that could host this, but
56
+ the requirement is a worker, and a worker is the cheaper, more portable, more debuggable answer.
57
+ Nothing in the data layout forecloses a GPU port; §12 keeps that door open.
58
+
59
+ ---
60
+
61
+ ## 3. Author-facing API
62
+
63
+ ```js
64
+ // An entity hierarchy — rope, chain, hanging sign, a prop built out of entities.
65
+ // Cloth simulates the transform subtree of the entity it is on. That entity is the anchor.
66
+ rope_top.add(Cloth.from(ClothDynamics.ROPE));
67
+
68
+ // A skinned model's garment — cape, skirt, banner, hair.
69
+ // Cloth simulates the JOINTS of the model instance this entity owns.
70
+ character.add(Cloth.from(ClothDynamics.SILK));
71
+ character.add(ClothRig.from(cape_proxy)); // cape_proxy: ClothProxy, built at import
72
+ ```
73
+
74
+ There is no mode enum and no discriminator field. **`Cloth` alone simulates the entity subtree;
75
+ `Cloth` + `ClothRig` simulates a skinned model's joints** — component presence doing the job an enum
76
+ would otherwise do badly. The solver is identical either way; only seeding and write-back differ.
77
+
78
+ Those are two cases rather than one because **the engine has two hierarchies, and that is a decision
79
+ rather than an accident**. `shade_node_to_entity_composition` expands a loaded model into entities and
80
+ gives a `ShadedGeometry` to every node that draws — except a skinned one, which "is not expanded, and
81
+ that is a boundary rather than an omission": it contributes its transform and its name and no
82
+ geometry, because its vertices deform against a skeleton the renderer owns and the GPU poses, and
83
+ making those joints entities is a design this program does not do (D47). A rope prop is entities all
84
+ the way down. A character's cape is not, and never will be. §11 is where that lands.
85
+
86
+ ### 3.1 `Cloth`
87
+
88
+ ```js
89
+ export class Cloth {
90
+ dynamics = new ClothDynamics(); // how it behaves — §3.3
91
+ blend = 1; // 0 = fully animated pose, 1 = fully simulated
92
+ layer = 1; // ClothCollider layer/mask filtering, RigidBody semantics
93
+ mask = 0xFFFFFFFF;
94
+ flags = ClothFlags.None;
95
+ }
96
+ ```
97
+
98
+ **The anchor is the entity the component is on**, and nothing names anything. Without a `ClothRig`
99
+ the particle set is the entity's own transform subtree, walked through
100
+ `TransformAttachmentSystem#findChildrenOf`/`#countChildrenOf` — the parent-to-children index the
101
+ engine already maintains. Put `Cloth` on the top link of a rope and you get the rope; put it on a
102
+ node with several chains under it and you get all of them in **one coupled solve**, which is what
103
+ makes self-collision between them work.
104
+
105
+ Two rules keep the walk unambiguous:
106
+
107
+ - **A nested `Cloth` claims its own subtree.** The walk stops when it meets another `Cloth`, so
108
+ independent hanging parts of one prop partition naturally.
109
+ - **`ClothExclude`** is a tag component that prunes a subtree from the walk, for the rig that has a
110
+ non-simulated attachment point in the middle of a chain.
111
+
112
+ With a `ClothRig`, the entity is instead the one that owns the skinned model instance, and the
113
+ subtree walk does not run at all — the particle set comes from the proxy's joint list (§3.2).
114
+
115
+ `blend` is the escape hatch for cinematics, LOD and "turn it off for this one shot". It is a lerp
116
+ between the animated pose and the simulated pose applied at write-back, not a solver parameter, so it
117
+ is free and always safe. **M1 note:** writing it wakes a sleeping cloth, because sleep skips the
118
+ write-back as well as the step (§7 P5) and a `blend` written to a sleeping cloth would otherwise take
119
+ effect at whatever later moment something else happened to wake it.
120
+
121
+ ### 3.2 `ClothRig`
122
+
123
+ ```js
124
+ export class ClothRig {
125
+ proxy = null; // ClothProxy — shared, immutable, built at import
126
+ skin = 0; // which of the instance's skins the proxy's joint indices are into
127
+ }
128
+ ```
129
+
130
+ A `ClothProxy` **object**, not a path. This is the convention the engine already uses for a component
131
+ that points at a built, shared, immutable asset: `Collider#shape` holds an `AbstractShape3D` and is
132
+ documented as *not* serialised because shapes are shared assets the pipeline wires up;
133
+ `ParticleEffect` holds a `ParticleLayout` and a `ParticleProgram` the same way. `ClothRig` serialises
134
+ the proxy's identity and the skin ordinal, and the asset pipeline resolves the rest.
135
+
136
+ **The proxy addresses joints by index, never by name.** A joint is a `Node3D` inside a
137
+ `SceneBundleInstance`, not an entity, so an `EntityReference` to one is impossible by construction —
138
+ and reintroducing strings at runtime to work around that would be the wrong answer. Instead the
139
+ binding is resolved **once, at import**: the builder has `SceneBundleInstance#nodes` (the by-name map
140
+ the engine keeps because sockets and effect anchors are authored as bone names) and turns names into
141
+ integer indices into `Skin#joints`. The runtime component holds integers.
142
+
143
+ ### 3.3 `ClothDynamics`
144
+
145
+ The parameters live in one value object, and the library is a set of instances of it.
146
+
147
+ ```js
148
+ export class ClothDynamics {
149
+ stretch = 0.7; // 0..1 normalised material coordinate
150
+ bend = 0.2; // 0..1
151
+ damping = 0.15; // 0..1
152
+ slack = 0.5; // 0..1 — how far the cloth may leave the animated pose (§3.4)
153
+ thickness = 0.02; // metres — particle radius, for collision offset and self-collision
154
+ inertia = 1; // 0..1 — how much of the anchor's world motion the cloth feels
155
+ drag = 0.1; // 0..1 — aerodynamic coupling to the air (§10)
156
+ substeps = 2; // solver budget
157
+ iterations = 4; // solver budget
158
+ flags = 0; // ClothDynamicsFlags.SelfCollision, ...
159
+ }
160
+ ```
161
+
162
+ The library is `ClothDynamics.SILK`, `.COTTON`, `.DENIM`, `.LEATHER`, `.ROPE`, `.CHAIN`, `.HAIR` —
163
+ frozen instances in `cloth_dynamics_library.js`. Assign one directly and it is shared, immutable and
164
+ free; call `.clone()` and you own a copy to edit. There is no field that silently rewrites other
165
+ fields, and no second "advanced" block: this *is* the parameter set, and the library is a set of
166
+ points in it that are known to be good rather than a mechanism.
167
+
168
+ The stiffnesses are normalised coordinates, not moduli in N/m — log-mapped internally so that `0.7`
169
+ means something an author can predict and `0.9` is not four orders of magnitude away from it. They are
170
+ independent, because the library carries the good combinations and that is protection enough; nothing
171
+ needs to be collapsed onto a single magic axis to keep an author out of trouble.
172
+
173
+ **M1 wrote that mapping (`cloth_dynamics_map.js`) and neither stiffness maps to newtons per metre.**
174
+ `stretch` maps to a *strain allowance*, because §6's measurement makes the fabric row hard and leaves
175
+ nothing for a stiffness to be. `bend` maps to a **ratio** of the row's own `m_eff/dt²` — at the fixed
176
+ step rather than the substep — for two reasons that are both wanted: the fabric's look becomes
177
+ invariant to how heavy the author made the particles, which is what a normalised knob should mean; and
178
+ since `k/(m/h²) = ratio/substeps²`, a bend row expressed that way is inside M0's dissipative band at
179
+ *any* substep count by construction, rather than by an author staying out of trouble. A stiffness in
180
+ N/m has neither property. The cost, stated: **bending saturates** at the top of that band, so a fabric
181
+ stiffer than `bend = 1` cannot be expressed as a soft row that also comes to rest.
182
+
183
+ `substeps` and `iterations` are budget rather than material, and they are here because a chain wants
184
+ more of both than a bedsheet does, so they are part of what "chain" means. Raising `iterations`
185
+ converges further toward the same answer (§5.1); raising `substeps` also reduces implicit Euler's
186
+ numerical damping, so it does change the drape slightly. Both are ordinary fields with ordinary
187
+ documentation, not hidden couplings.
188
+
189
+ `ClothDynamics` carries `equals` and `hash` like every other value type in the engine, so a component
190
+ holding one compares and hashes cheaply.
191
+
192
+ ### 3.4 Slack, and why there is no radius in metres
193
+
194
+ `slack` is dimensionless. Each particle's leash radius is derived, not authored:
195
+
196
+ ```
197
+ r_i = 2 · slack · d_geo,i
198
+ ```
199
+
200
+ **M1 corrected the factor of two, and it is a derivation rather than a fudge.** This paragraph
201
+ originally read `r_i = slack · d_geo,i`, which makes `slack = 1` a real and fairly tight constraint
202
+ instead of the absence of one: a rope hanging straight down cannot swing through ninety degrees,
203
+ because its tip has to travel `√2·d_geo` to get there and its leash is `d_geo`. The radius at which
204
+ the row is *provably* inert is `2·d_geo` — the tether already holds every particle within `d_geo` of
205
+ the anchor, the animated position it is leashed to is also within `d_geo` of the anchor since a chord
206
+ is never longer than the arc it subtends, so by the triangle inequality the two are never further
207
+ apart than that. With the factor of two in, `slack = 1` means exactly "no leash": the row cannot
208
+ bind, so it is not built at all, and there is no sentinel and no discontinuity to code around.
209
+ `MEASUREMENTS.md` §10.
210
+
211
+ where `d_geo,i` is the particle's baked geodesic distance to the fixed set. At `slack = 0` every
212
+ particle is welded to its animated position; at `slack = 1` a particle may be anywhere within its own
213
+ reach of that position. Three things fall out of that and none of them need a knob:
214
+
215
+ - **The profile is automatic.** A hem gets a long leash and a waistband gets a short one, because
216
+ that is what their geodesic depth says, not because someone painted it.
217
+ - **The fixed set falls out too.** A pinned particle has `d_geo = 0`, so `r_i = 0`, so the leash *is*
218
+ the pin. There is no separate attach constraint — one row covers both (§6).
219
+ - **There is no magic default.** The old formulation had a radius in metres with `0` meaning "derive
220
+ it from the mesh extent", which is the kind of overloaded sentinel that gets copied into a save file
221
+ and then means the wrong thing.
222
+
223
+ Slack is not a stretch allowance and does not govern inextensibility — the tether row does that, and
224
+ the two are different questions (§6). Slack asks how loosely the cloth is leashed to the animation;
225
+ the tether asks how far the fabric may extend from its anchor. A cape wants both: a moderate leash so
226
+ it follows the character, and a hard tether so it never becomes rubber.
227
+
228
+ ### 3.5 `ClothCollider`
229
+
230
+ ```js
231
+ export class ClothCollider {
232
+ inflation = 0; // extra thickness in metres, on top of ClothDynamics#thickness
233
+ friction_scale = 1; // multiplies the entity's Collider#friction
234
+ layer = 1; // RigidBody semantics, and see below
235
+ mask = 0xFFFFFFFF;
236
+ flags = 0; // ClothColliderFlags.Static
237
+ }
238
+ ```
239
+
240
+ Everything else is read from components the entity already has: geometry and friction from
241
+ `Collider`, pose from `Transform64`.
242
+
243
+ **M2 added the layer and the mask, because this paragraph originally said "layer filtering from the
244
+ `Cloth` side" and that is not a thing that can happen.** `Cloth#mask` is a mask *of collider layers*,
245
+ and §3.5 is also the paragraph that says a `ClothCollider` does not require a `RigidBody` — so there
246
+ is nowhere else in the tuple for a collider's layer to live. The pair is here with `RigidBody`'s own
247
+ semantics, symmetric: a cloth and a collider interact when each is in the other's mask.
248
+
249
+ **A `ClothCollider` does not require a `RigidBody`.** This is a deliberate divergence from
250
+ `FluidObstacle`, which does require one because it needs a wall velocity. Cloth's colliders are
251
+ overwhelmingly character bones — ordinary entities in a `TransformAttachment` hierarchy — and forcing
252
+ each of them to become a physics body to be seen by cloth would be a tax on the common case. Collider
253
+ velocity is derived from the pose delta between fixed steps, which the system caches anyway for swept
254
+ collision (§8.2). World props that *do* carry a `RigidBody` add a `ClothCollider` the same way and land
255
+ in the same index; the two cases are not distinguished.
256
+
257
+ ---
258
+
259
+ ## 4. Components and systems
260
+
261
+ ```
262
+ engine/physics/cloth/
263
+ ecs/
264
+ Cloth.js component: the simulated thing; anchor is its own entity
265
+ ClothFlags.js TeleportKeep, NeverSleep
266
+ ClothExclude.js tag: prune a subtree from the walk
267
+ ClothRig.js component: particles are a skinned model instance's joints
268
+ ClothDynamics.js value object: how it behaves
269
+ ClothDynamicsFlags.js SelfCollision, StrainLimit
270
+ cloth_dynamics_library.js SILK, COTTON, DENIM, LEATHER, ROPE, CHAIN, HAIR — frozen instances
271
+ cloth_dynamics_map.js normalised coordinates → row parameters; every constant measured
272
+ ClothCollider.js component: the RigidBody-analogue for collision
273
+ ClothColliderFlags.js
274
+ ClothSystem.js main-thread system: gather, step, write back
275
+ ClothInstance.js one live cloth: the binding between a subtree and a ClothState
276
+ cloth_seed_subtree.js §11.1's walk: entities → node_parent + animated_position
277
+ cloth_seed_rig.js §11.2's proxy: joints → node_parent + animated_position
278
+ cloth_build_rows.js everything after that, shared by both seeders
279
+ cloth_reconstruct_pose.js particles → a pose, shared by both write-backs
280
+ cloth_write_back.js that pose → Transform64 + TransformAttachment
281
+ cloth_write_back_rig.js that pose → Node3D.transform_local
282
+ cloth_gather_colliders.js the index's overlapping records, in the cloth's own frame
283
+ WorkerClothSystem.js drop-in worker variant (WorkerSystem subclass)
284
+ ClothWorkerCore.js
285
+ cloth.worker.js
286
+ makeClothWorker.js
287
+ cloth_worker_protocol.js
288
+ ClothSerializationAdapter.js
289
+ ClothRigSerializationAdapter.js
290
+ ClothColliderSerializationAdapter.js
291
+ collider/
292
+ ClothColliderIndex.js the index of live cloth colliders + their swept AABBs
293
+ ClothColliderRecord.js the packed layout: kind, params, both poses, bounds, interpolated pose
294
+ ClothColliderKind.js sphere, capsule, box, cylinder, plane
295
+ cloth_collider_pack.js AbstractShape3D → packed record
296
+ cloth_collider_bounds.js the swept AABB, shared by the index and each cloth's own table
297
+ cloth_collider_sdf.js pose interpolation, localisation, and the field dispatch
298
+ solver/
299
+ ClothState.js SoA particle + topology + constraint storage over one buffer
300
+ cloth_step.js the fixed step: predict, warm start, iterate, dual update, integrate
301
+ cloth_solve_vertex.js the per-vertex 3x3 block update
302
+ constraint/ one module per row type (§6)
303
+ cloth_color_particles.js graph colouring of the particle graph
304
+ constraint/cloth_leash_row.js §6's slack row and its tether row, which are one row model
305
+ build/
306
+ ClothProxy.js the built artefact
307
+ cloth_proxy_from_joints.js §11.3 steps 5–8, for a garment that is already rigged
308
+ cloth_proxy_build.js unrigged: source mesh → proxy (weld, simplify, extract, validate)
309
+ cloth_proxy_bind.js unrigged: render mesh → proxy binding weights
310
+ ClothDiagnostics.js dev-build tripwires
311
+ ```
312
+
313
+ Two systems:
314
+
315
+ - **`ClothColliderSystem`** observes `(Collider, Transform64, ClothCollider)` and maintains a
316
+ `ClothColliderIndex` — a flat array of packed records plus swept world AABBs. This is the same shape
317
+ as `AcousticOccluderIndex`/`OccluderBody` in the sound simulation, and for the same reason: the
318
+ consumers need a compact, pose-cached, broadphase-able view of a set of colliders that is not the
319
+ physics BVH. It cannot be the physics BVH, because `ColliderObserverSystem` deliberately skips
320
+ colliders with no owning body, and bone colliders have no body.
321
+
322
+ **M2 note: it has no `fixedUpdate`, and that is §4.1 applied a second time.** The index has to be
323
+ refreshed from the world's transforms *before* any cloth reads it, and the scheduler cannot express
324
+ that for exactly the reason §4.1 gives — a score is a sum over what a system references, so a system
325
+ can only be moved earlier by touching more, and `ClothSystem` (which reads and writes `Transform64`
326
+ and `TransformAttachment`) outscores one that only reads. So the answer is not a third mechanism, it
327
+ is one call site: `ClothSystem#fixedUpdate` calls `refresh()` at the top of its own step, before any
328
+ cloth is advanced. The collider poses are then read at exactly the moment the anchor poses are, which
329
+ is what makes a contact consistent rather than merely fresh. With no `ClothSystem` in the manager the
330
+ index is never refreshed, and nothing reads it either.
331
+
332
+ **And the index is a linear scan rather than a BVH**, which is a divergence from
333
+ `AcousticOccluderIndex` with two reasons. The query is one AABB per cloth per step against a set that
334
+ is a character's bones — a `ClothCollider` is an opt-in marker, not every collider in the scene — and
335
+ a tree over twenty leaves that all move every frame costs more to keep than to skip. And a
336
+ `PlaneShape3D` has an **unbounded** AABB, which a BVH cannot hold: every refit would grow the root to
337
+ infinity. If a scene ever wants thousands of cloth colliders, the shape of the fix is a BVH over the
338
+ bounded ones with the planes in a short list beside it.
339
+
340
+ - **`ClothSystem`** owns the simulation. Per fixed step: refresh the animated targets, gather the
341
+ overlapping colliders from the index, step, write back.
342
+
343
+ Cloth runs at the fixed rate and is interpolated for display, exactly as `PhysicsSystem` does — the
344
+ same producer/`__interp_restore` contract, so a cloth-driven `Transform64` is authoritative during the
345
+ fixed pass and interpolated outside it. Reusing the existing contract rather than inventing a second
346
+ one is what keeps a cloth-driven bone from fighting an animation-driven one.
347
+
348
+ ### 4.1 Ordering, and why the answer is not to be ordered
349
+
350
+ Cloth wants to read the skeleton *after* animation has posed it for this step and *before* anything
351
+ renders. The engine has exactly two ways to order systems: **registration order**, and what each
352
+ system declares in `components_used`, from which writers are sorted before readers. There is
353
+ deliberately no `runs_before`/`runs_after`, because naming other systems is the coupling that design
354
+ exists to avoid.
355
+
356
+ **Cloth both reads and writes `Transform64`**, which puts it on both sides of that component's own
357
+ rule, and M1 established that neither mechanism can express the relation — for a structural reason
358
+ rather than an arithmetic one. `updateExecutionOrder` scores a system as a **sum** over the components
359
+ it references and sorts descending, so a score can only be *raised* by touching more components or
360
+ touching them at a higher access level. The only way to sort **later** is therefore to touch strictly
361
+ less than the system you have to follow, and a consumer of a posed hierarchy touches strictly more.
362
+ Registration order cannot rescue it either: ties break by registration, and this is not a tie —
363
+ `ClothSystem` outscores `TransformAttachmentSystem` and any plausible poser outright, registered first
364
+ or last.
365
+
366
+ **So the answer is not a third mechanism. The answer is that cloth must not care.** An earlier draft
367
+ of M1 added an execution-phase number to `System`, which put the words "pose" and "animation" into a
368
+ layer of the engine that has no such vocabulary, and bought an ordering the design should not have
369
+ needed. What M1 ships instead is a write-back that is **idempotent under recomposition**: cloth writes
370
+ each node's local `TransformAttachment#transform` alongside its world `Transform64`, so a hierarchy
371
+ recomposition — which is what happens whenever anything announces on the anchor — reproduces the
372
+ simulated pose instead of replacing it with the authored one. Measured at **1.7e-15 m** across a
373
+ 16-link rope (`MEASUREMENTS.md` §15). With that, where cloth runs is a **quality** question.
374
+
375
+ And a small one. Running before the poser means reading last step's anchor pose, so the cloth's
376
+ *shape* is one fixed step stale; its *position* is not, because the attachment cascade carries the
377
+ whole subtree rigidly with the anchor from cloth's own local transforms. Measured on a 1.6 m rope: a
378
+ few centimetres under ordinary motion, up to a fifth of its own length at the sharpest velocity
379
+ reversal of a ±9 m/s square wave, and **not accumulating** — the same figure after fifteen seconds as
380
+ after two, because the leash and the tether bound the reachable set. `ClothSystem.spec.js` asserts the
381
+ idempotency, records the order the scheduler actually produces, and bounds that divergence.
382
+
383
+ What the declaration *does* buy is the half of the ordering that is real: cloth writes
384
+ `TransformAttachment#transform` and `TransformAttachmentSystem` reads it, so writer-before-reader puts
385
+ cloth first and the attachment system publishes its result. That falls out of `components_used` with
386
+ nothing else asked for.
387
+
388
+ **`InverseKinematicsSystem` is the same shape and reaches the same conclusion.** It reads world
389
+ `Transform64`s "the hierarchy has already composed" and writes local ones back — which is exactly the
390
+ arrangement above, and exactly why it is not fragile in the way its scoring suggests.
391
+
392
+ ---
393
+
394
+ ## 5. The solver
395
+
396
+ **Augmented Vertex Block Descent** (Giles, Diaz & Yuksel, SIGGRAPH 2025) — VBD's per-vertex
397
+ Gauss-Seidel block coordinate descent on the implicit-Euler variational energy, with an augmented
398
+ Lagrangian in place of pure penalties.
399
+
400
+ ### 5.1 Why this, and not XPBD
401
+
402
+ XPBD with small substeps is the incumbent: MagicaCloth2, Chaos Cloth, Blender, most of the field.
403
+ It works. Three properties push past it, and each maps onto a stated requirement:
404
+
405
+ - **Unconditional stability at any iteration count.** Every per-vertex update is a descent step on an
406
+ energy that is bounded below, so the update can be truncated at one iteration and the simulation is
407
+ still stable — just softer. That turns requirement 1 into a property of the update rule rather than
408
+ a property of tuning. XPBD is stable in practice, but its stability is a function of substep size
409
+ and stiffness; ours is not.
410
+ - **Parameters that keep their meaning.** AVBD targets the implicit-Euler solution, so a stiffness is
411
+ a material modulus and adding iterations moves the result *toward* the same answer rather than
412
+ changing which answer it is. Under XPBD, apparent stiffness and apparent damping both move when the
413
+ iteration budget moves, which is why cloth packages ship dozens of interacting sliders and
414
+ per-parameter animation curves to compensate. §3.3's small, independent parameter set is only
415
+ honest on a solver whose knobs are orthogonal to its budget.
416
+
417
+ This is iteration-count insensitivity, not substep insensitivity. Implicit Euler is numerically
418
+ damped by an amount that depends on `h`, so more substeps still means less artificial damping and
419
+ a livelier drape — which is why `substeps` is a documented field rather than a hidden constant.
420
+ - **Hard constraints without stiff penalties.** The augmented Lagrangian reaches effectively infinite
421
+ stiffness through an accumulating multiplier rather than a large `k`, so pins, tethers and slack
422
+ bounds are *hard* — enforced to convergence — while cloth stays soft, in the same sweep, without
423
+ the conditioning disaster a 10⁸ penalty would cause. VBD alone cannot do this; it is exactly the
424
+ limitation AVBD was written to fix.
425
+
426
+ Two smaller wins. Colouring the *particle* graph needs far fewer colours than colouring the
427
+ *constraint* graph — the VBD paper reports 8 colours for a 3,891-vertex tetrahedral mesh against 76
428
+ for its 14,802 tetrahedra — which matters for a future GPU port and for cache behaviour now. And the
429
+ per-vertex form is a natural fit for SoA typed arrays, which is what a worker needs anyway.
430
+
431
+ The cost is honest: more arithmetic per vertex than an XPBD projection, and a shorter track record
432
+ for cloth specifically. §18 carries both as risks with a measurement plan.
433
+
434
+ ### 5.2 The step
435
+
436
+ Per substep, with `h` the substep length, `m_i` particle mass, `y_i` the inertial target:
437
+
438
+ ```
439
+ predict y_i = x_i + h·v_i + h²·a_ext,i
440
+ x_i ← x_i + h·v_i + h²·ã_i (adaptive initialisation)
441
+
442
+ warm start for each HARD constraint c: (soft rows: k_c = stiffness, λ_c = 0)
443
+ λ_c ← λ_c · α · γ
444
+ k_c ← clamp(k_c · γ, k_min·s_c, k_max·s_c) s_c = the row's own m_eff/h²
445
+
446
+ iterate repeat `iterations` times:
447
+ for each colour: (parallel within a colour)
448
+ for each particle i in colour:
449
+ f = -(m_i/h²)(x_i - y_i)
450
+ H = (m_i/h²)·I
451
+ for each constraint c on i:
452
+ C = C_c(x); g = ∂C_c/∂x_i
453
+ fu = k_c·C + λ_c
454
+ fc = clamp(fu, fmin_c, fmax_c)
455
+ f -= fc·g
456
+ if fc > 0: (row in tension)
457
+ H += (fc/L)·(I − g gᵀ) (geometric stiffness, PSD part)
458
+ if fc == fu: (row active — not at a clamp)
459
+ H += k_c·(g gᵀ)
460
+ x_i += H⁻¹·f (3×3 LDLᵀ, capped at the shortest incident row)
461
+
462
+ dual update, for each HARD constraint c:
463
+ λ_c ← clamp(k_c·C_c + λ_c, fmin_c, fmax_c)
464
+ k_c ← min(k_c + β·|C_c|, k_max·s_c)
465
+
466
+ integrate v_i = (x_i - x_i^prev)/h
467
+ ```
468
+
469
+ The Hessian contribution is gated on the row being *active*. A clamped row's force is constant with
470
+ respect to position, so its true second derivative is zero; adding `k·ggᵀ` anyway would make an
471
+ inactive unilateral constraint resist motion it should not touch. It contributes its (constant) force
472
+ to `f` and nothing to `H`.
473
+
474
+ `α ∈ [0,1]` regularises the multiplier carried between steps, `γ ∈ [0,1)` decays warm-started duals so
475
+ a resting configuration bleeds off accumulated force instead of ringing, and `β` is the penalty ramp.
476
+ These are solver internals, global, and deliberately **not** on `ClothDynamics` — they are not a
477
+ property of a fabric. The reference 2D implementation's defaults are a rigid-body tuning and will not
478
+ transfer; §17 M0 makes picking cloth values a measured step with its own spec, not a copied constant.
479
+
480
+ **M0 measured them, and four things about this pseudocode were wrong.** The sweep and its full grids
481
+ are in `MEASUREMENTS.md`; the corrections are folded into the listing above and are, in short:
482
+
483
+ 1. **The five constants only govern *hard* rows.** A row whose material stiffness is finite is
484
+ representable as a plain penalty, and a plain penalty at the material stiffness *is* the material
485
+ law — there is nothing for a multiplier to add. Carrying one anyway drives `C` to zero and makes
486
+ every fabric inextensible regardless of what it was authored as: a 1 kN/m spring measured 100×
487
+ stiffer than Hooke. So a soft row is a pure penalty at its material stiffness and reads dead flat
488
+ against all five constants, which is what makes them honest as global internals. A row is **hard**
489
+ exactly when its stiffness is `Infinity` — §6's table already says `hard` in that column, and this
490
+ makes it literal rather than a threshold.
491
+ 2. **`k_min` and `k_max` are ratios of `m/h²`, not stiffnesses in N/m.** Held at a fixed multiple of
492
+ the row's own inertial scale, a 20-link hard chain produced the same residual column across five
493
+ decades of particle mass; held at a fixed stiffness it produced a different answer for every mass.
494
+ This paragraph's own reasoning already names `k_max/(m/h²)` as the quantity that matters — it just
495
+ stopped one step short of making the ratio the parameter.
496
+ 3. **`α` and `γ` act only through their product, and `α·γ ≥ 0.5` diverges.** At `α·γ ≤ 0.3` a 20-link
497
+ hard chain settles to rest with kinetic energy at 1e-9 J; at 0.5 it jitters; at 0.6 it detonates.
498
+ Residual improves monotonically towards that cliff, so the value is a margin decision:
499
+ **α·γ = 0.25**, a factor of two clear.
500
+ 4. **`β` could not be chosen from M0 data.** Above about 1e4 every M0 scenario gives an identical
501
+ answer, and with `k_min = k_max` — which measured as good as any ramp for M0's persistent rows —
502
+ it has no effect at all. The ramp exists for **transient** rows, a contact that should arrive soft
503
+ rather than shock the mesh on its first frame, and M0 has none. M2 has to measure it.
504
+
505
+ Chosen: **α = 0.25, γ = 1, β = 1e5 (unexercised), k_min = k_max = 8·(m/h²)**. γ sits at 1 because its
506
+ second job — decaying the penalty — has nothing to do while the band is a single point, so the whole
507
+ decay lives in α, whose only job is the multiplier. When M2's contacts make the band real, γ becomes
508
+ live and has to be re-measured.
509
+
510
+ **Adaptive initialisation** is VBD's: seed the iteration at `x + h·v + h²·ã` where `ã` interpolates
511
+ between zero and full external acceleration according to whether the previous step looked like free
512
+ fall or like resting contact. Without it, a low iteration count over-stretches under gravity on the
513
+ first iteration and the tethers spend the rest of the budget pulling it back.
514
+
515
+ **Chebyshev acceleration** (`ω₁ = 1`, `ω₂ = 2/(2−ρ²)`, `ωₙ = 4/(4−ρ²ωₙ₋₁)`) is **not here**. M2
516
+ built it as specified — including the gate the VBD paper requires, disabled for any particle in
517
+ contact this step, since accelerating a vertex whose constraint set just changed is where the method's
518
+ stability argument stops applying — and measured it against the first contacts the system has.
519
+
520
+ It lost on every axis. On a sheet landing at 3 m/s it left the penetration inside the run-to-run
521
+ spread and made the settled kinetic energy 1.5× worse; on a hanging cape it traded a third off the
522
+ penetration for ten times the residual energy, which is a livelier cloth rather than a
523
+ better-converged one; it costs 2–5%; and past `ρ = 0.9` it diverges, with `ρ = 0.99` reaching a
524
+ non-positive-definite Hessian inside a second. A mechanism that costs, does not help, and detonates at
525
+ the top of its own range is worse than its absence. `MEASUREMENTS.md` §21 keeps the grid so a future
526
+ attempt starts from the numbers.
527
+
528
+ ### 5.3 Why the update never explodes
529
+
530
+ `H = (m/h²)·I + Σ_tension (fc/L)·(I − g gᵀ) + Σ_active k_c·(g gᵀ)`. The mass term is positive
531
+ definite; every `k_c·g gᵀ` is a positive semidefinite rank-one term; every `(fc/L)·(I − g gᵀ)` with
532
+ `fc > 0` is positive semidefinite too. So `H` is symmetric positive definite by construction — for any
533
+ topology, any parameter values, any degenerate configuration, and regardless of how many rows are
534
+ clamped out. `H⁻¹f` is always a descent direction.
535
+
536
+ **Three things M0 measured changed this paragraph.** They are corrections to the mechanism, not to the
537
+ goal; the full evidence is in `MEASUREMENTS.md`.
538
+
539
+ **The geometric-stiffness term is kept where it is positive semidefinite, not dropped wholesale.**
540
+ For a distance row `∂²C/∂x² = (I − g gᵀ)/L`, which is PSD exactly when the row is in tension, so
541
+ `max(fc, 0)·∂²C/∂x²` can be added without touching the SPD argument — every term in `H` is still PSD
542
+ on top of a PD mass term, and there is still no threshold. Dropping it *all* was measured to make the
543
+ update overshoot sideways whenever `fc/L` passes `m/h²`, raising the vertex energy by 20% at a ratio
544
+ of 4 and by a factor of 40 at a ratio of 7e4. This is not "adding the indefinite term back": the
545
+ negative-semidefinite half, where the row is in compression, is still dropped, and dropping it there
546
+ is conservative rather than dangerous. Note the term is added whether or not the row is at a clamp —
547
+ a saturated row applies a constant-magnitude force that still swings as the row rotates.
548
+
549
+ **The 3×3 solve is an LDLᵀ factorisation, not a cofactor inverse.** They agree in exact arithmetic
550
+ and do not agree in `Float64`. A vertex carrying one very stiff row against a small mass term
551
+ assembles an `H` with a condition number in the billions, and the cofactor determinant — a sum of
552
+ triple products that has to cancel by that ratio squared — comes out **negative** on a matrix whose
553
+ eigenvalues are all positive (measured: eigenvalues 0.12, 0.12, 5.4e8; determinant −4.8e8 against a
554
+ true 7.75e6). The factorisation never forms those products; its pivots stayed positive throughout the
555
+ fuzz, and their product is the determinant to full precision. The dev-build assertion checks the
556
+ pivots, which *is* the positive-definiteness claim rather than a proxy for it.
557
+
558
+ **Positive definiteness gives a descent direction, not a monotone step.** `Δ = H⁻¹f` satisfies
559
+ `f·Δ > 0`, so the energy falls for a small enough step — and the update takes a full step of 1. Where
560
+ the quadratic model stops resembling the energy, a full step overshoots and climbs: measured falling
561
+ monotonically out to `t ≈ 0.001` of one step and then rising to 40× the starting energy at `t = 1`.
562
+ The step is therefore capped at the **shortest row incident on the particle** — the distance over
563
+ which "the direction to a neighbour" means anything, which is the mesh's own geometry rather than a
564
+ tuned constant, and which never binds for cloth in ordinary motion. With all three corrections in,
565
+ full-step energy increases on a realistic cape are 0.004% of updates and never exceed a fifth of the
566
+ local energy scale; across deliberately absurd cloth they are 1.5% and never exceed 1.0. §7 P1 states
567
+ the gate that follows from this.
568
+
569
+ A dev-build tripwire mirrors `find_non_finite_physics_state.js`: a post-step sweep for non-finite
570
+ particle state that names the first offender. It sits behind `assert.*` so it compiles out of consumer
571
+ bundles — the engine ships raw source, and a check moved out of `assert.*` stops being strippable.
572
+
573
+ ### 5.4 Colouring
574
+
575
+ The particle graph is coloured so no constraint touches two particles of the same colour, using the
576
+ existing `core/graph/coloring/colorizeGraphGreedy.js` and checked by the existing
577
+ `validateGraphColoring.js`. Bending stencils span four particles, so the graph is the mesh graph plus
578
+ the bend diagonals — around 8–10 colours for typical garment topology. Colouring runs once, on a
579
+ `Graph` object, and is baked into the `ClothProxy` as colour ranges over a permuted particle order;
580
+ for a chain it runs at link time on a graph of a few dozen nodes. Nothing colours per step and the
581
+ runtime never sees a graph object.
582
+
583
+ Self-collision rows appear and vanish per step and cannot be pre-coloured. They are accumulated into
584
+ a per-particle scratch buffer and applied Jacobi-style within the sweep — the same mixed
585
+ Gauss-Seidel/Jacobi treatment VBD uses for dynamic collisions.
586
+
587
+ **M2 found that a *collider* contact needs none of that.** A contact against a collider is **unary**:
588
+ one particle against a surface that is fixed for the substep. It couples no two particles, so there is
589
+ no Gauss-Seidel versus Jacobi distinction to make and nothing to keep out of the colouring — it
590
+ accumulates in the vertex update exactly like a leash row. What is true of a contact is that it *comes
591
+ and goes*, which is a storage problem rather than an ordering one: M2's answer is a fixed four slots
592
+ per particle inside `ClothState`'s own buffer, rebuilt each step and keyed on the collider's index
593
+ handle so a multiplier survives the rebuild. Determinism comes from the *set* being built by one pass
594
+ in a fixed order over a fixed table. The paragraph above stands unchanged for M4's rows, which really
595
+ are pairs. `MEASUREMENTS.md` §18.
596
+
597
+ ---
598
+
599
+ ## 6. Everything is one constraint row
600
+
601
+ Every feature in this system is a row in one table. A row is `(C(x), f_min, f_max, stiffness)`, and
602
+ the solver in §5.2 knows nothing else about it.
603
+
604
+ | Row | `C(x)` | `f_min` | `f_max` | Stiffness | Gives you |
605
+ |---|---|---|---|---|---|
606
+ | Stretch | `‖x_i − x_j‖ − L₀` | −∞ | +∞ | `k_stretch` | fabric that resists stretching |
607
+ | Bend | quadratic stencil `Σ w_k·x_k` | −∞ | +∞ | `k_bend` | fabric that resists folding |
608
+ | Slack | `‖x_i − s_i‖ − 2·slack·d_geo,i` | 0 | +∞ | hard | follows the animation; pins at `d_geo = 0` |
609
+ | Tether (LRA) | `‖x_i − p_anchor‖ − d_geo,i` | 0 | +∞ | hard | no rubber-band stretch |
610
+ | Backstop | `r_b − (x_i − b_i)·n_i` | 0 | +∞ | hard | never inside the body |
611
+ | Collision | `(r_i + infl) − sdf_c(x_i)` | 0 | +∞ | hard | colliders push cloth |
612
+ | Friction | tangential slip magnitude | 0 | `+μ·f_n` | hard | cloth grips |
613
+ | Self-collision | `‖x_i − x_j‖ − (r_i + r_j)` | −∞ | 0 | `k_self` | cloth doesn't pass through itself |
614
+ | Strain limit | `‖x_i − x_j‖ − L_max` | 0 | +∞ | hard | hard cap on elongation |
615
+
616
+ Unilateral rows fall out of the clamp: **`[0, +∞)` admits only forces that reduce `C`, `(−∞, 0]` only
617
+ forces that increase it**, and `(−∞, +∞)` is bilateral.
618
+
619
+ **M1 corrected three of those clamps and the sentence above them.** An earlier draft glossed the rule
620
+ as "`[0, +∞)` is push-only, `(−∞, 0]` is pull-only", which is true only relative to a particular sign
621
+ of `C` — the collision row writes `C` as `r − sdf` and the distance rows write it as `‖·‖ − r`, so the
622
+ same clamp means opposite things on them. Following the gloss rather than the rule gave Slack, Tether
623
+ and Strain limit `(−∞, 0]`, which under the solver's own `f -= fc·g` is the force that pushes a
624
+ distance row *apart*. Such a row does not bind weakly; it never binds at all, and it would drive a
625
+ particle away from the leash centre it is supposed to hold it near. `cloth_leash_row.spec.js`
626
+ demonstrates it directly and `MEASUREMENTS.md` §10 carries the derivation. **A row is hard exactly when its stiffness is `Infinity`** — the word in the table above,
627
+ made literal. A hard row's penalty lives in `[k_min, k_max]·(m/h²)` and its multiplier carries the
628
+ load; a soft row is a pure penalty at its material stiffness and carries no multiplier at all. M0
629
+ measured why it has to be one or the other rather than a sliding scale (§5.2), and measured what the
630
+ multiplier actually buys: not a smaller residual — at a fixed budget a stiff penalty is comparable —
631
+ but **settling**. A hard 20-link chain comes to rest with 1e-14 J of kinetic energy where the same
632
+ chain on a penalty of any stiffness sits in a limit cycle at 1e-4 J. That is §7 P5, and it is the
633
+ augmented Lagrangian's real return.
634
+
635
+ `C` for a bending row is a **vector** — the discrete mean-curvature vector — so that row carries three
636
+ multipliers against one penalty, and its clamps are absent because a bending moment has no sign to be
637
+ one-sided about. Every other row in the table is scalar.
638
+
639
+ **M2 corrected the last two rows of that table, and both corrections come from rules the table already
640
+ states.** The collision and friction rows carried named stiffnesses `k_contact` and `k_friction`, and
641
+ by M0's own rule — a row is hard exactly when its stiffness is `Infinity` — that made both of them
642
+ soft penalties. A soft row's entire force is `k·C` with `k` capped at `8·(m/h²)`, which is **4.6 N at
643
+ one full thickness of penetration**; the hard row measured producing 11 N for a sheet arriving at
644
+ 1 m/s and 376 N at 8 m/s. A soft contact holds a draped garment and fails every time one is put down.
645
+ Both rows are hard.
646
+
647
+ And friction's clamps were `±μ·f_n`, which is the *signed-slip* formulation — a row whose `C` is a
648
+ displacement along a chosen tangent. This row's `C` is the **magnitude** of the slip in the contact's
649
+ tangent plane, so `C ≥ 0` always and the negative half of that clamp names a force pulling the
650
+ particle further from where it stuck. `[0, μ·f_n]` is the same physics, and writing it as a magnitude
651
+ is what removes the tangent basis: a signed row needs two per contact, and any choice continuous frame
652
+ to frame carries state, which is exactly what §7 P4(a) exists to keep out. Measured against Coulomb:
653
+ the stick/slide transition sits on `tan θ` at 10°, 20°, 30°, 40° and 50°. `MEASUREMENTS.md` §18.
654
+
655
+ **There is no separate attach row.** A pinned particle is a slack row with `d_geo = 0`: the constraint
656
+ becomes `‖x_i − s_i‖ ≤ 0` under a pull-only clamp, which welds it. One row, one code path, and the
657
+ distinction between "pinned" and "loosely following" is a number rather than a branch. (The gradient of
658
+ `‖x − s‖` is undefined at `x = s`; the row is skipped below an epsilon, which is the standard guard and
659
+ is also exactly when it has nothing to do.)
660
+
661
+ **Slack and tether are different questions, and a cape needs both.** Slack bounds distance to the
662
+ particle's *animated position*; the tether bounds distance to the *anchor*. Slack alone implies a
663
+ tether bound of `(1 + slack)·d_geo` — enough to stop a catastrophe, not enough to stop visible rubber —
664
+ and for a garment with no meaningful animated pose to follow (a flag, a curtain, where `slack` is near
665
+ 1 by necessity) the tether is doing all the inextensibility work on its own.
666
+
667
+ This mirrors the doctrine already written into `physics/constraint/solve_constraints.js`, whose
668
+ 6-DOF joints are "one row model, parameterised by mode", with LOCKED and LIMITED differing only in
669
+ bias and clamp. Same idea, position level instead of velocity level. A reader who knows one knows the
670
+ other, and a new cloth feature is a new row rather than a new pass.
671
+
672
+ Two rows deserve a note.
673
+
674
+ **Bend is the quadratic model**, not a dihedral angle. Its Hessian is constant for a fixed rest shape,
675
+ so the stencil weights are precomputed at build time, `C` is linear in `x`, and `g` is a constant read
676
+ from the proxy — bending costs almost nothing per iteration, and M0 measured it at an eighth of a
677
+ stretch row per visit despite touching twice as many particles. The weights annihilate the rest shape
678
+ and every affine image of it, which is every in-plane deformation to first order; they do *not*
679
+ annihilate an arbitrary planar configuration, and that is the precise content of the near-isometric
680
+ assumption below. More importantly, it has **no singularity
681
+ at 0° or 180°**. Dihedral bending needs a normal, an angle and a sign, all of which degenerate when two
682
+ triangles become coplanar or invert, and that degeneracy is a classic source of exactly the twitching
683
+ this design exists to eliminate. The cost is that the quadratic model assumes a near-flat rest shape
684
+ and near-isometric deformation; a garment with a strongly curved rest shape it wants to hold will
685
+ under-resist. §18 carries that.
686
+
687
+ **Stretch is per-edge.** Edge springs on a triangle mesh do not resist shear on their own; the bend
688
+ rows and the slack bound between them keep the mesh from collapsing in practice, and a triangle-area
689
+ row is available for the cases where they do not. Full in-plane anisotropy is a non-goal (§2).
690
+
691
+ **A chain bends through a skip row, not through the quadratic stencil.** M1 found there is nothing to
692
+ build a hinge on: the stencil is a discrete mean curvature over a *surface*, four particles across the
693
+ diamond either side of a shared edge, and a rope has no diamond — `bt_edge_read_diamond` declines a
694
+ wire edge for exactly that reason and is right to. What a chain gets instead is an ordinary stretch
695
+ row between a node and its **grandparent**, at whatever distance the authored pose puts them. That is
696
+ this section's own doctrine applied once more, it costs no new row kind, and it keeps both properties
697
+ the quadratic model was chosen for: no normal, no angle and no sign, so nothing degenerates at 0° or
698
+ 180°, and a fold is high energy rather than a singular configuration. It also does something the
699
+ quadratic stencil explicitly cannot (§18) — because its rest length is read from the authored pose
700
+ rather than assumed flat, **it holds a curved rest shape**. `MEASUREMENTS.md` §9.
701
+
702
+ **And a stretch row has to be hard, which this table's `k_stretch` does not say.** M0 measured that a
703
+ *penalty* stiffer than about `8·(m/h²)` makes the step add energy rather than dissipate it — the cloth
704
+ sustains a limit cycle forever, and raising the iteration count shrinks it without removing it. For a
705
+ half-gram particle at 60 Hz × 2 substeps that boundary sits near 60 N/m, which is a rubber band rather
706
+ than a fabric, so every stiffness an author would reach for is on the wrong side of it. The augmented
707
+ Lagrangian is therefore not a refinement over a stiff penalty for this row: it is the only formulation
708
+ of it that comes to rest, because its penalty is capped at the top of the dissipative band and the
709
+ multiplier carries the rest. M1's normalised `ClothDynamics#stretch` should map to `Infinity` with a
710
+ strain-limit row governing extension, not to a large finite `k`. `MEASUREMENTS.md` §6.
711
+
712
+ **M1 built that and measured what the strain-limit row is actually worth, and the answer is "a
713
+ third".** It removes 34–38% of the peak over-stretch, consistently, at every budget — and it **never
714
+ reaches its own allowance**: at `stretch = 1` it asks for 0.1% of strain and delivers 5.9% at one
715
+ iteration per substep, 2.2% at 2×2 and 0.9% at 2×4. The reason is structural. A strain-limit row is a
716
+ *second hard row on the same edge with the same gradient*, so it competes for the same trust region
717
+ and the same penalty band as the fabric row it is backing up; it can add force in a direction force is
718
+ already being added in, and nothing more. Below about `stretch = 0.35` its allowance is looser than
719
+ what the fabric row does unaided and it is simply inert.
720
+
721
+ So **`stretch` is the weakest field in §3.3's parameter set**, and the honest statement is that at low
722
+ budgets the bound belongs to the budget rather than to the fabric. The row is worth its 13–15% of a
723
+ garment frame where the residual is visible and is not worth it where the residual is already around
724
+ one per cent, which is why it is a flag — `ClothDynamicsFlags.StrainLimit` — rather than always on,
725
+ and why the library entries at 2×4 clear it. `MEASUREMENTS.md` §11.
726
+
727
+ ---
728
+
729
+ ## 7. Pathology budget
730
+
731
+ The requirement was cloth that does not fold up, get stuck, or spaz out. Each failure mode below gets
732
+ a named mechanism and a spec that fails without it. This table is the acceptance criterion for the
733
+ whole system, and every row's spec is a standing gate, not a one-off.
734
+
735
+ **P1 — Blow-up, NaN, unbounded velocity.**
736
+ *Mechanism:* SPD Hessian by construction (§5.3), so every update is a descent direction; the step
737
+ capped at the shortest incident row so a full Newton step cannot leave the region its model describes;
738
+ a per-particle velocity clamp; the `assert.*` non-finite tripwire.
739
+
740
+ **M1 landed the clamp and it is not derived from `thickness`.** This row asked for one "derived from
741
+ `thickness` and `h`", and `thickness` turns out to be the wrong length scale: it is a *contact*
742
+ radius, so a clamp built from it is a **tunnelling** bound, and a tunnelling bound sits below ordinary
743
+ cloth speeds rather than above them. Silk is 4 mm thick, so "a particle may not cross its own radius
744
+ in a step" is 0.24 m/s at 60 Hz — against the 29 m/s the same silk reaches behind a sprinting anchor.
745
+ Any multiple large enough to stop the clamp being a *behaviour* for silk is large enough to be
746
+ meaningless for leather, whose thickness is five times silk's and whose speeds are not.
747
+
748
+ The scale that works is the solver's own **correction authority**,
749
+ `shortest_row · substeps · iterations / dt` — the trust region caps a vertex update at the shortest
750
+ row incident on the particle, so that product is the whole of what one fixed step can undo. M1
751
+ measured a cloth losing its bounds past it (§7 P2 below), and the clamp is four times it: a bound on
752
+ the solver being asked to do more than it can, scaling with the mesh and the budget rather than with a
753
+ radius nothing reads until M2. The smallest headroom over it in the library is 5.7×. M2 still needs
754
+ the tunnelling bound — it is a different number for a different job and it arrives with the contacts.
755
+ `MEASUREMENTS.md` §13.
756
+ *Spec:* fuzz over random topologies and random `ClothDynamics` values including absurd ones, 10,000
757
+ steps, assert every particle finite. **M0 corrected the second half of this.** "The per-vertex energy
758
+ never increases across an update" does not follow from an SPD Hessian and is not true — SPD buys a
759
+ descent direction, and the update takes a full step (§5.3). What is asserted instead, and holds:
760
+ every LDLᵀ pivot positive on every update (which *is* positive definiteness, checked where it is
761
+ used); nothing non-finite across 10,000 steps of absurd cloth; and full-step energy increases bounded
762
+ and rare — 0.004% of updates on a realistic cape, never above a fifth of the local energy scale, and
763
+ 1.5% / 1.0 across the absurd fuzz. Those measured figures are the thresholds the standing gate holds
764
+ the solver to, so a change that makes it worse fails.
765
+
766
+ **P2 — Over-stretch, the rubber cape.**
767
+ *Mechanism:* long-range attachments (Kim et al. 2012). Each particle carries the geodesic distance to
768
+ its nearest fixed particle, baked once, enforced as a hard unilateral row. Because it is hard rather
769
+ than a penalty, one iteration enforces it almost exactly — this is the row that makes low iteration
770
+ counts viable.
771
+ *Spec:* a 30-link × 3-strand rig at one iteration per substep, dropped through ninety degrees; assert
772
+ `max‖x − p_anchor‖ ≤ d_geo·(1+ε)` for every particle across 600 steps, and assert the same rig without
773
+ the rows does not hold.
774
+ *Measured, M1:* **1.0155 with the tether against 1.4650 without**, at 1×1. Four times the budget takes
775
+ the untethered rig to 1.0199, which is still worse than one iteration *with* tethers — so the tether
776
+ is not a cheaper way to buy convergence, it answers a question the per-edge rows cannot.
777
+
778
+ *Limit, stated, and M1 found it:* **the bound is conditional on the solver's correction authority.**
779
+ The trust region caps a vertex update at the shortest row incident on the particle (§5.3), so one
780
+ fixed step can move a particle at most `shortest_row · substeps · iterations`, and a displacement
781
+ larger than that is not one the tether has been given a chance to answer for. Measured: a 30-link
782
+ chain kicked at 16 m/s against 3.0 m/s of authority reaches **6.9× its own reach**, and the same kick
783
+ against 24 m/s of authority reaches 1.06×. Both recover — the excursion is transient, which is P4(c)
784
+ holding — but "no particle is ever further from the anchor than `d_geo`" is true only while the
785
+ velocity clamp of P1 keeps a particle inside what the solve can undo, and that is the reason the clamp
786
+ is built out of the same quantity. `MEASUREMENTS.md` §10.
787
+
788
+ **P3 — Tunnelling through the character.**
789
+ *Mechanism:* three layers. (a) Collision rows evaluate against the collider pose *interpolated to the
790
+ substep*, from the previous and current poses the index caches — cheap swept collision. (b) The slack
791
+ bound stops a particle long before it can travel far enough to cross a limb. (c) Substepping shrinks
792
+ per-step travel.
793
+
794
+ **M2 found (a) is two mechanisms and only had one of them.** Interpolating the poses does nothing
795
+ unless the contact **set** covers the sweep as well, and it did not: `cloth_contact_find` runs once
796
+ per step against the *end-of-step* pose, so a collider that crossed the cloth within the step is
797
+ already past it and no row is ever created. Measured on a capsule driven through a hanging sheet at
798
+ 20 m/s: **zero contact rows for the whole pass**, with the sheet untouched — not tunnelled through so
799
+ much as never noticed. The fix is one subtraction per record per step, folding the collider's own
800
+ travel into the discovery reach, and it makes 2 to 40 m/s behave alike (94.8 rows a step at 20 m/s
801
+ against 0.0 without). `MEASUREMENTS.md` §20.
802
+
803
+ **And the interpolation is of a translation and a quaternion, not of two matrices.** §8.2 said
804
+ matrices; a component-wise lerp of two rotation matrices is not a rotation, and halfway through a turn
805
+ of `θ` it scales the shape it poses by `cos(θ/2)`. At the half-radian per step
806
+ `CLOTH_ANCHOR_ROTATION_LIMIT` already calls a spin, a 25 cm collider loses 7.8 mm — twice a silk
807
+ garment's thickness — halfway through every step. `MEASUREMENTS.md` §19.
808
+
809
+ *Limit, stated:* both halves are swept in translation first. A collider spinning fast enough that a
810
+ point on its surface travels more than its own radius within one substep can still be missed, because
811
+ the discovery margin is built from the *centre's* travel. Full CCD for cloth is out of scope.
812
+ *Spec:* a capsule driven through a hanging sheet at 2 to 40 m/s, swept against unswept; assert the
813
+ swept pass creates rows at every speed and that no particle spends a step more than half a collider
814
+ radius inside. `cloth_collision.spec.js` carries the ECS-level companion.
815
+
816
+ **P4 — Folds, tangles, and stays stuck.** The named requirement, so four mechanisms:
817
+
818
+ *(a) No history-dependent normals.* Self-collision and collision normals are derived from the
819
+ proxy's own surface orientation and the collider's SDF gradient at the current position — never from
820
+ "which side was this on last frame". A history-based scheme latches onto a wrong side and stays
821
+ wrong indefinitely; an orientation-based one resolves a tangle as soon as the surrounding geometry
822
+ permits. This is the "predefined surface orientation" branch of the untangling literature, chosen
823
+ specifically because it has no state that *can* get stuck.
824
+
825
+ *(b) No degenerate fold state.* Quadratic bending (§6) means a fully inverted 180° fold is not a
826
+ singular configuration — it is simply high energy, and high energy relaxes.
827
+
828
+ *(c) The slack bound bounds the reachable set.* Every particle is under a hard leash of radius
829
+ `slack·d_geo,i` around its animated position, so the set of configurations the simulation can occupy
830
+ is a bounded neighbourhood of the animation. **Error cannot accumulate** — however bad a step is, the
831
+ next step starts inside that same neighbourhood, and there is no drift mode that walks the cloth
832
+ somewhere it cannot return from. That is the guarantee, and note what it does *not* claim: the
833
+ animated pose itself can be imperfect. It is collision-free in the bind pose (the build validates
834
+ exactly that, §11.3, and fails loudly with the offending vertex and collider named), but an extreme
835
+ animation pose can skin a garment slightly into a thigh. When that happens the attractor is slightly
836
+ wrong and the cloth is slightly wrong with it — bounded and self-limiting, not divergent.
837
+
838
+ This is also why `slack` is the one number worth reaching for when a garment misbehaves: it is
839
+ literally the size of the neighbourhood the simulation is allowed to explore. **M1 note:** with §3.4's
840
+ corrected factor of two, `slack = 1` makes that neighbourhood the whole of what the tether already
841
+ allows, so the guarantee at `slack = 1` is the tether's rather than the leash's — which is the right
842
+ answer for a rope, and is why every chain in the library sits there.
843
+
844
+ **M2 note, and it is a limit rather than a gap.** The escape hatch below watches a *residual*, and
845
+ there is a configuration whose residual is zero and which is still stuck: a rope authored exactly
846
+ along an axis, compressed by a plane whose normal is exactly that axis, has no lateral component
847
+ anywhere in the system and folds into an accordion in which every link is at its rest length. That
848
+ is an exact equilibrium, so nothing has anything to act on. Measured: an 8-link rope on a floor
849
+ stops 18 cm above it and stays; **one part in a thousand of lateral lean** — a millimetre across a
850
+ 10 cm link — and it lies down. Recorded rather than fixed, because the fix is noise injected by a
851
+ solver whose whole design commitment is that it needs none, and no authored scene is that
852
+ symmetric. `MEASUREMENTS.md` §22.
853
+
854
+ *(d) A bounded escape hatch.* If a particle's constraint residual stays above a threshold for N
855
+ consecutive steps, it blends to its animated position over a short window. Local, bounded, on by
856
+ default with a conservative threshold, and counted in `ClothDiagnostics` so that a garment relying on
857
+ it is visible rather than silently rescued.
858
+
859
+ *Spec:* deliberately invert half a sheet through itself, run, assert the residual falls below threshold
860
+ and the mesh is self-intersection-free within N steps; separately assert the escape hatch is not
861
+ triggered by a correctly authored garment under normal animation.
862
+
863
+ **P5 — Jitter at rest.**
864
+ *Mechanism:* the multiplier decay `α·γ < 1` bleeds accumulated force out of a resting configuration so
865
+ it cannot ring; per-cloth sleep when the maximum particle displacement over a window falls below a
866
+ threshold; wake on collider motion, anchor motion, wind change, or a `ClothDynamics` change.
867
+ *M0 found the gap, and it is wider than "nothing is damping it".* The mechanism reaches **hard** rows
868
+ only, because a soft row has no multiplier to decay — and a soft row whose penalty exceeds about
869
+ `8·(m/h²)` does not merely fail to dissipate, it makes the step **add** energy. Measured on a hanging
870
+ sheet: total mechanical energy climbing +6.8 J against a system whose entire gravitational potential
871
+ is 1.2 J, sustained indefinitely, and shrinking but never vanishing as iterations or substeps go up.
872
+ Below that ratio the same row is dissipative and settles. What stops it is `ClothDynamics#damping`,
873
+ which arrives with the component in M1 — so **damping is load-bearing for P5 rather than a taste
874
+ control**, and the M1 spec has to gate on a soft cloth actually settling. `MEASUREMENTS.md` §6.
875
+ *Spec:* a settled cloth reaches sleep within a bounded number of steps and its positions are bit-identical
876
+ across the following 300.
877
+ *M1 landed both halves and measured them.* Every library fabric, on a 12-link chain set swinging at
878
+ 3 m/s, sleeps: **220 steps for denim, 770 for silk**, everything else between, and the order is the
879
+ damping order. Sleep stops the **write-back** as well as the step, which is what makes "bit-identical"
880
+ a fact rather than a hope — a pose that is not rewritten cannot drift, and one rewritten from unchanged
881
+ inputs is only *probably* identical. A cloth wakes on anchor motion, on a `ClothDynamics` change, on a
882
+ `blend` change, and on an explicit `ClothSystem#wake` for anything it cannot see.
883
+
884
+ And the damping gate, on the configuration §6 measured the limit cycle in — a 16-link rope with its
885
+ stretch rows forced soft at 1e5 N/m, a ratio of about 350 — after 1,500 steps: **2.90e-3 J undamped,
886
+ 1.28e-6 J at the library's own `damping = 0.12`**, 1.82e-12 J at the top of the range. Three orders of
887
+ magnitude from a field the design first described as a taste control. Note what damping does *not* do:
888
+ it does not stop the step adding energy, it removes energy faster than the step adds it, which is why
889
+ the numbers keep falling to `damping = 1` instead of hitting a floor. `MEASUREMENTS.md` §12.
890
+
891
+ **P6 — Teleport and cut.**
892
+ *Mechanism:* anchor motion above a threshold in one step is a teleport — `Reset` (re-seed at the
893
+ animated pose, zero velocity) or `Keep` (carry the shape across). Default `Reset`, followed by a short
894
+ stabilisation window in which the velocity limit ramps back from nothing, so the first steps after a
895
+ reset cannot produce a whip.
896
+ *Spec:* teleport 1 km mid-swing; assert bounded velocity every step and convergence to the animated pose.
897
+ *Measured, M1:* `Reset` peaks at **0.000 m/s** across the 240 steps after the jump and lands on the
898
+ animated pose; `Keep` peaks at 5.58 m/s, which is the swing it was already carrying, and shifts by
899
+ 0.078 m in local coordinates against 1.489 m for the reset. The threshold is `max(4·reach, 2 m)` per
900
+ step, and a 9 m/s sprint does not reach it for any library fabric.
901
+
902
+ **M1 named the mode differently and found `Keep` is free.** There is no `ClothTeleportMode`: the choice
903
+ is binary, so it is `ClothFlags.TeleportKeep`, one bit on the component that already carries the
904
+ cloth's own switches — a mode enum for two values is the discriminator field §3.1 exists to avoid. And
905
+ `Keep` is *literally* free: MagicaCloth2 applies the anchor delta rigidly to every particle, but in a
906
+ frame anchored to the cloth's own entity the particles are already anchor-relative, so "apply the
907
+ delta" is doing nothing. The implementation is a `return`.
908
+
909
+ **P7 — Fast locomotion: whipping, lag, centrifugal spray.**
910
+ *Mechanism:* the simulation runs in a **local frame anchored to the cloth's own entity**, with
911
+ `ClothDynamics#inertia` controlling how much of the anchor's world motion the cloth is allowed to
912
+ feel, plus anchor linear and angular speed limits. This is MagicaCloth2's `InertiaConstraint` idea and
913
+ it is the correct one: it makes "character sprints, cape behaves" a default rather than a tuning
914
+ exercise.
915
+ *Spec:* drive the anchor along a step-function velocity profile; assert bounded particle speed throughout.
916
+ *Measured, M1:* a square wave of ±9 m/s, one second a phase. Peak local particle speed runs 11.3 to
917
+ 29.3 m/s across the library against clamps of 96 to 288, so the smallest headroom is **5.7×**; nothing
918
+ teleports, and nothing leaves its own reach by more than 0.35%. The anchor limits are derived rather
919
+ than authored — half a reach of travel and half a radian of rotation per fixed step, both expressed
920
+ against the cloth's own geometry so a 3 cm pendant and a 30 m mooring line get the same treatment.
921
+ `inertia` measures monotone and exactly zero at zero: 0, 0.20, 0.37, 0.52, 0.65 m of tip lag across
922
+ its range, which is what makes it a dial rather than a switch with a meaningless middle.
923
+ `MEASUREMENTS.md` §13.
924
+
925
+ **P8 — Degenerate authoring.**
926
+ *Mechanism:* build-time validation, not runtime tolerance. The proxy builder welds duplicates, drops
927
+ zero-area triangles, and refuses non-manifold and inconsistently-wound configurations. The existing
928
+ `bt_edge_read_diamond` already declines every configuration a bending stencil cannot be built on —
929
+ wire edges, boundary edges, non-manifold edges, non-triangular neighbours, inconsistent winding, and a
930
+ "diamond" that is really one doubled triangle — so the degenerate cases are rejected by a function that
931
+ has already thought about them rather than by new code.
932
+ *Spec:* a corpus of deliberately broken meshes, each producing a specific diagnostic and no proxy.
933
+
934
+ ---
935
+
936
+ ## 8. Collision against the physics world
937
+
938
+ ### 8.1 The index
939
+
940
+ `ClothColliderSystem` maintains `ClothColliderIndex`: a flat array of packed records, each holding the
941
+ shape kind and its parameters, the world matrix, its cached inverse, the previous step's matrix, the
942
+ world AABB, friction and inflation. `OccluderBody` in the acoustic simulator is the same record and is
943
+ the shape to copy — including its precondition that the pose is rigid, so a distance in the shape's
944
+ local frame equals a distance in world space.
945
+
946
+ Per step, `ClothSystem` queries the index with the cloth's own fattened AABB and gets the overlapping
947
+ records. That set is packed into shared memory for the worker; nothing on the far side of the worker
948
+ boundary is an object.
949
+
950
+ ### 8.2 Evaluating a collision
951
+
952
+ The collision row needs `sdf_c(x_i)` and its gradient. Bring the particle into the collider's local
953
+ frame, evaluate the closed-form SDF and gradient there, rotate the gradient back.
954
+
955
+ **The pose is a translation and a quaternion, and there is no cached inverse.** A rigid pose inverts by
956
+ conjugating its quaternion and subtracting its translation, which costs less than storing an inverse
957
+ and is exact rather than cached — and, more importantly, it is the only form the sweep can
958
+ interpolate. This paragraph originally said the sweep comes from "interpolating between the previous
959
+ and current **matrices**", and a component-wise lerp of two rotation matrices is not a rotation: it
960
+ scales the shape it poses by `cos(θ/2)`, which at the half-radian per step the anchor limit already
961
+ calls a spin is 7.8 mm off a 25 cm collider — twice a silk garment's thickness, every step.
962
+ `MEASUREMENTS.md` §19.
963
+
964
+ **And the sweep is two things, not one.** Interpolating the poses is useless unless the contact *set*
965
+ also covers the sweep; §7 P3 carries what that cost and what it now does.
966
+
967
+ **Supported kinds are analytic primitives**: sphere, capsule, box, cylinder, and a plane. That
968
+ restriction is universal in shipping cloth systems — MagicaCloth2 offers sphere, capsule and plane;
969
+ Chaos Cloth adds tapered capsules and convex hulls — and it is what makes the inner loop a handful of
970
+ arithmetic instead of a BVH descent. A `Collider` carrying a mesh or heightmap shape is **skipped with
971
+ one warning naming the entity**, and the documented answer is to add primitive `ClothCollider` children,
972
+ which is what an author would do anyway for a character.
973
+
974
+ The engine's shapes already carry the closed-form SDFs — `CapsuleShape3D#signed_distance_at_point`,
975
+ `BoxShape3D#signed_distance_at_point` and the rest are exact and inline. Their *gradients* are not:
976
+ `signed_distance_gradient_at_point` on capsule, box and cylinder all fall back to
977
+ `compute_signed_distance_gradient_by_sampling`, which is four SDF evaluations and a normalise. That is
978
+ fine for voxelising a fluid obstacle once per step. It is not fine in a per-particle, per-iteration
979
+ loop, so §14 makes the analytic gradients shared code that both sides use.
980
+
981
+ ### 8.3 Friction
982
+
983
+ Coulomb friction as a row on the same contact, with `μ` combining `Collider#friction` with
984
+ `ClothCollider#friction_scale`. The combine rule is the one `physics/contact/combine_material.js`
985
+ already applies, so cloth and rigid bodies agree about what a surface feels like.
986
+
987
+ **M2 made three of those words exact.** The clamp is `[0, μ·f_n]` rather than `±μ·f_n`, because the
988
+ row's `C` is the *magnitude* of the tangential slip — §6 carries the derivation and what writing it
989
+ that way buys. `f_n` is the collision row's force **this iteration**, not its converged multiplier
990
+ from this step: the multiplier is one iteration stale and therefore exactly zero on a contact's first
991
+ iteration, so at the one iteration per substep §5.1 says the solver must be usable at, friction would
992
+ never act at all. And the static/dynamic separation needs no smooth transition function of its own —
993
+ it falls out of the clamp, because a row under the cap is enforced to convergence and sticks, and one
994
+ at the cap applies exactly `μ·f_n` against the slip direction and slides.
995
+
996
+ The row's anchor — where the particle stuck — is stored in the **collider's** own frame and read back
997
+ through the interpolated pose, which is what makes a sliding surface drag cloth with it instead of a
998
+ point in space holding it still.
999
+
1000
+ ---
1001
+
1002
+ ## 9. Self-collision
1003
+
1004
+ Off by default — `ClothDynamicsFlags.SelfCollision`. It is the most expensive part of every cloth
1005
+ system that has it — MagicaCloth2's self-collision constraint is 2,564 lines against 606 for
1006
+ distance — and the pathology guarantees in §7 do not depend on it.
1007
+
1008
+ **M4 corrected which entries set it, and the axis the list was drawn along.** This paragraph used
1009
+ to name them by what the garment *is* — set on skirts, long coats and hair, clear on capes,
1010
+ ponytails and banners. What decides is **how far the fabric bends**. Measured on a folding sheet
1011
+ at each entry's own `bend`: silk, hair and cotton pass through themselves 8 to 11 times a sample
1012
+ and the row removes 71% to 81% of it; denim tangles a third as much; leather does not tangle at
1013
+ all — 0.18 crossings a sample — and the row makes it *worse*, because the few pairs it finds are
1014
+ noise it is adding to a fabric that was never going to fold that tightly. `CLOTH_SILK`,
1015
+ `CLOTH_COTTON` and `CLOTH_HAIR` set the flag; `CLOTH_DENIM`, `CLOTH_LEATHER` and both chains do
1016
+ not. `MEASUREMENTS.md` §33.
1017
+
1018
+ Two tiers:
1019
+
1020
+ **M4a — particle-particle repulsion. M4 built it.** A uniform hash grid over particles in the
1021
+ cloth's local frame; pairs closer than `r_i + r_j` get the unilateral row from §6. Pairs sharing a
1022
+ triangle or an edge are excluded, since they are already governed by stretch and bend rows and
1023
+ would otherwise fight them — in practice the exclusion is *sharing any row at all*, which is the
1024
+ same set plus a chain's skip rows.
1025
+
1026
+ **That `r` is not the fabric's thickness, and M4 got that wrong before it measured its way out.**
1027
+ It reads as the same `r` a collider contact uses, which is `ClothDynamics#thickness`; a fabric is
1028
+ 4 to 20 mm thick and a proxy's particles are 2 to 8 cm apart, so at that radius the two layers of
1029
+ a fold are almost never in contact and the row finds 1.6 to 3.7 pairs across a whole garment. The
1030
+ radius is a property of **the proxy**: `ClothState#self_radius`, `max(thickness, shortest_row/2)`,
1031
+ so the row's diameter is one particle spacing. At the fabric's own 6 mm the row removes 21% of a
1032
+ sheet's self-intersections; at half the shortest row it removes 82%. `MEASUREMENTS.md` §31.
1033
+
1034
+ **It also needs a ceiling, and the ceiling is a measured length.** A diameter that reaches the
1035
+ closest pair *no row governs* puts a cloth which is not folded at all in permanent contact with
1036
+ itself — leather, 20 mm thick on a 20 mm proxy, found 1,398 pairs a step across 576 particles
1037
+ standing still (§36). On a sheet that distance is two hops and could have been assumed; on a
1038
+ rigged garment, whose proxy is strips with nothing joining one to the next, it is the gap the
1039
+ artist left between strips and is half what the link length implies. So `ClothInstance` measures
1040
+ it once at seed, in the bind pose, and the ceiling is two fifths of it. `MEASUREMENTS.md` §37.
1041
+
1042
+ "O(n) with a small constant" is right about the shape and optimistic about the constant: the pair
1043
+ search is linear in particles with no term in the pair count, and it is **12% of a frame** at the
1044
+ §17 workload, and most of everything self-collision costs. The rows themselves are nearly free.
1045
+ `MEASUREMENTS.md` §34. "The great majority of visible interpenetration" is 82% of it, and the
1046
+ stiffness that does it is `8·(m_eff/h²)`, chosen on the crossing count rather than on M0's
1047
+ dissipative band — a one-sided row that vanishes when satisfied shows no energy growth at 64×
1048
+ that. `MEASUREMENTS.md` §32.
1049
+
1050
+ *This tier cannot see cloth passing between particles.* A sheet thinner than its particle spacing can
1051
+ still slip through itself. Stated, not hidden.
1052
+
1053
+ **M4b — point-triangle and edge-edge.** The full stencil set, which closes that gap, over the same
1054
+ grid. Deferred behind measurement: it roughly triples the self-collision cost and the benefit is
1055
+ garment-dependent.
1056
+
1057
+ **M4 makes that cost estimate the first thing to re-measure.** The stencils would ride on a grid
1058
+ that has already been built, and the grid is where nearly all the money goes — tripling the rows
1059
+ triples something that is 5% to 20% of the feature. `MEASUREMENTS.md` §34.
1060
+
1061
+ Both tiers derive their normals from the proxy's surface orientation, per P4(a).
1062
+
1063
+ **M4a's normal is the line between the two particles, not a surface orientation**, because a
1064
+ particle pair has no surface in it. What P4(a) is actually asking for — nothing history-dependent,
1065
+ no "which side was this on last frame" to latch onto — the pair normal satisfies completely and
1066
+ more simply: `(x_i − x_j)/‖x_i − x_j‖` at the current position, recomputed every iteration, with
1067
+ no multiplier, no warm start and no identity across steps. The sentence above is right about M4b,
1068
+ where a point-triangle stencil genuinely needs an orientation to choose a side.
1069
+
1070
+ There is no 3D uniform hash grid in `core` today; there is a well-tested 2D one
1071
+ (`core/geom/2d/hash-grid/SpatialHashGrid.js`) whose structure is the template. §14.
1072
+
1073
+ **M4 built `core/geom/3d/hash-grid/PointHashGrid3.js` and it is not that structure.** The 2D grid
1074
+ is persistent and incremental — a bounded cell array, elements that are AABBs and carry identity,
1075
+ insert/remove/move as the primitives. Cloth particles are points with no identity across steps in
1076
+ an unbounded domain, and *every one of them moves every step*, so the incremental primitive never
1077
+ gets to be incremental. `PointHashGrid3` is a counting sort into a power-of-two hash and has no
1078
+ insert, no remove and no element identity at all. The idea carried over; not one line of the
1079
+ structure did. `MEASUREMENTS.md` §34.
1080
+
1081
+ ---
1082
+
1083
+ ## 10. Wind and aerodynamics
1084
+
1085
+ Cloth that does not move with the air reads as dead, and this engine has something better than a wind
1086
+ zone: a **fluid simulator**. `FluidField` exposes `sampleVelocity(out, x, y, z)` with trilinear
1087
+ filtering over a MAC grid, `fluid_build_world_to_grid` builds the world→grid transform, and
1088
+ `FluidObstacle` already voxelises physics colliders into the field so the air is genuinely disturbed by
1089
+ the bodies in the scene.
1090
+
1091
+ So the design is: **a cloth overlapping a `FluidComponent` samples its velocity field per particle and
1092
+ applies aerodynamic drag against it**, scaled by `ClothDynamics#drag`. The term is an external
1093
+ acceleration, `a_drag = drag · (u_air − v) · |n·û|`, with the normal-facing factor making a sheet catch
1094
+ the wind broadside and slice through it edge-on — the difference between a flag and a rope.
1095
+
1096
+ The payoff is that a character running past a cape gets a wake, because the fluid solver already
1097
+ produces one; a fire's convection lifts a banner; a door slamming pushes a curtain. None of that needs
1098
+ cloth-specific authoring, and none of it needs a wind system that duplicates what the fluid system
1099
+ already does.
1100
+
1101
+ Fallback when there is no fluid field in range: a `GlobalFluidEffector`-shaped ambient term — a
1102
+ constant `wind` vector plus a small band-limited noise for gusting — read from the same interface, so
1103
+ the cloth code has one path and does not branch on whether a simulation is present.
1104
+
1105
+ Cost control: sampling is per particle per *step*, not per iteration, and a cloth outside every fluid
1106
+ field's bounds skips it entirely. Sleep (P5) wakes on a wind change so a settled banner does not stay
1107
+ asleep through a gust.
1108
+
1109
+ This is deferred to M6 — it is the feature most likely to be cut for schedule, and nothing else depends
1110
+ on it.
1111
+
1112
+ ---
1113
+
1114
+ ## 11. Geometry in, results out
1115
+
1116
+ **Cloth moves joints. It does not produce vertices.** The mapping from a simulated particle to a
1117
+ render vertex already exists in this engine and it is the **skin**: a `Skin` holds `joints: Node3D[]`
1118
+ plus inverse-bind matrices, every render vertex carries a four-entry weight palette into that joint
1119
+ list, and `node.global · inverse_bind` is what the GPU blends every frame. Cloth writes joint
1120
+ transforms; the existing skinning pass does the rest — including bounds refresh and BLAS refit, which
1121
+ a bespoke vertex-deformation path would have to reimplement.
1122
+
1123
+ That is the whole relation, and it is why there is no cloth-owned render mesh anywhere in this design.
1124
+
1125
+ ### 11.1 Entity hierarchies — `Cloth` alone
1126
+
1127
+ One particle per entity in the transform subtree of the entity the component is on, walked through
1128
+ `TransformAttachmentSystem#findChildrenOf`, stopping at a nested `Cloth` or a `ClothExclude`. Stretch
1129
+ rows along parent-child links, bend rows along each chain, and the anchor entity itself is the fixed
1130
+ set — so `d_geo` is hop distance from the anchor and every derived quantity in §3.4 works unchanged.
1131
+
1132
+ Output is written back to the subtree entities' `Transform64` — position directly, rotation derived
1133
+ from the direction to the child, interpolated between parent-driven and child-driven orientation, which
1134
+ is what keeps a two-link chain from looking hinged.
1135
+
1136
+ **M1 made three of those words exact.**
1137
+
1138
+ *Both transforms are written: the world `Transform64` and the local
1139
+ `TransformAttachment#transform`.* Writing only the world one is cheaper and is a trap — the attachment
1140
+ system recomposes a child from its local whenever the parent announces, so any announcement arriving
1141
+ after cloth had written would replace the simulated pose with the authored one, and where in the fixed
1142
+ step cloth ran would be a *correctness* question. With the local written too, a recomposition
1143
+ reproduces exactly what cloth just wrote (measured at 1.7e-15 m), and §4.1's ordering problem stops
1144
+ being one. It is also the engine's own precedent: `InverseKinematicsSystem` reads world transforms the
1145
+ hierarchy has composed and writes local ones back, and §11.2's rig path writes `Node3D.transform_local`
1146
+ for the same reason — a local transform is what a joint angle *is*.
1147
+
1148
+ The authored pose is not lost by being overwritten. It is captured once, when the cloth seeds, and
1149
+ lives in the cloth from then on — which is what `blend = 0` returns to, what the leash centres are
1150
+ measured from, and what a re-seed of a live cloth reads instead of the shape the solver left behind.
1151
+ The consequence, stated: **in the entity path the animated pose is constant in the anchor's frame.**
1152
+ That is a property of the case rather than a limitation of the code — a subtree's authored pose is
1153
+ rigid relative to its anchor — but it does mean a subtree whose *links* are independently animated is
1154
+ not an M1 case.
1155
+
1156
+ **M3 corrected the sentence that used to end this paragraph**, which said that was the rig path and
1157
+ that there the animated pose "comes from the skeleton and is live". For a **rigged** garment it is
1158
+ not: cloth claims those joints (§11.2), so nothing else poses them, so their authored pose is the
1159
+ proxy's baked bind pose — constant in the anchor's frame, exactly as a rope's is. What moves is the
1160
+ anchor, and the anchor is a bone of the character's own animated skeleton. The live case is the
1161
+ **unrigged** path, where the targets are mesh vertices skinned by
1162
+ `mesh_apply_skeletal_vertex_skinning` and genuinely move under the animation.
1163
+
1164
+ *The rotation is a **swing** on top of the animated orientation*, `q = swing(d_animated → d_simulated)
1165
+ ⊗ q_animated`, using the minimal (twist-free) arc. Twist is inherited from the animation rather than
1166
+ invented, because a chain of particles carries no twist degree of freedom and any twist this code
1167
+ produced would be a fabrication — and the whole thing degenerates correctly, since at `blend = 0` the
1168
+ simulated direction *is* the animated one and the swing is the identity. A node with both a parent and
1169
+ children takes the half-way rotation between the two swings; a leaf takes its parent's. The shortest
1170
+ arc had no primitive in `core` and now does (`quat3_shortest_arc`), which is §14's doctrine turning up
1171
+ a fourth time.
1172
+
1173
+ *Nothing is announced on a simulated node, and every pruned boundary is.* A `TRANSFORM64_EVENT_CHANGE`
1174
+ on a simulated node would make the attachment system recompose its children from the authored pose —
1175
+ undoing the write that was just made, and cascading, for a chain, quadratically. But the root of a
1176
+ `ClothExclude` subtree, and a nested `Cloth`'s anchor, are *not* particles and still have to move: the
1177
+ write-back poses each of them by hand against the link it hangs from and announces exactly there, which
1178
+ reaches everything below the cut through the ordinary cascade and reaches nothing above it.
1179
+
1180
+ This is the path for props that genuinely *are* entity hierarchies: a rope, a chain, a hanging sign, a
1181
+ mooring line, a rigid model whose parts were expanded into entities and each drew as a
1182
+ `ShadedGeometry`. It needs no new rendering code, because moving an entity's `Transform64` is already
1183
+ how anything moves.
1184
+
1185
+ ### 11.2 Skinned garments — `Cloth` + `ClothRig`
1186
+
1187
+ A character's cape is not an entity hierarchy and cannot be made into one.
1188
+ `shade_node_to_entity_composition` expands a model into entities and attaches a `ShadedGeometry` to
1189
+ each node that draws — but a skinned node contributes its transform and its name and **no geometry**,
1190
+ because its vertices deform against a skeleton the renderer owns and the GPU poses. Its joints are
1191
+ `Node3D`s inside the entity's `SceneBundleInstance`, and making them entities is explicitly a design
1192
+ this program does not do (D47). So for a skinned garment there is no `ShadedGeometry` component and no
1193
+ bone entities: the geometry is registered with `GPUAnimationManager` through
1194
+ `register_instance_animation`, and the only writable handle is the joint's `Node3D.transform_local` —
1195
+ the same handle the animation systems write.
1196
+
1197
+ **And cloth has to *claim* those joints, which §11.2 originally read as though it did not.** The
1198
+ sentence above says the handle is "the same handle the animation systems write", and they do not
1199
+ write it: `TransformAuthority` is explicit that a node a clip drives is `GPU`, that "the CPU
1200
+ allocates and seeds the row, then never writes to it again", and that "the node's own
1201
+ `transform_local` stops describing it and should not be read as if it did" — and
1202
+ `instantiate_scene_bundle` stamps `GPU` on every node a clip channel targets. So cloth writing
1203
+ `transform_local` on a clip-driven joint would be writing into a field nothing reads.
1204
+
1205
+ `cloth_seed_rig` therefore sets `TransformAuthority.CPU` on every joint it drives. The consequence,
1206
+ stated: **a joint cloth simulates stops being animatable by a clip.** Two writers of one row is the
1207
+ race the enum exists to prevent, and for a cape that is the point of simulating it; for a garment
1208
+ whose joints are also keyed it is an authoring error, and the claim is where it surfaces.
1209
+ `MEASUREMENTS.md` §25.
1210
+
1211
+ **The anchor's world pose is computed, never read back.** A joint of an animated skeleton has no
1212
+ CPU-side `transform_global` — nothing maintains it — so the rig path evaluates the anchor with
1213
+ `pose_evaluate_world` over the clips the entity is playing, which is the engine's own sanctioned
1214
+ answer to "where is this bone" and the one `query_entity_node_world_pose` gives gameplay. A cape and
1215
+ a scabbard on the same shoulder are then placed by the same evaluator off the same clock.
1216
+
1217
+ Cloth therefore drives joints, and the proxy names which ones. **Three resolutions, deliberately:**
1218
+
1219
+ | tier | order of magnitude, skirt | what it is | who owns it |
1220
+ |---|---|---|---|
1221
+ | render mesh | ~5,000 vertices | `MeshletGeometry`, GPU-resident, never touched by cloth | the asset |
1222
+ | sim proxy | ~400 particles | what the solver steps | `ClothProxy` |
1223
+ | output joints | ~60 | what `Skin#joints` holds; the palette binds render vertices to these | `ClothProxy` |
1224
+
1225
+ Decoupling the middle tier from the bottom one is the point. Simulation wants enough particles to
1226
+ drape; skinning wants only enough joints to *describe* the drape, and a four-weight palette blends
1227
+ smoothly between far fewer of them than the simulation needs. Each output joint takes its position and
1228
+ its frame from a small neighbourhood of particles — a triangle fan or a fitted patch — so the joint
1229
+ count is a build-time choice about deformation fidelity rather than a consequence of solver
1230
+ resolution. That is also what disposes of the "one node per particle" cost worry: nothing requires
1231
+ one node per particle.
1232
+
1233
+ Two cases, and they differ only in where the joints and weights came from:
1234
+
1235
+ - **The garment is already rigged** — an artist made 8–20 cape joints and skinned the cape to them.
1236
+ This is the common case and by far the cheapest. The proxy is thin: joint indices, the topology
1237
+ connecting them, rest lengths, `d_geo`. **There is no binding step and no generated geometry — the
1238
+ artist's skin is the relation.** A cape, a ponytail, a coat tail, a loincloth: all of this.
1239
+ - **The garment has no usable rig** and wants per-vertex drape — a full skirt. The importer generates
1240
+ the joint set and generates a skin binding render vertices to it, then bakes both into the proxy.
1241
+ At runtime this is *indistinguishable* from the rigged case: the GPU sees an ordinary skin, the
1242
+ solver sees an ordinary particle set.
1243
+
1244
+ Animated targets — the `s_i` that the slack row, blending and P4 all need — come from
1245
+ `mesh_apply_skeletal_vertex_skinning`, which already takes flat positions, weights, indices and 4×3
1246
+ bone matrices and writes flat output. Typed arrays in, typed arrays out, no objects: it crosses the
1247
+ worker boundary as-is.
1248
+
1249
+ **What was rejected.** A dedicated deformation pass — cloth writing vertex positions into a dynamic
1250
+ geometry buffer, with render vertices bound barycentrically to proxy triangles — is the obvious
1251
+ alternative and is genuinely simpler *as a deformation*: one frame per triangle rather than per joint,
1252
+ no palette width to respect. It loses because `MeshletGeometry` is meshlet-clustered and BLAS-backed,
1253
+ so a new path has to reimplement per-frame vertex upload, meshlet bounds refresh, normal
1254
+ recomputation and BLAS refit — all of which the skinning path already does and has playgrounds for.
1255
+ It stays written down as the fallback if M3's measurements go badly.
1256
+
1257
+ ### 11.3 Building a `ClothProxy`
1258
+
1259
+ At import, producing the object `ClothRig#proxy` points at. Almost entirely existing code.
1260
+
1261
+ For a **rigged** garment, only steps 5–8 run, over the joint graph rather than a mesh:
1262
+
1263
+ 1. Load the source garment into a `BinaryTopology` (`bt_mesh_from_indexed_geometry`).
1264
+ 2. Weld and clean (`geometry_deduplicate_vertices`, drop degenerate faces).
1265
+ 3. Decimate to the target particle count with `bt_mesh_simplify_by_error` — quadric error metric, via
1266
+ `bt_mesh_compute_vertex_quadrics`. This is the standard distance-based reduction every cloth package
1267
+ does, with a principled metric instead of a hand-rolled one.
1268
+ 4. Extract stretch rows from edges, bend stencils from `bt_edge_read_diamond`, and the boundary from
1269
+ `bt_collect_boundary_segments`.
1270
+ 5. Derive the **fixed set automatically**: particles whose skin weights are dominated by joints
1271
+ *outside* the garment's own joint set are pinned. This is what makes "works untouched" true — a
1272
+ cape pinned at the shoulders needs no painting, because the skin data already says where the cape
1273
+ stops being cape.
1274
+
1275
+ **M3 found this is the unrigged rule and that the rigged path has a better one.** For a garment
1276
+ that is already rigged there are no mesh vertices to read weights for — the particles *are*
1277
+ joints — and the topology answers directly: a joint whose parent is outside the named set is a
1278
+ joint the garment hangs from, and they all have to hang from the same bone. That bone is the
1279
+ anchor and its `d_geo` is zero, so §3.4's derived quantities collapse onto it with nothing else
1280
+ saying "this one is pinned". Several chains from one bone are one garment and are §3.1's coupled
1281
+ solve; chains from *different* bones are refused, because there is then no single frame to
1282
+ simulate in.
1283
+ 6. Bake `d_geo` — geodesic distance from every particle to the fixed set. This one array drives the
1284
+ tether row, the slack profile, and the pinning, so the three cannot disagree.
1285
+ 7. Colour the particle graph (`colorizeGraphGreedy`, checked by `validateGraphColoring`), and permute
1286
+ the particle order so each colour is a contiguous range.
1287
+ 8. Resolve joint **names to indices** into `Skin#joints`, using `SceneBundleInstance#nodes`. This is
1288
+ the only place a name appears anywhere in the system.
1289
+ 9. **Unrigged only:** choose the output joint set, fit each joint's neighbourhood and bind pose, and
1290
+ generate the skin's weights and inverse-bind matrices for the render mesh.
1291
+ 10. **Validate**: manifoldness, no zero-length edges, and — the P4(c) precondition — that the skinned
1292
+ bind pose is collision-free against the character's `ClothCollider` set.
1293
+
1294
+ Vertex painting (per-vertex stiffness or slack multiplier) is supported through an optional texture or
1295
+ vertex-colour channel and is never required. Steps 5 and 6 are the default, and the intent is that most
1296
+ garments never override them.
1297
+
1298
+ ---
1299
+
1300
+ ## 12. Data layout, threading, the worker
1301
+
1302
+ **One `SharedArrayBuffer` for the whole cloth world**, not one per instance. `WorkerSystem`'s model is
1303
+ a single shared buffer, a single command region and a single atomic publishing one in-flight step, and
1304
+ `WorkerFluidSystem` already shows how a variable set of simulated things fits that model: the command
1305
+ region carries a count and then a list of ids to step. Cloth does the same — each instance gets a
1306
+ region inside the buffer, and the command region names which instances are live this step, so sleeping
1307
+ (P5) and culled (§12.1) instances cost nothing but their absence from a list.
1308
+
1309
+ SoA throughout:
1310
+
1311
+ | Region | Type | Contents |
1312
+ |---|---|---|
1313
+ | particle state | `Float32Array` | `x`, `x_prev`, `v`, `y`, inverse mass, radius |
1314
+ | animated targets | `Float32Array` | `s`, backstop origin + normal |
1315
+ | topology | `Int32Array` | edge pairs, bend stencils, colour ranges, tether anchors |
1316
+ | rest data | `Float32Array` | rest lengths, bend weights, `d_geo` |
1317
+ | duals | `Float32Array` | `λ` and `k` per persistent constraint |
1318
+ | colliders | `Float32Array` | packed records for this step |
1319
+ | contacts | `Float32Array` | transient rows + their warm-start `λ`, keyed by (particle, collider slot) |
1320
+
1321
+ `ClothDynamics` reaches the worker through the command region, written every step — a dozen words into
1322
+ memory the worker already shares, cheaper than tracking dirtiness, and it keeps
1323
+ `cloth.dynamics.slack = 0.2` working live, which is the point of a value object rather than a preset
1324
+ that has to be re-applied.
1325
+
1326
+ `Float32` for particle state, not `Float64`. The simulation runs in the cloth's **local frame**, so
1327
+ coordinates are garment-sized rather than world-sized and f32 has ample precision; the payoff is half
1328
+ the bandwidth in the loop that dominates. The local frame is not a memory optimisation that happens to
1329
+ help — it is the same choice that makes P7's inertia handling natural, and the precision win follows.
1330
+ Write-back converts local f32 to world `Transform64` at the boundary, once per particle per step.
1331
+
1332
+ Transient contact rows need their multipliers warm-started across steps to be worth anything, so they
1333
+ are keyed by `(particle index, collider handle)` and matched on the next step. A collider that leaves
1334
+ the index drops its slot and its contacts start cold, which is correct.
1335
+
1336
+ **M2 made "slot" exact and it matters.** The key is the collider's **handle in the index**, not its
1337
+ record index in the cloth's own per-step table: that table is whatever this step's broadphase returned,
1338
+ in whatever order, so a record index names a different collider from one step to the next. Storage is a
1339
+ fixed `CLOTH_CONTACT_SLOTS` per particle inside `ClothState`'s single buffer — four, measured never to
1340
+ saturate on a twenty-collider scene and to average a tenth of one — which keeps §12's one-allocation
1341
+ property and bounds the worst case at the four *most violated* colliders, which is the four that matter.
1342
+
1343
+ **The worker.** `WorkerClothSystem` is a `WorkerSystem` subclass and follows `WorkerFluidSystem`
1344
+ exactly, because that pattern is already proven in this repo: `collect` packs colliders and animated
1345
+ targets into shared memory and writes the command words, a single `Atomics.store` publishes the step,
1346
+ `apply` reads the result on the next tick, and the fixed-step gate guarantees the worker is idle during
1347
+ every system's `fixedUpdate`. The split is the same shape too — arbitrary user-facing work (component
1348
+ reads, `Transform64` sync, index queries) stays on the main thread; the pure numeric step crosses.
1349
+
1350
+ The standing gate is the one the fluid system already holds itself to: **`ClothSystem` and
1351
+ `WorkerClothSystem` must produce bit-identical results.** Identical code over identical data in an
1352
+ identical order. That is what makes the worker a deployment choice rather than a behavioural fork, and
1353
+ it is why the core is a pure function over typed arrays from milestone zero even though the worker does
1354
+ not arrive until milestone five.
1355
+
1356
+ Testing the bridge needs no worker: `SystemWorkerLoopback` gives a real `SystemWorkerHost`, a real
1357
+ `SharedArrayBuffer` and real `Atomics` in-process, with message delivery and step execution as explicit
1358
+ events a spec can order. Only the thread is faked.
1359
+
1360
+ `SharedArrayBuffer` requires a cross-origin isolated page (`COOP`/`COEP`), which `WorkerFluidSystem`
1361
+ already documents. The main-thread `ClothSystem` is the fallback where that is not available, and it is
1362
+ not a degraded mode — it is the same code.
1363
+
1364
+ ### 12.1 Culling
1365
+
1366
+ Cloth outside the view frustum stops stepping, which for a crowd is the difference between a budget and
1367
+ a problem. Resuming without a pop means blending from the animated pose back to the simulated one over
1368
+ a short window rather than snapping — the same `blend` machinery from §3.1, driven by the system
1369
+ instead of the author.
1370
+
1371
+ ---
1372
+
1373
+ ## 13. Reuse ledger
1374
+
1375
+ What this design takes from the engine rather than building:
1376
+
1377
+ | Need | Existing code |
1378
+ |---|---|
1379
+ | Vector and quaternion math | `core/geom/vec3/*` (95 functions), `core/geom/3d/quaternion/*` |
1380
+ | Mesh topology, adjacency, bending stencils | `core/geom/3d/topology/struct/binary/` — `BinaryTopology`, `bt_edge_read_diamond`, `bt_edge_is_boundary`, `bt_collect_boundary_segments` |
1381
+ | Proxy decimation | `bt_mesh_simplify_by_error`, `bt_mesh_compute_vertex_quadrics` |
1382
+ | Mesh cleanup | `geometry_deduplicate_vertices` |
1383
+ | Graph colouring | `core/graph/coloring/colorizeGraphGreedy.js`, `validateGraphColoring.js` |
1384
+ | Collider shapes and their SDFs | `core/geom/3d/shape/*` — closed-form `signed_distance_at_point` on every primitive |
1385
+ | Collider AABBs, pose caching | `core/geom/3d/aabb/*`, `aabb3_matrix4_project` |
1386
+ | Collider ECS wiring | `Collider`, `ColliderFlags`, `ColliderObserverSystem` (as the pattern) |
1387
+ | "Opt a collider into a second simulation" | `FluidObstacle` + `FluidObstacleSystem`, `AcousticBody` |
1388
+ | Collider index shape | `AcousticOccluderIndex` + `OccluderBody` |
1389
+ | Component holds a built shared asset | `Collider#shape`, `ParticleEffect#program` — the convention `ClothRig#proxy` follows |
1390
+ | Surface material combination | `physics/contact/combine_material.js` |
1391
+ | Constraint-row doctrine | `physics/constraint/solve_constraints.js` |
1392
+ | Subtree walk | `TransformAttachmentSystem#findChildrenOf` / `#countChildrenOf`, `TransformAttachment` |
1393
+ | Animated targets | `mesh_apply_skeletal_vertex_skinning` (flat arrays, worker-safe) |
1394
+ | Wind / aerodynamics | `FluidField#sampleVelocity`, `fluid_build_world_to_grid`, `GlobalFluidEffector` |
1395
+ | Worker offload | `ecs/async/WorkerSystem.js`, `SystemWorkerHost`, `SystemWorkerLoopback`, `WorkerFluidSystem` as the worked example |
1396
+ | Fixed step + render interpolation | `PhysicsSystem`'s producer/`__interp_restore` contract |
1397
+ | Transforms | `Transform64`, `Node3D` |
1398
+ | Particle → render-vertex mapping | `Skin` — joints + inverse-bind matrices + the four-weight palette; cloth writes joints and the existing pass does the rest |
1399
+ | Reaching a model's joints from its entity | `SceneBundleInstance` (`skins`, `nodes` by name), `register_instance_animation` |
1400
+ | Deformation, bounds refresh, BLAS refit | `GPUMeshSkinningContext`, `shader_skin_matrix_prep`, `bounds_refresh/` — all of it inherited by driving joints rather than vertices |
1401
+ | Non-finite tripwire pattern | `find_non_finite_physics_state.js` |
1402
+ | Strippable assertions | `core/assert.js` |
1403
+ | Serialisation | the `*SerializationAdapter` pattern and its binary codecs |
1404
+
1405
+ ---
1406
+
1407
+ ## 14. New shared code this justifies
1408
+
1409
+ Three pieces belong in `core`, not in `cloth`, because the cloth need exposes a gap the engine has
1410
+ anyway:
1411
+
1412
+ 1. **Analytic SDF gradients** for sphere, capsule, box, cylinder and plane, as free functions in
1413
+ `core/geom/3d/shape/sdf/`. **M2 built them.** Before it, `signed_distance_gradient_at_point` on
1414
+ sphere, capsule, box and cylinder was `compute_signed_distance_gradient_by_sampling` — four SDF
1415
+ evaluations plus a normalise, for shapes whose gradients are two lines of algebra. The shape classes
1416
+ call the new functions, and so do their `signed_distance_at_point`s, so there is one implementation
1417
+ of each field rather than two that can drift; cloth calls the same functions on packed data.
1418
+
1419
+ One thing the sampled version was quietly wrong about, and it is the reason a degenerate normal
1420
+ needed a decision rather than a default: at a sphere's centre the forward difference returns
1421
+ `(1,1,1)/√3`, which is unit length and entirely an artefact of sampling three positive offsets from
1422
+ one point. The analytic functions return a documented arbitrary direction there instead, because a
1423
+ gradient of zero carries no force and a particle that reaches the exact centre of a sphere would
1424
+ stay there for ever — and "it does not get stuck" is the second design commitment in §1.
1425
+
1426
+ 2. **A 3D uniform hash grid.** **M4 built it**, as `core/geom/3d/hash-grid/PointHashGrid3.js`, and
1427
+ **not** modelled on `core/geom/2d/hash-grid/SpatialHashGrid.js` as this line asked for. The 2D
1428
+ grid is a persistent incremental structure over a bounded cell array holding AABBs with
1429
+ identity; a cloth's particles are points, carry no identity across steps, live in an unbounded
1430
+ domain and all move every step, so the operation that matters is *rebuild* and insert/remove
1431
+ never runs. `PointHashGrid3` is a counting sort — count, prefix-sum, scatter — into a
1432
+ power-of-two hash of the integer cell, with a `forEachNear` that walks the 27 neighbouring
1433
+ cells and de-duplicates the buckets they hash into. Useful anywhere a broadphase over many
1434
+ small equal-sized *points* is wanted; anything with extent and identity still wants the 2D
1435
+ grid's shape. `MEASUREMENTS.md` §34.
1436
+
1437
+ 3. **`PlaneShape3D`.** **M2 built it**: the half-space `{ p : n·p − offset ≤ 0 }`, with the outward
1438
+ normal and its offset, a constant gradient and no degenerate configuration anywhere. A box standing
1439
+ in for a ground plane has to be large enough that nothing reaches its edge and thin enough that
1440
+ nothing tunnels through it, and those pull against each other in `Float32`.
1441
+
1442
+ It is the one shape in the family that is **unbounded**, and that is a real cost paid in three
1443
+ places: `support` is left unimplemented, because `argmax(p·d)` over a half-space is at infinity for
1444
+ all but one direction and a large finite point would be a silently wrong contact manifold rather
1445
+ than a loud failure; `sample_random_point_in_volume` likewise, since there is no uniform
1446
+ distribution on an infinite volume; and `compute_bounding_box` answers with `±Infinity` on the
1447
+ unbounded axes, which is what the set is. A consumer that cannot hold an infinite AABB must not be
1448
+ handed a plane — which is why `ClothColliderIndex` is a linear scan rather than a BVH, and why it
1449
+ bounds a plane from its world normal instead of projecting that box.
1450
+
1451
+ 4. **A shortest-arc quaternion**, `core/geom/3d/quaternion/quat3_shortest_arc.js` — the minimal,
1452
+ twist-free rotation carrying one unit vector onto another. **M1 needed it and the family did not
1453
+ have it**: `quat3_*` had `multiply`, `integrate`, `nlerp` and the uint32 codecs but nothing that
1454
+ answers "orient this bone along that direction", which is the whole of §11.1's write-back. It is
1455
+ also the one place in the family with a genuine discontinuity — no continuous choice of axis exists
1456
+ on the whole sphere, so an antipodal pair has to pick one — and having it in `core` with a spec
1457
+ around that case is better than having it inlined in a write-back loop without.
1458
+
1459
+ Test helpers for all of it live inside the `.spec.js` files or in `__fixtures__`, per the repo rule —
1460
+ a shared helper module would ship on npm.
1461
+
1462
+ ---
1463
+
1464
+ ## 15. MagicaCloth2: what we take, what we leave
1465
+
1466
+ MagicaCloth2 is the reference and it is a good one. It has shipped, it is fast, and its feature set is
1467
+ the accumulated answer to a decade of production complaints. Taken:
1468
+
1469
+ - **Two cloth kinds over one solver.** MeshCloth and BoneCloth differ only in how particles are seeded
1470
+ and how results are written back. This is right and §11 copies it — expressed as component presence
1471
+ rather than an enum.
1472
+ - **A proxy mesh decoupled from the render mesh**, with distance-based reduction and custom skinning
1473
+ back to the render vertices. Also right; §11.3 does the same thing with `bt_mesh_simplify_by_error`.
1474
+ - **The inertia model.** World and local inertia fractions, movement and rotation speed limits, an
1475
+ anchor that cancels inertia for a character on a moving vehicle, teleport detection with Reset/Keep
1476
+ modes, and a stabilisation window after reset. This is the least glamorous part of the package and
1477
+ the most valuable; P6 and P7 are it, nearly verbatim.
1478
+ - **Max-distance and backstop** as first-class constraints rather than debugging aids. P3 and P4 lean on
1479
+ them harder than MagicaCloth does — here the leash is the correctness argument, not a polish pass.
1480
+ - **Tether/LRA** as the answer to over-stretch at low iteration counts.
1481
+
1482
+ Left:
1483
+
1484
+ - **The parameter surface.** MagicaCloth2's serialised data is a dozen constraint blocks, several of them
1485
+ animation curves over "depth", and its per-constraint files run to hundreds of lines of tuning. That is
1486
+ the direct consequence of a PBD solver whose apparent stiffness depends on iteration count: when the
1487
+ physical meaning of a slider moves with the budget, you end up shipping a curve per slider. AVBD's
1488
+ parameters do not move that way, so §3.3 can be one small value object — and the per-particle profile
1489
+ that MagicaCloth authors with curves falls out of `d_geo` instead (§3.4).
1490
+ - **Angle restoration and angle limit constraints.** These exist to give PBD chains a restoring force
1491
+ that bending alone cannot supply at low iteration counts. With a solver that converges, bend rows plus
1492
+ tethers cover the same ground with less to configure.
1493
+ - **A separate spring constraint.** Subsumed by the slack row with a non-zero radius.
1494
+ - **A distance constraint solved twice per substep** (before and after collision). An artefact of the
1495
+ Gauss-Seidel ordering; the augmented Lagrangian's dual update does this work.
1496
+ - **Its collision layering model.** We already have `Collider`, layers and masks; a parallel system would
1497
+ be a second thing to keep in sync.
1498
+ - **Its wind zones.** We have a fluid simulator (§10).
1499
+
1500
+ ---
1501
+
1502
+ ## 16. State of the art
1503
+
1504
+ **The line this design sits on.** PBD → XPBD → substepped XPBD → VBD → AVBD.
1505
+
1506
+ - **XPBD** (Macklin, Müller & Chentanez) made PBD stiffness independent of iteration count by
1507
+ introducing compliance and a per-constraint multiplier. **Small Steps in Physics Simulation**
1508
+ (Macklin et al. 2019) then showed that *n* substeps with one iteration each beats one step with *n*
1509
+ iterations — less constraint error, far less artificial damping, and better behaviour across a wider
1510
+ stiffness range than Krylov-based implicit solvers. Together these are the state of practice: Chaos
1511
+ Cloth, MagicaCloth2 and Blender's cloth all sit here.
1512
+ - **Vertex Block Descent** (Chen, Liu, Yang & Yuksel, SIGGRAPH 2024) reframed the step as block
1513
+ coordinate descent on implicit Euler's variational form, solving one 3×3 system per vertex per
1514
+ iteration. Unconditionally stable at any iteration count, no line search, and it colours the vertex
1515
+ graph rather than the constraint graph. Its reported failure mode is exactly the one that matters here:
1516
+ it struggles to converge under high stiffness ratios and has no mechanism for enforcing hard
1517
+ constraints — which is what a pinned garment on a rigid body *is*.
1518
+ - **Augmented Vertex Block Descent** (Giles, Diaz & Yuksel, SIGGRAPH 2025) fixes precisely that with an
1519
+ augmented Lagrangian: hard constraints at effectively infinite stiffness without the instability, plus
1520
+ substantially better convergence under high stiffness ratios. Reference implementations exist in 2D,
1521
+ in Metal, in PhysX, in Houdini, and — relevant to this engine — as a WebGPU solver.
1522
+ - **Going Further With Vertex Block Descent** (Saillant et al., 2025) extends VBD to higher-order
1523
+ elements and confirms that substepping improves its convergence — which is why §5.2 substeps rather
1524
+ than only iterating.
1525
+
1526
+ **The line this design does not sit on.** **Incremental Potential Contact** and its descendants —
1527
+ **C-IPC** for codimensional objects, **GIPC** and **AGIPC** on GPU — guarantee intersection-free,
1528
+ inversion-free results through log-barrier contact and continuous collision detection. They are the
1529
+ correct answer when correctness is the requirement, and they are the wrong answer at a millisecond
1530
+ budget. We take one idea from that family: IPC's smooth static/dynamic friction transition, which VBD
1531
+ also adopts.
1532
+
1533
+ **Self-collision** is where the field is currently moving, because parallel position solvers have made
1534
+ it the bottleneck rather than the solve. **Air Meshes** (Müller et al. 2015) tessellate the space
1535
+ between objects and prevent element inversion, which handles untangling robustly and automatically but
1536
+ requires maintaining a volumetric mesh. **Global Intersection Analysis** (Baraff, Witkin & Kass,
1537
+ "Untangling Cloth", 2003) is history-free and resolves tangles as soon as geometry permits — the
1538
+ property P4(a) is built on, even though we implement a far cheaper approximation of it. Recent work on
1539
+ hierarchical culling via discrete curvature targets the same bottleneck.
1540
+
1541
+ **Industry.** Chaos Cloth (Unreal) is substepped XPBD with long-range attachments, max distance and
1542
+ backstop distance/radius — the same safety constraints §7 relies on, which is useful independent
1543
+ confirmation that they are what production actually needs. Comparative studies of VBD against PBD in
1544
+ Unity report parity at low vertex counts and a widening VBD advantage as the count rises, which matches
1545
+ the per-iteration cost story: VBD does more arithmetic per vertex and far less coordination.
1546
+
1547
+ Sources:
1548
+ [Vertex Block Descent](https://arxiv.org/abs/2403.06321) ·
1549
+ [VBD project page](https://graphics.cs.utah.edu/research/projects/vbd/) ·
1550
+ [Augmented Vertex Block Descent](https://graphics.cs.utah.edu/research/projects/avbd/) ·
1551
+ [AVBD reference implementation](https://github.com/savant117/avbd-demo2d) ·
1552
+ [WebGPU AVBD](https://github.com/jure/webphysics) ·
1553
+ [Going Further With Vertex Block Descent](https://onlinelibrary.wiley.com/doi/10.1002/cav.70039) ·
1554
+ [XPBD](https://matthias-research.github.io/pages/publications/XPBD.pdf) ·
1555
+ [Small Steps in Physics Simulation](https://mmacklin.com/smallsteps.pdf) ·
1556
+ [Untangling Cloth](https://dl.acm.org/doi/10.1145/882262.882357) ·
1557
+ [Air Meshes for Robust Collision Handling](https://dl.acm.org/doi/10.1145/2766907) ·
1558
+ [Codimensional IPC](https://arxiv.org/pdf/2012.04457) ·
1559
+ [Efficient Self-Collision Culling via Discrete Curvature](https://www.mdpi.com/2227-7390/14/9/1504) ·
1560
+ [VBD vs PBD in Unity](https://www.mdpi.com/2076-3417/14/23/11072) ·
1561
+ [Chaos Cloth](https://dev.epicgames.com/documentation/en-us/unreal-engine/clothing-tool-in-unreal-engine)
1562
+
1563
+ ---
1564
+
1565
+ ## 17. Milestones
1566
+
1567
+ Each milestone is shippable and each `done` names evidence that ran. Nothing is reported complete on
1568
+ the strength of code existing.
1569
+
1570
+ **M0 — the solver core. DONE, 2026-09-10.** `ClothState`, `cloth_step`, the vertex update, stretch and
1571
+ bend rows, colouring. Pure functions over typed arrays; no ECS, no worker, no rendering.
1572
+ *Proofs, all green:* finite-difference agreement between each row's analytic gradient and its numerical
1573
+ gradient; the P1 property test (see the correction in §7 P1 — strict per-update energy monotonicity is
1574
+ not true and the gate is what replaced it); a measured choice of α, β, γ and `k_min`/`k_max` with the
1575
+ sweep recorded in `MEASUREMENTS.md`, nothing copied; the performance budget measured on real topology.
1576
+ 43 tests across six spec files.
1577
+
1578
+ **M0 changed the design in six places**, each with the measurement behind it in `MEASUREMENTS.md` and
1579
+ each folded back into §5.2, §5.3, §6, §7 P1 and §7 P5 above. In one line each: the multiplier and the
1580
+ penalty band apply only to *hard* rows; the band is a ratio of `m/h²` rather than a stiffness; the PSD
1581
+ half of the geometric-stiffness term has to be kept; the 3×3 solve has to be an LDLᵀ; an SPD Hessian
1582
+ gives a descent direction rather than a monotone step; and P5's jitter mechanism does not reach soft
1583
+ rows, which need M1's damping.
1584
+
1585
+ **Deliberately not in M0:** Chebyshev acceleration (§5.2) is gated on a particle not being in contact,
1586
+ and contacts arrive at M2, so there is nothing here to measure it against. The velocity clamp named in
1587
+ P1 is derived from `ClothDynamics#thickness` and belongs with the component that carries it — and it
1588
+ would have masked the property M0 exists to measure.
1589
+
1590
+ **M1 — chains end to end. DONE, 2026-09-10.** `Cloth`, `ClothFlags`, `ClothExclude`, `ClothDynamics`,
1591
+ `ClothDynamicsFlags`, `cloth_dynamics_library.js`, `ClothSystem`, subtree seeding and write-back, the
1592
+ slack and tether rows, the strain-limit row, the inertia model, teleport handling, sleep, and the
1593
+ velocity clamp P1 deferred. No collision.
1594
+ *Proofs, all green:* P2, P5, P6 and P7, each with a companion test that runs the same scenario with the
1595
+ mechanism switched off; `ClothDynamics` value semantics and the measured mapping; three ordering tests
1596
+ — the derived order, the recomposition idempotency that makes it not matter, and a bound on the
1597
+ divergence when it is inverted; a second playground page, `playground/rig.html`, driving the real
1598
+ ECS with a rope, a chain, a five-strand rig under one `Cloth`, a hanging sign with a `ClothExclude`,
1599
+ and a nested pair. **43 tests across four spec files** — the leash row's 8, the system's 9, the
1600
+ pathology budget's 11, the value semantics and the mapping's 15 — plus 5 for the shortest-arc
1601
+ primitive and 4 more in `system_execution_order.spec.js`, for 52 in all. The engine suite is green
1602
+ at 18,179.
1603
+
1604
+ **M1 changed the design in seven places**, each with the measurement behind it in `MEASUREMENTS.md`
1605
+ §9–15 and each folded back above. In one line each: three of §6's clamps had the wrong sign and would
1606
+ never have bound; §3.4's leash radius needs a factor of two before `slack = 1` means "no leash"; §7
1607
+ P1's velocity clamp cannot be derived from `thickness`, because that is a tunnelling bound and a
1608
+ tunnelling bound is *below* ordinary cloth speeds; §11.1's chain bending has no diamond to build a
1609
+ hinge on and uses a skip row instead; §11.1's write-back has to write the **local** transform as well
1610
+ as the world one; the levers no longer close the frame budget one at a time; and the strain-limit row
1611
+ buys a third of the over-stretch rather than the allowance it asks for, which makes `stretch` the
1612
+ weakest field in the parameter set.
1613
+
1614
+ **And one thing M1 got wrong before it got it right, which is worth recording because the wrong answer
1615
+ was plausible.** §4.1 correctly identified that neither of the engine's two ordering mechanisms can
1616
+ place cloth after a poser, and the first attempt was to add a third — an execution-phase number on
1617
+ `System`, with a `PostPose` value. That put the vocabulary of animation into `engine/ecs`, which has
1618
+ none, to buy an ordering the design should not have needed in the first place. Removing the need was
1619
+ both smaller and better: writing the local transform makes the write-back idempotent, which turns the
1620
+ placement into a bounded quality question and leaves the scheduler alone.
1621
+
1622
+ **Deliberately not in M1:** P4(d)'s bounded escape hatch, which needs a per-particle residual monitor
1623
+ and belongs with the collision rows that make a particle get *stuck* in the first place — a chain has
1624
+ no configuration to be stuck in. Chebyshev acceleration, still gated on contacts that arrive at M2. `β`,
1625
+ which M0 could not choose and M1 has no transient rows to choose it with either — every row M1 adds is
1626
+ persistent. `ClothSerializationAdapter` and its siblings: nothing in M1's scope list names them, and a
1627
+ codec written before `ClothRig` exists would be revised by M3 before it was ever loaded.
1628
+ Interpolation: cloth writes `Transform64` at the fixed rate and §12's producer/`__interp_restore`
1629
+ contract is not wired, which shows as a cloth updating at the fixed rate rather than the frame rate
1630
+ and is a visible-but-not-wrong gap. M5 is where it belongs, with the worker.
1631
+ **This is the first shippable feature.**
1632
+
1633
+ **M2 — collision. DONE, 2026-09-10.** `ClothCollider`, `ClothColliderFlags`, `ClothColliderSystem`,
1634
+ `ClothColliderIndex`, the packed record and its swept bounds, analytic SDF gradients and
1635
+ `PlaneShape3D` in `core` (§14.1, §14.3), the contact row and its friction row, the backstop row, and a
1636
+ measured `β` and contact penalty band.
1637
+ *Proofs, all green:* the packed field dispatch agreeing with the shape objects it was extracted from,
1638
+ across all five kinds under a non-axis-aligned pose; the index's swept bounds, layer filter, handle
1639
+ reuse and plane handling; the contact row against Coulomb's own answer for a slope; friction's anchor
1640
+ dragging cloth with a sliding surface; P3 measured swept against unswept from 2 to 40 m/s; the whole
1641
+ stack through a real `EntityManager`, including a collider arriving, leaving, being filtered out and
1642
+ waking a sleeping cloth. **53 tests across five new cloth spec files** — 15 for the collider layer, 21
1643
+ for the two new rows, 12 for the ECS path — plus **21 in `core`** across two more, for the SDF family
1644
+ and `PlaneShape3D`, and the M0 and M1 suites unchanged at 93. The engine suite is green at 18,251. A third playground page, `playground/collide.html`, with six collider
1645
+ scenes, a sweep toggle and the contact band live.
1646
+
1647
+ **M2 changed the design in six places**, each with the measurement behind it in `MEASUREMENTS.md`
1648
+ §16–23 and each folded back above. In one line each: §8.2's swept pose cannot be a lerp of two
1649
+ matrices, because that is not a rotation and it shrinks the collider by twice a garment's thickness at
1650
+ the anchor's own rotation limit; sweeping the poses does nothing unless the contact **set** is swept
1651
+ too, and without that a capsule at 20 m/s produced *no rows at all*; §6's collision and friction rows
1652
+ cannot be soft penalties, because a soft row's whole force is 4.6 N against the 376 N an 8 m/s arrival
1653
+ needs; friction's clamp is one-sided, because its `C` is a magnitude; §5.4's Jacobi treatment is not
1654
+ needed for a collider contact, which is unary; and Chebyshev acceleration, which §5.2 carried as
1655
+ available, loses on every axis and is gone.
1656
+
1657
+ **Deliberately not in M2:** P4(d)'s bounded escape hatch, still — M2 has the contacts that make a
1658
+ particle get stuck, and also measured the one stuck configuration whose *residual is zero*, which is
1659
+ the quantity the escape hatch was to watch (§7 P4). It belongs with the self-collision of M4, where a
1660
+ particle can be pinched between two rows rather than merely held by one. The backstop row is built,
1661
+ specced and driven by the playground, but nothing **authors** one: its plane comes from a garment's own
1662
+ skinned surface and a skinned garment is M3. Two-way coupling, per §2. `ClothSerializationAdapter` and
1663
+ its siblings, per M1's own reasoning.
1664
+
1665
+ **M3 — skinned garments, the rigged path. DONE, 2026-09-10.** `ClothRig`, `ClothProxy`,
1666
+ `cloth_proxy_from_joints` (§11.3 steps 5–8), the rig seeder, and joint write-back into
1667
+ `Node3D.transform_local`. **The unrigged path is not here** — §11.3 step 9's generated joint set and
1668
+ generated skin — and §18 carries what M3 measured about it instead.
1669
+ *Proofs, all green:* the P8 corpus for a joint tree, each refusal naming what an author can act on;
1670
+ the rig path end to end through a real `EntityManager` — the authority claim, the tether under a
1671
+ swinging shoulder, `blend = 0` reproducing the baked bind pose, a model that has not loaded waiting
1672
+ rather than failing, a proxy that does not fit its skin refused once by name, and a rigged cape
1673
+ colliding with a body; and the entity path unchanged beside it. **23 tests across two new spec
1674
+ files** — 12 for the proxy build, 11 for the rig path — plus 14 unchanged for the pose query M3
1675
+ refactored. The engine suite is green at 18,274. A fourth playground page,
1676
+ `playground/garment.html`, with a `Node3D` skeleton, four garments and four motion profiles.
1677
+
1678
+ **M3 changed the design in four places**, each with the measurement behind it in `MEASUREMENTS.md`
1679
+ §24–29 and each folded back above. In one line each: §11.2's writable handle is *not* what the
1680
+ animation systems write, and cloth has to claim `TransformAuthority.CPU` to make its write-back
1681
+ visible at all; §11.1's rig path is not "live" for a rigged garment, because cloth owns those joints
1682
+ and their authored pose is the proxy's baked bind pose; §11.3 step 5's weight-derived fixed set is
1683
+ the unrigged rule and the topology answers better for a rigged garment; and §11.2's "~60 output
1684
+ joints" is four to six times short of what a four-weight palette needs for a few per cent of
1685
+ fidelity.
1686
+
1687
+ **And the strongest result is a number rather than a correction.** §11 claims the two paths are "the
1688
+ solver, identical either way". Built as an entity subtree and as a skin's joints, the same garment
1689
+ produces **bit-identical** particle trajectories across three fabrics and three motion profiles.
1690
+ That is what the row builder and the pose reconstruction being *one* function each buys, and it is
1691
+ why M3 moved both out of the entity path's files rather than copying them.
1692
+
1693
+ **Deliberately not in M3:** the unrigged path, per §17's own sequencing and behind §18's measured
1694
+ budget. §11.3 step 10's bind-pose collision validation, which `cloth_proxy_from_joints` cannot do
1695
+ because it has a joint tree and no collider set — and which `MEASUREMENTS.md` §29 makes the argument
1696
+ for, because a garment authored inside its own body reads as a *tether* failure and costs an hour to
1697
+ diagnose. `ClothProxy`'s binary codec and `ClothRigSerializationAdapter`, for M1's own reason: a
1698
+ codec written before the unrigged path exists would be revised before it was ever loaded.
1699
+
1700
+ **M4 — self-collision. DONE, 2026-09-11.** `core/geom/3d/hash-grid/PointHashGrid3.js`, the
1701
+ particle-particle row (`solver/constraint/cloth_self_row.js`), the pair search
1702
+ (`solver/cloth_self_find.js`) with its exclusion set, and `ClothState`'s pair storage, Jacobi
1703
+ scratch and `self_radius`. Wired into `ClothSystem` behind `ClothDynamicsFlags.SelfCollision`,
1704
+ which three library entries now set. **M4b is not here** — point-triangle and edge-edge, per §9's
1705
+ own deferral — and §34 is the argument for re-pricing it before anyone builds it.
1706
+ *Proofs, all green:* the P4 tangle spec extended to self-intersection counts, as this line asks —
1707
+ a folding sheet crossing itself, and the row removing more than half of those crossings where the
1708
+ same sheet without it does not; the row's sign, and its Jacobi scratch being rebuilt rather than
1709
+ accumulated so a pair that separates stops pushing; the exclusion rule against a stretch row, a
1710
+ bend stencil and a pinned particle, and each pair found once with the lower index first; and the
1711
+ grid's counting sort, its 27-cell walk, its de-duplication across hash collisions and its
1712
+ independence from where in space the points sit; and the radius at both ends — a sheet's closest
1713
+ ungoverned pair being exactly two hops, strips measuring their gap rather than their link length, and
1714
+ a pinned pair not counting because no row will ever act on it. **22 tests across four new spec
1715
+ files** — the grid's 9, the search's 4, the row's 4, the radius's 5 — plus the library's
1716
+ self-collision assertion rewritten and `ClothState`'s buffer test extended. The engine suite is green
1717
+ at 18,296. The garment playground gains a self-collision toggle and a live pair count beside its
1718
+ contact count.
1719
+
1720
+ **M4 changed the design in four places**, each with the measurement behind it in `MEASUREMENTS.md`
1721
+ §30–37 and each folded back above. In one line each: §9's radius is the **proxy's** resolution and
1722
+ not the fabric's thickness, which is the difference between removing 21% of a sheet's
1723
+ self-intersections and removing 82%; §14.2's 3D hash grid is *not* modelled on the 2D one, because
1724
+ a cloth's particles are points without identity that all move every step, so the operation that
1725
+ matters is rebuild and insert/remove never runs; §9's list of which entries set the flag was drawn
1726
+ along what the garment is rather than how far the fabric bends, and leather — at the top of the
1727
+ bend scale — does not tangle at all and is made slightly *worse* by the row; and M4a's normal is
1728
+ the line between two particles rather than the surface orientation §9 promises, which satisfies
1729
+ what P4(a) is actually asking for and does it more simply.
1730
+
1731
+ **And one thing the design had no line for at all.** §9 never wrote a radius down, which is how
1732
+ that question stayed open long enough to be got wrong three times. `max(thickness, shortest_row/2)`
1733
+ has an upper end: a diameter reaching the closest pair *no row governs* puts a cloth which is not
1734
+ folded at all in permanent contact with itself. Leather at 20 mm on a 20 mm proxy is exactly that
1735
+ case and found 1,398 pairs a step on a 576-particle sheet that was barely folded (§36). And that
1736
+ distance has to be **measured** rather than assumed to be two hops, because two hops is a fact
1737
+ about sheets: the playground's cape has 8 cm links and an 8.5 cm gap between strips, half what the
1738
+ link length implies, and the assumed ceiling left it with three pairs permanently in contact at
1739
+ rest. `ClothInstance#closest_free_pair` is measured once at seed and the ceiling is two fifths of
1740
+ it. On a sheet the two rules agree exactly, so §31–36 stand. `MEASUREMENTS.md` §37.
1741
+
1742
+ **And the playground earned its keep.** Every measurement from §31 to §36 is on a sheet, because a
1743
+ sheet is the only thing here with a surface to pass through. Put the same row on the geometry M3
1744
+ actually ships and it does something no sheet could have shown: **without it a cape settles at half
1745
+ the width it was drawn at** — 0.178 m against a 0.340 m bind pose — because nothing holds five
1746
+ independent strips apart and gravity swings them all into the same place. With it, 0.351 m. That is
1747
+ not a transient tangle of the kind §32 measured; it is what the garment settles into.
1748
+
1749
+ **Deliberately not in M4:** **conditional storage for the pair list.** `ClothState` is one buffer
1750
+ sized at seed, and M4's three self-collision regions are 16% of it on the §17 workload — 100 KB a
1751
+ garment — whether or not the flag is ever set, which four of the seven library entries never do.
1752
+ Sizing them lazily would make `ClothDynamicsFlags.SelfCollision` a reseed trigger, which it is not
1753
+ today, and that is a change to the reseed contract rather than a tidy-up. `MEASUREMENTS.md` §33.
1754
+ M4b, above. A **swept pair search** — the set is discovered from the
1755
+ positions the last step left, with no margin for the travel of the step about to run, which is the
1756
+ shape of the gap §20 found in the contact set. §35 went looking for it and found the opposite:
1757
+ widening the search a hundred and fifty times over does not move the crossing count, so what is
1758
+ left is not a discovery problem but the tier's own stated limit, and it is M4b's. And **P4(d)'s
1759
+ bounded escape hatch**, which M2's entry above handed to M4 on the grounds that self-collision is
1760
+ what gives a residual monitor something to escape from — measured across ninety-six fold
1761
+ realisations, a self-tangled sheet unties itself every time the gust stops, so M4 still has no
1762
+ configuration to escape from. The case P4(d) names is a particle wedged between a collider *and* a
1763
+ fold, which is collision and self-collision together, and M4 has not measured it.
1764
+
1765
+ **M5 — the worker.** `WorkerClothSystem`, `ClothWorkerCore`, `cloth.worker.js`, the protocol.
1766
+ *Proofs:* bit-parity between `ClothSystem` and `WorkerClothSystem` as a standing gate; loopback specs
1767
+ covering step ordering, message ordering and shutdown; a measured main-thread cost reduction.
1768
+
1769
+ **M6 — wind.** Fluid-field sampling, aerodynamic drag, the ambient fallback.
1770
+ *Proofs:* a playground with a banner in a simulated wake; a measured cost showing the per-step sampling
1771
+ stays inside budget. Cuttable without affecting anything else.
1772
+
1773
+ **Performance budget — measured at M0, re-measured at M1, and it still does not hold on its own.** One
1774
+ character's full cloth complement — 1,024 particles at 2 substeps × 4 iterations, on a triangulated
1775
+ patch carrying 16.8 row incidences per particle — cost **3.50 ms per frame** at best at M0, against a
1776
+ 2 ms target. **M1's rows made it 4.61 ms**: the strain limit is 0.73 ms (it doubles the stretch table,
1777
+ and the stretch rows are already 69% of the frame), the tether 0.36 ms, the slack row 0.10 ms. What
1778
+ that costs the plan is stated below.
1779
+
1780
+ The estimate was wrong in its reasoning as well as its number: **gathering neighbour positions is not
1781
+ what dominates.** The controlled test is to relabel the source vertices at random, which destroys the
1782
+ locality `cloth_color_order` provides and changes nothing else — same colouring, same rows, same
1783
+ arithmetic. It costs nothing measurable at the 1,024 particles §17 budgets for (the whole state fits in
1784
+ L2) and 11% at four times that size. So the *entire* memory-locality component of the gather is a few
1785
+ per cent of the frame, and a layout optimisation has at most 11% to win.
1786
+
1787
+ Deleting the workload piece by piece puts 69% of the frame in the stretch rows, 18% in the bend rows
1788
+ and 7% in everything else. That is a split of what each row kind *causes*, not of the arithmetic in
1789
+ its accumulate: the variants sit in different physical states, and an isolated loop over one accumulate
1790
+ measures a converged mesh rather than a moving one and disagrees with the deletion by a factor of five
1791
+ on the stretch row. `MEASUREMENTS.md` §7 carries the discrepancy rather than a story that resolves it.
1792
+
1793
+ The levers, priced at M0 (`MEASUREMENTS.md` §7) and again on M1's row set (§14):
1794
+
1795
+ | Lever | M0's rows | M1's rows |
1796
+ |---|---|---|
1797
+ | Fewer iterations — 1,024 at 2×**2** | **1.69 ms** inside | **2.38 ms** over |
1798
+ | Fewer substeps — 1,024 at 1×4 | **1.68 ms** inside | **2.40 ms** over |
1799
+ | Fewer particles — ~500 at 2×4 | **1.54 ms** inside | **2.53 ms** over |
1800
+
1801
+ **No single lever reaches 2 ms any more.** Each of them lands inside when a second is spent alongside
1802
+ it — 400 particles at 2×4 is 1.72 ms, 576 at 2×2 is 1.28 ms, 1,024 at 1×2 is 1.17 ms — so this is a
1803
+ sizing decision rather than a wall, and it is one the library now makes explicitly: every garment entry
1804
+ spends two levers and says which two. The barycentric binding fallback from §11.2 is still not needed.
1805
+
1806
+ Every figure here is the best of four independent rounds, which agree to ±5%. Cost is close to linear
1807
+ in both particles and sweeps, so any one lever is enough on its own and they compose. **Note what the worker does not do:** §12 moves this off the main thread, it does
1808
+ not make it cheaper, so "2 ms on the worker" with several characters in flight is a scheduling question
1809
+ this measurement does not answer.
1810
+
1811
+ **Re-measured at M2, and the library is not re-sized.** M2 adds a broadphase pass per particle per
1812
+ step, up to four contact rows per particle, and two field evaluations per contact per iteration. On the
1813
+ same workload: 4.43 ms with no collider system against M1's 4.61 — agreement to 4%, inside M1's own
1814
+ spread — 4.47 ms with a collider out of range, and 4.6 to 5.5 ms with one to twenty colliders touching.
1815
+ The column is not monotone in the collider count, because the variants sit in different physical states
1816
+ and a cloth draped over a sphere is not the same workload as one hanging free; §7's warning about
1817
+ attributing cost by deletion applies unchanged. What it licenses is that the collision layer costs
1818
+ between nothing and a quarter of a frame and does not scale with the collider count over the range a
1819
+ character occupies. Every library entry's own budget is untouched. `MEASUREMENTS.md` §23.
1820
+
1821
+ Re-measure at M4 and M5.
1822
+
1823
+ ---
1824
+
1825
+ ## 18. Risks and open questions
1826
+
1827
+ **AVBD has a short track record for cloth. — MEASURED, and the risk was real.** VBD's paper covers
1828
+ cloth; AVBD's public reference implementations are 2D and rigid-body-focused. The augmented Lagrangian
1829
+ layer is well understood in the abstract, but its interaction with cloth's particular constraint mix —
1830
+ many soft rows, a few hard ones, transient contacts — is not something anyone has published numbers on.
1831
+ M0 found exactly that interaction to be where the design was wrong: **the multiplier must not touch a
1832
+ soft row at all** (it drove a 1 kN/m spring 100× stiffer than Hooke), and **the penalty band is only
1833
+ meaningful relative to `m/h²`**, which is a cloth-specific statement because cloth's mass term is four
1834
+ orders of magnitude below a rigid body's. Both are fixed and measured (§5.2, `MEASUREMENTS.md` §3–4).
1835
+ The core is now stable across 10,000 steps of deliberately absurd cloth, settles a hard chain to 1e-14 J
1836
+ at 80 links deep, and reproduces Hooke exactly on a soft row. The §6 row abstraction still means the
1837
+ descent loop could be replaced with substepped XPBD without touching the constraint definitions, and
1838
+ that fallback still costs one module — but nothing measured so far argues for taking it.
1839
+
1840
+ **Per-vertex Hessian assembly in JavaScript may not hit the budget. — MEASURED, and it does not.**
1841
+ 3.50 ms against a 2 ms target for 1,024 particles at 2×4. *Resolved by:* the plan's own first lever —
1842
+ half the iteration count, or half the particles, lands inside — so this is a sizing decision for M1's
1843
+ library and M3's proxy rather than an open risk. What is *not* resolved is that the cost is
1844
+ concentrated in the stretch row and only a third of that is the gather, so the obvious memory-layout
1845
+ optimisation is aimed at the smaller half. `MEASUREMENTS.md` §7.
1846
+
1847
+ **System ordering. — DISSOLVED rather than resolved.** §4.1 carries the reasoning; in short, the
1848
+ derived score is a *sum* over what a system references, so touching more can only move a system
1849
+ **earlier**, and a consumer of a posed hierarchy touches strictly more than the poser. There is no
1850
+ declaration cloth could have made, and registration order does not break a non-tie. The engine has two
1851
+ ordering mechanisms and neither expresses this.
1852
+
1853
+ The answer is not a third mechanism, it is not needing one: cloth writes each node's **local**
1854
+ transform alongside its world one, so a hierarchy recomposition reproduces the simulated pose rather
1855
+ than replacing it — measured at 1.7e-15 m — and the placement stops being a correctness question.
1856
+ *What is left, and it is a real cost:* running before the poser means the cloth's shape is one fixed
1857
+ step stale, which measures at a few centimetres on a 1.6 m rope under ordinary motion and up to a
1858
+ fifth of its own length at the sharpest reversal of a ±9 m/s square wave. It does not accumulate.
1859
+ An application that cares registers accordingly and gets nothing, because this is not a tie; an
1860
+ application that does not care is unaffected, which is the common case and the one this trades for.
1861
+ `MEASUREMENTS.md` §15.
1862
+
1863
+ **The unrigged path's joint budget. — MEASURED, and §11.2's guess was low.** A rigged garment costs
1864
+ nothing new; an unrigged one needs a generated joint set, and how many joints a drape takes through a
1865
+ four-weight palette was an open empirical question. M3 measured it: a 33×33 cape simulated at full
1866
+ resolution, reconstructed by linear blend skinning from k-by-k fitted joints, error against the
1867
+ reference. **RMS error is inversely proportional to the joint count** — the product is flat across a
1868
+ factor of 72 in joints — and the worst case falls as about `N^−0.83`. At §11.2's "~60 output joints"
1869
+ the worst-case error is 5% of the garment's own size, which is five grid cells and reads as faceting;
1870
+ **80 to 120 joints** puts it inside one. A crumpled cloth needs about three times as many, so the
1871
+ number is per-fabric rather than per-garment. `MEASUREMENTS.md` §28. The barycentric deformation pass
1872
+ (§11.2) remains the designed fallback.
1873
+
1874
+ **Per-joint frames. — MEASURED, and the degeneracy did not happen.** A particle has a position; a
1875
+ joint needs an orientation, fitted from a neighbourhood every frame, and §18 expected "a fold that
1876
+ collapses a triangle fan" to have no well-defined frame. Across 800 frames × up to 121 joints,
1877
+ including a deliberately crumpled variant with bending at 1e-7 and a gust four times as hard, the
1878
+ count of degenerate fits is **zero**. The mechanism is that a tangent is a difference across two
1879
+ links and the stretch rows are hard, so each link holds its length and the only way the difference
1880
+ vanishes is a fold of exactly 180° at the joint's own vertex. That is possible rather than forbidden,
1881
+ so a future unrigged path keeps the epsilon and the fallback; it is no longer the thing to be most
1882
+ worried about. `MEASUREMENTS.md` §28.
1883
+
1884
+ **Quadratic bending cannot hold a curved rest shape.** A garment authored with a strong permanent curve
1885
+ will relax flatter than intended. M0 measured the exact boundary: the stencil annihilates the rest shape
1886
+ and **every affine image of it** — which is every in-plane deformation to first order, so a flat sheet
1887
+ being sheared, stretched or rotated stays at zero bending energy — but it does *not* annihilate an
1888
+ arbitrary planar configuration. Four coplanar particles that are not an affine image of the rest four
1889
+ read as bent. *Mitigation:* accepted for the fabrics the library targets. If a case appears, the fix is
1890
+ a rest-curvature offset in the stencil, which is a change to one row and not to the solver.
1891
+
1892
+ **Swept collision is translation-first, and it is two mechanisms rather than one. — MEASURED.** P3
1893
+ states the limit. M2 found that the half nobody had written down — sweeping the contact **set**, not
1894
+ just the poses — was the half that mattered: without it a capsule at 20 m/s created zero rows and the
1895
+ sheet was never touched. With the collider's travel folded into the discovery reach, 2 to 40 m/s all
1896
+ behave. What remains is that both halves are built from the collider's *centre*: a collider spinning
1897
+ fast enough that a point on its surface travels more than its own radius within one substep can still
1898
+ be missed. *Mitigation:* more substeps in the affected `ClothDynamics`; genuine CCD stays out of scope.
1899
+ The shape of a fix, if one is ever wanted, is to build the discovery margin from the swept **surface**
1900
+ travel — `|Δt| + θ·R` — which is one more term and no new structure. `MEASUREMENTS.md` §20.
1901
+
1902
+ **Open — a rigid collider driven through pinned cloth wraps rather than parts.** A contact row bounds
1903
+ the interpenetration; it cannot prevent it, because the cloth has nowhere to go. The playground's
1904
+ spinning-bar scene is the case, and it settles at 18 mm inside a 25 mm bar. This is not a solver
1905
+ failure — a kinematic collider is infinitely strong by construction and the cloth is inextensible and
1906
+ pinned — but it is the configuration a garment author will find first, and the answer is authoring
1907
+ (a collider that does not sweep through the garment's own plane) rather than a solver mechanism.
1908
+
1909
+ **A soft-row cloth does not come to rest. — CLOSED by M1's damping, and the size is measured.** M0
1910
+ measured a soft chain landing in a bounded limit cycle that 2,000 further steps do not move, and no
1911
+ solver constant reaches it, because `α·γ` decays a multiplier and a soft row has none. `damping` does
1912
+ reach it: on the configuration §6 measured, 2.90e-3 J undamped against 1.28e-6 J at the library's own
1913
+ `damping = 0.12`, and 1.82e-12 J at the top of the range. `cloth_pathology.spec.js` gates on exactly
1914
+ that pair.
1915
+ *What this does not claim:* damping does not stop the step adding energy, it removes energy faster than
1916
+ the step adds it. The equilibrium is bounded rather than zero — which is why the numbers keep falling
1917
+ all the way to `damping = 1` instead of hitting a floor — and a cloth whose rows are soft and far above
1918
+ the dissipative band is still a cloth being rescued rather than a cloth behaving. M1's mapping does not
1919
+ produce one; the gate exists so a future mapping that does is caught. `MEASUREMENTS.md` §12.
1920
+
1921
+ **The escape hatch could mask authoring errors.** P4(d) rescues a stuck particle, which means a badly
1922
+ authored garment can look acceptable while relying on it. *Mitigation:* `ClothDiagnostics` counts
1923
+ escape-hatch activations per cloth and surfaces them, so "this garment is being rescued 30 times a
1924
+ second" is visible rather than invisible.
1925
+
1926
+ **Open — two-way coupling.** Cloth does not push rigid bodies. The row model could carry it (the
1927
+ collision row's multiplier is a force, and applying its negation to the collider's body is mechanically
1928
+ straightforward), but the stability of that loop across two solvers with different time discretisations
1929
+ is a real question and is not answered here.
1930
+
1931
+ **Open — the fixed set for an unskinned surface, and M3 found there are three rules rather than
1932
+ two.** Step 5 of §11.3 derives the fixed set from skin weights, which is right for a garment on a
1933
+ skeleton. A **rigged** garment does not need weights at all: the topology answers, and a joint whose
1934
+ parent is outside the proxy is the fixed set (§11.3, corrected). What is still open is the third
1935
+ case — a flag, a curtain, a banner that is not skinned at all — where there is neither a joint tree
1936
+ nor a weight to read. Those also sit at `slack ≈ 1` by necessity, so the tether carries all the
1937
+ inextensibility, but the fixed set still has to come from the mesh boundary or from authoring, and
1938
+ neither is built. It belongs with the unrigged path, which is where a mesh first becomes a particle
1939
+ set.
1940
+
1941
+ **Open — LOD.** Distance-based particle-count reduction would need either multiple baked proxies per
1942
+ garment or a runtime hierarchy. Culling (§12.1) covers the off-screen case; the far-but-visible case is
1943
+ unaddressed.
1944
+
1945
+ **Open — `stretch` is a weak control, and it is not obvious what would make it a strong one.** M1
1946
+ measured the strain-limit row removing about a third of the peak over-stretch and never reaching its
1947
+ own allowance, because it is a second hard row competing with the first for the same trust region and
1948
+ the same penalty band (§6). A fabric's *extension* is therefore governed by the iteration budget more
1949
+ than by the fabric, and the library says so by which entries build the row at all. Three things might
1950
+ change that and none is free: a soft fabric row inside the dissipative band with the hard row acting
1951
+ only as the limit (which reintroduces M0's settling problem at any realistic stiffness); a per-row
1952
+ penalty band, making `k_max/(m/h²)` a material property rather than a global (which `MEASUREMENTS.md`
1953
+ §4 shows trades stretchiness against settling); or accepting that near-inextensibility is what fabric
1954
+ *is* and demoting `stretch` to a documented weak knob. M2's contacts do not bear on it either way.
1955
+
1956
+ **Open — the write-back has no interpolation.** §12 gives cloth `PhysicsSystem`'s producer /
1957
+ `__interp_restore` contract, and M1 does not wire it: cloth writes `Transform64` at the fixed rate and
1958
+ nothing blends between ticks, so a cloth updates at 60 Hz on a 165 Hz display. That is visible and it
1959
+ is not wrong — the poses are authoritative, they are simply held. It lands with M5, where the worker
1960
+ makes the fixed-step producer contract load-bearing for a second reason.
1961
+
1962
+ **Open — the subtree is walked once.** A rope's links do not come and go, so `cloth_seed_subtree` runs
1963
+ on first step and `ClothSystem#reseed` is how a caller says the structure changed. That is the same
1964
+ contract `TransformAttachment#parent` already carries, and it is the right default; what it does not
1965
+ have is a way to *notice*. An entity added under a live `Cloth` is silently not simulated until
1966
+ someone re-seeds, which is a class of authoring mistake with no diagnostic behind it. `ClothDiagnostics`
1967
+ is where one would go.