@woosh/meep-engine 3.24.0 → 3.26.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 (349) hide show
  1. package/package.json +1 -1
  2. package/src/core/geom/3d/shape/HeightMapShape3D.d.ts +59 -0
  3. package/src/core/geom/3d/shape/HeightMapShape3D.d.ts.map +1 -1
  4. package/src/core/geom/3d/shape/HeightMapShape3D.js +285 -0
  5. package/src/core/geom/3d/shape/PosedShape3D.d.ts.map +1 -1
  6. package/src/core/geom/3d/shape/PosedShape3D.js +57 -0
  7. package/src/core/geom/3d/shape/TransformedShape3D.d.ts.map +1 -1
  8. package/src/core/geom/3d/shape/TransformedShape3D.js +102 -0
  9. package/src/core/geom/3d/shape/UnionShape3D.d.ts.map +1 -1
  10. package/src/core/geom/3d/shape/UnionShape3D.js +64 -0
  11. package/src/engine/graphics3/PickingSystem.d.ts +3 -3
  12. package/src/engine/graphics3/PickingSystem.d.ts.map +1 -1
  13. package/src/engine/graphics3/PickingSystem.js +52 -55
  14. package/src/engine/graphics3/shader_picking_gather.d.ts +40 -0
  15. package/src/engine/graphics3/shader_picking_gather.d.ts.map +1 -0
  16. package/src/engine/graphics3/shader_picking_gather.js +120 -0
  17. package/src/engine/physics/cloth/MEASUREMENTS.md +1632 -0
  18. package/src/engine/physics/cloth/PLAN.md +738 -95
  19. package/src/engine/physics/cloth/collider/ClothColliderIndex.d.ts +84 -17
  20. package/src/engine/physics/cloth/collider/ClothColliderIndex.d.ts.map +1 -1
  21. package/src/engine/physics/cloth/collider/ClothColliderIndex.js +451 -42
  22. package/src/engine/physics/cloth/ecs/ClothColliderSerializationAdapter.d.ts +52 -0
  23. package/src/engine/physics/cloth/ecs/ClothColliderSerializationAdapter.d.ts.map +1 -0
  24. package/src/engine/physics/cloth/ecs/ClothColliderSerializationAdapter.js +70 -0
  25. package/src/engine/physics/cloth/ecs/ClothDynamics.d.ts +12 -3
  26. package/src/engine/physics/cloth/ecs/ClothDynamics.d.ts.map +1 -1
  27. package/src/engine/physics/cloth/ecs/ClothDynamics.js +340 -331
  28. package/src/engine/physics/cloth/ecs/ClothInstance.d.ts +101 -29
  29. package/src/engine/physics/cloth/ecs/ClothInstance.d.ts.map +1 -1
  30. package/src/engine/physics/cloth/ecs/ClothInstance.js +110 -31
  31. package/src/engine/physics/cloth/ecs/ClothSerializationAdapter.d.ts +84 -0
  32. package/src/engine/physics/cloth/ecs/ClothSerializationAdapter.d.ts.map +1 -0
  33. package/src/engine/physics/cloth/ecs/ClothSerializationAdapter.js +141 -0
  34. package/src/engine/physics/cloth/ecs/ClothSystem.d.ts +71 -81
  35. package/src/engine/physics/cloth/ecs/ClothSystem.d.ts.map +1 -1
  36. package/src/engine/physics/cloth/ecs/ClothSystem.js +135 -856
  37. package/src/engine/physics/cloth/ecs/ClothWorkerCore.d.ts +48 -0
  38. package/src/engine/physics/cloth/ecs/ClothWorkerCore.d.ts.map +1 -0
  39. package/src/engine/physics/cloth/ecs/ClothWorkerCore.js +107 -0
  40. package/src/engine/physics/cloth/ecs/ClothWorld.d.ts +323 -0
  41. package/src/engine/physics/cloth/ecs/ClothWorld.d.ts.map +1 -0
  42. package/src/engine/physics/cloth/ecs/ClothWorld.js +1248 -0
  43. package/src/engine/physics/cloth/ecs/WorkerClothSystem.d.ts +192 -0
  44. package/src/engine/physics/cloth/ecs/WorkerClothSystem.d.ts.map +1 -0
  45. package/src/engine/physics/cloth/ecs/WorkerClothSystem.js +578 -0
  46. package/src/engine/physics/cloth/ecs/cloth.worker.d.ts +2 -0
  47. package/src/engine/physics/cloth/ecs/cloth.worker.d.ts.map +1 -0
  48. package/src/engine/physics/cloth/ecs/cloth.worker.js +12 -0
  49. package/src/engine/physics/cloth/ecs/cloth_build_rows.d.ts.map +1 -1
  50. package/src/engine/physics/cloth/ecs/cloth_build_rows.js +2 -1
  51. package/src/engine/physics/cloth/ecs/cloth_dynamics_map.d.ts +85 -3
  52. package/src/engine/physics/cloth/ecs/cloth_dynamics_map.d.ts.map +1 -1
  53. package/src/engine/physics/cloth/ecs/cloth_dynamics_map.js +366 -271
  54. package/src/engine/physics/cloth/ecs/cloth_gather_colliders.d.ts +95 -12
  55. package/src/engine/physics/cloth/ecs/cloth_gather_colliders.d.ts.map +1 -1
  56. package/src/engine/physics/cloth/ecs/cloth_gather_colliders.js +170 -27
  57. package/src/engine/physics/cloth/ecs/cloth_seed_rig.d.ts +19 -0
  58. package/src/engine/physics/cloth/ecs/cloth_seed_rig.d.ts.map +1 -1
  59. package/src/engine/physics/cloth/ecs/cloth_seed_rig.js +249 -201
  60. package/src/engine/physics/cloth/ecs/cloth_seed_subtree.d.ts +21 -0
  61. package/src/engine/physics/cloth/ecs/cloth_seed_subtree.d.ts.map +1 -1
  62. package/src/engine/physics/cloth/ecs/cloth_seed_subtree.js +62 -1
  63. package/src/engine/physics/cloth/ecs/cloth_worker_protocol.d.ts +29 -0
  64. package/src/engine/physics/cloth/ecs/cloth_worker_protocol.d.ts.map +1 -0
  65. package/src/engine/physics/cloth/ecs/cloth_worker_protocol.js +78 -0
  66. package/src/engine/physics/cloth/ecs/cloth_write_back.d.ts.map +1 -1
  67. package/src/engine/physics/cloth/ecs/cloth_write_back.js +18 -10
  68. package/src/engine/physics/cloth/ecs/makeClothWorker.d.ts +17 -0
  69. package/src/engine/physics/cloth/ecs/makeClothWorker.d.ts.map +1 -0
  70. package/src/engine/physics/cloth/ecs/makeClothWorker.js +18 -0
  71. package/src/engine/physics/cloth/playground/README.md +73 -2
  72. package/src/engine/physics/cloth/playground/collide_main.js +1 -1
  73. package/src/engine/physics/cloth/playground/wind.html +166 -0
  74. package/src/engine/physics/cloth/playground/wind_build.d.ts +81 -0
  75. package/src/engine/physics/cloth/playground/wind_build.d.ts.map +1 -0
  76. package/src/engine/physics/cloth/playground/wind_build.js +141 -0
  77. package/src/engine/physics/cloth/playground/wind_main.d.ts +2 -0
  78. package/src/engine/physics/cloth/playground/wind_main.d.ts.map +1 -0
  79. package/src/engine/physics/cloth/playground/wind_main.js +681 -0
  80. package/src/engine/physics/cloth/solver/ClothState.d.ts +134 -79
  81. package/src/engine/physics/cloth/solver/ClothState.d.ts.map +1 -1
  82. package/src/engine/physics/cloth/solver/ClothState.js +273 -12
  83. package/src/engine/physics/cloth/solver/cloth_contact_find.d.ts +29 -8
  84. package/src/engine/physics/cloth/solver/cloth_contact_find.d.ts.map +1 -1
  85. package/src/engine/physics/cloth/solver/cloth_contact_find.js +37 -9
  86. package/src/engine/physics/cloth/solver/cloth_solver_constants.d.ts +45 -2
  87. package/src/engine/physics/cloth/solver/cloth_solver_constants.d.ts.map +1 -1
  88. package/src/engine/physics/cloth/solver/cloth_solver_constants.js +46 -2
  89. package/src/engine/physics/cloth/solver/cloth_step.d.ts +21 -2
  90. package/src/engine/physics/cloth/solver/cloth_step.d.ts.map +1 -1
  91. package/src/engine/physics/cloth/solver/cloth_step.js +173 -4
  92. package/src/engine/physics/cloth/solver/cloth_step_instance.d.ts +40 -0
  93. package/src/engine/physics/cloth/solver/cloth_step_instance.d.ts.map +1 -0
  94. package/src/engine/physics/cloth/solver/cloth_step_instance.js +284 -0
  95. package/src/engine/physics/cloth/solver/cloth_wind_accelerate.d.ts +107 -0
  96. package/src/engine/physics/cloth/solver/cloth_wind_accelerate.d.ts.map +1 -0
  97. package/src/engine/physics/cloth/solver/cloth_wind_accelerate.js +263 -0
  98. package/src/engine/physics/cloth/solver/constraint/cloth_backstop_row.d.ts +9 -2
  99. package/src/engine/physics/cloth/solver/constraint/cloth_backstop_row.d.ts.map +1 -1
  100. package/src/engine/physics/cloth/solver/constraint/cloth_backstop_row.js +9 -2
  101. package/src/engine/physics/cloth/wind/AbstractClothWind.d.ts +102 -0
  102. package/src/engine/physics/cloth/wind/AbstractClothWind.d.ts.map +1 -0
  103. package/src/engine/physics/cloth/wind/AbstractClothWind.js +114 -0
  104. package/src/engine/physics/cloth/wind/ClothAmbientWind.d.ts +87 -0
  105. package/src/engine/physics/cloth/wind/ClothAmbientWind.d.ts.map +1 -0
  106. package/src/engine/physics/cloth/wind/ClothAmbientWind.js +185 -0
  107. package/src/engine/physics/cloth/wind/ClothFluidWind.d.ts +79 -0
  108. package/src/engine/physics/cloth/wind/ClothFluidWind.d.ts.map +1 -0
  109. package/src/engine/physics/cloth/wind/ClothFluidWind.js +213 -0
  110. package/src/engine/physics/cloth/wind/cloth_sample_air.d.ts +106 -0
  111. package/src/engine/physics/cloth/wind/cloth_sample_air.d.ts.map +1 -0
  112. package/src/engine/physics/cloth/wind/cloth_sample_air.js +297 -0
  113. package/src/engine/physics/fluid/ecs/FluidObstacleSystem.d.ts +4 -4
  114. package/src/shade/device/mock/texture_copy.d.ts.map +1 -1
  115. package/src/shade/device/mock/texture_copy.js +28 -0
  116. package/src/shade/playground/vgeo_runtime/README.md +94 -0
  117. package/src/shade/playground/vgeo_runtime/index.html +62 -0
  118. package/src/shade/playground/vgeo_runtime/main.d.ts +2 -0
  119. package/src/shade/playground/vgeo_runtime/main.d.ts.map +1 -0
  120. package/src/shade/playground/vgeo_runtime/main.js +399 -0
  121. package/src/shade/playground/vgeo_viewer/sample_asset.js +1 -1
  122. package/src/shade/renderer/camera/Camera.d.ts +14 -0
  123. package/src/shade/renderer/camera/Camera.d.ts.map +1 -1
  124. package/src/shade/renderer/camera/Camera.js +7 -1
  125. package/src/shade/renderer/geometry/GEOMETRY_METADATA_STRUCT.d.ts.map +1 -1
  126. package/src/shade/renderer/geometry/GEOMETRY_METADATA_STRUCT.js +16 -1
  127. package/src/shade/renderer/geometry/GPUGeometryManager.d.ts.map +1 -1
  128. package/src/shade/renderer/geometry/GPUGeometryManager.js +29 -9
  129. package/src/shade/renderer/geometry/GPUGeometryMetadata.d.ts +10 -0
  130. package/src/shade/renderer/geometry/GPUGeometryMetadata.d.ts.map +1 -1
  131. package/src/shade/renderer/geometry/GPUGeometryMetadata.js +13 -0
  132. package/src/shade/renderer/geometry/virtual/VGEO_FORMAT.md +46 -18
  133. package/src/shade/renderer/geometry/virtual/VIRTUAL_GEOMETRY_DESIGN.md +70 -22
  134. package/src/shade/renderer/geometry/virtual/VIRTUAL_GEOMETRY_PLAN.md +97 -19
  135. package/src/shade/renderer/geometry/virtual/build/VGeoBuildOptions.d.ts +12 -2
  136. package/src/shade/renderer/geometry/virtual/build/VGeoBuildOptions.d.ts.map +1 -1
  137. package/src/shade/renderer/geometry/virtual/build/VGeoBuildOptions.js +14 -3
  138. package/src/shade/renderer/geometry/virtual/build/vgeo_assemble_pages.d.ts +2 -2
  139. package/src/shade/renderer/geometry/virtual/build/vgeo_assemble_pages.d.ts.map +1 -1
  140. package/src/shade/renderer/geometry/virtual/build/vgeo_assemble_pages.js +124 -6
  141. package/src/shade/renderer/geometry/virtual/build/vgeo_page_node_count.d.ts +22 -0
  142. package/src/shade/renderer/geometry/virtual/build/vgeo_page_node_count.d.ts.map +1 -0
  143. package/src/shade/renderer/geometry/virtual/build/vgeo_page_node_count.js +53 -0
  144. package/src/shade/renderer/geometry/virtual/format/VGeoWriteOptions.d.ts +8 -1
  145. package/src/shade/renderer/geometry/virtual/format/VGeoWriteOptions.d.ts.map +1 -1
  146. package/src/shade/renderer/geometry/virtual/format/VGeoWriteOptions.js +8 -1
  147. package/src/shade/renderer/geometry/virtual/format/header/VGEO_FEATURE_IGNORABLE_BOUNDED_PAGES.d.ts +16 -0
  148. package/src/shade/renderer/geometry/virtual/format/header/VGEO_FEATURE_IGNORABLE_BOUNDED_PAGES.d.ts.map +1 -0
  149. package/src/shade/renderer/geometry/virtual/format/header/VGEO_FEATURE_IGNORABLE_BOUNDED_PAGES.js +15 -0
  150. package/src/shade/renderer/geometry/virtual/format/page/VGEO_DEFAULT_PAGE_SIZE.d.ts +54 -0
  151. package/src/shade/renderer/geometry/virtual/format/page/VGEO_DEFAULT_PAGE_SIZE.d.ts.map +1 -0
  152. package/src/shade/renderer/geometry/virtual/format/page/VGEO_DEFAULT_PAGE_SIZE.js +53 -0
  153. package/src/shade/renderer/geometry/virtual/format/read/VGeoContainerHeader.d.ts +13 -2
  154. package/src/shade/renderer/geometry/virtual/format/read/VGeoContainerHeader.d.ts.map +1 -1
  155. package/src/shade/renderer/geometry/virtual/format/read/VGeoContainerHeader.js +14 -2
  156. package/src/shade/renderer/geometry/virtual/format/read/VGeoPage.d.ts +100 -0
  157. package/src/shade/renderer/geometry/virtual/format/read/VGeoPage.d.ts.map +1 -1
  158. package/src/shade/renderer/geometry/virtual/format/read/VGeoPage.js +113 -0
  159. package/src/shade/renderer/geometry/virtual/format/read/vgeo_read_header.d.ts.map +1 -1
  160. package/src/shade/renderer/geometry/virtual/format/read/vgeo_read_header.js +5 -0
  161. package/src/shade/renderer/geometry/virtual/format/read/vgeo_read_page.d.ts.map +1 -1
  162. package/src/shade/renderer/geometry/virtual/format/read/vgeo_read_page.js +108 -0
  163. package/src/shade/renderer/geometry/virtual/format/vgeo_validate_container.d.ts.map +1 -1
  164. package/src/shade/renderer/geometry/virtual/format/vgeo_validate_container.js +23 -0
  165. package/src/shade/renderer/geometry/virtual/format/vgeo_write_container.d.ts.map +1 -1
  166. package/src/shade/renderer/geometry/virtual/format/vgeo_write_container.js +40 -0
  167. package/src/shade/renderer/geometry/virtual/runtime/GPUVirtualGeometryPool.d.ts +228 -0
  168. package/src/shade/renderer/geometry/virtual/runtime/GPUVirtualGeometryPool.d.ts.map +1 -0
  169. package/src/shade/renderer/geometry/virtual/runtime/GPUVirtualGeometryPool.js +932 -0
  170. package/src/shade/renderer/geometry/virtual/runtime/GPUVirtualGeometryRuntime.d.ts +176 -0
  171. package/src/shade/renderer/geometry/virtual/runtime/GPUVirtualGeometryRuntime.d.ts.map +1 -0
  172. package/src/shade/renderer/geometry/virtual/runtime/GPUVirtualGeometryRuntime.js +425 -0
  173. package/src/shade/renderer/geometry/virtual/runtime/REVIEW_LEDGER.md +241 -0
  174. package/src/shade/renderer/geometry/virtual/runtime/RUNTIME_PLAN.md +574 -0
  175. package/src/shade/renderer/geometry/virtual/runtime/VGeoFeedbackLoop.d.ts +120 -0
  176. package/src/shade/renderer/geometry/virtual/runtime/VGeoFeedbackLoop.d.ts.map +1 -0
  177. package/src/shade/renderer/geometry/virtual/runtime/VGeoFeedbackLoop.js +674 -0
  178. package/src/shade/renderer/geometry/virtual/runtime/VGeoRuntimeTables.d.ts +287 -0
  179. package/src/shade/renderer/geometry/virtual/runtime/VGeoRuntimeTables.d.ts.map +1 -0
  180. package/src/shade/renderer/geometry/virtual/runtime/VGeoRuntimeTables.js +976 -0
  181. package/src/shade/renderer/geometry/virtual/runtime/VirtualGeometry.d.ts +42 -0
  182. package/src/shade/renderer/geometry/virtual/runtime/VirtualGeometry.d.ts.map +1 -0
  183. package/src/shade/renderer/geometry/virtual/runtime/VirtualGeometry.js +96 -0
  184. package/src/shade/renderer/geometry/virtual/runtime/cut/VGEO_CUT_FLAG_CULL.d.ts +16 -0
  185. package/src/shade/renderer/geometry/virtual/runtime/cut/VGEO_CUT_FLAG_CULL.d.ts.map +1 -0
  186. package/src/shade/renderer/geometry/virtual/runtime/cut/VGEO_CUT_FLAG_CULL.js +15 -0
  187. package/src/shade/renderer/geometry/virtual/runtime/cut/VGEO_CUT_PARAMS_STRUCT.d.ts +19 -0
  188. package/src/shade/renderer/geometry/virtual/runtime/cut/VGEO_CUT_PARAMS_STRUCT.d.ts.map +1 -0
  189. package/src/shade/renderer/geometry/virtual/runtime/cut/VGEO_CUT_PARAMS_STRUCT.js +83 -0
  190. package/src/shade/renderer/geometry/virtual/runtime/cut/VGEO_CUT_WORKGROUP_SIZE.d.ts +9 -0
  191. package/src/shade/renderer/geometry/virtual/runtime/cut/VGEO_CUT_WORKGROUP_SIZE.d.ts.map +1 -0
  192. package/src/shade/renderer/geometry/virtual/runtime/cut/VGEO_CUT_WORKGROUP_SIZE.js +8 -0
  193. package/src/shade/renderer/geometry/virtual/runtime/cut/chunk_vgeo_cut_access.d.ts +19 -0
  194. package/src/shade/renderer/geometry/virtual/runtime/cut/chunk_vgeo_cut_access.d.ts.map +1 -0
  195. package/src/shade/renderer/geometry/virtual/runtime/cut/chunk_vgeo_cut_access.js +160 -0
  196. package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_collect.d.ts +3 -0
  197. package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_collect.d.ts.map +1 -0
  198. package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_collect.js +255 -0
  199. package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_queue_prepare.d.ts +3 -0
  200. package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_queue_prepare.d.ts.map +1 -0
  201. package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_queue_prepare.js +80 -0
  202. package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_seed.d.ts +3 -0
  203. package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_seed.d.ts.map +1 -0
  204. package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_seed.js +144 -0
  205. package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_traverse.d.ts +3 -0
  206. package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_traverse.d.ts.map +1 -0
  207. package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_traverse.js +530 -0
  208. package/src/shade/renderer/geometry/virtual/runtime/cut/vgeo_cut_feedback_layout.d.ts +39 -0
  209. package/src/shade/renderer/geometry/virtual/runtime/cut/vgeo_cut_feedback_layout.d.ts.map +1 -0
  210. package/src/shade/renderer/geometry/virtual/runtime/cut/vgeo_cut_feedback_layout.js +54 -0
  211. package/src/shade/renderer/geometry/virtual/runtime/graph_vgeo_expand_if_enabled.d.ts +41 -0
  212. package/src/shade/renderer/geometry/virtual/runtime/graph_vgeo_expand_if_enabled.d.ts.map +1 -0
  213. package/src/shade/renderer/geometry/virtual/runtime/graph_vgeo_expand_if_enabled.js +56 -0
  214. package/src/shade/renderer/geometry/virtual/runtime/graph_vgeo_expand_instances_to_meshlets.d.ts +49 -0
  215. package/src/shade/renderer/geometry/virtual/runtime/graph_vgeo_expand_instances_to_meshlets.d.ts.map +1 -0
  216. package/src/shade/renderer/geometry/virtual/runtime/graph_vgeo_expand_instances_to_meshlets.js +328 -0
  217. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_CLUSTER_ROW_OFFSET.d.ts +10 -0
  218. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_CLUSTER_ROW_OFFSET.d.ts.map +1 -0
  219. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_CLUSTER_ROW_OFFSET.js +51 -0
  220. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_CLUSTER_ROW_WORDS.d.ts +13 -0
  221. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_CLUSTER_ROW_WORDS.d.ts.map +1 -0
  222. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_CLUSTER_ROW_WORDS.js +12 -0
  223. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_CUT_STAT.d.ts +17 -0
  224. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_CUT_STAT.d.ts.map +1 -0
  225. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_CUT_STAT.js +99 -0
  226. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_CUT_STAT_COUNT.d.ts +9 -0
  227. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_CUT_STAT_COUNT.d.ts.map +1 -0
  228. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_CUT_STAT_COUNT.js +8 -0
  229. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_FEEDBACK_OFFSET.d.ts +7 -0
  230. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_FEEDBACK_OFFSET.d.ts.map +1 -0
  231. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_FEEDBACK_OFFSET.js +27 -0
  232. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GEOMETRY_ROW_NONE.d.ts +14 -0
  233. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GEOMETRY_ROW_NONE.d.ts.map +1 -0
  234. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GEOMETRY_ROW_NONE.js +13 -0
  235. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GEOMETRY_ROW_OFFSET.d.ts +7 -0
  236. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GEOMETRY_ROW_OFFSET.d.ts.map +1 -0
  237. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GEOMETRY_ROW_OFFSET.js +35 -0
  238. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GEOMETRY_ROW_WORDS.d.ts +9 -0
  239. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GEOMETRY_ROW_WORDS.d.ts.map +1 -0
  240. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GEOMETRY_ROW_WORDS.js +8 -0
  241. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GROUP_FLAG_SELECTABLE.d.ts +15 -0
  242. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GROUP_FLAG_SELECTABLE.d.ts.map +1 -0
  243. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GROUP_FLAG_SELECTABLE.js +14 -0
  244. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GROUP_ROW_OFFSET.d.ts +7 -0
  245. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GROUP_ROW_OFFSET.d.ts.map +1 -0
  246. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GROUP_ROW_OFFSET.js +36 -0
  247. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GROUP_ROW_WORDS.d.ts +10 -0
  248. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GROUP_ROW_WORDS.d.ts.map +1 -0
  249. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GROUP_ROW_WORDS.js +9 -0
  250. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_INSTANCE_OFFSET.d.ts +11 -0
  251. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_INSTANCE_OFFSET.d.ts.map +1 -0
  252. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_INSTANCE_OFFSET.js +54 -0
  253. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_INSTANCE_WORDS.d.ts +9 -0
  254. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_INSTANCE_WORDS.d.ts.map +1 -0
  255. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_INSTANCE_WORDS.js +8 -0
  256. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_NODE_ROW_LEAF_BIT.d.ts +11 -0
  257. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_NODE_ROW_LEAF_BIT.d.ts.map +1 -0
  258. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_NODE_ROW_LEAF_BIT.js +10 -0
  259. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_NODE_ROW_OFFSET.d.ts +7 -0
  260. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_NODE_ROW_OFFSET.d.ts.map +1 -0
  261. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_NODE_ROW_OFFSET.js +30 -0
  262. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_NODE_ROW_WORDS.d.ts +9 -0
  263. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_NODE_ROW_WORDS.d.ts.map +1 -0
  264. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_NODE_ROW_WORDS.js +8 -0
  265. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_NO_CHILD_PAGE.d.ts +13 -0
  266. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_NO_CHILD_PAGE.d.ts.map +1 -0
  267. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_NO_CHILD_PAGE.js +12 -0
  268. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_PAGE_ROW_NONE.d.ts +14 -0
  269. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_PAGE_ROW_NONE.d.ts.map +1 -0
  270. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_PAGE_ROW_NONE.js +13 -0
  271. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_PAGE_ROW_OFFSET.d.ts +11 -0
  272. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_PAGE_ROW_OFFSET.d.ts.map +1 -0
  273. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_PAGE_ROW_OFFSET.js +61 -0
  274. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_PAGE_ROW_WORDS.d.ts +9 -0
  275. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_PAGE_ROW_WORDS.d.ts.map +1 -0
  276. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_PAGE_ROW_WORDS.js +8 -0
  277. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_QUEUE_ITEM_WORDS.d.ts +13 -0
  278. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_QUEUE_ITEM_WORDS.d.ts.map +1 -0
  279. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_QUEUE_ITEM_WORDS.js +12 -0
  280. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_QUEUE_TARGET_GROUP_BIT.d.ts +9 -0
  281. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_QUEUE_TARGET_GROUP_BIT.d.ts.map +1 -0
  282. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_QUEUE_TARGET_GROUP_BIT.js +8 -0
  283. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_WANT_WORDS.d.ts +20 -0
  284. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_WANT_WORDS.d.ts.map +1 -0
  285. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_WANT_WORDS.js +19 -0
  286. package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_meshlet_batch.d.ts +23 -0
  287. package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_meshlet_batch.d.ts.map +1 -0
  288. package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_meshlet_batch.js +70 -0
  289. package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_page_block_words.d.ts +18 -0
  290. package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_page_block_words.d.ts.map +1 -0
  291. package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_page_block_words.js +25 -0
  292. package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_page_slot_words.d.ts +35 -0
  293. package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_page_slot_words.d.ts.map +1 -0
  294. package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_page_slot_words.js +41 -0
  295. package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_write_page_block.d.ts +32 -0
  296. package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_write_page_block.d.ts.map +1 -0
  297. package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_write_page_block.js +138 -0
  298. package/src/shade/renderer/loader/gltf/tiny-gltf.d.ts +1 -1
  299. package/src/shade/renderer/postprocess/nss/NSS.d.ts +1 -1
  300. package/src/shade/renderer/rasterize/bucket/prepare_meshlet_draw_commands_by_material.d.ts.map +1 -1
  301. package/src/shade/renderer/rasterize/bucket/prepare_meshlet_draw_commands_by_material.js +9 -0
  302. package/src/shade/renderer/rasterize/fast/graph_rasterize_scene_fast.d.ts.map +1 -1
  303. package/src/shade/renderer/rasterize/fast/graph_rasterize_scene_fast.js +12 -1
  304. package/src/shade/renderer/rasterize/standard/graph_rasterize_partial_opaque.d.ts.map +1 -1
  305. package/src/shade/renderer/rasterize/standard/graph_rasterize_partial_opaque.js +12 -1
  306. package/src/shade/renderer/rasterize/standard/graph_rasterize_remaining_opaque.d.ts.map +1 -1
  307. package/src/shade/renderer/rasterize/standard/graph_rasterize_remaining_opaque.js +10 -0
  308. package/src/shade/renderer/scene/GPUSceneContext.d.ts +18 -0
  309. package/src/shade/renderer/scene/GPUSceneContext.d.ts.map +1 -1
  310. package/src/shade/renderer/scene/GPUSceneContext.js +647 -594
  311. package/src/shade/renderer/scene/rows/GPUSceneRows.d.ts.map +1 -1
  312. package/src/shade/renderer/scene/rows/GPUSceneRows.js +22 -0
  313. package/src/shade/renderer/shader/chunk/geometry/mat3/chunk_mat3_singular_values.d.ts +35 -0
  314. package/src/shade/renderer/shader/chunk/geometry/mat3/chunk_mat3_singular_values.d.ts.map +1 -0
  315. package/src/shade/renderer/shader/chunk/geometry/mat3/chunk_mat3_singular_values.js +91 -0
  316. package/src/engine/graphics3/instantiate_scene_bundle.d.ts +0 -54
  317. package/src/engine/graphics3/instantiate_scene_bundle.d.ts.map +0 -1
  318. package/src/engine/graphics3/shade_node_to_entity_composition.d.ts +0 -39
  319. package/src/engine/graphics3/shade_node_to_entity_composition.d.ts.map +0 -1
  320. package/src/shade/renderer/animation/compute_skin_world_bounds.d.ts +0 -35
  321. package/src/shade/renderer/animation/compute_skin_world_bounds.d.ts.map +0 -1
  322. package/src/shade/renderer/animation/compute_skinned_mesh_clip_bounding_sphere.d.ts +0 -96
  323. package/src/shade/renderer/animation/compute_skinned_mesh_clip_bounding_sphere.d.ts.map +0 -1
  324. package/src/shade/renderer/animation/pose/pose_evaluate_world.d.ts +0 -20
  325. package/src/shade/renderer/animation/pose/pose_evaluate_world.d.ts.map +0 -1
  326. package/src/shade/renderer/animation/skin_bind_transform.d.ts +0 -25
  327. package/src/shade/renderer/animation/skin_bind_transform.d.ts.map +0 -1
  328. package/src/shade/renderer/animation/skin_frame_defect.d.ts +0 -34
  329. package/src/shade/renderer/animation/skin_frame_defect.d.ts.map +0 -1
  330. package/src/shade/renderer/animation/skin_joint_matrix.d.ts +0 -24
  331. package/src/shade/renderer/animation/skin_joint_matrix.d.ts.map +0 -1
  332. package/src/shade/renderer/animation/skin_normalize_mesh_frame.d.ts +0 -70
  333. package/src/shade/renderer/animation/skin_normalize_mesh_frame.d.ts.map +0 -1
  334. package/src/shade/renderer/buffer/table/GPUReadbackStagingRing.d.ts +0 -96
  335. package/src/shade/renderer/buffer/table/GPUReadbackStagingRing.d.ts.map +0 -1
  336. package/src/shade/renderer/scene/InstanceBatch.d.ts +0 -92
  337. package/src/shade/renderer/scene/InstanceBatch.d.ts.map +0 -1
  338. package/src/shade/renderer/scene/Mesh.d.ts +0 -55
  339. package/src/shade/renderer/scene/Mesh.d.ts.map +0 -1
  340. package/src/shade/renderer/scene/Node3D.d.ts +0 -159
  341. package/src/shade/renderer/scene/Node3D.d.ts.map +0 -1
  342. package/src/shade/renderer/scene/Node3DDirtyList.d.ts +0 -59
  343. package/src/shade/renderer/scene/Node3DDirtyList.d.ts.map +0 -1
  344. package/src/shade/renderer/scene/SceneNodeBinding.d.ts +0 -52
  345. package/src/shade/renderer/scene/SceneNodeBinding.d.ts.map +0 -1
  346. package/src/shade/renderer/scene/SkinnedMesh.d.ts +0 -27
  347. package/src/shade/renderer/scene/SkinnedMesh.d.ts.map +0 -1
  348. package/src/shade/renderer/scene/TransformAuthority.d.ts +0 -19
  349. package/src/shade/renderer/scene/TransformAuthority.d.ts.map +0 -1
