@woosh/meep-engine 3.24.0 → 3.25.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 (322) hide show
  1. package/package.json +1 -1
  2. package/src/engine/graphics3/PickingSystem.d.ts +3 -3
  3. package/src/engine/graphics3/PickingSystem.d.ts.map +1 -1
  4. package/src/engine/graphics3/PickingSystem.js +52 -55
  5. package/src/engine/graphics3/shader_picking_gather.d.ts +40 -0
  6. package/src/engine/graphics3/shader_picking_gather.d.ts.map +1 -0
  7. package/src/engine/graphics3/shader_picking_gather.js +120 -0
  8. package/src/engine/physics/cloth/MEASUREMENTS.md +1050 -0
  9. package/src/engine/physics/cloth/PLAN.md +411 -49
  10. package/src/engine/physics/cloth/ecs/ClothColliderSerializationAdapter.d.ts +52 -0
  11. package/src/engine/physics/cloth/ecs/ClothColliderSerializationAdapter.d.ts.map +1 -0
  12. package/src/engine/physics/cloth/ecs/ClothColliderSerializationAdapter.js +70 -0
  13. package/src/engine/physics/cloth/ecs/ClothDynamics.d.ts +12 -3
  14. package/src/engine/physics/cloth/ecs/ClothDynamics.d.ts.map +1 -1
  15. package/src/engine/physics/cloth/ecs/ClothDynamics.js +340 -331
  16. package/src/engine/physics/cloth/ecs/ClothInstance.d.ts +36 -22
  17. package/src/engine/physics/cloth/ecs/ClothInstance.d.ts.map +1 -1
  18. package/src/engine/physics/cloth/ecs/ClothInstance.js +38 -23
  19. package/src/engine/physics/cloth/ecs/ClothSerializationAdapter.d.ts +84 -0
  20. package/src/engine/physics/cloth/ecs/ClothSerializationAdapter.d.ts.map +1 -0
  21. package/src/engine/physics/cloth/ecs/ClothSerializationAdapter.js +141 -0
  22. package/src/engine/physics/cloth/ecs/ClothSystem.d.ts +51 -82
  23. package/src/engine/physics/cloth/ecs/ClothSystem.d.ts.map +1 -1
  24. package/src/engine/physics/cloth/ecs/ClothSystem.js +81 -869
  25. package/src/engine/physics/cloth/ecs/ClothWorkerCore.d.ts +48 -0
  26. package/src/engine/physics/cloth/ecs/ClothWorkerCore.d.ts.map +1 -0
  27. package/src/engine/physics/cloth/ecs/ClothWorkerCore.js +107 -0
  28. package/src/engine/physics/cloth/ecs/ClothWorld.d.ts +286 -0
  29. package/src/engine/physics/cloth/ecs/ClothWorld.d.ts.map +1 -0
  30. package/src/engine/physics/cloth/ecs/ClothWorld.js +1104 -0
  31. package/src/engine/physics/cloth/ecs/WorkerClothSystem.d.ts +182 -0
  32. package/src/engine/physics/cloth/ecs/WorkerClothSystem.d.ts.map +1 -0
  33. package/src/engine/physics/cloth/ecs/WorkerClothSystem.js +562 -0
  34. package/src/engine/physics/cloth/ecs/cloth.worker.d.ts +2 -0
  35. package/src/engine/physics/cloth/ecs/cloth.worker.d.ts.map +1 -0
  36. package/src/engine/physics/cloth/ecs/cloth.worker.js +12 -0
  37. package/src/engine/physics/cloth/ecs/cloth_build_rows.d.ts.map +1 -1
  38. package/src/engine/physics/cloth/ecs/cloth_build_rows.js +2 -1
  39. package/src/engine/physics/cloth/ecs/cloth_dynamics_map.d.ts +58 -0
  40. package/src/engine/physics/cloth/ecs/cloth_dynamics_map.d.ts.map +1 -1
  41. package/src/engine/physics/cloth/ecs/cloth_dynamics_map.js +341 -271
  42. package/src/engine/physics/cloth/ecs/cloth_gather_colliders.d.ts +20 -2
  43. package/src/engine/physics/cloth/ecs/cloth_gather_colliders.d.ts.map +1 -1
  44. package/src/engine/physics/cloth/ecs/cloth_gather_colliders.js +39 -15
  45. package/src/engine/physics/cloth/ecs/cloth_worker_protocol.d.ts +29 -0
  46. package/src/engine/physics/cloth/ecs/cloth_worker_protocol.d.ts.map +1 -0
  47. package/src/engine/physics/cloth/ecs/cloth_worker_protocol.js +78 -0
  48. package/src/engine/physics/cloth/ecs/makeClothWorker.d.ts +17 -0
  49. package/src/engine/physics/cloth/ecs/makeClothWorker.d.ts.map +1 -0
  50. package/src/engine/physics/cloth/ecs/makeClothWorker.js +18 -0
  51. package/src/engine/physics/cloth/playground/README.md +73 -2
  52. package/src/engine/physics/cloth/playground/wind.html +166 -0
  53. package/src/engine/physics/cloth/playground/wind_build.d.ts +81 -0
  54. package/src/engine/physics/cloth/playground/wind_build.d.ts.map +1 -0
  55. package/src/engine/physics/cloth/playground/wind_build.js +141 -0
  56. package/src/engine/physics/cloth/playground/wind_main.d.ts +2 -0
  57. package/src/engine/physics/cloth/playground/wind_main.d.ts.map +1 -0
  58. package/src/engine/physics/cloth/playground/wind_main.js +681 -0
  59. package/src/engine/physics/cloth/solver/ClothState.d.ts +134 -79
  60. package/src/engine/physics/cloth/solver/ClothState.d.ts.map +1 -1
  61. package/src/engine/physics/cloth/solver/ClothState.js +273 -12
  62. package/src/engine/physics/cloth/solver/cloth_solver_constants.d.ts +33 -0
  63. package/src/engine/physics/cloth/solver/cloth_solver_constants.d.ts.map +1 -1
  64. package/src/engine/physics/cloth/solver/cloth_solver_constants.js +34 -0
  65. package/src/engine/physics/cloth/solver/cloth_step.d.ts +21 -2
  66. package/src/engine/physics/cloth/solver/cloth_step.d.ts.map +1 -1
  67. package/src/engine/physics/cloth/solver/cloth_step.js +173 -4
  68. package/src/engine/physics/cloth/solver/cloth_step_instance.d.ts +40 -0
  69. package/src/engine/physics/cloth/solver/cloth_step_instance.d.ts.map +1 -0
  70. package/src/engine/physics/cloth/solver/cloth_step_instance.js +284 -0
  71. package/src/engine/physics/cloth/solver/cloth_wind_accelerate.d.ts +107 -0
  72. package/src/engine/physics/cloth/solver/cloth_wind_accelerate.d.ts.map +1 -0
  73. package/src/engine/physics/cloth/solver/cloth_wind_accelerate.js +263 -0
  74. package/src/engine/physics/cloth/wind/AbstractClothWind.d.ts +88 -0
  75. package/src/engine/physics/cloth/wind/AbstractClothWind.d.ts.map +1 -0
  76. package/src/engine/physics/cloth/wind/AbstractClothWind.js +100 -0
  77. package/src/engine/physics/cloth/wind/ClothAmbientWind.d.ts +85 -0
  78. package/src/engine/physics/cloth/wind/ClothAmbientWind.d.ts.map +1 -0
  79. package/src/engine/physics/cloth/wind/ClothAmbientWind.js +182 -0
  80. package/src/engine/physics/cloth/wind/ClothFluidWind.d.ts +79 -0
  81. package/src/engine/physics/cloth/wind/ClothFluidWind.d.ts.map +1 -0
  82. package/src/engine/physics/cloth/wind/ClothFluidWind.js +210 -0
  83. package/src/engine/physics/cloth/wind/cloth_sample_air.d.ts +101 -0
  84. package/src/engine/physics/cloth/wind/cloth_sample_air.d.ts.map +1 -0
  85. package/src/engine/physics/cloth/wind/cloth_sample_air.js +290 -0
  86. package/src/engine/physics/fluid/ecs/FluidObstacleSystem.d.ts +4 -4
  87. package/src/shade/device/mock/texture_copy.d.ts.map +1 -1
  88. package/src/shade/device/mock/texture_copy.js +28 -0
  89. package/src/shade/playground/vgeo_runtime/README.md +94 -0
  90. package/src/shade/playground/vgeo_runtime/index.html +62 -0
  91. package/src/shade/playground/vgeo_runtime/main.d.ts +2 -0
  92. package/src/shade/playground/vgeo_runtime/main.d.ts.map +1 -0
  93. package/src/shade/playground/vgeo_runtime/main.js +399 -0
  94. package/src/shade/playground/vgeo_viewer/sample_asset.js +1 -1
  95. package/src/shade/renderer/camera/Camera.d.ts +14 -0
  96. package/src/shade/renderer/camera/Camera.d.ts.map +1 -1
  97. package/src/shade/renderer/camera/Camera.js +7 -1
  98. package/src/shade/renderer/geometry/GEOMETRY_METADATA_STRUCT.d.ts.map +1 -1
  99. package/src/shade/renderer/geometry/GEOMETRY_METADATA_STRUCT.js +16 -1
  100. package/src/shade/renderer/geometry/GPUGeometryManager.d.ts.map +1 -1
  101. package/src/shade/renderer/geometry/GPUGeometryManager.js +29 -9
  102. package/src/shade/renderer/geometry/GPUGeometryMetadata.d.ts +10 -0
  103. package/src/shade/renderer/geometry/GPUGeometryMetadata.d.ts.map +1 -1
  104. package/src/shade/renderer/geometry/GPUGeometryMetadata.js +13 -0
  105. package/src/shade/renderer/geometry/virtual/VGEO_FORMAT.md +46 -18
  106. package/src/shade/renderer/geometry/virtual/VIRTUAL_GEOMETRY_DESIGN.md +70 -22
  107. package/src/shade/renderer/geometry/virtual/VIRTUAL_GEOMETRY_PLAN.md +97 -19
  108. package/src/shade/renderer/geometry/virtual/build/VGeoBuildOptions.d.ts +12 -2
  109. package/src/shade/renderer/geometry/virtual/build/VGeoBuildOptions.d.ts.map +1 -1
  110. package/src/shade/renderer/geometry/virtual/build/VGeoBuildOptions.js +14 -3
  111. package/src/shade/renderer/geometry/virtual/build/vgeo_assemble_pages.d.ts +2 -2
  112. package/src/shade/renderer/geometry/virtual/build/vgeo_assemble_pages.d.ts.map +1 -1
  113. package/src/shade/renderer/geometry/virtual/build/vgeo_assemble_pages.js +124 -6
  114. package/src/shade/renderer/geometry/virtual/build/vgeo_page_node_count.d.ts +22 -0
  115. package/src/shade/renderer/geometry/virtual/build/vgeo_page_node_count.d.ts.map +1 -0
  116. package/src/shade/renderer/geometry/virtual/build/vgeo_page_node_count.js +53 -0
  117. package/src/shade/renderer/geometry/virtual/format/VGeoWriteOptions.d.ts +8 -1
  118. package/src/shade/renderer/geometry/virtual/format/VGeoWriteOptions.d.ts.map +1 -1
  119. package/src/shade/renderer/geometry/virtual/format/VGeoWriteOptions.js +8 -1
  120. package/src/shade/renderer/geometry/virtual/format/header/VGEO_FEATURE_IGNORABLE_BOUNDED_PAGES.d.ts +16 -0
  121. package/src/shade/renderer/geometry/virtual/format/header/VGEO_FEATURE_IGNORABLE_BOUNDED_PAGES.d.ts.map +1 -0
  122. package/src/shade/renderer/geometry/virtual/format/header/VGEO_FEATURE_IGNORABLE_BOUNDED_PAGES.js +15 -0
  123. package/src/shade/renderer/geometry/virtual/format/page/VGEO_DEFAULT_PAGE_SIZE.d.ts +54 -0
  124. package/src/shade/renderer/geometry/virtual/format/page/VGEO_DEFAULT_PAGE_SIZE.d.ts.map +1 -0
  125. package/src/shade/renderer/geometry/virtual/format/page/VGEO_DEFAULT_PAGE_SIZE.js +53 -0
  126. package/src/shade/renderer/geometry/virtual/format/read/VGeoContainerHeader.d.ts +13 -2
  127. package/src/shade/renderer/geometry/virtual/format/read/VGeoContainerHeader.d.ts.map +1 -1
  128. package/src/shade/renderer/geometry/virtual/format/read/VGeoContainerHeader.js +14 -2
  129. package/src/shade/renderer/geometry/virtual/format/read/VGeoPage.d.ts +100 -0
  130. package/src/shade/renderer/geometry/virtual/format/read/VGeoPage.d.ts.map +1 -1
  131. package/src/shade/renderer/geometry/virtual/format/read/VGeoPage.js +113 -0
  132. package/src/shade/renderer/geometry/virtual/format/read/vgeo_read_header.d.ts.map +1 -1
  133. package/src/shade/renderer/geometry/virtual/format/read/vgeo_read_header.js +5 -0
  134. package/src/shade/renderer/geometry/virtual/format/read/vgeo_read_page.d.ts.map +1 -1
  135. package/src/shade/renderer/geometry/virtual/format/read/vgeo_read_page.js +108 -0
  136. package/src/shade/renderer/geometry/virtual/format/vgeo_validate_container.d.ts.map +1 -1
  137. package/src/shade/renderer/geometry/virtual/format/vgeo_validate_container.js +23 -0
  138. package/src/shade/renderer/geometry/virtual/format/vgeo_write_container.d.ts.map +1 -1
  139. package/src/shade/renderer/geometry/virtual/format/vgeo_write_container.js +40 -0
  140. package/src/shade/renderer/geometry/virtual/runtime/GPUVirtualGeometryPool.d.ts +228 -0
  141. package/src/shade/renderer/geometry/virtual/runtime/GPUVirtualGeometryPool.d.ts.map +1 -0
  142. package/src/shade/renderer/geometry/virtual/runtime/GPUVirtualGeometryPool.js +932 -0
  143. package/src/shade/renderer/geometry/virtual/runtime/GPUVirtualGeometryRuntime.d.ts +176 -0
  144. package/src/shade/renderer/geometry/virtual/runtime/GPUVirtualGeometryRuntime.d.ts.map +1 -0
  145. package/src/shade/renderer/geometry/virtual/runtime/GPUVirtualGeometryRuntime.js +425 -0
  146. package/src/shade/renderer/geometry/virtual/runtime/REVIEW_LEDGER.md +241 -0
  147. package/src/shade/renderer/geometry/virtual/runtime/RUNTIME_PLAN.md +574 -0
  148. package/src/shade/renderer/geometry/virtual/runtime/VGeoFeedbackLoop.d.ts +120 -0
  149. package/src/shade/renderer/geometry/virtual/runtime/VGeoFeedbackLoop.d.ts.map +1 -0
  150. package/src/shade/renderer/geometry/virtual/runtime/VGeoFeedbackLoop.js +674 -0
  151. package/src/shade/renderer/geometry/virtual/runtime/VGeoRuntimeTables.d.ts +287 -0
  152. package/src/shade/renderer/geometry/virtual/runtime/VGeoRuntimeTables.d.ts.map +1 -0
  153. package/src/shade/renderer/geometry/virtual/runtime/VGeoRuntimeTables.js +976 -0
  154. package/src/shade/renderer/geometry/virtual/runtime/VirtualGeometry.d.ts +42 -0
  155. package/src/shade/renderer/geometry/virtual/runtime/VirtualGeometry.d.ts.map +1 -0
  156. package/src/shade/renderer/geometry/virtual/runtime/VirtualGeometry.js +96 -0
  157. package/src/shade/renderer/geometry/virtual/runtime/cut/VGEO_CUT_FLAG_CULL.d.ts +16 -0
  158. package/src/shade/renderer/geometry/virtual/runtime/cut/VGEO_CUT_FLAG_CULL.d.ts.map +1 -0
  159. package/src/shade/renderer/geometry/virtual/runtime/cut/VGEO_CUT_FLAG_CULL.js +15 -0
  160. package/src/shade/renderer/geometry/virtual/runtime/cut/VGEO_CUT_PARAMS_STRUCT.d.ts +19 -0
  161. package/src/shade/renderer/geometry/virtual/runtime/cut/VGEO_CUT_PARAMS_STRUCT.d.ts.map +1 -0
  162. package/src/shade/renderer/geometry/virtual/runtime/cut/VGEO_CUT_PARAMS_STRUCT.js +83 -0
  163. package/src/shade/renderer/geometry/virtual/runtime/cut/VGEO_CUT_WORKGROUP_SIZE.d.ts +9 -0
  164. package/src/shade/renderer/geometry/virtual/runtime/cut/VGEO_CUT_WORKGROUP_SIZE.d.ts.map +1 -0
  165. package/src/shade/renderer/geometry/virtual/runtime/cut/VGEO_CUT_WORKGROUP_SIZE.js +8 -0
  166. package/src/shade/renderer/geometry/virtual/runtime/cut/chunk_vgeo_cut_access.d.ts +19 -0
  167. package/src/shade/renderer/geometry/virtual/runtime/cut/chunk_vgeo_cut_access.d.ts.map +1 -0
  168. package/src/shade/renderer/geometry/virtual/runtime/cut/chunk_vgeo_cut_access.js +160 -0
  169. package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_collect.d.ts +3 -0
  170. package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_collect.d.ts.map +1 -0
  171. package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_collect.js +255 -0
  172. package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_queue_prepare.d.ts +3 -0
  173. package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_queue_prepare.d.ts.map +1 -0
  174. package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_queue_prepare.js +80 -0
  175. package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_seed.d.ts +3 -0
  176. package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_seed.d.ts.map +1 -0
  177. package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_seed.js +144 -0
  178. package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_traverse.d.ts +3 -0
  179. package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_traverse.d.ts.map +1 -0
  180. package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_traverse.js +530 -0
  181. package/src/shade/renderer/geometry/virtual/runtime/cut/vgeo_cut_feedback_layout.d.ts +39 -0
  182. package/src/shade/renderer/geometry/virtual/runtime/cut/vgeo_cut_feedback_layout.d.ts.map +1 -0
  183. package/src/shade/renderer/geometry/virtual/runtime/cut/vgeo_cut_feedback_layout.js +54 -0
  184. package/src/shade/renderer/geometry/virtual/runtime/graph_vgeo_expand_if_enabled.d.ts +41 -0
  185. package/src/shade/renderer/geometry/virtual/runtime/graph_vgeo_expand_if_enabled.d.ts.map +1 -0
  186. package/src/shade/renderer/geometry/virtual/runtime/graph_vgeo_expand_if_enabled.js +56 -0
  187. package/src/shade/renderer/geometry/virtual/runtime/graph_vgeo_expand_instances_to_meshlets.d.ts +49 -0
  188. package/src/shade/renderer/geometry/virtual/runtime/graph_vgeo_expand_instances_to_meshlets.d.ts.map +1 -0
  189. package/src/shade/renderer/geometry/virtual/runtime/graph_vgeo_expand_instances_to_meshlets.js +328 -0
  190. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_CLUSTER_ROW_OFFSET.d.ts +10 -0
  191. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_CLUSTER_ROW_OFFSET.d.ts.map +1 -0
  192. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_CLUSTER_ROW_OFFSET.js +51 -0
  193. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_CLUSTER_ROW_WORDS.d.ts +13 -0
  194. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_CLUSTER_ROW_WORDS.d.ts.map +1 -0
  195. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_CLUSTER_ROW_WORDS.js +12 -0
  196. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_CUT_STAT.d.ts +17 -0
  197. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_CUT_STAT.d.ts.map +1 -0
  198. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_CUT_STAT.js +99 -0
  199. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_CUT_STAT_COUNT.d.ts +9 -0
  200. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_CUT_STAT_COUNT.d.ts.map +1 -0
  201. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_CUT_STAT_COUNT.js +8 -0
  202. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_FEEDBACK_OFFSET.d.ts +7 -0
  203. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_FEEDBACK_OFFSET.d.ts.map +1 -0
  204. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_FEEDBACK_OFFSET.js +27 -0
  205. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GEOMETRY_ROW_NONE.d.ts +14 -0
  206. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GEOMETRY_ROW_NONE.d.ts.map +1 -0
  207. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GEOMETRY_ROW_NONE.js +13 -0
  208. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GEOMETRY_ROW_OFFSET.d.ts +7 -0
  209. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GEOMETRY_ROW_OFFSET.d.ts.map +1 -0
  210. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GEOMETRY_ROW_OFFSET.js +35 -0
  211. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GEOMETRY_ROW_WORDS.d.ts +9 -0
  212. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GEOMETRY_ROW_WORDS.d.ts.map +1 -0
  213. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GEOMETRY_ROW_WORDS.js +8 -0
  214. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GROUP_FLAG_SELECTABLE.d.ts +15 -0
  215. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GROUP_FLAG_SELECTABLE.d.ts.map +1 -0
  216. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GROUP_FLAG_SELECTABLE.js +14 -0
  217. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GROUP_ROW_OFFSET.d.ts +7 -0
  218. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GROUP_ROW_OFFSET.d.ts.map +1 -0
  219. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GROUP_ROW_OFFSET.js +36 -0
  220. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GROUP_ROW_WORDS.d.ts +10 -0
  221. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GROUP_ROW_WORDS.d.ts.map +1 -0
  222. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GROUP_ROW_WORDS.js +9 -0
  223. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_INSTANCE_OFFSET.d.ts +11 -0
  224. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_INSTANCE_OFFSET.d.ts.map +1 -0
  225. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_INSTANCE_OFFSET.js +54 -0
  226. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_INSTANCE_WORDS.d.ts +9 -0
  227. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_INSTANCE_WORDS.d.ts.map +1 -0
  228. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_INSTANCE_WORDS.js +8 -0
  229. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_NODE_ROW_LEAF_BIT.d.ts +11 -0
  230. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_NODE_ROW_LEAF_BIT.d.ts.map +1 -0
  231. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_NODE_ROW_LEAF_BIT.js +10 -0
  232. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_NODE_ROW_OFFSET.d.ts +7 -0
  233. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_NODE_ROW_OFFSET.d.ts.map +1 -0
  234. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_NODE_ROW_OFFSET.js +30 -0
  235. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_NODE_ROW_WORDS.d.ts +9 -0
  236. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_NODE_ROW_WORDS.d.ts.map +1 -0
  237. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_NODE_ROW_WORDS.js +8 -0
  238. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_NO_CHILD_PAGE.d.ts +13 -0
  239. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_NO_CHILD_PAGE.d.ts.map +1 -0
  240. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_NO_CHILD_PAGE.js +12 -0
  241. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_PAGE_ROW_NONE.d.ts +14 -0
  242. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_PAGE_ROW_NONE.d.ts.map +1 -0
  243. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_PAGE_ROW_NONE.js +13 -0
  244. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_PAGE_ROW_OFFSET.d.ts +11 -0
  245. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_PAGE_ROW_OFFSET.d.ts.map +1 -0
  246. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_PAGE_ROW_OFFSET.js +61 -0
  247. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_PAGE_ROW_WORDS.d.ts +9 -0
  248. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_PAGE_ROW_WORDS.d.ts.map +1 -0
  249. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_PAGE_ROW_WORDS.js +8 -0
  250. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_QUEUE_ITEM_WORDS.d.ts +13 -0
  251. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_QUEUE_ITEM_WORDS.d.ts.map +1 -0
  252. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_QUEUE_ITEM_WORDS.js +12 -0
  253. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_QUEUE_TARGET_GROUP_BIT.d.ts +9 -0
  254. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_QUEUE_TARGET_GROUP_BIT.d.ts.map +1 -0
  255. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_QUEUE_TARGET_GROUP_BIT.js +8 -0
  256. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_WANT_WORDS.d.ts +20 -0
  257. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_WANT_WORDS.d.ts.map +1 -0
  258. package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_WANT_WORDS.js +19 -0
  259. package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_meshlet_batch.d.ts +23 -0
  260. package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_meshlet_batch.d.ts.map +1 -0
  261. package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_meshlet_batch.js +70 -0
  262. package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_page_block_words.d.ts +18 -0
  263. package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_page_block_words.d.ts.map +1 -0
  264. package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_page_block_words.js +25 -0
  265. package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_page_slot_words.d.ts +35 -0
  266. package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_page_slot_words.d.ts.map +1 -0
  267. package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_page_slot_words.js +41 -0
  268. package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_write_page_block.d.ts +32 -0
  269. package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_write_page_block.d.ts.map +1 -0
  270. package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_write_page_block.js +138 -0
  271. package/src/shade/renderer/loader/gltf/tiny-gltf.d.ts +1 -1
  272. package/src/shade/renderer/postprocess/nss/NSS.d.ts +1 -1
  273. package/src/shade/renderer/rasterize/bucket/prepare_meshlet_draw_commands_by_material.d.ts.map +1 -1
  274. package/src/shade/renderer/rasterize/bucket/prepare_meshlet_draw_commands_by_material.js +9 -0
  275. package/src/shade/renderer/rasterize/fast/graph_rasterize_scene_fast.d.ts.map +1 -1
  276. package/src/shade/renderer/rasterize/fast/graph_rasterize_scene_fast.js +12 -1
  277. package/src/shade/renderer/rasterize/standard/graph_rasterize_partial_opaque.d.ts.map +1 -1
  278. package/src/shade/renderer/rasterize/standard/graph_rasterize_partial_opaque.js +12 -1
  279. package/src/shade/renderer/rasterize/standard/graph_rasterize_remaining_opaque.d.ts.map +1 -1
  280. package/src/shade/renderer/rasterize/standard/graph_rasterize_remaining_opaque.js +10 -0
  281. package/src/shade/renderer/scene/GPUSceneContext.d.ts +18 -0
  282. package/src/shade/renderer/scene/GPUSceneContext.d.ts.map +1 -1
  283. package/src/shade/renderer/scene/GPUSceneContext.js +647 -594
  284. package/src/shade/renderer/scene/rows/GPUSceneRows.d.ts.map +1 -1
  285. package/src/shade/renderer/scene/rows/GPUSceneRows.js +22 -0
  286. package/src/shade/renderer/shader/chunk/geometry/mat3/chunk_mat3_singular_values.d.ts +35 -0
  287. package/src/shade/renderer/shader/chunk/geometry/mat3/chunk_mat3_singular_values.d.ts.map +1 -0
  288. package/src/shade/renderer/shader/chunk/geometry/mat3/chunk_mat3_singular_values.js +91 -0
  289. package/src/engine/graphics3/instantiate_scene_bundle.d.ts +0 -54
  290. package/src/engine/graphics3/instantiate_scene_bundle.d.ts.map +0 -1
  291. package/src/engine/graphics3/shade_node_to_entity_composition.d.ts +0 -39
  292. package/src/engine/graphics3/shade_node_to_entity_composition.d.ts.map +0 -1
  293. package/src/shade/renderer/animation/compute_skin_world_bounds.d.ts +0 -35
  294. package/src/shade/renderer/animation/compute_skin_world_bounds.d.ts.map +0 -1
  295. package/src/shade/renderer/animation/compute_skinned_mesh_clip_bounding_sphere.d.ts +0 -96
  296. package/src/shade/renderer/animation/compute_skinned_mesh_clip_bounding_sphere.d.ts.map +0 -1
  297. package/src/shade/renderer/animation/pose/pose_evaluate_world.d.ts +0 -20
  298. package/src/shade/renderer/animation/pose/pose_evaluate_world.d.ts.map +0 -1
  299. package/src/shade/renderer/animation/skin_bind_transform.d.ts +0 -25
  300. package/src/shade/renderer/animation/skin_bind_transform.d.ts.map +0 -1
  301. package/src/shade/renderer/animation/skin_frame_defect.d.ts +0 -34
  302. package/src/shade/renderer/animation/skin_frame_defect.d.ts.map +0 -1
  303. package/src/shade/renderer/animation/skin_joint_matrix.d.ts +0 -24
  304. package/src/shade/renderer/animation/skin_joint_matrix.d.ts.map +0 -1
  305. package/src/shade/renderer/animation/skin_normalize_mesh_frame.d.ts +0 -70
  306. package/src/shade/renderer/animation/skin_normalize_mesh_frame.d.ts.map +0 -1
  307. package/src/shade/renderer/buffer/table/GPUReadbackStagingRing.d.ts +0 -96
  308. package/src/shade/renderer/buffer/table/GPUReadbackStagingRing.d.ts.map +0 -1
  309. package/src/shade/renderer/scene/InstanceBatch.d.ts +0 -92
  310. package/src/shade/renderer/scene/InstanceBatch.d.ts.map +0 -1
  311. package/src/shade/renderer/scene/Mesh.d.ts +0 -55
  312. package/src/shade/renderer/scene/Mesh.d.ts.map +0 -1
  313. package/src/shade/renderer/scene/Node3D.d.ts +0 -159
  314. package/src/shade/renderer/scene/Node3D.d.ts.map +0 -1
  315. package/src/shade/renderer/scene/Node3DDirtyList.d.ts +0 -59
  316. package/src/shade/renderer/scene/Node3DDirtyList.d.ts.map +0 -1
  317. package/src/shade/renderer/scene/SceneNodeBinding.d.ts +0 -52
  318. package/src/shade/renderer/scene/SceneNodeBinding.d.ts.map +0 -1
  319. package/src/shade/renderer/scene/SkinnedMesh.d.ts +0 -27
  320. package/src/shade/renderer/scene/SkinnedMesh.d.ts.map +0 -1
  321. package/src/shade/renderer/scene/TransformAuthority.d.ts +0 -19
  322. package/src/shade/renderer/scene/TransformAuthority.d.ts.map +0 -1