@@ -23,37 +23,120 @@
23
23
  *
24
24
  * ## The query box
25
25
  *
26
- * The cloth's own particle bounds, fattened by how far a contact reaches, and
27
- * then by how far the solver will let a particle travel in one step. The second
28
- * term is what stops a fast cloth outrunning its own broadphase within the step
29
- * it was gathered for; it is the velocity clamp of §7 P1 read as a distance,
30
- * which is the quantity it was built out of.
26
+ * The cloth's own particle bounds, fattened by exactly what
27
+ * `cloth_contact_find` will reach for — no more, because a broadphase that is
28
+ * wider than its narrowphase is collecting colliders it will then throw away.
29
+ * {@link cloth_gather_reach} is that quantity and carries the derivation.
30
+ *
31
+ * It used to be the velocity clamp of §7 P1 read as a distance. That was wrong
32
+ * in both directions at once. The clamp is `4 · shortest_row · substeps ·
33
+ * iterations`, which for a rope of 10 cm links at 2 × 4 is **3.2 m** a step —
34
+ * so the box was fattened by metres to catch motion measured in centimetres,
35
+ * and a garment in a crowd collected every bone in the street and overflowed
36
+ * its table. `cloth_contact_find`'s own docblock had already worked out that
37
+ * this clamp is "about 154 m/s … three orders of magnitude" past real cloth
38
+ * speed and stopped using it (§54); the gather kept it. And being enormous, it
39
+ * hid the fact that it was also **missing** two terms the narrowphase does
40
+ * reach with — collider inflation and the collider's own travel — so a wide
41
+ * enough inflation was a row the gather never handed over.
42
+ *
43
+ * ## Where the table lives, and why it stopped growing
44
+ *
45
+ * In `ClothState`'s single buffer, {@link CLOTH_COLLIDER_SLOTS} records of it,
46
+ * which is §12's own layout. M2 grew a per-instance array instead, because the
47
+ * size is a property of the world rather than of the cloth — still true, and
48
+ * still not the deciding argument. M5's worker steps the cloth out of shared
49
+ * memory, and an array that can be replaced mid-run is memory the worker would
50
+ * have to be told about again before it could be named. A fixed region makes the
51
+ * two systems read the same bytes by construction.
52
+ *
53
+ * A cloth whose broadphase returns more than the capacity keeps the first
54
+ * {@link CLOTH_COLLIDER_SLOTS} the index hands back and says so once. That is
55
+ * arbitrary among the overflow — the index answers in its own order — which is
56
+ * why it warns rather than trusting a rule it does not have, and why the
57
+ * capacity is set well clear of what a scene reaches. `MEASUREMENTS.md` §41 is
58
+ * what the library's garments actually reach, and the answer is that they reach
59
+ * whatever the characters around them carry.
31
60
  *
32
61
  * @author Alex Goldring
33
62
  * @copyright Company Named Limited (c) 2026
34
63
  */
64
+ /**
65
+ * How far past its own particles a cloth has to look, metres.
66
+ *
67
+ * The gather has one job the solver depends on: the set it hands over must
68
+ * contain every collider `cloth_contact_find` would draw a row against. So the
69
+ * margin is that function's own reach, maximised over the things the gather
70
+ * cannot yet know — which collider, and which particle:
71
+ *
72
+ * (radius + inflation) · (1 + CLOTH_CONTACT_MARGIN) the contact itself
73
+ * + collider travel §20, the collider's approach
74
+ * + |v| · dt §54, the particle's own
75
+ *
76
+ * The radius term is added by {@link cloth_gather_colliders}, which knows the
77
+ * cloth's `contact_radius`; this supplies the rest. Inflation and collider
78
+ * travel come from the index as maxima over every live record, because the
79
+ * gather has not queried yet and so cannot know which records it will get.
80
+ *
81
+ * **The velocity is read before the step and the narrowphase reads it after
82
+ * `damp`**, which only ever scales it down — so this is an upper bound on the
83
+ * travel the rows are actually discovered with, not an estimate of it. That
84
+ * ordering is what makes a margin this tight safe; if a step ever gains speed
85
+ * before `cloth_contact_find`, this stops being a bound and the term has to
86
+ * carry the acceleration too.
87
+ *
88
+ * @param {ClothState} state
89
+ * @param {ClothColliderIndex} index
90
+ * @param {number} dt fixed step, seconds
91
+ * @returns {number} metres
92
+ */
93
+ export function cloth_gather_reach(state: ClothState, index: ClothColliderIndex, dt: number): number;
35
94
  /**
36
95
  * Query the index and rewrite the overlapping colliders into the cloth's frame.
37
96
  *
38
- * @param {ClothInstance} instance filled in place — `collider_table`,
39
- * `collider_key` and `collider_count`
97
+ * @param {ClothInstance} instance read for its anchor pose and filter; its
98
+ * state's `collider_table`, `collider_key` and `collider_count` are filled
40
99
  * @param {ClothColliderIndex} index
41
- * @param {number} reach how far a particle may travel this step, metres
100
+ * @param {number} reach how far past its particles the cloth has to look,
101
+ * metres — {@link cloth_gather_reach}
42
102
  * @returns {number} how many colliders were gathered
43
103
  */