@@ -0,0 +1,562 @@
1
+ import { ResourceAccessKind } from "../../../../core/model/ResourceAccessKind.js";
2
+ import { ResourceAccessSpecification } from "../../../../core/model/ResourceAccessSpecification.js";
3
+ import { WorkerSystem } from "../../../ecs/async/WorkerSystem.js";
4
+ import {
5
+ TransformAttachment
6
+ } from "../../../ecs/transform-attachment/TransformAttachment.js";
7
+ import { Transform64 } from "../../../ecs/transform/Transform64.js";
8
+ import { ClothStepParam } from "../solver/cloth_step_instance.js";
9
+ import { Cloth } from "./Cloth.js";
10
+ import { ClothCollider } from "./ClothCollider.js";
11
+ import { ClothExclude } from "./ClothExclude.js";
12
+ import { ClothRig } from "./ClothRig.js";
13
+ import { ClothWorld } from "./ClothWorld.js";
14
+ import {
15
+ ClothCommand,
16
+ cloth_command_offset,
17
+ cloth_command_word_count
18
+ } from "./cloth_worker_protocol.js";
19
+
20
+ /**
21
+ * Default ceiling on simultaneously stepped cloths. Sizes the command region,
22
+ * which is allocated once at startup and cannot grow.
23
+ * @type {number}
24
+ */
25
+ const DEFAULT_MAX_CLOTH_COUNT = 32;
26
+
27
+ /**
28
+ * Drop-in alternative to {@link ClothSystem} that runs the solve on a worker
29
+ * thread.
30
+ *
31
+ * ## What moves, and what does not
32
+ *
33
+ * A cloth's fixed step is "work that needs the world" followed by "arithmetic
34
+ * over typed arrays", and `MEASUREMENTS.md` §7 puts 69% of the frame in the
35
+ * stretch rows alone — so the split is where §12 drew it:
36
+ *
37
+ * - **main thread**: seeding, the anchor's pose, the local-frame carry, the
38
+ * leash centres, the collider broadphase, the sleep test and the write-back.
39
+ * All of it reads components, walks hierarchies or queries an index, and
40
+ * none of it is where the time goes.
41
+ * - **worker**: `cloth_step_instance(state, exclusions, params, offset)` — the
42
+ * damping, the contact search, the self-collision pair search, the solve and
43
+ * the velocity clamp.
44
+ *
45
+ * Both sides call {@link ClothWorld}, and both hand `cloth_step_instance` the
46
+ * *same* `Float64` parameter block — {@link ClothSystem} in a private scratch
47
+ * array, this one in a slice of the shared command region. Identical code over
48
+ * identical data in an identical order, so results are bit-for-bit equal to
49
+ * {@link ClothSystem}'s (`WorkerClothSystem.spec.js` holds that as a standing
50
+ * gate).
51
+ *
52
+ * Nothing is copied. A cloth's `ClothState` lives in a {@link SharedArrayBuffer}
53
+ * and the worker steps it in place; a completed step is published by advancing a
54
+ * single atomic.
55
+ *
56
+ * ## Using it
57
+ *
58
+ * ```js
59
+ * entityManager.addSystem(new WorkerClothSystem({ worker_factory: makeClothWorker }));
60
+ * ```
61
+ *
62
+ * There is no per-component opt-in, unlike {@link WorkerFluidSystem}'s
63
+ * `field.shared_memory`: a cloth's state does not exist until the cloth seeds,
64
+ * and seeding is this system's own work, so it simply builds them shared.
65
+ *
66
+ * Requires a cross-origin isolated page (`Cross-Origin-Opener-Policy:
67
+ * same-origin` + `Cross-Origin-Embedder-Policy: require-corp`) — without it
68
+ * `SharedArrayBuffer` does not exist and startup throws.
69
+ *
70
+ * ## Ownership — the one behavioural difference
71
+ *
72
+ * {@link ClothSystem} leaves every cloth consistent at all times. Here a cloth's
73
+ * `ClothState` is **owned by the worker** from the moment this system's
74
+ * `fixedUpdate` dispatches until the next tick joins the result. Concretely:
75
+ *
76
+ * - The `Transform64`/`Node3D` poses this system writes are *not* affected:
77
+ * the write-back happens at join, on this thread, inside the fixed pass. A
78
+ * renderer reading a cloth's transforms reads them exactly as it always did.
79
+ * - What must not be read outside the fixed pass is `ClothInstance#state` —
80
+ * particle positions, velocities, the contact slots. Nothing in the engine
81
+ * does; the playgrounds' diagnostics run inside the fixed pass.
82
+ * - {@link ClothColliderSystem} is refreshed from inside this system's own
83
+ * `collect`, as it is under {@link ClothSystem}, so the index is never read
84
+ * while a step is in flight.
85
+ *
86
+ * Two further differences from {@link ClothSystem}:
87
+ *
88
+ * - Results lag by one tick: the pose written at tick `T` is step `T - 1`'s.
89
+ * The *sequence* of states is unchanged — it is observed one tick later.
90
+ * - A newly seeded cloth is not stepped until the worker acknowledges its
91
+ * registration (a cold-plane round trip, so at least one tick and in
92
+ * practice a few). Until then it is not advanced either — not stepped, not
93
+ * carried across anchor motion, not written back — which is what keeps the
94
+ * step *sequence* identical to {@link ClothSystem}'s rather than merely
95
+ * similar. A garment therefore holds its bind pose for a few ticks after it
96
+ * spawns, and a re-seed does the same, because a re-seed builds a new buffer
97
+ * and the worker has to be told about it.
98
+ *
99
+ * @author Alex Goldring
100
+ * @copyright Company Named Limited (c) 2026
101
+ */
102
+ export class WorkerClothSystem extends WorkerSystem {
103
+
104
+ dependencies = [Cloth, Transform64];
105
+
106
+ components_used = [
107
+ ResourceAccessSpecification.from(Cloth, ResourceAccessKind.Read),
108
+ ResourceAccessSpecification.from(Transform64, ResourceAccessKind.Read | ResourceAccessKind.Write),
109
+ ResourceAccessSpecification.from(TransformAttachment, ResourceAccessKind.Read | ResourceAccessKind.Write),
110
+ ResourceAccessSpecification.from(ClothExclude, ResourceAccessKind.Read),
111
+ ResourceAccessSpecification.from(ClothCollider, ResourceAccessKind.Read),
112
+ ResourceAccessSpecification.from(ClothRig, ResourceAccessKind.Read)
113
+ ];
114
+
115
+ /**
116
+ * The cloths, and everything about stepping one that is not arithmetic.
117
+ * Shared with {@link ClothSystem}, which is what makes the two systems one
118
+ * implementation.
119
+ * @type {ClothWorld}
120
+ */
121
+ world = new ClothWorld();
122
+
123
+ /**
124
+ * @type {(() => Worker)|null}
125
+ */
126
+ #worker_factory = null;
127
+
128
+ /**
129
+ * @type {number}
130
+ */
131
+ #max_cloth_count = DEFAULT_MAX_CLOTH_COUNT;
132
+
133
+ /**
134
+ * The cold-plane message that announced each registered cloth, the state it
135
+ * announced, and whether the worker has acknowledged it.
136
+ *
137
+ * Keyed by instance, and carrying the `ClothState` rather than trusting the
138
+ * instance still to hold it: a re-seed replaces the state with a new buffer,
139
+ * and the registration the worker holds then names memory nobody writes to
140
+ * any more. Comparing identity is how that is noticed without a dirty flag.
141
+ * @type {Map<ClothInstance, {id: number, sequence: number, state: ClothState, acknowledged: boolean}>}
142
+ */
143
+ #registrations = new Map();
144
+
145
+ /**
146
+ * Cloths announced but not yet acknowledged.
147
+ * @type {ClothInstance[]}
148
+ */
149
+ #pending = [];
150
+
151
+ /**
152
+ * Cloths dispatched at the tick now in flight, in nomination order — the
153
+ * ones {@link apply} will finish.
154
+ * @type {ClothInstance[]}
155
+ */
156
+ #dispatched = [];
157
+
158
+ /**
159
+ * @type {number}
160
+ */
161
+ #next_cloth_id = 1;
162
+
163
+ /**
164
+ * Latches the max_cloth_count overflow report so a persistent
165
+ * misconfiguration warns once instead of once per tick.
166
+ * @type {boolean}
167
+ */
168
+ #cloth_overflow_reported = false;
169
+
170
+ /**
171
+ * @param {object} options
172
+ * @param {() => Worker} options.worker_factory spawns the worker. Supplied
173
+ * rather than hard-coded because the spawn expression needs
174
+ * `import.meta.url`, which cannot be parsed by the CommonJS transform
175
+ * the test runner uses — see `makeClothWorker.js`.
176
+ * @param {number} [options.max_cloth_count] ceiling on simultaneously
177
+ * stepped cloths; sizes the fixed command region.
178
+ */
179
+ constructor({ worker_factory, max_cloth_count = DEFAULT_MAX_CLOTH_COUNT } = {}) {
180
+ super();
181
+
182
+ this.#worker_factory = worker_factory;
183
+ this.#max_cloth_count = max_cloth_count;
184
+
185
+ this.world.shared_state = true;
186
+
187
+ this.command_word_count = cloth_command_word_count(max_cloth_count);
188
+ }
189
+
190
+ /**
191
+ * World gravity, m/s². Rotated into each cloth's local frame per step.
192
+ * @returns {Float64Array}
193
+ */
194
+ get gravity() {
195
+ return this.world.gravity;
196
+ }
197
+
198
+ /**
199
+ * @param {Float64Array} value
200
+ */
201
+ set gravity(value) {
202
+ this.world.gravity = value;
203
+ }
204
+
205
+ /**
206
+ * Where the air comes from — see {@link ClothWorld#wind}. Sampled on **this**
207
+ * thread even under the worker, because a fluid field cannot cross and its
208
+ * answer can: `cloth_sample_air.js` is the argument, and it lands in a region
209
+ * of the cloth's own shared buffer.
210
+ * @returns {AbstractClothWind|null}
211
+ */
212
+ get wind() {
213
+ return this.world.wind;
214
+ }
215
+
216
+ /**
217
+ * @param {AbstractClothWind|null} value
218
+ */
219
+ set wind(value) {
220
+ this.world.wind = value;
221
+ }
222
+
223
+ /**
224
+ * @returns {ClothInstance[]}
225
+ */
226
+ get instances() {
227
+ return this.world.instances;
228
+ }
229
+
230
+ /**
231
+ * @returns {{instance_of: function(number): (PrefabInstance|null)}|null}
232
+ */
233
+ get models() {
234
+ return this.world.models;
235
+ }
236
+
237
+ /**
238
+ * @param {{instance_of: function(number): (PrefabInstance|null)}|null} value
239
+ */
240
+ set models(value) {
241
+ this.world.models = value;
242
+ }
243
+
244
+ /**
245
+ * @returns {Worker}
246
+ */
247
+ createWorker() {
248
+ if (typeof this.#worker_factory !== "function") {
249
+ throw new Error(
250
+ "WorkerClothSystem requires a worker factory:"
251
+ + " new WorkerClothSystem({ worker_factory: makeClothWorker })"
252
+ );
253
+ }
254
+
255
+ return this.#worker_factory();
256
+ }
257
+
258
+ /**
259
+ * @param {EntityManager} entityManager
260
+ * @returns {Promise<void>}
261
+ */
262
+ async startup(entityManager) {
263
+ this.world.attach(entityManager);
264
+
265
+ await super.startup(entityManager);
266
+ }
267
+
268
+ /**
269
+ * @param {EntityManager} entityManager
270
+ * @returns {Promise<void>}
271
+ */
272
+ async shutdown(entityManager) {
273
+ await super.shutdown(entityManager);
274
+
275
+ this.#registrations.clear();
276
+ this.#pending.length = 0;
277
+ this.#dispatched.length = 0;
278
+ }
279
+
280
+ /**
281
+ * @param {Cloth} cloth
282
+ * @param {Transform64} transform
283
+ * @param {number} entity
284
+ */
285
+ link(cloth, transform, entity) {
286
+ this.world.link(cloth, transform, entity);
287
+ }
288
+
289
+ /**
290
+ * @param {Cloth} cloth
291
+ * @param {Transform64} transform
292
+ * @param {number} entity
293
+ */
294
+ unlink(cloth, transform, entity) {
295
+ const instance = this.world.unlink(entity);
296
+
297
+ if (instance !== undefined) {
298
+ this.#retire(instance);
299
+ }
300
+ }
301
+
302
+ /**
303
+ * Throw away a cloth's binding so the next step walks its subtree again.
304
+ * @param {number} entity
305
+ * @returns {void}
306
+ */
307
+ reseed(entity) {
308
+ this.world.reseed(entity);
309
+ }
310
+
311
+ /**
312
+ * Wake a sleeping cloth.
313
+ * @param {number} entity
314
+ * @returns {void}
315
+ */
316
+ wake(entity) {
317
+ this.world.wake(entity);
318
+ }
319
+
320
+ /**
321
+ * @param {number} entity
322
+ * @returns {ClothInstance|undefined}
323
+ */
324
+ instanceOf(entity) {
325
+ return this.world.instanceOf(entity);
326
+ }
327
+
328
+ /**
329
+ * @returns {boolean} whether cloth *particle state* may currently be read
330
+ * from the main thread. False while a step is in flight. The poses
331
+ * on the scene are always readable — they are written at join.
332
+ */
333
+ get is_state_readable() {
334
+ return !this.is_step_in_flight;
335
+ }
336
+
337
+ /**
338
+ * @param {Float64Array} command
339
+ * @param {number} tick
340
+ * @param {number} time_delta_seconds
341
+ * @returns {boolean}
342
+ */
343
+ collect(command, tick, time_delta_seconds) {
344
+ const em = this.entityManager;
345
+
346
+ if (em === null) {
347
+ return false;
348
+ }
349
+
350
+ const ecd = em.dataset;
351
+
352
+ if (ecd === null || ecd === undefined) {
353
+ return false;
354
+ }
355
+
356
+ this.#promote_acknowledged_cloths();
357
+
358
+ const world = this.world;
359
+
360
+ world.begin(ecd, time_delta_seconds);
361
+
362
+ const instances = world.instances;
363
+
364
+ const max_cloth_count = this.#max_cloth_count;
365
+
366
+ const dispatched = this.#dispatched;
367
+
368
+ dispatched.length = 0;
369
+
370
+ let cloth_count = 0;
371
+
372
+ for (let i = 0; i < instances.length; i++) {
373
+ const instance = instances[i];
374
+
375
+ if (!world.ensure_seeded(instance, ecd, time_delta_seconds)) {
376
+ continue;
377
+ }
378
+
379
+ const registration = this.#registrations.get(instance);
380
+
381
+ if (registration === undefined || registration.state !== instance.state) {
382
+ // Either the cloth has just seeded, or a re-seed built it a new
383
+ // buffer. Announce the current one and wait — nominating memory
384
+ // the worker has not attached to is a protocol error, and
385
+ // advancing the cloth without stepping it would put its step
386
+ // sequence out of step with ClothSystem's for the rest of the
387
+ // run.
388
+ this.#register(instance);
389
+
390
+ continue;
391
+ }
392
+
393
+ if (!registration.acknowledged) {
394
+ continue;
395
+ }
396
+
397
+ if (cloth_count === max_cloth_count) {
398
+ if (!this.#cloth_overflow_reported) {
399
+ this.#cloth_overflow_reported = true;
400
+
401
+ console.error(
402
+ `WorkerClothSystem: more live cloths than max_cloth_count (${max_cloth_count});`
403
+ + ` the remainder will not be simulated. Raise max_cloth_count in the constructor.`
404
+ );
405
+ }
406
+
407
+ break;
408
+ }
409
+
410
+ const offset = cloth_command_offset(cloth_count);
411
+
412
+ if (!world.advance(instance, time_delta_seconds, command, offset)) {
413
+ // Asleep. §7 P5: not stepped, not written back, and costing
414
+ // nothing but its absence from this list.
415
+ continue;
416
+ }
417
+
418
+ command[offset + ClothStepParam.ID] = registration.id;
419
+
420
+ dispatched.push(instance);
421
+
422
+ cloth_count++;
423
+ }
424
+
425
+ if (cloth_count === 0) {
426
+ // Nothing to do. Skipping the dispatch also keeps the fixed-step
427
+ // gate open, since there is no result to wait for.
428
+ return false;
429
+ }
430
+
431
+ command[ClothCommand.CLOTH_COUNT] = cloth_count;
432
+
433
+ return true;
434
+ }
435
+
436
+ /**
437
+ * The worker stepped each nominated cloth in place, so joining is the sleep
438
+ * test and the write-back — the half of `ClothSystem`'s loop that needs the
439
+ * scene rather than the arithmetic.
440
+ *
441
+ * @param {number} tick
442
+ */
443
+ apply(tick) {
444
+ const ecd = this.entityManager.dataset;
445
+
446
+ if (ecd === null || ecd === undefined) {
447
+ return;
448
+ }
449
+
450
+ const dispatched = this.#dispatched;
451
+
452
+ const world = this.world;
453
+
454
+ for (let i = 0; i < dispatched.length; i++) {
455
+ const instance = dispatched[i];
456
+
457
+ if (!this.#registrations.has(instance)) {
458
+ // Unlinked between dispatch and join. Its entity is gone, so
459
+ // there is nothing to write the pose onto.
460
+ continue;
461
+ }
462
+
463
+ world.finish(instance, ecd);
464
+ }
465
+
466
+ dispatched.length = 0;
467
+ }
468
+
469
+ /**
470
+ * Announce a cloth's current `ClothState` to the worker, retiring whatever
471
+ * it was registered with before.
472
+ *
473
+ * @param {ClothInstance} instance
474
+ * @private
475
+ */
476
+ #register(instance) {
477
+ const state = instance.state;
478
+
479
+ if (!state.isSharedMemory()) {
480
+ // Not an assert: asserts are stripped from a production build, and a
481
+ // non-shared buffer does not fail loudly on its own — `postMessage`
482
+ // structured-clones it, both threads get a private copy of a cloth,
483
+ // and each simulates a garment the other cannot see. A cloth built
484
+ // through this system is always shared (`ClothWorld#shared_state`),
485
+ // so reaching here means someone handed it a world that is not.
486
+ throw new Error(
487
+ `WorkerClothSystem: the ClothState of entity ${instance.entity} is not shared-memory backed,`
488
+ + ` so the worker would step a copy of it. Build the world with shared_state set, or use`
489
+ + ` ClothSystem, which is the same solver on this thread.`
490
+ );
491
+ }
492
+
493
+ this.#retire(instance);
494
+
495
+ const id = this.#next_cloth_id++;
496
+
497
+ const sequence = this.postToWorker({
498
+ type: "add_cloth",
499
+ id,
500
+ state: state.getSharedDescriptor(),
501
+ self_exclusions: instance.self_exclusions
502
+ });
503
+
504
+ this.#registrations.set(instance, { id, sequence, state, acknowledged: false });
505
+ this.#pending.push(instance);
506
+ }
507
+
508
+ /**
509
+ * Drop a cloth's registration, telling the worker to forget it.
510
+ *
511
+ * @param {ClothInstance} instance
512
+ * @private
513
+ */
514
+ #retire(instance) {
515
+ const registration = this.#registrations.get(instance);
516
+
517
+ if (registration === undefined) {
518
+ return;
519
+ }
520
+
521
+ this.#registrations.delete(instance);
522
+
523
+ const pending_index = this.#pending.indexOf(instance);
524
+
525
+ if (pending_index !== -1) {
526
+ this.#pending.splice(pending_index, 1);
527
+ }
528
+
529
+ // Safe even mid-step: the worker may still be stepping this cloth, and
530
+ // will simply finish. It is dropped from the next dispatch regardless of
531
+ // when the message lands, and the shared buffer outlives both sides'
532
+ // references.
533
+ this.postToWorker({ type: "remove_cloth", id: registration.id });
534
+ }
535
+
536
+ /**
537
+ * Move cloths whose registration message the worker has consumed into the
538
+ * dispatchable set. Until then the worker has no view of their memory and
539
+ * nominating them would be a protocol error.
540
+ *
541
+ * @private
542
+ */
543
+ #promote_acknowledged_cloths() {
544
+ let write = 0;
545
+
546
+ for (let i = 0; i < this.#pending.length; i++) {
547
+ const instance = this.#pending[i];
548
+
549
+ const registration = this.#registrations.get(instance);
550
+
551
+ if (registration !== undefined && this.isMessageHandled(registration.sequence)) {
552
+ registration.acknowledged = true;
553
+
554
+ continue;
555
+ }
556
+
557
+ this.#pending[write++] = instance;
558
+ }
559
+
560
+ this.#pending.length = write;
561
+ }
562
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=cloth.worker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cloth.worker.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/physics/cloth/ecs/cloth.worker.js"],"names":[],"mappings":""}
@@ -0,0 +1,12 @@
1
+ import { SystemWorkerHost } from "../../../ecs/async/SystemWorkerHost.js";
2
+ import { ClothWorkerCore } from "./ClothWorkerCore.js";
3
+
4
+ /**
5
+ * Worker entry point for {@link WorkerClothSystem}.
6
+ *
7
+ * A real module worker rather than a generated blob, so the solver it pulls in
8
+ * is the ordinary `cloth_step_instance` — same source, same bundler treatment,
9
+ * same source maps — which is what makes bit-parity with the main-thread
10
+ * {@link ClothSystem} a property of the build rather than a coincidence.
11
+ */
12
+ SystemWorkerHost.serve(new ClothWorkerCore());
@@ -1 +1 @@
1
- {"version":3,"file":"cloth_build_rows.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/physics/cloth/ecs/cloth_build_rows.js"],"names":[],"mappings":"AAuDA;;;;GAIG;AACH,+DAFa,IAAI,CAyBhB;AAID;;;;;;;GAOG;AACH,8DAHW,MAAM,GACJ,IAAI,CA4LhB;AAWD;;;;;;;;;;;;;;;;GAgBG;AACH,kEAHW,MAAM,GACJ,IAAI,CAoChB;AAED;;;;;;;;;;;GAWG;AACH,iGAFa,OAAO,CAkBnB;AAhXD;;;;;;;;;;;;;;;;;;GAkBG;AAEH;;;;GAIG;AACH,kCAFU,MAAM,CAEwB;AAIxC;;;;;;;;;;;;;;;;GAgBG;AACH,gCAFU,MAAM,CAEmB"}
1
+ {"version":3,"file":"cloth_build_rows.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/physics/cloth/ecs/cloth_build_rows.js"],"names":[],"mappings":"AAuDA;;;;GAIG;AACH,+DAFa,IAAI,CAyBhB;AAID;;;;;;;GAOG;AACH,8DAHW,MAAM,GACJ,IAAI,CA6LhB;AAWD;;;;;;;;;;;;;;;;GAgBG;AACH,kEAHW,MAAM,GACJ,IAAI,CAoChB;AAED;;;;;;;;;;;GAWG;AACH,iGAFa,OAAO,CAkBnB;AAjXD;;;;;;;;;;;;;;;;;;GAkBG;AAEH;;;;GAIG;AACH,kCAFU,MAAM,CAEwB;AAIxC;;;;;;;;;;;;;;;;GAgBG;AACH,gCAFU,MAAM,CAEmB"}
@@ -249,7 +249,8 @@ export function cloth_build_rows(instance, dt) {
249
249
  stretch_force_min: Float32Array.from(stretch_force_min),
250
250
  stretch_force_max: Float32Array.from(stretch_force_max),
251
251
  leash_particle: Int32Array.from(leash_particle),
252
- leash_radius: Float32Array.from(leash_radius)
252
+ leash_radius: Float32Array.from(leash_radius),
253
+ shared: instance.shared_state
253
254
  });