44
104
  export function cloth_gather_colliders(instance: ClothInstance, index: ClothColliderIndex, reach: number): number;
45
105
  /**
46
- * Whether any collider overlapping this cloth moved between the previous step
47
- * and this one — §7 P5's "wake on collider motion", asked without waking.
106
+ * Whether the colliders overlapping this cloth have changed since the step it
107
+ * last took — §7 P5's "wake on collider motion", asked without waking.
48
108
  *
49
109
  * A sleeping cloth is not stepped and not written back, so something has to
50
- * notice when the world it was resting against moves. This is that something,
51
- * and it is a broadphase query plus a pose comparison: cheaper than a step by
110
+ * notice when the world it was resting against changes. This is that something,
111
+ * and it is a broadphase query plus two comparisons: cheaper than a step by
52
112
  * three orders of magnitude, which is what makes sleep worth having at all.
53
113
  *
114
+ * **Two comparisons, and the set is the one M2 did not have.** A pose
115
+ * comparison answers "did anything move", and `ClothColliderSystem#link`
116
+ * *places* a new collider rather than posing it — previous equals current — so
117
+ * a sphere spawned around a sleeping rope is a collider that has not moved.
118
+ * Measured: the rope slept through it and stayed asleep three hundred steps
119
+ * later with four of its six links inside. A handle appearing in the gathered
120
+ * set, or leaving it, is a change to the world the cloth went to sleep in
121
+ * whatever the poses say, and it costs one integer compare per record.
122
+ *
123
+ * The query uses the reach the cloth's last *step* gathered with, so the two
124
+ * sets are answers to the same question. A set built at zero margin against one
125
+ * built at a step's travel would differ for reasons that are about the margin.
126
+ *
54
127
  * @param {ClothInstance} instance
55
128
  * @param {ClothColliderIndex} index
56
129
  * @returns {boolean}
57
130
  */
58
131
  export function cloth_colliders_moved(instance: ClothInstance, index: ClothColliderIndex): boolean;
132
+ /**
133
+ * Record the set this cloth is about to step against, so the next wake test has
134
+ * something to compare with. Called only where the cloth really will be
135
+ * stepped — a set gathered by the wake test itself is a question, not a step.
136
+ *
137
+ * @param {ClothInstance} instance
138
+ * @param {number} reach the margin the gather used, metres
139
+ * @returns {void}
140
+ */
141
+ export function cloth_remember_colliders(instance: ClothInstance, reach: number): void;
59
142
  //# sourceMappingURL=cloth_gather_colliders.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"cloth_gather_colliders.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/physics/cloth/ecs/cloth_gather_colliders.js"],"names":[],"mappings":"AA8BA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAEH;;;;;;;;GAQG;AACH,kGAHW,MAAM,GACJ,MAAM,CAsJlB;AAgDD;;;;;;;;;;;;GAYG;AACH,2FAFa,OAAO,CAsBnB"}
1
+ {"version":3,"file":"cloth_gather_colliders.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/physics/cloth/ecs/cloth_gather_colliders.js"],"names":[],"mappings":"AAgCA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8DG;AAEH;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,qFAHW,MAAM,GACJ,MAAM,CAwBlB;AAED;;;;;;;;;GASG;AACH,kGAJW,MAAM,GAEJ,MAAM,CA6JlB;AAgDD;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,2FAFa,OAAO,CAoCnB;AAED;;;;;;;;GAQG;AACH,yEAHW,MAAM,GACJ,IAAI,CAehB"}
@@ -27,6 +27,8 @@ import {
27
27
  CCR_TZ
28
28
  } from "../collider/ClothColliderRecord.js";