254
255
 
255
256
  const particle_of_node = new Int32Array(node_count);
@@ -31,6 +31,36 @@ export function cloth_bend_ratio(bend: number): number;
31
31
  * @returns {number}
32
32
  */
33
33
  export function cloth_velocity_limit(shortest_row: number, substeps: number, iterations: number, dt: number): number;
34
+ /**
35
+ * §10's aerodynamic coupling as the **per-step response** the step multiplies
36
+ * the relative flow by, 1/s.
37
+ *
38
+ * Not a rate, and the difference is a stability argument rather than a
39
+ * convenience. The step holds one acceleration for the whole fixed step, so an
40
+ * explicit `rate·(u − v)` changes the velocity by `rate·dt·(u − v)` — which
41
+ * overshoots the air once `rate·dt > 1` and diverges past 2. §1's first
42
+ * commitment is "not at 5 fps", which is a `dt` of 0.2 s and a rate of 10.
43
+ *
44
+ * The exact solution of the same linear ODE has no such boundary:
45
+ *
46
+ * Δv = (1 − e^(−rate·dt))·(u − v)
47
+ *
48
+ * closes a fraction of the gap that is strictly below one for every `rate` and
49
+ * every `dt`, so the drag can never push a particle past the air it is
50
+ * relaxing toward. Dividing by `dt` turns it back into the acceleration the
51
+ * solver wants, and the exponential is evaluated **once per cloth per step** on
52
+ * the main thread rather than per particle.
53
+ *
54
+ * It is also the same step `GlobalFluidEffector` takes for the air itself —
55
+ * both are relaxations toward a velocity, and a cloth and the air around it
56
+ * reaching their common answer by the same arithmetic is a symmetry worth
57
+ * having.
58
+ *
59
+ * @param {number} drag `[0, 1]`
60
+ * @param {number} dt fixed step, seconds
61
+ * @returns {number} 1/s; `0` when there is no coupling at all
62
+ */
63
+ export function cloth_drag_response(drag: number, dt: number): number;
34
64
  /**
35
65
  * Fraction of a particle's velocity surviving one fixed step. §7 P5, and see
36
66
  * {@link ClothDynamics#damping} for why this is a correctness mechanism rather
@@ -218,6 +248,34 @@ export const CLOTH_TELEPORT_FLOOR: number;
218
248
  * @type {number}
219
249
  */