29
29
  import { cloth_collider_refit_bounds } from "../collider/cloth_collider_bounds.js";
30
+ import { CLOTH_CONTACT_MARGIN } from "../solver/cloth_contact_find.js";
31
+ import { CLOTH_COLLIDER_SLOTS } from "../solver/cloth_solver_constants.js";
30
32
 
31
33
  /**
32
34
  * # Bringing the world's colliders into a cloth's frame
@@ -53,23 +55,106 @@ import { cloth_collider_refit_bounds } from "../collider/cloth_collider_bounds.j
53
55
  *
54
56
  * ## The query box
55
57
  *
56
- * The cloth's own particle bounds, fattened by how far a contact reaches, and
57
- * then by how far the solver will let a particle travel in one step. The second
58
- * term is what stops a fast cloth outrunning its own broadphase within the step
59
- * it was gathered for; it is the velocity clamp of §7 P1 read as a distance,
60
- * which is the quantity it was built out of.
58
+ * The cloth's own particle bounds, fattened by exactly what
59
+ * `cloth_contact_find` will reach for — no more, because a broadphase that is
60
+ * wider than its narrowphase is collecting colliders it will then throw away.
61
+ * {@link cloth_gather_reach} is that quantity and carries the derivation.
62
+ *
63
+ * It used to be the velocity clamp of §7 P1 read as a distance. That was wrong
64
+ * in both directions at once. The clamp is `4 · shortest_row · substeps ·
65
+ * iterations`, which for a rope of 10 cm links at 2 × 4 is **3.2 m** a step —
66
+ * so the box was fattened by metres to catch motion measured in centimetres,
67
+ * and a garment in a crowd collected every bone in the street and overflowed
68
+ * its table. `cloth_contact_find`'s own docblock had already worked out that
69
+ * this clamp is "about 154 m/s … three orders of magnitude" past real cloth
70
+ * speed and stopped using it (§54); the gather kept it. And being enormous, it
71
+ * hid the fact that it was also **missing** two terms the narrowphase does
72
+ * reach with — collider inflation and the collider's own travel — so a wide
73
+ * enough inflation was a row the gather never handed over.
74
+ *
75
+ * ## Where the table lives, and why it stopped growing
76
+ *
77
+ * In `ClothState`'s single buffer, {@link CLOTH_COLLIDER_SLOTS} records of it,
78
+ * which is §12's own layout. M2 grew a per-instance array instead, because the
79
+ * size is a property of the world rather than of the cloth — still true, and
80
+ * still not the deciding argument. M5's worker steps the cloth out of shared
81
+ * memory, and an array that can be replaced mid-run is memory the worker would
82
+ * have to be told about again before it could be named. A fixed region makes the
83
+ * two systems read the same bytes by construction.
84
+ *
85
+ * A cloth whose broadphase returns more than the capacity keeps the first
86
+ * {@link CLOTH_COLLIDER_SLOTS} the index hands back and says so once. That is
87
+ * arbitrary among the overflow — the index answers in its own order — which is
88
+ * why it warns rather than trusting a rule it does not have, and why the
89
+ * capacity is set well clear of what a scene reaches. `MEASUREMENTS.md` §41 is
90
+ * what the library's garments actually reach, and the answer is that they reach
91
+ * whatever the characters around them carry.
61
92
  *
62
93
  * @author Alex Goldring
63
94
  * @copyright Company Named Limited (c) 2026
64
95
  */
65
96
 
97
+ /**
98
+ * How far past its own particles a cloth has to look, metres.
99
+ *
100
+ * The gather has one job the solver depends on: the set it hands over must
101
+ * contain every collider `cloth_contact_find` would draw a row against. So the
102
+ * margin is that function's own reach, maximised over the things the gather
103
+ * cannot yet know — which collider, and which particle:
104
+ *
105
+ * (radius + inflation) · (1 + CLOTH_CONTACT_MARGIN) the contact itself
106
+ * + collider travel §20, the collider's approach
107
+ * + |v| · dt §54, the particle's own
108
+ *
109
+ * The radius term is added by {@link cloth_gather_colliders}, which knows the
110
+ * cloth's `contact_radius`; this supplies the rest. Inflation and collider
111
+ * travel come from the index as maxima over every live record, because the
112
+ * gather has not queried yet and so cannot know which records it will get.
113
+ *
114
+ * **The velocity is read before the step and the narrowphase reads it after
115
+ * `damp`**, which only ever scales it down — so this is an upper bound on the
116
+ * travel the rows are actually discovered with, not an estimate of it. That
117
+ * ordering is what makes a margin this tight safe; if a step ever gains speed
118
+ * before `cloth_contact_find`, this stops being a bound and the term has to
119
+ * carry the acceleration too.
120
+ *
121
+ * @param {ClothState} state
122
+ * @param {ClothColliderIndex} index
123
+ * @param {number} dt fixed step, seconds
124
+ * @returns {number} metres
125
+ */
126
+ export function cloth_gather_reach(state, index, dt) {
127
+ const velocity = state.velocity;
128
+
129
+ const particle_count = state.particle_count;
130
+
131
+ let fastest_squared = 0;
132
+
133
+ for (let i = 0; i < particle_count; i++) {
134
+ const p = i * 3;
135
+
136
+ const speed_squared = velocity[p] * velocity[p]
137
+ + velocity[p + 1] * velocity[p + 1]
138
+ + velocity[p + 2] * velocity[p + 2];
139
+
140
+ if (speed_squared > fastest_squared) {
141
+ fastest_squared = speed_squared;
142
+ }
143
+ }
144
+
145
+ return dt * Math.sqrt(fastest_squared)
146
+ + index.max_collider_travel
147
+ + index.max_inflation * (1 + CLOTH_CONTACT_MARGIN);
148
+ }
149
+
66
150
  /**
67
151
  * Query the index and rewrite the overlapping colliders into the cloth's frame.
68
152
  *
69
- * @param {ClothInstance} instance filled in place — `collider_table`,
70
- * `collider_key` and `collider_count`
153
+ * @param {ClothInstance} instance read for its anchor pose and filter; its
154
+ * state's `collider_table`, `collider_key` and `collider_count` are filled
71
155
  * @param {ClothColliderIndex} index
72
- * @param {number} reach how far a particle may travel this step, metres
156
+ * @param {number} reach how far past its particles the cloth has to look,
157
+ * metres — {@link cloth_gather_reach}
73
158
  * @returns {number} how many colliders were gathered
74
159
  */