220
250
  export const CLOTH_STABILISE_STEPS: number;
251
+ /**
252
+ * Aerodynamic relaxation rate at `drag = 1`, per second (§10).
253
+ *
254
+ * ## Linear, not log
255
+ *
256
+ * `bend` is log-mapped because a stiffness spans decades and an author needs
257
+ * the whole range to be useful. Drag does not: the library's own entries run
258
+ * from leather at 0.05 to silk at 0.45, a factor of nine, and a linear map is
259
+ * the one that keeps that factor of nine meaning a factor of nine. It is also
260
+ * exactly zero at zero without a special case, which a log map cannot be.
261
+ *
262
+ * ## Sixty, because that is "the cloth goes where the air goes"
263
+ *
264
+ * The rate is a reciprocal time constant, so what `drag = 1` has to mean is a
265
+ * cloth with no aerodynamic memory at all — one that takes the air's velocity
266
+ * within a step. At 60 Hz, a rate of 60 closes 63% of the gap to the air every
267
+ * step and has a time constant of 17 ms, which is that. The library then reads:
268
+ * silk 27/s (37 ms), hair 18/s, cotton 12/s (83 ms), rope 7.2/s, denim 4.8/s
269
+ * (0.21 s), leather and chain 3/s (0.33 s) — a light banner that answers a gust
270
+ * within a couple of frames and an armour skirt that takes a third of a second
271
+ * to notice one, which is the ordering the fabrics already claimed.
272
+ *
273
+ * Raising it further buys nothing: {@link cloth_drag_response} saturates at
274
+ * `1/dt` by construction, so past about `1/dt` the whole range compresses into
275
+ * "the cloth is a streamer". `MEASUREMENTS.md` §48.
276
+ * @type {number}
277
+ */
278
+ export const CLOTH_DRAG_RATE_MAX: number;
221
279
  /**
222
280
  * Speed below which a particle counts as still, as a fraction of the cloth's
223
281
  * reach per second. A metre-long rope sleeps once nothing on it is moving
@@ -1 +1 @@
1
- {"version":3,"file":"cloth_dynamics_map.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/physics/cloth/ecs/cloth_dynamics_map.js"],"names":[],"mappings":"AA6MA;;;;;;;;GAQG;AACH,gDAHW,MAAM,GACJ,MAAM,CAMlB;AAED;;;;;;;;GAQG;AACH,uCAHW,MAAM,GACJ,MAAM,CAUlB;AAED;;;;;;;;;;;GAWG;AACH,mDAPW,MAAM,YAEN,MAAM,cACN,MAAM,MACN,MAAM,GACJ,MAAM,CAIlB;AAED;;;;;;;;GAQG;AACH,kDAJW,MAAM,MACN,MAAM,GACJ,MAAM,CAQlB;AA9QD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AAEH;;;;;GAKG;AACH,+BAFU,MAAM,CAEqB;AAErC;;;;;GAKG;AACH,+BAFU,MAAM,CAEqB;AAErC;;;;;;;;;;;GAWG;AACH,mCAFU,MAAM,CAEsB;AAEtC;;;;;GAKG;AACH,mCAFU,MAAM,CAEyB;AAEzC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AACH,+CAFU,MAAM,CAEkC;AAElD;;;;;;;;GAQG;AACH,iCAFU,MAAM,CAEqB;AAErC;;;;;;;;;;;;;GAaG;AACH,wCAFU,MAAM,CAE6B;AAE7C;;;;;;;;GAQG;AACH,0CAFU,MAAM,CAE+B;AAE/C;;;;;;;;GAQG;AACH,mCAFU,MAAM,CAEsB;AAEtC;;;;;;;;GAQG;AACH,mCAFU,MAAM,CAEsB;AAEtC;;;;;;;GAOG;AACH,oCAFU,MAAM,CAEwB;AAExC;;;;;GAKG;AACH,sCAFU,MAAM,CAE4B;AAE5C;;;;;GAKG;AACH,gCAFU,MAAM,CAEoB"}
1
+ {"version":3,"file":"cloth_dynamics_map.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/physics/cloth/ecs/cloth_dynamics_map.js"],"names":[],"mappings":"AA0OA;;;;;;;;GAQG;AACH,gDAHW,MAAM,GACJ,MAAM,CAMlB;AAED;;;;;;;;GAQG;AACH,uCAHW,MAAM,GACJ,MAAM,CAUlB;AAED;;;;;;;;;;;GAWG;AACH,mDAPW,MAAM,YAEN,MAAM,cACN,MAAM,MACN,MAAM,GACJ,MAAM,CAIlB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,0CAJW,MAAM,MACN,MAAM,GACJ,MAAM,CAYlB;AAED;;;;;;;;GAQG;AACH,kDAJW,MAAM,MACN,MAAM,GACJ,MAAM,CAQlB;AApVD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AAEH;;;;;GAKG;AACH,+BAFU,MAAM,CAEqB;AAErC;;;;;GAKG;AACH,+BAFU,MAAM,CAEqB;AAErC;;;;;;;;;;;GAWG;AACH,mCAFU,MAAM,CAEsB;AAEtC;;;;;GAKG;AACH,mCAFU,MAAM,CAEyB;AAEzC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AACH,+CAFU,MAAM,CAEkC;AAElD;;;;;;;;GAQG;AACH,iCAFU,MAAM,CAEqB;AAErC;;;;;;;;;;;;;GAaG;AACH,wCAFU,MAAM,CAE6B;AAE7C;;;;;;;;GAQG;AACH,0CAFU,MAAM,CAE+B;AAE/C;;;;;;;;GAQG;AACH,mCAFU,MAAM,CAEsB;AAEtC;;;;;;;;GAQG;AACH,mCAFU,MAAM,CAEsB;AAEtC;;;;;;;GAOG;AACH,oCAFU,MAAM,CAEwB;AAExC;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,kCAFU,MAAM,CAEsB;AAEtC;;;;;GAKG;AACH,sCAFU,MAAM,CAE4B;AAE5C;;;;;GAKG;AACH,gCAFU,MAAM,CAEoB"}