75
160
  export function cloth_gather_colliders(instance, index, reach) {
@@ -101,12 +186,14 @@ export function cloth_gather_colliders(instance, index, reach) {
101
186
  }
102
187
 
103
188
  if (particle_count === 0) {
104
- instance.collider_count = 0;
189
+ state.collider_count = 0;
105
190
 
106
191
  return 0;
107
192
  }
108
193
 
109
- const margin = reach + state.contact_radius * 2;
194
+ // The contact's own reach, on the same terms `cloth_contact_find` states
195
+ // it in, plus everything {@link cloth_gather_reach} already folded in.
196
+ const margin = reach + state.contact_radius * (1 + CLOTH_CONTACT_MARGIN);
110
197
 
111
198
  min_x -= margin;
112
199
  min_y -= margin;
@@ -160,25 +247,30 @@ export function cloth_gather_colliders(instance, index, reach) {
160
247
 
161
248
  const cloth = instance.cloth;
162
249
 
163
- const found = index.query(
250
+ const overlapping = index.query(
164
251
  HANDLES, world_min_x, world_min_y, world_min_z,
165
252
  world_max_x, world_max_y, world_max_z,
166
253
  cloth.layer, cloth.mask
167
254
  );
168
255
 
169
- if (instance.collider_table === null || instance.collider_table.length < found * CCR_STRIDE) {
170
- let capacity = 8;
256
+ let found = overlapping;
171
257
 
172
- while (capacity < found) {
173
- capacity *= 2;
174
- }
258
+ if (found > CLOTH_COLLIDER_SLOTS) {
259
+ found = CLOTH_COLLIDER_SLOTS;
260
+
261
+ if (!instance.collider_overflow_reported) {
262
+ instance.collider_overflow_reported = true;
175
263
 
176
- instance.collider_table = new Float32Array(capacity * CCR_STRIDE);
177
- instance.collider_key = new Int32Array(capacity);
264
+ console.warn(
265
+ `ClothSystem: entity ${instance.entity} overlaps ${overlapping} cloth colliders and the`
266
+ + ` per-cloth table holds ${CLOTH_COLLIDER_SLOTS}; the rest are not collided against.`
267
+ + ` Narrow the cloth's layer/mask, or split the collider.`
268
+ );
269
+ }
178
270
  }
179
271
 
180
- const table = instance.collider_table;
181
- const keys = instance.collider_key;
272
+ const table = state.collider_table;
273
+ const keys = state.collider_key;
182
274
 
183
275
  const source = index.table;
184
276
 
@@ -217,7 +309,7 @@ export function cloth_gather_colliders(instance, index, reach) {
217
309
  cloth_collider_refit_bounds(table, i, CCR_STRIDE);
218
310
  }
219
311
 
220
- instance.collider_count = found;
312
+ state.collider_count = found;
221
313
 
222
314
  return found;
223
315
  }
@@ -269,22 +361,49 @@ function localise(
269
361
  }
270
362
 
271
363
  /**
272
- * Whether any collider overlapping this cloth moved between the previous step
273
- * and this one — §7 P5's "wake on collider motion", asked without waking.
364
+ * Whether the colliders overlapping this cloth have changed since the step it
365
+ * last took — §7 P5's "wake on collider motion", asked without waking.
274
366
  *
275
367
  * A sleeping cloth is not stepped and not written back, so something has to
276
- * notice when the world it was resting against moves. This is that something,
277
- * and it is a broadphase query plus a pose comparison: cheaper than a step by
368
+ * notice when the world it was resting against changes. This is that something,
369
+ * and it is a broadphase query plus two comparisons: cheaper than a step by
278
370
  * three orders of magnitude, which is what makes sleep worth having at all.
279
371
  *
372
+ * **Two comparisons, and the set is the one M2 did not have.** A pose
373
+ * comparison answers "did anything move", and `ClothColliderSystem#link`
374
+ * *places* a new collider rather than posing it — previous equals current — so
375
+ * a sphere spawned around a sleeping rope is a collider that has not moved.
376
+ * Measured: the rope slept through it and stayed asleep three hundred steps
377
+ * later with four of its six links inside. A handle appearing in the gathered
378
+ * set, or leaving it, is a change to the world the cloth went to sleep in
379
+ * whatever the poses say, and it costs one integer compare per record.
380
+ *
381
+ * The query uses the reach the cloth's last *step* gathered with, so the two
382
+ * sets are answers to the same question. A set built at zero margin against one
383
+ * built at a step's travel would differ for reasons that are about the margin.
384
+ *
280
385
  * @param {ClothInstance} instance
281
386
  * @param {ClothColliderIndex} index
282
387
  * @returns {boolean}
283
388
  */
284
389
  export function cloth_colliders_moved(instance, index) {
285
- const found = cloth_gather_colliders(instance, index, 0);
390
+ const found = cloth_gather_colliders(instance, index, instance.gather_reach);
391
+
392
+ const keys = instance.state.collider_key;
286
393
 
287
- const table = instance.collider_table;
394
+ if (found !== instance.collider_key_count) {
395
+ return true;
396
+ }
397
+
398
+ const seen = instance.collider_keys;
399
+
400
+ for (let i = 0; i < found; i++) {
401
+ if (keys[i] !== seen[i]) {
402
+ return true;
403
+ }
404
+ }
405
+
406
+ const table = instance.state.collider_table;
288
407
 
289
408
  for (let i = 0; i < found; i++) {
290
409
  const r = i * CCR_STRIDE;
@@ -303,6 +422,30 @@ export function cloth_colliders_moved(instance, index) {
303
422
  return false;
304
423
  }
305
424
 
425
+ /**
426
+ * Record the set this cloth is about to step against, so the next wake test has
427
+ * something to compare with. Called only where the cloth really will be
428
+ * stepped — a set gathered by the wake test itself is a question, not a step.
429
+ *
430
+ * @param {ClothInstance} instance
431
+ * @param {number} reach the margin the gather used, metres
432
+ * @returns {void}
433
+ */
434
+ export function cloth_remember_colliders(instance, reach) {
435
+ const count = instance.state.collider_count;
436
+
437
+ const keys = instance.state.collider_key;
438
+
439
+ const seen = instance.collider_keys;
440
+
441
+ for (let i = 0; i < count; i++) {
442
+ seen[i] = keys[i];
443
+ }
444
+
445
+ instance.collider_key_count = count;
446
+ instance.gather_reach = reach;
447
+ }
448
+
306
449
  /**
307
450
  * @type {number[]}
308
451
  * @private
@@ -51,4 +51,23 @@
51
51
  * @param {number} dt
52
52
  */
53
53
  export function cloth_seed_rig(instance: ClothInstance, proxy: ClothProxy, joints: number[], ecd: EntityComponentDataset, dt: number): void;
54
+ /**
55
+ * Give back every joint's `TransformAttachment` authority that this cloth's
56
+ * seeding took from the GPU.
57
+ *
58
+ * The seed revokes so that the write-back reaches the row at all, and the
59
+ * consequence the module docblock states — "a joint cloth simulates stops being
60
+ * animatable by a clip" — is only the right trade while the cloth is *there*.
61
+ * A garment removed and nothing re-granting leaves its joints owned by a CPU
62
+ * that is no longer writing them: neither animated nor simulated, and stuck in
63
+ * the pose the solver stopped in.
64
+ *
65
+ * Only the joints the revoke actually changed are given back, so a joint that
66
+ * was already the CPU's before cloth arrived stays the CPU's.
67
+ *
68
+ * @param {ClothInstance} instance
69
+ * @param {EntityComponentDataset} ecd
70
+ * @returns {void}
71
+ */
72
+ export function cloth_release_rig(instance: ClothInstance, ecd: EntityComponentDataset): void;
54
73
  //# sourceMappingURL=cloth_seed_rig.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"cloth_seed_rig.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/physics/cloth/ecs/cloth_seed_rig.js"],"names":[],"mappings":"AAQA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AAEH;;;;;;;;GAQG;AACH,mFAJW,MAAM,EAAE,mCAER,MAAM,QAyEhB"}
1
+ {"version":3,"file":"cloth_seed_rig.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/physics/cloth/ecs/cloth_seed_rig.js"],"names":[],"mappings":"AASA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AAEH;;;;;;;;GAQG;AACH,mFAJW,MAAM,EAAE,mCAER,MAAM,QAkFhB;AAoED;;;;;;;;;;;;;;;;;GAiBG;AACH,yFAFa,IAAI,CAoBhB"}